Pregunta

Debo programar un shell simple en C para mi proyecto que puede implementar variables de entorno. Examiné cómo usar el getenv, setenv, putenv. Hasta ahora todo bien, he intentado usar el getenv para mostrar las variables de shell ... bueno ... con algunos exitosos. Pero tengo la sensación de que mi razonamiento es defectuoso. tengo un char** argv que contiene entrada analizada de la entrada del usuario. Ahora lo comprobo si argv comienza con el comando "eco" y luego si alguna de las siguientes entradas comienza con un $ firmar o no. Aquí está mi código:

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;

}

Creo que el shell de Linux normal encuentra el $ Firme, expande la variable antes de invocar el comando ECHO. Mi caparazón no sigue este principio, se está expandiendo variables dentro del comando Echo en sí. ¿Alguna idea de cómo puedo implementar esto? Gracias.

EDITAR:

Un problema que tengo es: echo $HOME y echo HOME me da el mismo resultado que está mal.

EDITAR:

Después de varias pruebas, todo funciona bien. Pero para probarlo realmente necesitaré crear una variable local entonces echo este valor. Lo probé usando putenv función pero no crea la variable local.

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

entrada del usuario: char *userInput ¿Se obtiene la entrada de la línea de comando usando fgets()

¿Fue útil?

Solución

Está pidiendo específicamente al código que haga getenv () para la cadena, incluso si $ no se encuentra. Por eso buscará $ en casa o hogar. Simplemente elimine el caso más para no encontrar el signo de dólar, y asegúrese de inicializar la variable a NULL en su declaración, y colóquelo dentro del bucle.

Algo así:

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

Editar: En cuanto a su metodología, ¿por qué verifica específicamente el ECHO? ¿Por qué no hacerlo genérico y verificar todos los argumentos, incluidos los primeros? En realidad, probablemente desee sustituir todas las variables de entorno potenciales, por lo que si tuviera myeCo = Echo en algún lugar, lo siguiente funcionaría. Para que sea más genérico, tendría esta función, que luego ejecutaría las cosas basadas en las variables expandidas. Podría hacerlo todo bien y tener funciones separadas, pero para adaptarse a todo aquí, he actualizado el código anterior en consecuencia, aunque no lo he probado. ;)

Editar: Dicho esto, el comentario de Werewindle sobre hacer esto se aplica anteriormente: reemplaza los argumentos, como aquí, y luego usa esa matriz de argumentos actualizados para que una función separada haga lo que sea necesario. :)

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

Editar: En cuanto a la situación de Putenv (), querrá algo estructurado como lo siguiente. De esta manera, lo establecerá para el shell y cualquier otro proceso que ejecute en el 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
}

(Con suerte final) Editar: Como explicación, los procesos generalmente no (¿quizás no?) Afectan el entorno de los procesos por encima de ellos en su jerarquía; Solo al revés. Entonces, si Putenv () en un niño, los hermanos de ese niño (es decir, otros procesos bifurcados de su padre) no obtendrán el cambio del entorno.

¡Me alegro de poder ser de ayuda!

Otros consejos

Sí, las conchas normales expanden las variables durante la línea de comando de análisis. Por lo tanto, necesita variables sustitutivas en la función, que produce una matriz que "contiene entrada analizada de la entrada del usuario". En este código de caso para echo (y otros comandos) será mucho más corto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top