Frage

Ich soll eine einfache Shell in C für mein Projekt programmieren, mit dem Umgebungsvariablen implementiert werden können. Ich habe nachgeschlagen, wie man Getenv, Setenv, Putenv benutzt. So weit so gut, dass ich versucht habe, das Getenv zu verwenden, um die Shell -Variablen zu zeigen ... na ja ... mit einigen Erfolg. Aber ich habe das Gefühl, dass meine Argumentation fehlerhaft ist. Ich habe ein char** argv Dies enthält eine Parseneingabe aus der Benutzereingabe. Ich überprüfe jetzt, ob argv beginnt mit dem Befehl "echo" und wenn eine der folgenden Eingänge mit a beginnt $ Zeichen oder nicht. Hier ist mein Code:

int executeVariables(char** arguments){
    int i = 0;
    if(strcmp(arguments[i], "echo") == 0){
        char *variable;
        for(i = 1; arguments[i] != NULL; i++){
            char *str = arguments[i];
            if( *(str + 0) == '$'){
                variable = getenv(str + 1);
            }else{
                variable = getenv(str);
            }
            if(!variable){
                //puts("not a variable");
                printf("%s ", arguments[i]);
            }else{
                //puts("a variable");
                printf("%s ", variable);
            }
        }
        printf("\n");
        exit(0);
    }

    return 1;

}

Ich denke, dass normale Linux -Shell das findet $ Sign, es erweitert die Variable, bevor er den Echo -Befehl aufgerufen hat. Meine Hülle folgt diesem Prinzip nicht, sondern erweitert Variablen im Echo -Befehl selbst. Irgendeine Idee, wie ich das umsetzen kann? Vielen Dank.

BEARBEITEN:

Ein Problem, das ich habe, ist: echo $HOME und echo HOME Gibt mir das gleiche Ergebnis, was falsch ist.

BEARBEITEN:

Nach verschiedenen Tests funktioniert alles gut. Aber um es wirklich zu testen, muss ich dann eine lokale Variable erstellen echo dieser Wert. Ich habe es versucht, es zu verwenden putenv Funktion, aber die lokale Variable erstellt nicht.

i = 0;
char** temp = malloc(sizeof (*temp));
if(strstr(userInput, "=") != NULL){
    //puts("we got equals");
    puts(userInput);
    if(putenv(userInput) == 0){
       printf("doing putenv(%s)\n", userInput);
        exit(0);
    }
    else{
        puts("couldnt putenv");
       exit(1);
    }
}

Benutzereingabe: char *userInput Wird die Eingabe aus der Befehlszeile verwendet fgets()

War es hilfreich?

Lösung

Sie bitten den Code ausdrücklich, Getenv () für die Zeichenfolge zu machen, auch wenn $ nicht gefunden wird. Deshalb wird es $ zu Hause oder zu Hause suchen. Entfernen Sie einfach den anderen Fall, wenn Sie das Dollar-Sign nicht gefunden haben, und stellen Sie sicher, dass Sie die Variable in der Erklärung in die Null initialisieren und in die Schleife legen.

So etwas so:

// First, perform replacements
int executeVariables(char** arguments){
    int i = 0;

    for(i = 0; arguments[i] != NULL; i++){
        char *str = arguments[i];

        if(*str == '$'){
            // make sure the result isn't NULL, though I'm not sure a real shell does
            char *tmp = getenv(str + 1);
            if (tmp != NULL) {
                arguments[i] = getenv(str + 1); // save off the argument
            }
        }
    }

    // Then actually execute the function. This would be like bash's echo builtin
    if (strcmp(arguments[0], "echo") == 0) {
        int i;
        for (i = 1; arguments[i] != NULL; i++) {
            printf("%s ", arguments[i]);
        }
        printf("\n");
    }

    // Other functions could go here

    return 1;
}

Bearbeiten: Warum prüfen Sie in Bezug auf Ihre Methodik speziell nach Echo? Warum nicht generisch machen und alle Argumente, einschließlich des ersten, überprüfen? Sie möchten wahrscheinlich alle potenziellen Umgebungsvariablen ersetzen. Wenn Sie also irgendwo MyEcho = Echo hätten, würde Folgendes funktionieren. Um es generischer zu machen, hätten Sie diese Funktion, die dann das Zeug basierend auf den erweiterten Variablen ausführen würde. Sie könnten alles schön machen und separate Funktionen haben, aber um hier alles in den Code zu passen, habe ich den obigen Code entsprechend aktualisiert, obwohl ich ihn nicht getestet habe. ;))

Bearbeiten: Davon abgesehen gilt der Kommentar von Werwindle, dies früher zu tun - ersetzen Sie die Argumente, wie hier, und verwenden Sie dann dieses aktualisierte Argumentearray, um eine separate Funktion zu haben, was sie tun muss. :)

> $MYVAR totally awesome $HOME
totally awesome /home/user

Bearbeiten: Was die Situation Putenv () betrifft, möchten Sie etwas strukturiertes wie die folgenden. Auf diese Weise wird es für die Shell und alle anderen Prozesse, die Sie in der Shell durchführen, festgelegt.

void do_args_env(char *args[])
{
    // do putenv, etc.
}

// inside main loop in shell process
while (1) { // just an example
    if (check_args_syntax(args) != 0) {
        // error
    }

    do_args_env(args);

    // fork and do other stuff
}

(Hoffentlich endgültig) Bearbeiten: Als Erklärung beeinflussen Prozesse im Allgemeinen nicht (vielleicht nicht?) Auf die Umgebung von Prozessen über ihnen in ihrer Hierarchie. Nur umgekehrt. Wenn Sie also in einem Kind Pastenv (), werden die Geschwister dieses Kindes (dh andere von seinen Eltern gezogene Prozesse) nicht die Umweltveränderung erhalten.

Ich bin froh, dass ich helfen könnte!

Andere Tipps

Ja, normale Shells erweitern Variablen während der Parsen -Befehlszeile. Sie benötigen also Ersatzvariablen in der Funktion, die ein Array erzeugt, das "analysierte Eingaben aus der Benutzereingabe enthält". In diesem Fallcode für echo (und andere Befehle) wird viel kürzer sein.

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