extern char *environ;
Рекомендуется следовать последнему формату передачи для лучшей переносимости программ на другие платформы UNIX.
Рис. 2.6. Передача переменных окружения
Приведем пример программы, соответствующую стандарту POSIX.1, которая выводит значения всех аргументов, переданных функции main() : число переданных параметров, сами параметры и значения первых десяти переменных окружения.
#include
extern char **environ;
main(int argc, char *argv[]) {
int i;
printf("число параметров, переданных программе %s равно %d\n",
argv[0], argc-1);
for (i=1; i
if (environ[i] != NULL)
printf("environ[%d] : %s\n", i, environ[i]);
}
В результате компиляции будет создан исполняемый файл программы (по умолчанию a.out). Запустив его, мы увидим следующую информацию:
$ a.out first second 3
число параметров, переданных программе a.out равно 3
argv[1] = first
argv[2] = second
argv[3] = 3
environ[0] : LOGNAME=andy
environ[1] : MAIL=/var/mail/andy
environ[2] : LD_LIBRARY_PATH=/usr/openwin/lib:/usr/ucblib
environ[3] : PAGER=/usr/bin/pg
environ[4] : TERM=vt100
environ[5] : PATH=/usr/bin:/bin:/etc:/usr/sbin:/sbin:/usr/ccs/bin:/usr/local/bin
environ[6] : HOME=/home/andy
environ[7] : SHELL=/usr/local/bin/bash
Максимальный объем памяти для хранения параметров и переменных окружения программы ограничен величиной ARG_MAX
, определенной в файле . Это и другие системные ограничения могут быть получены с помощью функции sysconf(2) .
Для получения и установки значений конкретных переменных окружения используются две функции: getenv(3C) и putenv(3C) :
#include
char *getenv(const char *name);
возвращает значение переменной окружения name
, a
int putenv(const char *string);
помещает переменную и ее значение ( var_name=var_value
) в окружение программы.
В качестве примера приведем программу, похожую по своей функциональности на предыдущую, которая выборочно выводит значения переменных и устанавливает новые значения по желанию пользователя.
#include
#include
#include
main(int argc, char *argv[]) {
char *term;
char buf[200], var[200];
/* Проверим, определена ли переменная TERM */
if ((term = getenv("TERM")) == NULL)
/* Если переменная не определена, получим от пользователя ее значение и
поместим переменную в окружение программы */
{
printf("переменная TERM не определена, введите значение: ");
putenv(var);
} else
/* Если переменная TERM определена, предоставим пользователю возможность
изменить ее значение, после чего поместим ее в окружение процесса */
{
printf("TERM=%s. Change? [N]", getenv("TERM"));
gets(buf);
if (buf[0] == 'Y' || buf[0] == 'y') {
printf("TERM=");
gets{buf);
sprintf(var, "TERM=%s", buf);
putenv(var);
printf("new %s\n", var);
}
}
}
Сначала программа проверяет, определена ли переменная TERM
. Если переменная TERM
не определена, пользователю предлагается ввести ее значение. Если же переменная TERM
определена, пользователю предлагается изменить ее значение, после чего новое значение помещается в окружение программы.
Запуск этой программы приведет к следующим результатам:
$ а.out
TERM=ansi. Change? [N] y
TERM= vt100
new TERM=vt100
$
К сожалению, введенное значение переменной будет действительно только для данного процесса и порожденных им процессов: если после завершения программы a.outвывести значение TERM
, то видно, что оно не изменилось:
$ echo $TERM
ansi
$
Наследование окружения программы мы обсудим в разделе "Создание и управление процессами" далее в этой главе.
Переменные окружения, как и параметры, позволяют передавать программе некоторую информацию. Однако если программа является интерактивной, основную информацию она, скорее всего, будет получать непосредственно от пользователя. В связи с этим встает вопрос: каким образом программа узнает, где находится пользователь, чтобы правильно считывать и выводить информацию? Другими словами, программе необходимо знать, с каким терминальным устройством работает пользователь, запустивший ее.
Обычно при запуске программы на выполнение из командной строки shell автоматически устанавливает для нее три стандартных потока ввода/вывода: для ввода данных, для вывода информации и для вывода сообщений об ошибках. Начальную ассоциацию этих потоков (их файловых дескрипторов) с конкретными устройствами производит терминальный сервер (в большинстве систем это процесс getty(1M) ), который открывает специальный файл устройства, связанный с терминалом пользователя, и получает соответствующие дескрипторы. Эти потоки наследует командный интерпретатор shell и передает их запускаемой программе. При этом shell может изменить стандартные направления (по умолчанию все три потока связаны с терминалом пользователя), если пользователь указал на это с помощью специальных директив перенаправления потока (>, <, >>, <<) см. главу 1, раздел "Пользовательская среда UNIX"). Раздел "Группы и сеансы" внесет окончательную ясность в этот вопрос при описании управляющего терминала.
Читать дальше