diff options
Diffstat (limited to 'util-linux/getopt.c')
-rw-r--r-- | util-linux/getopt.c | 456 |
1 files changed, 228 insertions, 228 deletions
diff --git a/util-linux/getopt.c b/util-linux/getopt.c index fc3b9f97e..16dcbbca0 100644 --- a/util-linux/getopt.c +++ b/util-linux/getopt.c | |||
@@ -71,7 +71,7 @@ static int alternative; /* 0 is getopt_long, 1 is getopt_long_only */ | |||
71 | /* Function prototypes */ | 71 | /* Function prototypes */ |
72 | static const char *normalize(const char *arg); | 72 | static const char *normalize(const char *arg); |
73 | static int generate_output(char * argv[],int argc,const char *optstr, | 73 | static int generate_output(char * argv[],int argc,const char *optstr, |
74 | const struct option *longopts); | 74 | const struct option *longopts); |
75 | static void add_long_options(char *options); | 75 | static void add_long_options(char *options); |
76 | static void add_longopt(const char *name,int has_arg); | 76 | static void add_longopt(const char *name,int has_arg); |
77 | static void set_shell(const char *new_shell); | 77 | static void set_shell(const char *new_shell); |
@@ -88,57 +88,57 @@ static void set_shell(const char *new_shell); | |||
88 | */ | 88 | */ |
89 | const char *normalize(const char *arg) | 89 | const char *normalize(const char *arg) |
90 | { | 90 | { |
91 | static char *BUFFER=NULL; | 91 | static char *BUFFER=NULL; |
92 | const char *argptr=arg; | 92 | const char *argptr=arg; |
93 | char *bufptr; | 93 | char *bufptr; |
94 | 94 | ||
95 | free(BUFFER); | 95 | free(BUFFER); |
96 | 96 | ||
97 | if (!quote) { /* Just copy arg */ | 97 | if (!quote) { /* Just copy arg */ |
98 | BUFFER=bb_xstrdup(arg); | 98 | BUFFER=bb_xstrdup(arg); |
99 | return BUFFER; | 99 | return BUFFER; |
100 | } | 100 | } |
101 | 101 | ||
102 | /* Each character in arg may take up to four characters in the result: | 102 | /* Each character in arg may take up to four characters in the result: |
103 | For a quote we need a closing quote, a backslash, a quote and an | 103 | For a quote we need a closing quote, a backslash, a quote and an |
104 | opening quote! We need also the global opening and closing quote, | 104 | opening quote! We need also the global opening and closing quote, |
105 | and one extra character for '\0'. */ | 105 | and one extra character for '\0'. */ |
106 | BUFFER=xmalloc(strlen(arg)*4+3); | 106 | BUFFER=xmalloc(strlen(arg)*4+3); |
107 | 107 | ||
108 | bufptr=BUFFER; | 108 | bufptr=BUFFER; |
109 | *bufptr++='\''; | 109 | *bufptr++='\''; |
110 | 110 | ||
111 | while (*argptr) { | 111 | while (*argptr) { |
112 | if (*argptr == '\'') { | 112 | if (*argptr == '\'') { |
113 | /* Quote: replace it with: '\'' */ | 113 | /* Quote: replace it with: '\'' */ |
114 | *bufptr++='\''; | 114 | *bufptr++='\''; |
115 | *bufptr++='\\'; | 115 | *bufptr++='\\'; |
116 | *bufptr++='\''; | 116 | *bufptr++='\''; |
117 | *bufptr++='\''; | 117 | *bufptr++='\''; |
118 | } else if (shell==TCSH && *argptr=='!') { | 118 | } else if (shell==TCSH && *argptr=='!') { |
119 | /* Exclamation mark: replace it with: \! */ | 119 | /* Exclamation mark: replace it with: \! */ |
120 | *bufptr++='\''; | 120 | *bufptr++='\''; |
121 | *bufptr++='\\'; | 121 | *bufptr++='\\'; |
122 | *bufptr++='!'; | 122 | *bufptr++='!'; |
123 | *bufptr++='\''; | 123 | *bufptr++='\''; |
124 | } else if (shell==TCSH && *argptr=='\n') { | 124 | } else if (shell==TCSH && *argptr=='\n') { |
125 | /* Newline: replace it with: \n */ | 125 | /* Newline: replace it with: \n */ |
126 | *bufptr++='\\'; | 126 | *bufptr++='\\'; |
127 | *bufptr++='n'; | 127 | *bufptr++='n'; |
128 | } else if (shell==TCSH && isspace(*argptr)) { | 128 | } else if (shell==TCSH && isspace(*argptr)) { |
129 | /* Non-newline whitespace: replace it with \<ws> */ | 129 | /* Non-newline whitespace: replace it with \<ws> */ |
130 | *bufptr++='\''; | 130 | *bufptr++='\''; |
131 | *bufptr++='\\'; | 131 | *bufptr++='\\'; |
132 | *bufptr++=*argptr; | 132 | *bufptr++=*argptr; |
133 | *bufptr++='\''; | 133 | *bufptr++='\''; |
134 | } else | 134 | } else |
135 | /* Just copy */ | 135 | /* Just copy */ |
136 | *bufptr++=*argptr; | 136 | *bufptr++=*argptr; |
137 | argptr++; | 137 | argptr++; |
138 | } | 138 | } |
139 | *bufptr++='\''; | 139 | *bufptr++='\''; |
140 | *bufptr++='\0'; | 140 | *bufptr++='\0'; |
141 | return BUFFER; | 141 | return BUFFER; |
142 | } | 142 | } |
143 | 143 | ||
144 | /* | 144 | /* |
@@ -149,47 +149,47 @@ const char *normalize(const char *arg) | |||
149 | * Other settings are found in global variables. | 149 | * Other settings are found in global variables. |
150 | */ | 150 | */ |
151 | int generate_output(char * argv[],int argc,const char *optstr, | 151 | int generate_output(char * argv[],int argc,const char *optstr, |
152 | const struct option *longopts) | 152 | const struct option *longopts) |
153 | { | 153 | { |
154 | int exit_code = 0; /* We assume everything will be OK */ | 154 | int exit_code = 0; /* We assume everything will be OK */ |
155 | int opt; | 155 | int opt; |
156 | int longindex; | 156 | int longindex; |
157 | const char *charptr; | 157 | const char *charptr; |
158 | 158 | ||
159 | if (quiet_errors) /* No error reporting from getopt(3) */ | 159 | if (quiet_errors) /* No error reporting from getopt(3) */ |
160 | opterr=0; | 160 | opterr=0; |
161 | optind=0; /* Reset getopt(3) */ | 161 | optind=0; /* Reset getopt(3) */ |
162 | 162 | ||
163 | while ((opt = (alternative? | 163 | while ((opt = (alternative? |
164 | getopt_long_only(argc,argv,optstr,longopts,&longindex): | 164 | getopt_long_only(argc,argv,optstr,longopts,&longindex): |
165 | getopt_long(argc,argv,optstr,longopts,&longindex))) | 165 | getopt_long(argc,argv,optstr,longopts,&longindex))) |
166 | != EOF) | 166 | != EOF) |
167 | if (opt == '?' || opt == ':' ) | 167 | if (opt == '?' || opt == ':' ) |
168 | exit_code = 1; | 168 | exit_code = 1; |
169 | else if (!quiet_output) { | 169 | else if (!quiet_output) { |
170 | if (opt == LONG_OPT) { | 170 | if (opt == LONG_OPT) { |
171 | printf(" --%s",longopts[longindex].name); | 171 | printf(" --%s",longopts[longindex].name); |
172 | if (longopts[longindex].has_arg) | 172 | if (longopts[longindex].has_arg) |
173 | printf(" %s", | 173 | printf(" %s", |
174 | normalize(optarg?optarg:"")); | 174 | normalize(optarg?optarg:"")); |
175 | } else if (opt == NON_OPT) | 175 | } else if (opt == NON_OPT) |
176 | printf(" %s",normalize(optarg)); | 176 | printf(" %s",normalize(optarg)); |
177 | else { | 177 | else { |
178 | printf(" -%c",opt); | 178 | printf(" -%c",opt); |
179 | charptr = strchr(optstr,opt); | 179 | charptr = strchr(optstr,opt); |
180 | if (charptr != NULL && *++charptr == ':') | 180 | if (charptr != NULL && *++charptr == ':') |
181 | printf(" %s", | 181 | printf(" %s", |
182 | normalize(optarg?optarg:"")); | 182 | normalize(optarg?optarg:"")); |
183 | } | 183 | } |
184 | } | 184 | } |
185 | 185 | ||
186 | if (! quiet_output) { | 186 | if (! quiet_output) { |
187 | printf(" --"); | 187 | printf(" --"); |
188 | while (optind < argc) | 188 | while (optind < argc) |
189 | printf(" %s",normalize(argv[optind++])); | 189 | printf(" %s",normalize(argv[optind++])); |
190 | printf("\n"); | 190 | printf("\n"); |
191 | } | 191 | } |
192 | return exit_code; | 192 | return exit_code; |
193 | } | 193 | } |
194 | 194 | ||
195 | static struct option *long_options; | 195 | static struct option *long_options; |
@@ -201,32 +201,32 @@ static const int LONG_OPTIONS_INCR = 10; | |||
201 | /* Register a long option. The contents of name is copied. */ | 201 | /* Register a long option. The contents of name is copied. */ |
202 | void add_longopt(const char *name,int has_arg) | 202 | void add_longopt(const char *name,int has_arg) |
203 | { | 203 | { |
204 | if (!name) { /* init */ | 204 | if (!name) { /* init */ |
205 | free(long_options); | 205 | free(long_options); |
206 | long_options=NULL; | 206 | long_options=NULL; |
207 | long_options_length=0; | 207 | long_options_length=0; |
208 | long_options_nr=0; | 208 | long_options_nr=0; |
209 | } | 209 | } |
210 | 210 | ||
211 | if (long_options_nr == long_options_length) { | 211 | if (long_options_nr == long_options_length) { |
212 | long_options_length += LONG_OPTIONS_INCR; | 212 | long_options_length += LONG_OPTIONS_INCR; |
213 | long_options=xrealloc(long_options, | 213 | long_options=xrealloc(long_options, |
214 | sizeof(struct option) * | 214 | sizeof(struct option) * |
215 | long_options_length); | 215 | long_options_length); |
216 | } | 216 | } |
217 | 217 | ||
218 | long_options[long_options_nr].name=NULL; | 218 | long_options[long_options_nr].name=NULL; |
219 | long_options[long_options_nr].has_arg=0; | 219 | long_options[long_options_nr].has_arg=0; |
220 | long_options[long_options_nr].flag=NULL; | 220 | long_options[long_options_nr].flag=NULL; |
221 | long_options[long_options_nr].val=0; | 221 | long_options[long_options_nr].val=0; |
222 | 222 | ||
223 | if (long_options_nr) { /* Not for init! */ | 223 | if (long_options_nr) { /* Not for init! */ |
224 | long_options[long_options_nr-1].has_arg=has_arg; | 224 | long_options[long_options_nr-1].has_arg=has_arg; |
225 | long_options[long_options_nr-1].flag=NULL; | 225 | long_options[long_options_nr-1].flag=NULL; |
226 | long_options[long_options_nr-1].val=LONG_OPT; | 226 | long_options[long_options_nr-1].val=LONG_OPT; |
227 | long_options[long_options_nr-1].name=bb_xstrdup(name); | 227 | long_options[long_options_nr-1].name=bb_xstrdup(name); |
228 | } | 228 | } |
229 | long_options_nr++; | 229 | long_options_nr++; |
230 | } | 230 | } |
231 | 231 | ||
232 | 232 | ||
@@ -237,43 +237,43 @@ void add_longopt(const char *name,int has_arg) | |||
237 | */ | 237 | */ |
238 | void add_long_options(char *options) | 238 | void add_long_options(char *options) |
239 | { | 239 | { |
240 | int arg_opt, tlen; | 240 | int arg_opt, tlen; |
241 | char *tokptr=strtok(options,", \t\n"); | 241 | char *tokptr=strtok(options,", \t\n"); |
242 | while (tokptr) { | 242 | while (tokptr) { |
243 | arg_opt=no_argument; | 243 | arg_opt=no_argument; |
244 | tlen=strlen(tokptr); | 244 | tlen=strlen(tokptr); |
245 | if (tlen > 0) { | 245 | if (tlen > 0) { |
246 | if (tokptr[tlen-1] == ':') { | 246 | if (tokptr[tlen-1] == ':') { |
247 | if (tlen > 1 && tokptr[tlen-2] == ':') { | 247 | if (tlen > 1 && tokptr[tlen-2] == ':') { |
248 | tokptr[tlen-2]='\0'; | 248 | tokptr[tlen-2]='\0'; |
249 | tlen -= 2; | 249 | tlen -= 2; |
250 | arg_opt=optional_argument; | 250 | arg_opt=optional_argument; |
251 | } else { | 251 | } else { |
252 | tokptr[tlen-1]='\0'; | 252 | tokptr[tlen-1]='\0'; |
253 | tlen -= 1; | 253 | tlen -= 1; |
254 | arg_opt=required_argument; | 254 | arg_opt=required_argument; |
255 | } | 255 | } |
256 | if (tlen == 0) | 256 | if (tlen == 0) |
257 | bb_error_msg("empty long option after -l or --long argument"); | 257 | bb_error_msg("empty long option after -l or --long argument"); |
258 | } | 258 | } |
259 | add_longopt(tokptr,arg_opt); | 259 | add_longopt(tokptr,arg_opt); |
260 | } | 260 | } |
261 | tokptr=strtok(NULL,", \t\n"); | 261 | tokptr=strtok(NULL,", \t\n"); |
262 | } | 262 | } |
263 | } | 263 | } |
264 | 264 | ||
265 | void set_shell(const char *new_shell) | 265 | void set_shell(const char *new_shell) |
266 | { | 266 | { |
267 | if (!strcmp(new_shell,"bash")) | 267 | if (!strcmp(new_shell,"bash")) |
268 | shell=BASH; | 268 | shell=BASH; |
269 | else if (!strcmp(new_shell,"tcsh")) | 269 | else if (!strcmp(new_shell,"tcsh")) |
270 | shell=TCSH; | 270 | shell=TCSH; |
271 | else if (!strcmp(new_shell,"sh")) | 271 | else if (!strcmp(new_shell,"sh")) |
272 | shell=BASH; | 272 | shell=BASH; |
273 | else if (!strcmp(new_shell,"csh")) | 273 | else if (!strcmp(new_shell,"csh")) |
274 | shell=TCSH; | 274 | shell=TCSH; |
275 | else | 275 | else |
276 | bb_error_msg("unknown shell after -s or --shell argument"); | 276 | bb_error_msg("unknown shell after -s or --shell argument"); |
277 | } | 277 | } |
278 | 278 | ||
279 | 279 | ||
@@ -287,16 +287,16 @@ void set_shell(const char *new_shell) | |||
287 | 287 | ||
288 | static const struct option longopts[]= | 288 | static const struct option longopts[]= |
289 | { | 289 | { |
290 | {"options",required_argument,NULL,'o'}, | 290 | {"options",required_argument,NULL,'o'}, |
291 | {"longoptions",required_argument,NULL,'l'}, | 291 | {"longoptions",required_argument,NULL,'l'}, |
292 | {"quiet",no_argument,NULL,'q'}, | 292 | {"quiet",no_argument,NULL,'q'}, |
293 | {"quiet-output",no_argument,NULL,'Q'}, | 293 | {"quiet-output",no_argument,NULL,'Q'}, |
294 | {"shell",required_argument,NULL,'s'}, | 294 | {"shell",required_argument,NULL,'s'}, |
295 | {"test",no_argument,NULL,'T'}, | 295 | {"test",no_argument,NULL,'T'}, |
296 | {"unquoted",no_argument,NULL,'u'}, | 296 | {"unquoted",no_argument,NULL,'u'}, |
297 | {"alternative",no_argument,NULL,'a'}, | 297 | {"alternative",no_argument,NULL,'a'}, |
298 | {"name",required_argument,NULL,'n'}, | 298 | {"name",required_argument,NULL,'n'}, |
299 | {NULL,0,NULL,0} | 299 | {NULL,0,NULL,0} |
300 | }; | 300 | }; |
301 | 301 | ||
302 | /* Stop scanning as soon as a non-option argument is found! */ | 302 | /* Stop scanning as soon as a non-option argument is found! */ |
@@ -305,77 +305,77 @@ static const char shortopts[]="+ao:l:n:qQs:Tu"; | |||
305 | 305 | ||
306 | int getopt_main(int argc, char *argv[]) | 306 | int getopt_main(int argc, char *argv[]) |
307 | { | 307 | { |
308 | const char *optstr = NULL; | 308 | const char *optstr = NULL; |
309 | char *name = NULL; | 309 | char *name = NULL; |
310 | int opt; | 310 | int opt; |
311 | int compatible=0; | 311 | int compatible=0; |
312 | 312 | ||
313 | init_longopt(); | 313 | init_longopt(); |
314 | 314 | ||
315 | if (getenv("GETOPT_COMPATIBLE")) | 315 | if (getenv("GETOPT_COMPATIBLE")) |
316 | compatible=1; | 316 | compatible=1; |
317 | 317 | ||
318 | if (argc == 1) { | 318 | if (argc == 1) { |
319 | if (compatible) { | 319 | if (compatible) { |
320 | /* For some reason, the original getopt gave no error | 320 | /* For some reason, the original getopt gave no error |
321 | when there were no arguments. */ | 321 | when there were no arguments. */ |
322 | printf(" --\n"); | 322 | printf(" --\n"); |
323 | return 0; | 323 | return 0; |
324 | } else | 324 | } else |
325 | bb_error_msg_and_die("missing optstring argument"); | 325 | bb_error_msg_and_die("missing optstring argument"); |
326 | } | 326 | } |
327 | 327 | ||
328 | if (argv[1][0] != '-' || compatible) { | 328 | if (argv[1][0] != '-' || compatible) { |
329 | char *s; | 329 | char *s; |
330 | 330 | ||
331 | quote=0; | 331 | quote=0; |
332 | s=xmalloc(strlen(argv[1])+1); | 332 | s=xmalloc(strlen(argv[1])+1); |
333 | strcpy(s,argv[1]+strspn(argv[1],"-+")); | 333 | strcpy(s,argv[1]+strspn(argv[1],"-+")); |
334 | argv[1]=argv[0]; | 334 | argv[1]=argv[0]; |
335 | return (generate_output(argv+1,argc-1,s,long_options)); | 335 | return (generate_output(argv+1,argc-1,s,long_options)); |
336 | } | 336 | } |
337 | 337 | ||
338 | while ((opt=getopt_long(argc,argv,shortopts,longopts,NULL)) != EOF) | 338 | while ((opt=getopt_long(argc,argv,shortopts,longopts,NULL)) != EOF) |
339 | switch (opt) { | 339 | switch (opt) { |
340 | case 'a': | 340 | case 'a': |
341 | alternative=1; | 341 | alternative=1; |
342 | break; | 342 | break; |
343 | case 'o': | 343 | case 'o': |
344 | optstr = optarg; | 344 | optstr = optarg; |
345 | break; | 345 | break; |
346 | case 'l': | 346 | case 'l': |
347 | add_long_options(optarg); | 347 | add_long_options(optarg); |
348 | break; | 348 | break; |
349 | case 'n': | 349 | case 'n': |
350 | name = optarg; | 350 | name = optarg; |
351 | break; | 351 | break; |
352 | case 'q': | 352 | case 'q': |
353 | quiet_errors=1; | 353 | quiet_errors=1; |
354 | break; | 354 | break; |
355 | case 'Q': | 355 | case 'Q': |
356 | quiet_output=1; | 356 | quiet_output=1; |
357 | break; | 357 | break; |
358 | case 's': | 358 | case 's': |
359 | set_shell(optarg); | 359 | set_shell(optarg); |
360 | break; | 360 | break; |
361 | case 'T': | 361 | case 'T': |
362 | return 4; | 362 | return 4; |
363 | case 'u': | 363 | case 'u': |
364 | quote=0; | 364 | quote=0; |
365 | break; | 365 | break; |
366 | default: | 366 | default: |
367 | bb_show_usage(); | 367 | bb_show_usage(); |
368 | } | 368 | } |
369 | 369 | ||
370 | if (!optstr) { | 370 | if (!optstr) { |
371 | if (optind >= argc) | 371 | if (optind >= argc) |
372 | bb_error_msg_and_die("missing optstring argument"); | 372 | bb_error_msg_and_die("missing optstring argument"); |
373 | else optstr=argv[optind++]; | 373 | else optstr=argv[optind++]; |
374 | } | 374 | } |
375 | if (name) | 375 | if (name) |
376 | argv[optind-1]=name; | 376 | argv[optind-1]=name; |
377 | else | 377 | else |
378 | argv[optind-1]=argv[0]; | 378 | argv[optind-1]=argv[0]; |
379 | return (generate_output(argv+optind-1,argc-optind+1,optstr,long_options)); | 379 | return (generate_output(argv+optind-1,argc-optind+1,optstr,long_options)); |
380 | } | 380 | } |
381 | 381 | ||