Les variables d'environnement en shell linux simple,
-
26-10-2019 - |
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()
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.