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

ЗАМЕЧАНИЕ. GNU putenv() имеет дополнительную (документированную) особенность в своем поведении. Если строка аргумента является именем без следующего за ним символа =, именованная переменная удаляется. Программа GNU env, которую мы рассмотрим далее в мой главе, полагается на такое поведение.

Функция unsetenv() удаляет переменную из окружения:

unsetenv("PATH");

Наконец, функция clearenv() полностью очищает окружение:

if (clearenv() != 0) {

 /* обработать ошибку */

}

Эта функция не стандартизирована POSIX, хотя она доступна в GNU/Linux и нескольких коммерческих вариантах Unix. Ее следует использовать, если приложение должно быть очень безопасным и нужно построить собственное окружение с нуля. Если clearenv() недоступна, в справке GNU/Linux для clearenv(3) рекомендуется использовать для выполнения этой задачи 'environ = NULL'.

<p>2.4.2. Окружение в целом: <code>environ</code></p>

Правильным способом работы с окружением является использование функций, описанных в предыдущем разделе. Однако, стоит взглянуть на то, как это работает «под капотом».

Внешняя переменная environ предоставляет доступ таким же способом, как argv предоставляет доступ к аргументам командной строки. Вы сами должны объявить переменную. Хотя она и стандартизирована POSIX, environ намеренно не объявлена ни в одном стандартном заголовочном файле (Это, кажется, прослеживается из исторической практики.) Вот объявление:

extern char **environ; /* Смотрите, нет заголовочного файла POSIX */

Как и в argv, завершающим элементом environ является NULL. Однако, здесь нет переменной «числа строк окружения», которая соответствовала бы argc. Следующая простая программа распечатывает все окружение:

/* ch02-printenv.c --- Распечатать окружение. */

#include

extern char **environ;

int main(int argc, char **argv) {

 int i;

 if (environ != NULL)

  for (i = 0; environ[i] != NULL; i++)

   printf("%s\n", environ[i]);

 return 0;

}

Хотя это и маловероятно, перед попыткой использовать environ эта программа проверяет, что она не равна NULL.

Переменные хранятся в окружении в случайном порядке. Хотя некоторые оболочки Unix хранят переменные окружения в отсортированном по именам переменных виде, это формально не требуется, и многие оболочки не сортируют их.

В качестве уловки реализации можно получить доступ к окружению, объявив третий параметр main():

int main(int argc, char **argv, char **envp) {

 ...

}

Затем можно использовать envp также, как environ. Хотя это иногда можно увидеть в старом коде, мы не рекомендуем такое использование; environ является официальным, стандартным, переносимым способом получения доступа ко всему окружению, если это вам необходимо.

<p>2.4.3. GNU <code>env</code></p>

Чтобы завершить главу, рассмотрим GNU версию команды env. Эта команда добавляет переменные к окружению в ходе выполнения одной команды. Она может использоваться также для очищения окружения в ходе этой команды или для удаления отдельных переменных окружения. Программа обеспечивает нас двойной функциональностью, поскольку проявляет возможности как getopt_long(), так и несколько других возможностей, обсуждавшихся в этом разделе. Вот как вызывается программа:

$ env --help

Usage: env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]

/* Устанавливает соответствующее VALUE для каждого NAME и запускает COMMAND */

-i, --ignore-environment /* запустить с пустым окружением */

-u, --unset=NAME         /* удалить переменную из окружения */

Перейти на страницу:

Похожие книги