179 putenv(*envp);
180
181 optind = 0; /* Принудительная реинициализация GNU getopt. */
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
putenv()
: при вызове с одним лишь именем переменной (без указанного значения) putenv()
удаляет ее из окружения.После опций в командной строке помещаются новые или замещающие переменные окружения. Строки 189–190 продолжают сканирование командной строки, отыскивая установки переменных окружения в виде '
По достижении строки 192, если в командной строке ничего не осталось, предполагается, что env
Если остались аргументы, они представляют имя команды, которую нужно вызвать, и аргументы для передачи этой новой команде. Это делается с помощью системного вызова execvp()
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
означает, что файл не содержит записи в каталоге.) 126
означает, что файл существует, но была какая-то другая ошибка.2.5. Резюме
• Программы на С получают аргументы своей командной строки через параметры argc
argv
. Функция getopt()
предоставляет стандартный способ для последовательного разбора опций и их аргументов GNU версия getopt()
предоставляет некоторые расширения, a getopt_long()
и getopt_long_only()
дает возможность легкого разбора длинных опций.• Окружение представляет собой набор пар '
getenv()
, setenv()
, putenv()
и unsetenv()
). При необходимости можно получить доступ ко всему окружению через внешнюю переменную environ
или через третий аргумент char **envp
функции main()
. Последний способ не рекомендуется.Упражнения
1. Предположим, что программа принимает опции -a
-b
и -с
, и что -b
требует наличия аргумента. Напишите для этой программы код ручного разбора аргументов без использования getopt()
или getopt_long()
. Для завершения обработки опций принимается --
. Убедитесь, что -ас работает, также, как -bYANKEES
, -b YANKEES
и -abYANKEES
. Протестируйте программу.