Frage

Ich schreibe meine eigene Shell in C.Es muss in der Lage sein, das aktuelle Verzeichnis des Benutzers anzuzeigen und Befehle basierend auf dem vollständigen Pfad auszuführen (muss execv verwenden) und erlauben Sie dem Benutzer, das Verzeichnis mit cd zu ändern.

Das IST eine Hausaufgabe.Der Lehrer gab uns nur eine grundlegende Einführung in C und einen sehr kurzen Grundriss, wie das Programm funktionieren sollte.Da ich nicht der Typ bin, der so schnell aufgibt, habe ich drei Tage lang recherchiert, wie das geht, aber jetzt bin ich ratlos.

Folgendes habe ich bisher:

  • Zeigt den Benutzernamen, den Computernamen und das aktuelle Verzeichnis des Benutzers an (standardmäßig das Home-Verzeichnis).
  • Fordert den Benutzer zur Eingabe auf und ruft die Eingabe ab
  • Teilt die Benutzereingabe durch „ “ in ein Array von Argumenten auf
  • Teilt die Umgebungsvariable PATH nach „:“ in ein Array von Tokens auf

Ich bin mir nicht sicher, wie ich von hier aus fortfahren soll.Ich weiß, dass ich den Befehl execv verwenden muss, aber bei meiner Recherche auf Google habe ich kein Beispiel gefunden, das ich verstehe.Wenn der Befehl beispielsweise bin/ls lautet, woher weiß execv dann, dass alle Dateien/Ordner aus dem Home-Verzeichnis angezeigt werden?Wie teile ich dem System mit, dass ich das Verzeichnis geändert habe?

Ich habe diese Seite oft genutzt, was hilfreich war: http://linuxgazette.net/111/ramankutty.html aber auch hier bin ich ratlos.

Vielen Dank für Ihre Hilfe.Lassen Sie mich wissen, ob ich einen Teil meines vorhandenen Codes veröffentlichen sollte. Ich bin mir allerdings nicht sicher, ob das notwendig ist.

War es hilfreich?

Lösung

Um den cd-Befehl zu implementieren, benötigen Sie lediglich den Systemaufruf chdir.

#include <unistd.h>

int chdir(
    const char *path /* the path name */
);

Sie können also einfach so etwas aufrufen:

int ret1 = chdir("../foo/bar");

Der Rückgabewert von chdir ist 0, wenn ein Wechsel in dieses Verzeichnis möglich war und -1, wenn ein Fehler aufgetreten ist.Für den Fehler sollten Sie die Manpage konsolidieren.

Das aktuelle Verzeichnis kann von jedem Programm überprüft werden, also wenn Sie es ausführen ls ohne Argumente, dann prüft ls, in welchem ​​Verzeichnis es läuft und verwendet dieses Verzeichnis als einziges Argument.Dies ist eine Funktion von ls und nicht von the execv Anruf.

Für den zweiten Teil.

#include <unistd.h>
int execv(
     const char *path, /* programm path*/
     char *const argv[]/* argument vector*/
);

execv führt eine ausführbare Datei zum angegebenen Zeitpunkt aus path und mit den angegebenen Argumenten argv.Wenn Sie also ausführen möchten /bin/ls ../foo /bar, Sie brauchen etwas Ähnliches

char *cmd_str = "/bin/ls";
char *argv[] = {cmd_str, "../foo", "/bar", NULL };
if (execv(cmd_str, argv) == -1 ){
    /* an error occurred */
}

Der von zurückgegebene Fehler execv ist -1.Wenn Sie wissen möchten, warum der Befehl nicht ausgeführt wurde, schauen Sie sich die Manpages an.

Der NULL In char *argv[] = {cmd_str, "../foo", "/bar", NULL }; soll darauf hinweisen, dass es nach dem keine weiteren Argumente gibt NULL.

Der dritte Teil.Unix-basierte Systeme behandeln Befehle mit einem / darin normalerweise als Befehle, die direkt ausgeführt werden können.Das bedeutet, dass Sie zunächst prüfen, ob die angegebene Befehlszeichenfolge einen Schrägstrich enthält.

int ret_value;
if (strchr(cmd_str, '/')
    if (execv(cmd_str, argv) == -1 ){
        /* an error occurred */
    }

Wenn kein Schrägstrich vorhanden ist, müssen Sie alle Verzeichnisse durchgehen PATH und prüfen Sie, ob Sie den Befehl ausführen können.Der gegebene Befehl lautet also ls ../foo /bar und nehmen wir den Wert von an PATH Ist ".:/sbin:/bin:/usr/bin".Wir würden dann versuchen, zuerst auszuführen ./ls ../foo /bar Dann /usr/bin/ls ../foo /bar und zuletzt /bin/ls ../foo /bar.

Hoffe das hilft.

Andere Tipps

Zum Beispiel, wenn der Befehl lautet bin/ls, wie funktioniert execv Kennen Sie die Anzeige aller Dateien/Ordner aus dem Home-Verzeichnis?Wie teile ich dem System mit, dass ich das Verzeichnis geändert habe?

Jeder Prozess verfügt über ein aktuelles Arbeitsverzeichnis, das mit geändert werden kann chdir.Untergeordnete Prozesse erben das Arbeitsverzeichnis von ihren übergeordneten Prozessen.Im Allgemeinen verwaltet Ihre Shell also ihr aktuelles Arbeitsverzeichnis als Reaktion darauf cd Vom Benutzer eingegebene Befehle.Wenn ein Befehl eingegeben wird, der nicht integriert ist, werden Sie Folgendes tun fork um einen untergeordneten Prozess zu erstellen und dann aufzurufen execv dort, um die Binärdatei auszuführen.

Wenn Sie das nehmen möchten PATH Berücksichtigen Sie Programmnamen, die keinen Verzeichnisteil enthalten, dann sollten Sie alle möglichen Kombinationen von a ausprobieren PATH Element und den Programmnamen.Sie können entweder prüfen, ob die genannte Datei existiert, oder einfach versuchen, sie auszuführen und mit der nächsten fortzufahren, wenn dies fehlschlägt.Ich falle execv Anrufe scheiterten, Sie müssen anrufen _exit um den Kindprozess zu beenden.

Beachten Sie, dass die meisten Shells jeden Befehl behandeln, der a enthält / als ein Pfad, an den übergeben wird execv direkt.Wenn der Pfad dies nicht tut Start mit einem /, dann handelt es sich um einen relativen Pfad, und das Betriebssystem löst ihn in Bezug auf das aktuelle Arbeitsverzeichnis auf.Mit anderen Worten, die bin/ls aus Ihrem Beispiel würde sich auf die beziehen ls binär in der bin Verzeichnis, das ein Unterverzeichnis des aktuellen Arbeitsverzeichnisses ist.Nur Befehle, die keine enthalten / überhaupt werden entweder als eingebauter Befehl interpretiert (wie cd) oder der Name einer Binärdatei, die sich auf der befindet PATH.

Das erste Argument dazu execv ist der Pfad, wie Sie ihn berechnet haben.Das erste Element der argv Die Liste entspricht traditionell dem Namen, wie er eingegeben wurde, d. h.ohne Zusatz PATH Verzeichnis.Nach diesem ersten Argument werden alle zusätzlichen Befehlszeilenparameter übergeben, gefolgt von a NULL um die Liste zu beenden.

Ich denke, das Problem besteht darin, dass Sie glauben, dass die Shell für die Arbeit verantwortlich ist ls. ls ist nicht wirklich ein „Teil“ der Shell (zumindest in diesem Fall).die Muschel ausführt ein Programm namens ls.Die meisten Kommentare scheinen zu erklären, wie man findet ls, aber ich glaube nicht, dass Sie darüber verwirrt sind.

Sie sollten sorgfältig überlegen, wozu die Shell dient, bevor Sie sie schreiben.Die Kommentare haben indirekt darauf hingewiesen, dass die Shell „einfach“ Programme wie „aufrufen“ muss ls Und chdir, ihre Aufgaben nicht erfüllen.

ls weiß von selbst, dass es, wenn keine Argumente angegeben werden, die Dateien im aktuellen Arbeitsverzeichnis auflisten soll, wie von zurückgegeben getcwd

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top