Domanda

Sono programmare una semplice shell in C per il mio progetto in grado di implementare le variabili d'ambiente. Alzai gli occhi su come utilizzare il getenv, setenv, putenv. Fin qui tutto bene ho provato ad utilizzare il getenv per mostrare le variabili di shell ... beh ... con qualche successo. Ma ho la sensazione che il mio ragionamento è viziata. Ho una char** argv contenente ingresso parsed dall'input dell'utente. Ora controllare se argv avvia con il comando "echo" e quindi se uno qualsiasi dei seguenti ingressi inizia con un segno $ oppure no. Ecco il mio codice:

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;

}

Credo che normale shell Linux rileva il segno $, si espande la variabile prima di richiamare il comando echo. Mio guscio non seguire questo principio, si sta espandendo variabili all'interno del comando echo stessa. Qualsiasi idea di come posso realizzare questo? Grazie.

EDIT:

Un problema che ho è:. echo $HOME e echo HOME mi dà lo stesso risultato che è sbagliato

EDIT:

Dopo vari test tutto funziona bene. Ma per davvero testarlo avrò bisogno di creare una variabile locale, allora echo questo valore. Ho provato utilizzando la funzione putenv ma non crea la variabile locale.

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);
    }
}

UserInput: char *userInput è l'ingresso ottenuto dalla riga comandi utilizzando fgets()

È stato utile?

Soluzione

Stai chiedendo esplicitamente il codice per fare getenv () per la stringa, anche se non viene trovato $. Ecco perché sarà lookup $ casa o casa. Basta togliere il caso altro per non trovare il dollaro-segno, e assicurarsi di inizializzare variabili NULL alla sua dichiarazione, e metterlo all'interno del ciclo.

Qualcosa in questo modo:

// 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;
}

Modifica Per quanto riguarda la vostra metodologia va, perché si fa a controllare specificamente per l'eco? Perché non renderla generica e controllare tutti gli argomenti, tra cui il primo? In realtà probabilmente vuole sostituire tutti i potenziali variabili d'ambiente, quindi se avete avuto MYECHO = eco da qualche parte, il seguente avrebbe funzionato. Per renderlo più generico, si avrebbe questa funzione, che sarebbe quindi eseguire la roba in base alle variabili espansi. Si potrebbe rendere il tutto piacevole e hanno funzioni distinte, ma per entrare tutto in qui, ho aggiornato il codice di cui sopra di conseguenza, anche se non ho provato. ;)

Modifica Detto questo, il commento di werewindle a fare questo in precedenza non applicare - sostituire le argomentazioni, come qui, e quindi utilizzare tale aggiornato serie argomenti di avere una funzione separata fare tutto ciò che ha bisogno di fare. :)

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

Modifica Per quanto riguarda la situazione putenv (), si vorrà qualcosa di strutturato come segue. In questo modo, lo imposterà per il guscio, e tutti gli altri processi si esegue nella shell.

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
}

(si spera definitivo) Edit: Come una spiegazione, processi generalmente non (? Forse non può) influenzare l'ambiente dei processi sopra di loro nella loro gerarchia; solo il contrario. Quindi, se si putenv () in un bambino, fratelli che del bambino (cioè altri processi biforcuta dal suo genitore) non sarà possibile ottenere il cambiamento di ambiente.

I Glad potrebbe essere di aiuto!

Altri suggerimenti

Sì, conchiglie normali espandere le variabili durante l'analisi della riga di comando. Quindi è necessario sostituire le variabili in funzione, che produce matrice che "contiene ingresso analizzata dal input dell'utente". In questo codice caso echo (e altri comandi) sarà molto più breve.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top