Операционная система UNIX - страница 53
и 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"). Раздел "Группы и сеансы" внесет окончательную ясность в этот вопрос при описании управляющего терминала.
Такой механизм позволяет программисту не задумываться о местонахождении пользователя, и в то же время обеспечить получение и передачу данных именно запустившему данную программу пользователю.
Завершая разговор о запуске программ, заметим, что при компиляции программы редактор связей устанавливает точку входа в программу, указывающую на библиотечную функцию _start(). Эта функция инициализирует процесс, создавая кадр стека, устанавливая значения переменных и, в конечном итоге, вызывая функцию main().
Завершение C-программы
Существует несколько способов завершения программы. Основными являются возврат из функции main()[17] и вызов функций