Вопрос

Я должен запрограммировать простую оболочку в C для моего проекта, который может реализовать переменные среды. Я посмотрел на то, как использовать Getenv, Setenv, Putenv. Пока все хорошо, я пытался использовать getenv, чтобы показать переменные раковины ... ну ... с некоторыми успехами. Но у меня есть ощущение, что мои рассуждения ошибочны. у меня есть char** argv который содержит анализируемый ввод от пользовательского ввода. Теперь я проверяю, если argv начинается с команды "Echo", а затем, если какой -либо из следующих входов начинается с $ знак или нет. Вот мой код:

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;

}

Я думаю, что нормальная оболочка Linux находит $ Подпишите, он расширяет переменную перед вызовом команды Echo. Моя оболочка не соблюдает этот принцип, он расширяет переменные внутри самой команды Echo. Есть идеи относительно того, как я могу это реализовать? Спасибо.

РЕДАКТИРОВАТЬ:

Проблема у меня есть: echo $HOME а также echo HOME дает мне тот же результат, который неверный.

РЕДАКТИРОВАТЬ:

После различных тестов все работает хорошо. Но чтобы действительно проверить это, мне нужно создать локальную переменную, тогда echo это значение. Я попробовал это с помощью putenv Функция, но это не создает локальную переменную.

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 Получен ли вход из командной строки с использованием fgets()

Это было полезно?

Решение

Вы специально просите код сделать getenv () для строки, даже если $ не найден. Вот почему он будет поиск дома или дома. Просто удалите случай 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;
}

Редактировать: Что касается вашей методологии, почему вы специально проверяете на Echo? Почему бы не сделать его общим, и проверить все аргументы, включая первые? На самом деле вы, вероятно, хотите заменить все потенциальные переменные среды, поэтому, если у вас где -то было где -то 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 () у ребенка, братья и сестры этого ребенка (т. Е. Другие процессы, выпущенные от его родителя), не смогут изменить окружающую среду.

Рад, что мог бы помочь!

Другие советы

Да, нормальные раковины расширяют переменные во время командной строки анализа. Таким образом, вам нужны заменяющие переменные в функции, которые создают массив, который «содержит анализируемый ввод от пользовательского ввода». В этом случае код для echo (и другие команды) будут намного короче.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top