Подтвердить что ты не робот

Установите переменные среды в C

Есть ли способ установить переменные среды в Linux с помощью C?

Я попробовал setenv() и putenv(), но они, похоже, не работают для меня.

4b9b3361

Ответ 1

Я собираюсь сделать здесь дикое предположение, но нормальная причина, по которой эти функции не работают, заключается не в том, что они не работают, а потому, что пользователь действительно не понимает, как работают переменные среды. Например, если у меня есть эта программа:

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

И затем я запускаю его из оболочки, он не будет изменять среду оболочки - нет способа для этого дочернего процесса. Поэтому команды оболочки, которые изменяют среду, являются встроенными, и почему вам нужно source a script, который содержит параметры переменных, которые вы хотите добавить в свою оболочку, а не просто запускать их.

Ответ 2

Любая программа unix запускается в отдельном процессе из процесса, который запускает его; это "детский" процесс.

Когда запускается программа - будь то в командной строке или любым другим способом - система создает новый процесс, который является (более или менее) копией родительского процесса. Эта копия включает переменные среды в родительском процессе, и это механизм, посредством которого дочерний процесс "наследует" переменные среды родителя. (в основном это говорит о других ответах)

То есть, процесс только когда-либо устанавливает свои собственные переменные среды.

Другие указали на поиск оболочки script, как способ установки переменных среды в текущем процессе, но если вам нужно программно установить переменные в текущем (оболочном) процессе, то есть несколько косвенный способ, чтобы это возможно.

Рассмотрим это:

% 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
% 

Встроенный eval оценивает свой аргумент так, как будто этот аргумент был введен в командной строке. Это пример sh-стиля; вариант csh-стиля остается в виде упражнения!

Ответ 3

Переменная окружения, заданная setenv()/putenv(), будет установлена ​​для процесса, выполняющего эти функции, и будет наследоваться процессами, запущенными им. Однако он не будет транслироваться в оболочку, которая выполнила вашу программу.

Почему моя обертка вокруг setenv() не работает?

Ответ 4

Блок среды является локальным процессом и копируется в дочерние процессы. Поэтому, если вы меняете переменные, новое значение влияет только на процесс и дочерние процессы, возникшие после изменения. Разумеется, он не изменит оболочку, которую вы запускали.

Ответ 5

Я получил его из моей Advanced Programming in UNIX Environment".

Среда отображает массив указателей на фактические строки с именем = значение, а строки среды обычно хранятся в верхней части пространства памяти процесса над стеком.

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

  • Если мы изменяем существующее имя:

    a. Если размер нового значения меньше или равен размеру существующего значения, мы можем просто скопировать новую строку поверх старой строки.

    b. Если размер нового значения больше старого, мы должны malloc получить место для новой строки, скопировать новую строку в эту область, а затем заменить старый указатель в списке окружения для имени с указателем на эту выделенную область.

  • Если мы добавляем новое имя, это сложнее. Во-первых, мы должны вызвать malloc, чтобы выделить место для строки name = value и скопировать строку в эту область.

    a. Затем, если в первый раз мы добавили новое имя, нам нужно вызвать malloc, чтобы получить место для нового списка указателей. Мы копируем старый список среды в эту новую область и сохраняем указатель на строку name = value в конце этого списка указателей. Разумеется, мы также сохраняем нулевой указатель в конце этого списка. Наконец, мы устанавливаем окружение, чтобы указать на этот новый список указателей. если исходный список окружения содержался выше вершины стека, как это обычно бывает, мы переместили этот список указателей в кучу. Но большинство указателей в этом списке по-прежнему указывают на строки с именем = value над верхней частью стека.

    b. Если мы не добавили новые строки в список окружения, мы знаем, что мы уже выделили место для списка в куче, поэтому мы просто вызовите realloc, чтобы выделить место для еще одного указателя. Указатель на новую строку name = value хранится в конце списка (поверх предыдущего нулевого указателя), за которым следует нулевой указатель.

Все самое лучшее.