Linux программирование в примерах | страница 46
>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. */