Сетенв, Унсетенв, Путенв - PullRequest
       29

Сетенв, Унсетенв, Путенв

5 голосов
/ 06 октября 2011

Я работаю над пользовательской оболочкой для класса системного программирования.Нам было поручено реализовать встроенные команды setenv() и unsetenv() с подсказкой проверить справочные страницы для putenv().

Моя проблема в том, что setenv(char*, char*, int) и putenv(char*) похоже не работает вообще.Мой код для выполнения введенной команды выглядит следующим образом:

//... skipping past stuff for IO redirection
pid = fork();
if(pid == 0){
    //child
    if(!strcmp(_simpleCommands[0]->_arguments[0],"printenv")){
        //check if command is "printenv"
        extern char **environ;
        int i;
        for(i = 0; environ[i] != NULL; i++){
            printf("%s\n",environ[i]);
        }
        exit(0);
    }
    if(!strcmp(_simpleCommands[0]->_arguments[0],"setenv")){
        //if command is "setenv" get parameters char* A, char* B
        char * p = _simpleCommands[0]->_arguments[1];
        char * s = _simpleCommands[0]->_arguments[2];

        //putenv(char* s) needs to be formatted A=B; A is variable B is value
        char param[strlen(p) + strlen(s) + 1];
        strcat(param,p);
        strcat(param,"=");
        strcat(param,s);
        putenv(param);
        //setenv(p,s,1);
        exit(0);
    }
    if(!strcmp(_simpleCommands[0]->_arguments[0],"unsetenv")){
        //remove environment variable
        unsetenv(_simpleCommands[0]->_arguments[0]);
        exit(0);
    }
    //execute command
    execvp(_simpleCommands[0]->_arguments[0],_simpleCommands->_arguments);
    perror("-myshell");
    _exit(1);
}

//omitting restore IO defaults...

Если я запускаю printenv, он работает правильно, но если я пытаюсь установить новую переменную, используя putenv() или setenv() my *Команда 1016 * возвращает точно такую ​​же вещь, поэтому она, похоже, не работает.

В качестве примечания, проблема может заключаться не в функциях или в том, как я их вызвал, потому что моя оболочка выполняет командыкак будто он должен был отформатировать подстановочный знак (* или ?), что, я не уверен, должно произойти.

Ответы [ 2 ]

6 голосов
/ 06 октября 2011

Вы, кажется, безоговорочно вызываете fork перед проверкой командной строки. Но некоторые встроенные команды оболочки должны выполняться в процессе parent , чтобы их влияние сохранялось. Все встроенные модули, которые управляют средой, попадают в эту категорию.

Кроме того, я бы не стал использовать функции манипулирования средой библиотеки C, если бы писал оболочку. Я бы использовал три аргумента main, скопировал envp в структуру данных под моим полным контролем и затем вернул бы это обратно в execve. Это отчасти потому, что я фанат контроля, а отчасти потому, что почти невозможно что-либо усложнить с setenv и / или putenv и не иметь утечки памяти. См. этот старый вопрос SO для подробностей.

0 голосов
/ 06 октября 2011

Что заставляет вас думать, что это не работает?Я написал простой тестовый пример ниже ... и он сработал, как и ожидалось.

Убедитесь, что setevn и prientevn вызываются в одинаковом процессе.

#include <stdlib.h>
#include <assert.h>
int main()
{


 char * s= "stack=overflow";

 int ret =  putenv(s);

 assert(ret == 0);

 //printout all the env
 extern char **environ;
        int i;
        for(i = 0; environ[i] != NULL; i++){
            printf("%s\n",environ[i]);
        }


 return 0; 

}
pierr@ubuntu:~/workspace/so/c/env$ ./test | grep stack
stack=overflow
...