- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Linux программирование в примерах - Арнольд Роббинс
Шрифт:
Интервал:
Закладка:
121 program_name);
122 fputs (_("
123 Set each NAME to VALUE in the environment and run COMMAND. n
124 n
125 -i, --ignore-environment start with an empty environmentn
126 -u, --unset=NAME remove variable from the environmentn
127 "), stdout);
128 fputs(HELP_OPTION_DESCRIPTION, stdout);
129 fputs(VERSION_OPTION_DESCRIPTION, stdout);
130 fputs(_("
131 n
132 A mere - implies -i. If no COMMAND, print the resulting
133 environment.n"), stdout);
134 printf(_("nReport bugs to <%s>.n"), PACKAGE_BUGREPORT);
135 }
136 exit(status);
137 }
Первая часть main() объявляет переменные и настраивает локализацию. Функции setlocale(), bindtextdomain() и textdomain() (строки 147–149) обсуждаются в главе 13 «Интернационализация и локализация». Отметим, что эта программа использует аргумент main() envp (строка 140). Это единственная программа Coreutils, которая так делает. Наконец, вызов atexit() в строке 151 (см. раздел 9.1.5.3. «Функции завершения») регистрирует библиотечную функцию Coreutils, которая очищает все выходные буферы и закрывает stdout, выдавая сообщение при ошибке. Следующая часть программы обрабатывает аргументы командной строки, используя getopt_long().
139 int
140 main(register int argc, register char **argv, char **envp)
141 {
142 char *dummy_environ[1];
143 int optc;
144 int ignore_environment = 0;
145
146 program_name = argv[0];
147 setlocale(LC_ALL, "");
148 bindtextdomain(PACKAGE, LOCALEDIR);
149 textdomain(PACKAGE);
150
151 atexit(close_stdout);
152
153 while ((optc = getopt_long(argc, argv, "+iu:", longopts, NULL)) != -1)
154 {
155 switch (optc)
156 {
157 case 0:
158 break;
159 case 'i':
160 ignore_environment = 1;
161 break;
162 case 'u':
163 break;
164 case_GETOPT_HELP_CHAR;
165 case_GETOPT_VERSION_CHAR(PROGRAM_NAME, AUTHORS);
166 default:
167 usage(2);
168 }
169 }
170
171 if (optind != argc && !strcmp(argv[optind], "-"))
172 ignore_environment = 1;
Вот отрывок из файла src/sys2.h в дистрибутиве Coreutils с упомянутыми ранее определениями и макросом 'case_GETOPT_xxx', использованным выше (строки 164–165):
/* Вынесение за скобки общей части кода, обрабатывающего --help и
--version. */
/* Эти значения перечисления никак не могут конфликтовать со значениями опций,
обычно используемыми командами, включая CHAR_MAX + 1 и т.д. Избегайте
CHAR_MIN - 1, т.к. оно может равняться -1, значение завершения опций getopt.
*/
enum {
GETOPT_HELP_CHAR = (CHAR_MIN — 2),
GETOPT_VERSION_CHAR = (CHAR_MIN - 3)
};
#define GETOPT_HELP_OPTION_DECL
"help", no_argument, 0, GETOPT_HELP_CHAR
#define GETOPT_VERSION_OPTION_DECL
"version", no_argument, 0, GETOPT_VERSION_CHAR
#define case_GETOPT_HELP_CHAR
case GETOPT_HELP_CHAR:
usage(EXIT_SUCCESS);
break;
#define case_GETOPT_VERSION_CHAR(Program_name, Authors)
case GETOPT_VERSION_CHAR:
version_etc(stdout, Program_name, PACKAGE, VERSION, Authors);
exit(EXIT_SUCCESS);
break;
Результатом этого кода является печать сообщения об использовании утилиты для --help и печать информации о версии для --version. Обе опции завершаются успешно («Успешный» и «неудачный» статусы завершения описаны в разделе 9.1.5.1 «Определение статуса завершения процесса».) Поскольку в Coreutils входят десятки утилит, имеет смысл вынести за скобки и стандартизовать как можно больше повторяющегося кода.
Возвращаясь к env.с:
174 environ = dummy_environ;
175 environ[0] = NULL;
176
177 if (!ignore_environment)
178 for (; *envp; envp++)
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. Программа осуществляет это, повторно сканируя командную строку и удаляя перечисленные там имена. Удаление переменных окружения основывается на обсуждавшейся ранее особенности 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 означает, что файл не содержит записи в каталоге.) 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. Протестируйте программу.
2. Реализуйте getopt(). Для первой версии вы можете не беспокоиться насчет случая 'optstring[0] == ':''. Можете также игнорировать opterr.
3. Добавьте код для 'optstring[0] == ':'' и opterr к своей версии getopt().
4. Распечатайте и прочтите файлы GNU getopt.h, getopt.с и getopt1.с.
5. Напишите программу, которая объявляет как environ, так и envp, и сравните их значения.
6. Разбор аргументов командной строки и опций является тем колесом, которое многие люди не могут не изобретать вновь. Вы можете захотеть познакомиться с различными анализирующими аргументы пакетами, помимо getopt() и getopt_long(), такими, как:

