aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
author"Vladimir N. Oleynik" <dzo@simtreas.ru>2005-10-14 09:56:52 +0000
committer"Vladimir N. Oleynik" <dzo@simtreas.ru>2005-10-14 09:56:52 +0000
commitf704b27b5bb8bd5acaed9464714db34ccef06cc8 (patch)
tree06f15d778a64ba361219d8227f87422173bf0da8 /libbb
parent8c7a7e6e63c01d2d575bbaa43e1768ad2b97179b (diff)
downloadbusybox-w32-f704b27b5bb8bd5acaed9464714db34ccef06cc8.tar.gz
busybox-w32-f704b27b5bb8bd5acaed9464714db34ccef06cc8.tar.bz2
busybox-w32-f704b27b5bb8bd5acaed9464714db34ccef06cc8.zip
- new bb_opt_complementally syntax, use [-:?] only - 'free' chars
- new bb_getopt_ulflags features: check max and min args, convert first argv to options special for ar and tar applets - use bb_default_error_retval for env applet
Diffstat (limited to 'libbb')
-rw-r--r--libbb/getopt_ulflags.c181
1 files changed, 117 insertions, 64 deletions
diff --git a/libbb/getopt_ulflags.c b/libbb/getopt_ulflags.c
index 5f35c583c..47f65d6b2 100644
--- a/libbb/getopt_ulflags.c
+++ b/libbb/getopt_ulflags.c
@@ -66,7 +66,7 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...)
66 &pointer_to_arg_for_c, &pointer_to_arg_for_d); 66 &pointer_to_arg_for_c, &pointer_to_arg_for_d);
67 67
68 The type of the pointer (char* or llist_t *) may be controlled 68 The type of the pointer (char* or llist_t *) may be controlled
69 by the "*" special character that is set in the external string 69 by the "::" special separator that is set in the external string
70 bb_opt_complementally (see below for more info). 70 bb_opt_complementally (see below for more info).
71 71
72static const struct option bb_default_long_options[] 72static const struct option bb_default_long_options[]
@@ -127,13 +127,13 @@ const char *bb_opt_complementally
127 127
128 w_counter is a pointer to an integer. It has to be passed to 128 w_counter is a pointer to an integer. It has to be passed to
129 bb_getopt_ulflags() after all other option argument sinks. 129 bb_getopt_ulflags() after all other option argument sinks.
130 For example: accept multiple -v to indicate the level of verbosity and 130 For example: accept multiple -v to indicate the level of verbosity
131 for each -b optarg, add optarg to my_b. Finally, if b is given, turn off 131 and for each -b optarg, add optarg to my_b. Finally, if b is given,
132 c and vice versa: 132 turn off c and vice versa:
133 133
134 llist_t *my_b = NULL; 134 llist_t *my_b = NULL;
135 int verbose_level = 0; 135 int verbose_level = 0;
136 bb_opt_complementally = "vv:b*:b-c:c-b"; 136 bb_opt_complementally = "vv:b::b-c:c-b";
137 f = bb_getopt_ulflags(argc, argv, "vb:c", &my_b, &verbose_level); 137 f = bb_getopt_ulflags(argc, argv, "vb:c", &my_b, &verbose_level);
138 if((f & 2)) // -c after -b unset this -b flag 138 if((f & 2)) // -c after -b unset this -b flag
139 while (my_b) { dosomething_with(my_b->data) ; my_b = my_b->link; } 139 while (my_b) { dosomething_with(my_b->data) ; my_b = my_b->link; }
@@ -164,15 +164,14 @@ Special characters:
164 opt = bb_getopt_ulflags(argc, argv, "sd:x", &smax_print_depth); 164 opt = bb_getopt_ulflags(argc, argv, "sd:x", &smax_print_depth);
165 165
166 if (opt & 2) { 166 if (opt & 2) {
167 max_print_depth = bb_xgetularg10_bnd(smax_print_depth, 167 max_print_depth = atoi(smax_print_depth);
168 0, INT_MAX);
169 } 168 }
170 if(opt & 4) 169 if(opt & 4)
171 printf("Detected odd -x usaging\n"); 170 printf("Detected odd -x usaging\n");
172 171
173 "-" A minus as the first char in a bb_opt_complementally group means to 172 "-" A dash as the first char in a bb_opt_complementally group means to
174 convert the arguments as option. 173 convert the arguments as option. Next char for this case can`t set
175 For example: 174 [0-9], recomended use ':' or end of line. For example:
176 175
177 bb_opt_complementally = "-:w-x:x-w"; 176 bb_opt_complementally = "-:w-x:x-w";
178 bb_getopt_ulflags(argc, argv, "wx"); 177 bb_getopt_ulflags(argc, argv, "wx");
@@ -180,7 +179,10 @@ Special characters:
180 Allows any arguments to be given without a dash (./program w x) 179 Allows any arguments to be given without a dash (./program w x)
181 as well as with a dash (./program -x). Why unset -w see above. 180 as well as with a dash (./program -x). Why unset -w see above.
182 181
183 "~" A tilde between two options, or between an option and a group 182 "-N" A dash as the first char in a bb_opt_complementally group with
183 number 0-9 as one char is means check minimal arguments required.
184
185 "--" A double dash between two options, or between an option and a group
184 of options, means that they are mutually exclusive. Unlike 186 of options, means that they are mutually exclusive. Unlike
185 the "-" case above, an error will be forced if the options 187 the "-" case above, an error will be forced if the options
186 are used together. 188 are used together.
@@ -189,7 +191,7 @@ Special characters:
189 The cut applet must have only one type of list specified, so 191 The cut applet must have only one type of list specified, so
190 -b, -c and -f are mutally exclusive and should raise an error 192 -b, -c and -f are mutally exclusive and should raise an error
191 if specified together. In this case you must set 193 if specified together. In this case you must set
192 bb_opt_complementally = "b~cf:c~bf:f~bc". If two of the 194 bb_opt_complementally = "b--cf:c--bf:f--bc". If two of the
193 mutually exclusive options are found, bb_getopt_ulflags's 195 mutually exclusive options are found, bb_getopt_ulflags's
194 return value will have the error flag set (BB_GETOPT_ERROR) so 196 return value will have the error flag set (BB_GETOPT_ERROR) so
195 that we can check for it: 197 that we can check for it:
@@ -199,9 +201,13 @@ Special characters:
199 201
200 "?" A "ask" as the first char in a bb_opt_complementally group give: 202 "?" A "ask" as the first char in a bb_opt_complementally group give:
201 if previous point set BB_GETOPT_ERROR, don`t return and 203 if previous point set BB_GETOPT_ERROR, don`t return and
202 call previous example internally 204 call previous example internally. Next char for this case can`t
205 set to [0-9], recomended use ':' or end of line.
206
207 "?N" A "ask" as the first char in a bb_opt_complementally group with
208 number 0-9 as one char is means check maximal arguments possible.
203 209
204 "*" A star after a char in bb_opt_complementally means that the 210 "::" A double colon after a char in bb_opt_complementally means that the
205 option can occur multiple times: 211 option can occur multiple times:
206 212
207 For example: 213 For example:
@@ -213,33 +219,45 @@ Special characters:
213 (this pointer must be initializated to NULL if the list is empty 219 (this pointer must be initializated to NULL if the list is empty
214 as required by *llist_add_to(llist_t *old_head, char *new_item).) 220 as required by *llist_add_to(llist_t *old_head, char *new_item).)
215 221
216 bb_opt_complementally = "e*"; 222 bb_opt_complementally = "e::";
217 223
218 bb_getopt_ulflags(argc, argv, "e:", &patterns); 224 bb_getopt_ulflags(argc, argv, "e:", &patterns);
219 $ grep -e user -e root /etc/passwd 225 $ grep -e user -e root /etc/passwd
220 root:x:0:0:root:/root:/bin/bash 226 root:x:0:0:root:/root:/bin/bash
221 user:x:500:500::/home/user:/bin/bash 227 user:x:500:500::/home/user:/bin/bash
222 228
229 "--" A double dash as the first char in a bb_opt_complementally group
230 means make first argv[1] as option always as may be added -, special
231 for "ar" and "tar" applets.
232
223 "?" A "ask" between main and group options causes the second of the two 233 "?" A "ask" between main and group options causes the second of the two
224 to be depending required if first is given on the command line. 234 to be depending required as or if first is given on the command line.
225 For example from "id" applet: 235 For example from "id" applet:
226 236
227 // Don't allow -n -r -rn -ug -rug -nug -rnug 237 // Don't allow -n -r -rn -ug -rug -nug -rnug
228 bb_opt_complementally = "?u~g:g~u:r?ug:n?ug"; 238 bb_opt_complementally = "r?ug:n?ug:?u--g:g--u";
229 flags = bb_getopt_ulflags(argc, argv, "rnug"); 239 flags = bb_getopt_ulflags(argc, argv, "rnug");
230 240
231 This example allowed only: 241 This example allowed only:
232 $ id; id -u; id -g; id -ru; id -nu; id -rg; id -ng; id -rnu; id -rng 242 $ id; id -u; id -g; id -ru; id -nu; id -rg; id -ng; id -rnu; id -rng
233 243
234 "?" A "ask" between equivalent options in bb_opt_complementally means 244 "X" A one options in bb_opt_complementally group means
235 requires this option always, checked after switch off from 245 requires this option always with "or" logic if more one specified,
236 complementally logic 246 checked after switch off from complementally logic.
237 For example from "start-stop-daemon" applet: 247 For example from "start-stop-daemon" applet:
238 248
239 // Don't allow -KS -SK, but -S or -K required 249 // Don't allow -KS -SK, but -S or -K required
240 bb_opt_complementally = "?:K?K:S?S:K~S:S~K"; 250 bb_opt_complementally = "K:S:?K--S:S--K";
241 flags = bb_getopt_ulflags(argc, argv, "KS...); 251 flags = bb_getopt_ulflags(argc, argv, "KS...);
242 252
253
254 "x--x" give error if double or more used -x option
255
256 Don`t forget ':' store. For example "?322-22-23X-x-a" interpretet as
257 "?3:22:-2:2-2:2-3Xa:2--x": max args is 3, count -2 usaged, min args is 2,
258 -2 option triggered, unset -3 and -X and -a if -2 any usaged, give error if
259 after -2 the -x option usaged.
260
243*/ 261*/
244 262
245const char *bb_opt_complementally; 263const char *bb_opt_complementally;
@@ -277,22 +295,25 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...)
277 const struct option *l_o; 295 const struct option *l_o;
278 unsigned long trigger; 296 unsigned long trigger;
279 char **pargv = NULL; 297 char **pargv = NULL;
298 int min_arg = 0;
299 int max_arg = -1;
280 300
281#define SHOW_USAGE_IF_ERROR 1 301#define SHOW_USAGE_IF_ERROR 1
282#define ARGV_IS_OPTS 2 302#define ALL_ARGV_IS_OPTS 2
303#define FIRST_ARGV_IS_OPT 4
304#define FREE_FIRST_ARGV_IS_OPT 8
283 int spec_flgs = 0; 305 int spec_flgs = 0;
284 306
285 va_start (p, applet_opts); 307 va_start (p, applet_opts);
286 308
287 /* skip GNU extension */
288 s = applet_opts;
289 if(*s == '+' || *s == '-')
290 s++;
291
292 c = 0; 309 c = 0;
293 on_off = complementally; 310 on_off = complementally;
294 memset(on_off, 0, sizeof(complementally)); 311 memset(on_off, 0, sizeof(complementally));
295 312
313 /* skip GNU extension */
314 s = applet_opts;
315 if(*s == '+' || *s == '-')
316 s++;
296 for (; *s; s++) { 317 for (; *s; s++) {
297 if(c >= (int)(sizeof(flags)*8)) 318 if(c >= (int)(sizeof(flags)*8))
298 break; 319 break;
@@ -324,68 +345,86 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...)
324 c++; 345 c++;
325 } 346 }
326 } 347 }
327 c = 0;
328 for (s = bb_opt_complementally; s && *s; s++) { 348 for (s = bb_opt_complementally; s && *s; s++) {
329 t_complementally *pair; 349 t_complementally *pair;
350 unsigned long *pair_switch;
330 351
331 if (*s == ':') { 352 if (*s == ':')
332 c = 0;
333 continue;
334 }
335 if (c)
336 continue; 353 continue;
354 c = s[1];
337 if(*s == '?') { 355 if(*s == '?') {
338 spec_flgs |= SHOW_USAGE_IF_ERROR; 356 if(c < '0' || c > '9') {
357 spec_flgs |= SHOW_USAGE_IF_ERROR;
358 } else {
359 max_arg = c - '0';
360 s++;
361 }
339 continue; 362 continue;
340 } 363 }
341 if(*s == '-') { 364 if(*s == '-') {
342 spec_flgs |= ARGV_IS_OPTS; 365 if(c < '0' || c > '9') {
366 if(c == '-') {
367 spec_flgs |= FIRST_ARGV_IS_OPT;
368 s++;
369 } else
370 spec_flgs |= ALL_ARGV_IS_OPTS;
371 } else {
372 min_arg = c - '0';
373 s++;
374 }
343 continue; 375 continue;
344 } 376 }
345 for (on_off = complementally; on_off->opt; on_off++) 377 for (on_off = complementally; on_off->opt; on_off++)
346 if (on_off->opt == *s) 378 if (on_off->opt == *s)
347 break; 379 break;
380 if(c == ':' && s[2] == ':') {
381 on_off->list_flg++;
382 continue;
383 }
384 if(c == ':' || c == '\0') {
385 requires |= on_off->switch_on;
386 continue;
387 }
388 if(c == *s) {
389 on_off->counter = va_arg (p, int *);
390 s++;
391 }
348 pair = on_off; 392 pair = on_off;
393 pair_switch = &(pair->switch_on);
349 for(s++; *s && *s != ':'; s++) { 394 for(s++; *s && *s != ':'; s++) {
350 if (*s == '-' || *s == '~' || *s == '?') { 395 if(*s == '?') {
351 c = *s; 396 pair_switch = &(pair->requires);
352 } else if(*s == '*') { 397 } else if (*s == '-') {
353 pair->list_flg++; 398 if(pair_switch == &(pair->switch_off))
354 } else {
355 unsigned long *pair_switch;
356
357 switch(c) {
358 case '-':
359 pair_switch = &(pair->switch_off);
360 break;
361 case '~':
362 pair_switch = &(pair->incongruously); 399 pair_switch = &(pair->incongruously);
363 break; 400 else
364 case '?': 401 pair_switch = &(pair->switch_off);
365 pair_switch = &(pair->requires); 402 } else {
366 break;
367 default:
368 pair_switch = &(pair->switch_on);
369 }
370 for (on_off = complementally; on_off->opt; on_off++) 403 for (on_off = complementally; on_off->opt; on_off++)
371 if (on_off->opt == *s) { 404 if (on_off->opt == *s) {
372 if(pair_switch == &(on_off->switch_on)) 405 *pair_switch |= on_off->switch_on;
373 on_off->counter = va_arg (p, int *);
374 else if(pair_switch == &(on_off->requires))
375 requires |= on_off->switch_on;
376 else
377 *pair_switch |= on_off->switch_on;
378 break; 406 break;
379 } 407 }
380 } 408 }
381 } 409 }
382 s--; 410 s--;
383 } 411 }
384 412 va_end (p);
413
414#if defined(CONFIG_AR) || defined(CONFIG_TAR)
415 if((spec_flgs & FIRST_ARGV_IS_OPT)) {
416 if(argv[1] && argv[1][0] != '-' && argv[1][0] != '\0') {
417 argv[1] = bb_xasprintf("-%s", argv[1]);
418 if(ENABLE_FEATURE_CLEAN_UP)
419 spec_flgs |= FREE_FIRST_ARGV_IS_OPT;
420 }
421 }
422#endif
385 while ((c = getopt_long (argc, argv, applet_opts, 423 while ((c = getopt_long (argc, argv, applet_opts,
386 bb_applet_long_options, NULL)) >= 0) { 424 bb_applet_long_options, NULL)) >= 0) {
387 425#ifdef CONFIG_PS
388loop_arg_is_opt: 426loop_arg_is_opt:
427#endif
389 for (on_off = complementally; on_off->opt != c; on_off++) { 428 for (on_off = complementally; on_off->opt != c; on_off++) {
390 /* c==0 if long opt have non NULL flag */ 429 /* c==0 if long opt have non NULL flag */
391 if(on_off->opt == 0 && c != 0) 430 if(on_off->opt == 0 && c != 0)
@@ -408,10 +447,14 @@ loop_arg_is_opt:
408 } else if (on_off->optarg) { 447 } else if (on_off->optarg) {
409 *(char **)(on_off->optarg) = optarg; 448 *(char **)(on_off->optarg) = optarg;
410 } 449 }
450#ifdef CONFIG_PS
411 if(pargv != NULL) 451 if(pargv != NULL)
412 break; 452 break;
453#endif
413 } 454 }
414 if((spec_flgs & ARGV_IS_OPTS)) { 455
456#ifdef CONFIG_PS
457 if((spec_flgs & ALL_ARGV_IS_OPTS)) {
415 /* process argv is option, for example "ps" applet */ 458 /* process argv is option, for example "ps" applet */
416 if(pargv == NULL) 459 if(pargv == NULL)
417 pargv = argv + optind; 460 pargv = argv + optind;
@@ -425,6 +468,13 @@ loop_arg_is_opt:
425 } 468 }
426 } 469 }
427 } 470 }
471#endif
472
473#if (defined(CONFIG_AR) || defined(CONFIG_TAR)) && \
474 defined(CONFIG_FEATURE_CLEAN_UP)
475 if((spec_flgs & FREE_FIRST_ARGV_IS_OPT))
476 free(argv[1]);
477#endif
428 /* check depending requires for given options */ 478 /* check depending requires for given options */
429 for (on_off = complementally; on_off->opt; on_off++) { 479 for (on_off = complementally; on_off->opt; on_off++) {
430 if(on_off->requires && (flags & on_off->switch_on) && 480 if(on_off->requires && (flags & on_off->switch_on) &&
@@ -433,5 +483,8 @@ loop_arg_is_opt:
433 } 483 }
434 if(requires && (flags & requires) == 0) 484 if(requires && (flags & requires) == 0)
435 bb_show_usage (); 485 bb_show_usage ();
486 argc -= optind;
487 if(argc < min_arg || (max_arg >= 0 && argc > max_arg))
488 bb_show_usage ();
436 return flags; 489 return flags;
437} 490}