Вы специально запрашиваете код для выполнения getenv () для строки, даже если $ не найден. Вот почему он будет искать $ HOME или HOME. Просто удалите случай else, чтобы не найти знак доллара, и обязательно инициализируйте переменную NULL при ее объявлении и поместите его в цикл.
Примерно так:
// 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;
}
Редактировать: Что касается вашей методологии, почему вы специально проверяете эхо? Почему бы не сделать его общим и проверить все аргументы, включая первый? На самом деле вы, вероятно, захотите заменить все потенциальные переменные среды, поэтому, если у вас где-нибудь есть MYECHO = echo, будет работать следующее. Чтобы сделать его более общим, у вас будет эта функция, которая затем будет выполнять материал на основе расширенных переменных. Вы могли бы сделать все это красиво и иметь отдельные функции, но чтобы вместить все это здесь, я соответственно обновил приведенный выше код, хотя я не проверял его. ;)
Редактировать: При этом замечание оборотня о том, как сделать это ранее, действительно применимо - замените аргументы, как здесь, и затем используйте этот обновленный массив аргументов, чтобы отдельная функция делала все, что ей нужно , :)
> $MYVAR totally awesome $HOME
totally awesome /home/user
Редактировать: Что касается ситуации с putenv (), вам понадобится нечто структурированное, как показано ниже. Таким образом, он установит его для оболочки и любых других процессов, которые вы запускаете в оболочке.
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
}
(Надеюсь, окончательный вариант) Редактировать: В качестве объяснения процессы обычно не (возможно, не могут?) Влиять на среду процессов над ними в их иерархии; только наоборот. Поэтому, если вы выполняете putenv () в дочернем элементе, родные элементы этого дочернего элемента (то есть другие процессы, разветвленные от его родительского элемента) не получат изменения среды.
Рад, что могу помочь!