Question

Je suis à programmer une simple coquille en C pour mon projet qui peut mettre en œuvre des variables d'environnement. Je levai les yeux sur la façon d'utiliser le getenv, setenv, putenv. Jusqu'à présent, si bien que je l'ai essayé d'utiliser le getenv pour afficher les variables shell ... eh bien ... avec quelques succès. Mais j'ai le sentiment que mon raisonnement est erroné. J'ai un char** argv qui contient une entrée analysée à partir de l'entrée utilisateur. Je vérifie maintenant si commence argv avec la commande « echo » et si l'une des entrées suivantes commence par un signe $ ou non. Voici mon 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;

}

Je pense que shell linux normale trouve le signe $, il étend la variable avant d'appeler la commande d'écho. Mon shell ne suit pas ce principe, il est en expansion des variables dans la commande d'écho lui-même. Toute idée de comment je peux mettre en œuvre ce? Merci.

EDIT:

Un problème que j'ai est:. echo $HOME et echo HOME me donne le même résultat qui est faux

EDIT:

Après différents tests tout fonctionne bien. Mais pour tester vraiment je vais avoir besoin de créer une variable locale puis echo cette valeur. Je l'ai essayé d'utiliser la fonction putenv mais il ne crée pas la variable 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 est l'entrée obtenu à partir de la ligne de commande en utilisant fgets()

Était-ce utile?

La solution

Vous demandez spécifiquement le code pour faire getenv () pour la chaîne, même si on ne trouve pas $. Voilà pourquoi il lookup $ HOME ou HOME. Il suffit de retirer le cas d'autre pour ne pas trouver le signe dollar, et assurez-vous d'initialiser la variable à NULL à sa déclaration, et le mettre dans la boucle.

Quelque chose comme ceci:

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

Modifier Dans la mesure où votre méthodologie va, pourquoi avez-vous spécifiquement pour vérifier l'écho? Pourquoi ne pas rendre générique, et vérifier tous les arguments, y compris le premier? En fait, vous voudrez probablement de remplacer toutes les variables d'environnement potentiels, donc si vous aviez myecho = écho quelque part, ce qui suit fonctionnerait. Pour le rendre plus générique, vous auriez cette fonction, qui serait alors exécuter les choses en fonction des variables étendues. Vous pouvez faire tout bien et ont des fonctions distinctes, mais pour l'adapter tout ici, je l'ai mis à jour le code ci-dessus en conséquence, bien que je ne l'ai pas testé. ;)

Modifier Cela étant dit, le commentaire de Werewindle à faire plus tôt ne s'applique - remplacer les arguments, comme ici, et ensuite utiliser ce tableau d'arguments mis à jour pour avoir une fonction distincte faire ce qu'il doit faire. :)

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

Modifier En ce qui concerne la situation putenv (), vous voulez quelque chose structuré comme suit. De cette façon, il sera mis pour la coquille, ainsi que tout autre processus que vous exécutez dans le 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
}

(un peu de chance finale) Edit: Comme explication, les processus ne généralement pas (? Peut-être pas) affectent l'environnement des processus ci-dessus dans leur hiérarchie; que l'inverse. Donc, si vous putenv () chez un enfant, frères et sœurs de cet enfant (à savoir d'autres processus fourchue de son parent) ne sera pas obtenir le changement d'environnement.

Je suis content pourrait être utile!

Autres conseils

Oui, les coquilles epxand des variables lors de l'analyse en ligne de commande. Vous avez donc besoin de substituer les variables en fonction, qui produit tableau qui « contient l'entrée de l'entrée analysable utilisateur ». Dans ce code de cas pour echo (et d'autres commandes) sera beaucoup plus courte.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top