• В SUSv3 разрешается реализация функции getenv() для возвращения ее результата с использованием статически выделенного буфера, который может быть перезаписан последующими вызовами getenv(), setenv(), putenv() или unsetenv(). Хотя в glibc-реализации getenv() статический буфер таким образом не применяется, портируемая программа, которой нужно сохранить строку, возвращенную вызовом getenv(), прежде чем вызвать одну из этих функций, должна скопировать эту строку в другое место.
Иногда процессу есть смысл изменить свою среду. Одна из причин такого изменения состоит в том, что факт изменения среды будет виден дочерним процессам, создаваемым им впоследствии.
Возможно также, что нужно определить переменную, которая станет видна новой, исполняемой с помощью функции exec() программе, которая будет загружена в память этого процесса. В этом смысле среда является формой не только межпроцессного, но и межпрограммного взаимодействия. (Более подробно этот метод будет рассмотрен в главе 27, где объясняется порядок разрешения программе с помощью функций exec() заменять саму себя новой программой в том же процессе.)
Функция putenv() добавляет новую переменную к среде вызывающего ее процесса или изменяет значение существующей переменной.
#include
int putenv(char *
Возвращает 0 при успешном завершении или ненулевое значение при ошибке
Аргумент string является указателем на строку вида ИМЯ=значение. После вызова putenv() эта строка становится частью среды. Иначе говоря, строка, на которую указывает string, не будет скопирована в среду, а, наоборот, один из элементов среды будет указывать на то же самое место, что и string. Следовательно, если в дальнейшем изменить байты, на которые указывает string, такое изменение повлияет на среду процесса. Поэтому string не должна быть автоматически создаваемой переменной (то есть символьным массивом, размещаемым в стеке), поскольку эта область памяти может быть перезаписана после возвращения из функции, в которой определена переменная.
Обратите внимание на то, что putenv() возвращает при ошибке не –1, а ненулевое значение.
В glibc-реализации функции putenv() предоставляется нестандартное расширение. Если в строке, на которую указывает аргумент string, нет знака равенства (=), то переменная среды, идентифицируемая аргументом string, удаляется из списка переменных среды.
Функция setenv() является альтернативой putenv(), предназначенной для добавления переменной к среде.
#include
int setenv(const char *
Возвращает 0 при успешном завершении или –1 при ошибке
Функция setenv() создает новую переменную среды путем выделения буфера памяти для строки вида ИМЯ=значение и копирует в этот буфер строки, указываемые аргументами name и value. Заметьте, что мы ни в коем случае не должны ставить знак равенства после name или в начале value, поскольку setenv() дописывает этот символ при добавлении нового определения к среде.
Функция setenv() не изменяет среду, если переменная, идентифицируемая аргументом name, уже существует, а аргумент overwrite имеет значение 0. Если у overwrite ненулевое значение, среда всегда изменяется.
Тот факт, что setenv() копирует свои аргументы, означает, что в отличие от putenv() мы можем впоследствии изменить содержимое строк, на которые указывают аргументы name и value, не оказывая влияния на среду. Это также означает, что использование автоматически создаваемых переменных в качестве аргументов setenv() не создает никаких проблем.
Функция unsetenv() удаляет из среды переменную, идентифицируемую аргументом name.
#include
int unsetenv(const char *
Возвращает 0 при успешном завершении или –1 при ошибке
Как и для setenv(), аргумент name не должен включать в себя знак равенства.
И setenv() и unsetenv() берут начало из BSD и не так популярны, как putenv(). Хотя в исходном стандарте POSIX.1 или в SUSv2 они не упоминались, их включили в SUSv3.
В версиях glibc, предшествующих 2.2.2, функция unsetenv() имела прототип, возвращающий void. Именно такой прототип unsetenv() был в исходной реализации BSD, и некоторые реализации UNIX до сих пор следуют этому BSD-прототипу.
Временами требуется удалить целиком всю среду, а затем выстроить ее заново с заданными значениями. Это, к примеру, может понадобиться для безопасного выполнения программ с установлением идентификатором пользователя (set-user-ID) (см. раздел 38.8). Среду можно удалить, присвоив переменной environ значение NULL:
environ = NULL;
Именно такое действие и предпринимается в библиотечной функции clearenv().
#define _BSD_SOURCE /* Или: #define _SVID_SOURCE */
#include
int clearenv(void)
Возвращает 0 при успешном завершении или ненулевое значение при ошибке