Linux программирование в примерах | страница 47



>182 while ((optc = getopt_long(argc, argv, "+iu:", longopts, NULL)) != -1)

>183  if (optc == 'u')

>184   putenv(optarg); /* Требуется GNU putenv. */

>185

>186 if (optind !=argc && !strcmp(argv[optind], "-")) /* Пропустить опции */

>187  ++optind;

>188

>189 while (optind < argc && strchr(argv[optind], '=')) /* Установить

>     переменные окружения * /

>190 putenv(argv[optind++]);

>191

>192 /* Если программа не указана, напечатать переменные окружения и выйти. */

>193 if (optind == argc)

>194 {

>195  while (*environ)

>196   puts (*environ++);

>197  exit(EXIT_SUCCESS);

>198 }

Строки 174–179 переносят существующие переменные в новую копию окружения. В глобальную переменную >environ помещается указатель на пустой локальный массив. Параметр >envp поддерживает доступ к первоначальному окружению.

Строки 181–184 удаляют переменные окружения, указанные в опции >-u. Программа осуществляет это, повторно сканируя командную строку и удаляя перечисленные там имена. Удаление переменных окружения основывается на обсуждавшейся ранее особенности GNU >putenv(): при вызове с одним лишь именем переменной (без указанного значения) >putenv() удаляет ее из окружения.

После опций в командной строке помещаются новые или замещающие переменные окружения. Строки 189–190 продолжают сканирование командной строки, отыскивая установки переменных окружения в виде '>имя=значение'.

По достижении строки 192, если в командной строке ничего не осталось, предполагается, что >env печатает новое окружение и выходит из программы. Она это и делает (строки 195–197).

Если остались аргументы, они представляют имя команды, которую нужно вызвать, и аргументы для передачи этой новой команде. Это делается с помощью системного вызова >execvp() (строка 200), который замещает текущую программу новой. (Этот вызов обсуждается в разделе 9.1.4 «Запуск новой программы: семейство >exec()»; пока не беспокойтесь о деталях.) Если этот вызов возвращается в текущую программу, он потерпел неудачу. В таком случае >env выводит сообщение об ошибке и завершает программу.

>200  execvp(argv[optind], &argv[optind]);

>201

>202  {

>203   int exit_status = (errno == ENOENT ? 127 : 126);

>204   error(0, errno, "%s", argv[optind]);

>205   exit(exit_status);

>206  }

>207 }

Значения кода завершения >126 и >127 (определяемые в строке 203) соответствуют стандарту POSIX. >127 означает, что программа, которую >execvp() попыталась запустить, не существует. (>ENOENT означает, что файл не содержит записи в каталоге.)