Imposta le variabili d’ambiente in C

C’è un modo per impostare le variabili d’ambiente in Linux usando C?

Ho provato setenv() e putenv() , ma non sembrano funzionare per me.

Qui farò un’ipotesi, ma la normale ragione per cui queste funzioni sembrano non funzionare non è perché non funzionano, ma perché l’utente non capisce veramente come funzionano le variabili d’ambiente. Ad esempio, se ho questo programma:

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

E poi lo eseguo dalla shell, non modificherà l’ambiente della shell – non c’è modo per un processo figlio di farlo. Ecco perché i comandi della shell che modificano l’ambiente sono incorporati e perché è necessario creare uno script che contenga impostazioni variabili che si desidera aggiungere alla shell, piuttosto che semplicemente eseguirlo.

Qualsiasi programma unix viene eseguito in un processo separato dal processo che lo avvia; questo è un processo “figlio”.

Quando viene avviato un programma, che sia sulla riga di comando o in qualsiasi altro modo, il sistema crea un nuovo processo che è (più o meno) una copia del processo genitore. Quella copia include le variabili di ambiente nel processo genitore, e questo è il meccanismo mediante il quale il processo figlio “eredita” le variabili d’ambiente del suo genitore. (questo è in gran parte ciò che altre risposte hanno detto)

Cioè, un processo imposta sempre e solo le proprie variabili d’ambiente.

Altri hanno menzionato l’uso di uno script di shell come metodo per impostare le variabili di ambiente nel processo corrente, ma se è necessario impostare variabili nel processo corrente (shell) a livello di codice, allora c’è un modo leggermente indiretto che è ansible.

Considera questo:

 % cat envs.c #include  int main(int argc, char**argv) { int i; for (i=1; i 

L' eval incorporato valuta il suo argomento come se quell'argomento fosse stato digitato al prompt della shell. Questo è un esempio di sh-style; la variante in stile csh è lasciata come esercizio!

La variabile di ambiente impostata da setenv () / putenv () verrà impostata per il processo che esegue queste funzioni e sarà ereditata dai processi avviati da essa. Tuttavia, non verrà trasmesso nella shell che ha eseguito il tuo programma.

Perché il mio wrapper attorno a setenv () non funziona?

Il blocco dell’ambiente è process-local e copiato nei processi figli. Quindi, se si modificano le variabili, il nuovo valore influisce solo sul processo e sui processi figli generati dopo la modifica. Sicuramente non cambierà la shell da cui sei partito.

L’ho preso dal mio libro ” Programmazione avanzata nel UNIX Environment “ .

L’ambiente elenca l’array di puntatori alle stringhe name = value effettive e le stringhe dell’ambiente vengono in genere memorizzate nella parte superiore dello spazio di memoria di un processo, sopra lo stack.

Cancellare una stringa è semplice; troviamo semplicemente il puntatore nell’elenco degli ambienti e spostiamo tutti i puntatori successivi in ​​basso di uno. Ma aggiungere una stringa o modificare una stringa esistente è più difficile. Lo spazio nella parte superiore della pila non può essere espanso, perché è spesso nella parte superiore dello spazio degli indirizzi del processo e quindi non può espandersi verso l’alto; non può essere espanso verso il basso, perché non è ansible spostare tutti i frame dello stack sottostanti.

  1. Se stiamo modificando un nome esistente:

    un. Se la dimensione del nuovo valore è inferiore o uguale alla dimensione del valore esistente, possiamo semplicemente copiare la nuova stringa sulla vecchia stringa.

    b. Se la dimensione del nuovo valore è maggiore di quella precedente, tuttavia, è necessario malloc per ottenere spazio per la nuova stringa, copiare la nuova stringa in quest’area e quindi sostituire il puntatore precedente nell’elenco di ambienti per nome con il puntatore a questa area assegnata.

  2. Se stiamo aggiungendo un nuovo nome, è più complicato. Per prima cosa, dobbiamo chiamare malloc per allocare spazio per la stringa name = value e copiare la stringa in quest’area.

    un. Quindi, se è la prima volta che aggiungiamo un nuovo nome, dobbiamo chiamare malloc per ottenere spazio per una nuova lista di indicatori. Copiamo la vecchia lista di ambienti in questa nuova area e memorizziamo un puntatore alla stringa name = value alla fine di questo elenco di puntatori. Memorizziamo anche un puntatore nullo alla fine di questo elenco, ovviamente. Infine, impostiamo environ per puntare a questa nuova lista di puntatori. se l’elenco di ambiente originale era contenuto sopra la cima dello stack, come è comune, abbiamo spostato questo elenco di puntatori all’heap. Ma la maggior parte dei puntatori in questa lista puntano ancora su stringhe name = value sopra la cima della pila.

    b. Se non è la prima volta che aggiungiamo nuove stringhe all’elenco degli ambienti, sappiamo che abbiamo già allocato spazio per la lista sull’heap, quindi chiamiamo solo realloc per allocare spazio per un altro puntatore. Il puntatore alla nuova stringa name = value viene archiviato alla fine dell’elenco (sopra il precedente puntatore nullo), seguito da un puntatore nullo.

Ti auguro il meglio.