Skip to main content.

Navigation:

Aufgabe 1: Kommandozeilenparser

Ziel

Aufgabe

In dieser Aufgabe soll anhand der Vorgaben ein minimaler Kommandointerpreter erzeugt werden. Zu diesem Zweck soll die Vorgabe so erweitert werden, dass eine Benutzereingabe in einen bereitgestellten Puffer eingelesen und anschließend ausgewerte wird. Ist die Eingabe länger als der übergebene Puffer soll sie verworfen und ein Fehler gemeldet werden.

Nachdem der Puffer mit einer Eingabe gefüllt wurde, muss diese Eingabe in ihre Bestandteile zerlegt und die gefundenen Komponenten bzw. Worte in einer geeigneten Struktur abgelegt werden. Syntaktische Fehler sind dabei durch entsprechende Meldungen anzuzeigen. Es werden folgende Annahmen zur Struktur einer Eingabezeile gemacht:

Die Funktionsfähigkeit der Erweiterung soll anhand des internen Kommandos 'help' gezeigt werden. Dieses Kommando ist im Rahmen der Aufgabe zu implementieren.

Implementierungshinweise

Die Aufgabe besteht im Wesentlichen aus drei Teilen: der Eingabe, der Auswertung der Eingabe und der Umsetzung eines Kommandos. Da die einzelnen Elemente der Aufgabe voneinander abhängen empfehlen wir folgende Bearbeitungsreihenfolge:

  1. Umsetzung der Eingabe in der Methode int readline(char* s, int c);
    Hinweise: Eine Zeile wird begrenzt durch '\n' oder EOF, weitere Infos: getchar(3)
  2. Implementierung der Klasse Parser als Superklasse von BSShell. Dafür muss eine Struktur definiert werden, in der die gefundenen Komponenten bzw. Worte abgelegt werden und auf die die Klasse BSShell zugreifen kann. Diese Struktur kann beispielsweise so aussehen:
    struct command {
      struct command *next; /* Zeiger auf naechste Kommando */
      char **token1;        /* Woerter vor "|" */
      int numtok1;          /* Anzahl der Woerter vor "|" */
      char **token2;        /* Woerter hinter "|" */
      int numtok2;          /* Anzahl der Woerter hinter "|" */
      char *input;          /* Wort hinter "<" */
      char *output;         /* Wort hinter ">" */
      short backgr;         /* "&" im Kommando */
      short ispipe;         /* "|" im Kommando */
    };
    Die Funktionalität eures Kommandozeilenparsers könnt Ihr dann mit der Methode void output(); testen. Beispiel:
    prompt> ls -l       file| wc &wc      -l > x file
    token1 = "ls", "-l", "file"
    numtok1 = 3
    token2 = "wc"
    numtok2 = 1
    backgr = true
    ispipe = true
    
    token1 = "wc", "-l", "file"
    numtok1 = 3
    output = "x"
    
    prompt>    ls -l |
    parse: Invalid null command.
    Weitere Infos: bash, sh, tcsh, strtok(3), strcmp(3)
  3. Umsetzung der Ausführung der erkannten Kommandosequenzen. Zu diesem Zweck wird die Methode bool execute(); verwendet.
  4. Umsetzung des Kommandos 'help' entsprechend der Beispielvorgaben in der Klasse Builtin. Später kommen noch andere Kommandos hinzu die dazu verwendet werden auf den Speicher und das Dateisystem zuzugreifen (memtest, dir, ls, cd, mkdir, rmdir, echo, usw.)

Hinweis: Achtet auf eine saubere Verwaltung aller von Euch allozierten Puffer. Achtet außerdem darauf, daß Funktionen und Variablen, die modullokal gültig sind, als static gekennzeichnet werden.

Vorgabe

Zur Lösung der Aufgabe benötigt ihr die erste Vorgabe. Sie enthält neben dem bereit vollständigem Quellcode auch das Makefile und einige Tools, die es euch ermöglichen eueren Kommandointerpreter zu übersetzen und zu testen.