2010-08-05 16 views
28

¿Hay alguna forma de establecer variables de entorno en Linux utilizando C?Establecer variables de entorno en C

Probé setenv() y putenv(), pero no parecen funcionar para mí.

+0

¿Por qué crees que no funcionaron? (Es decir, ¿cómo lo ha probado? Getenv?) –

+0

¿Podría publicar un ejemplo de código y una demostración que muestre cómo no funcionan? – FrustratedWithFormsDesigner

Respuesta

44

Voy a adivinar aquí, pero la razón normal por la que estas funciones parecen no funcionar no es porque no funcionen, sino porque el usuario realmente no entiende cómo funcionan las variables de entorno. Por ejemplo, si tengo este programa:

int main(int argc, char **argv) 
{ 
    putenv("SomeVariable=SomeValue"); 
    return 0; 
} 

Y luego lo ejecuto desde el shell, no va a modificar el entorno de la cáscara - no hay manera para que un proceso hijo para hacer eso. Es por eso que los comandos del shell que modifican el entorno son comandos integrados, y por qué necesita source una secuencia de comandos que contiene las configuraciones variables que desea agregar a su caparazón, en lugar de simplemente ejecutarlo.

+0

El corolario de esto es obtener el comportamiento "ejecutar programa para establecer variables" en el shell: 1) escribe un script de shell para hacer el trabajo y 2) no lo ejecuta de la manera habitual, sino que lo 'fuente'. (Por cierto en la mayoría de las conchas '. Script' es lo mismo que' source script' y mucho menos tipeo.) – dmckee

+0

Eso tiene mucho sentido, gracias :) Sí, eso era lo que estaba haciendo. Soy nuevo en Linux, así que discúlpeme si esta es una pregunta estúpida, pero no hay forma de que un proceso secundario establezca el entorno de shells en C, y al no obtener un script. Realizo una pasantía en esta empresa y me pidieron que escribiera una función para configurar la zona horaria de un dispositivo que ejecuta Linux, así que estaba tratando de configurar el entorno TZ del shell. – iman453

+0

@iman: prueba 'man -k tz' para ver algunas opciones. En mi máquina Mac OS X, lo que aparece es 'tzset (3)' ... – dmckee

5

La variable de entorno establecida por setenv()/putenv() se establecerá para el proceso que ejecutó estas funciones y será heredada por los procesos iniciados por ella. Sin embargo, no será emitido en el shell que ejecutó su programa.

Why isn't my wrapper around setenv() working?

1

El bloque de entorno es un proceso local, y se copia en procesos secundarios. Por lo tanto, si cambia las variables, el nuevo valor solo afecta su proceso y los procesos secundarios se generan después del cambio. Seguramente no cambiará el proyectil desde el que se lanzó.

-2

Lo recibí de mi "Advanced Programming in the UNIX Environment" libro.

El entorno enumera la matriz de punteros a las cadenas de nombre = valor real, y las cadenas de entorno normalmente se almacenan en la parte superior del espacio de memoria de un proceso, encima de la pila.

Eliminar una cadena es simple; simplemente buscamos el puntero en la lista de entornos y movemos todos los punteros subsecuentes hacia abajo uno. Pero agregar una cadena o modificar una cadena existente es más difícil. El espacio en la parte superior de la pila no se puede expandir, porque a menudo está en la parte superior del espacio de direcciones del proceso y, por lo tanto, no puede expandirse hacia arriba; no se puede expandir hacia abajo, porque no se pueden mover todos los marcos de pila debajo.

  1. Si estamos modificando un nombre existente:

    a. Si el tamaño del nuevo valor es menor o igual que el tamaño del valor existente, podemos simplemente copiar la nueva cadena sobre la cadena anterior.

    b. Si el tamaño del nuevo valor es mayor que el anterior, sin embargo, debemos malloc para obtener espacio para la nueva cadena, copiar la nueva cadena en esta área y luego reemplazar el puntero antiguo en la lista de entorno por el nombre con el puntero a esta área asignada.

  2. Si agregamos un nombre nuevo, es más complicado. En primer lugar, debemos llamar a malloc para asignar espacio para la cadena name = value y copiar la cadena a esta área.

    a. Entonces, si es la primera vez que agregamos un nombre nuevo, debemos llamar a malloc para obtener espacio para una nueva lista de punteros.Copiamos la lista de entorno anterior a esta nueva área y almacenamos un puntero a la cadena name = value al final de esta lista de punteros. También almacenamos un puntero nulo al final de esta lista, por supuesto. Finalmente, establecemos el entorno para apuntar a esta nueva lista de punteros. si la lista del entorno original estaba contenida encima de la parte superior de la pila, como es común, entonces hemos movido esta lista de punteros al montón. Pero la mayoría de los punteros en esta lista aún apuntan a nombre = cadenas de valor por encima de la parte superior de la pila.

    b. Si esta no es la primera vez que agregamos cadenas nuevas a la lista de entornos, entonces sabemos que ya hemos asignado espacio para la lista en el montón, así que simplemente llamamos a realloc para asignar espacio para un puntero más. El puntero a la nueva cadena name = value se almacena al final de la lista (en la parte superior del puntero nulo anterior), seguido de un puntero nulo.

Todo lo mejor.

+0

No estoy seguro de haber entendido la pregunta del OP ... – dmckee

+0

Tiene razón :-). Según tengo entendido, se enfrenta a algunos en su ejecutable después de establecer variables env. – Hemant

9

Cualquier programa Unix se ejecuta en un proceso separado del proceso que lo inicia; este es un proceso 'infantil'.

Cuando se inicia un programa, ya sea en la línea de comandos o de cualquier otra forma, el sistema crea un nuevo proceso que es (más o menos) una copia del proceso principal. Esa copia incluye las variables de entorno en el proceso padre, y este es el mecanismo por el cual el proceso hijo 'hereda' las variables de entorno de su elemento primario. (Esto es en gran medida lo que otros han dicho respuestas aquí)

es decir, un proceso sólo vez establece sus propias variables de entorno.

Otros han mencionado el origen de un script de shell, como una forma de establecer variables de entorno en el proceso actual, pero si necesita establecer variables en el proceso actual (shell) mediante programación, entonces hay una manera indirecta de que sea posible .

Considera:

% cat envs.c 
#include <stdio.h> 
int main(int argc, char**argv) 
{ 
    int i; 
    for (i=1; i<argc; i++) { 
     printf("ENV%d=%s\n", i, argv[i]); 
    } 
} 
% echo $ENV1 

% ./envs one two 
ENV1=one 
ENV2=two 
% eval `./envs one two` 
% echo $ENV1 
one 
% 

El built-in eval evalúa su argumento como si ese argumento se tipificaron en el intérprete de comandos. Este es un ejemplo de estilo sh; la variante de estilo csh se deja como un ejercicio!

+0

Noté que esto fue votado negativamente. Alguna indicación de por qué? ¿Alguien detectó un error? –

+0

No estoy seguro de por qué alguien podría menospreciar esto. Extraño. ¡Parece una buena solución para mí! – wasatchwizard

+0

Supongo que es porque la respuesta establece la variable de entorno utilizando el comando bash incorporado 'eval', que son las posibilidades de que el programador no pueda usar bash en absoluto. Si el programador puede usar un script de shell (que no siempre es el caso, de ahí la pregunta), hay otras maneras más obvias y mejores de establecer la variable de entorno distinta de la evaluación específica de bash. (p.s. No volví a bajar) –

Cuestiones relacionadas