diff options
| author | "Vladimir N. Oleynik" <dzo@simtreas.ru> | 2005-10-11 14:38:01 +0000 |
|---|---|---|
| committer | "Vladimir N. Oleynik" <dzo@simtreas.ru> | 2005-10-11 14:38:01 +0000 |
| commit | 064f04e7e2b1316f7c3de1ac7dd1fc4d4e108dd5 (patch) | |
| tree | dcf88d0a287b1f154984bfc0acb292631df2f1f3 /libbb | |
| parent | ff567f7943f50b88dea14cd27636168ba2d319b5 (diff) | |
| download | busybox-w32-064f04e7e2b1316f7c3de1ac7dd1fc4d4e108dd5.tar.gz busybox-w32-064f04e7e2b1316f7c3de1ac7dd1fc4d4e108dd5.tar.bz2 busybox-w32-064f04e7e2b1316f7c3de1ac7dd1fc4d4e108dd5.zip | |
- use complementally '!' to '?' - 'ask' is best 'free' char for this.
- more long opt compatibility, can set flag for long opt struct now
- more logic: check opt-depend requires and global requires, special for 'id' and 'start-stop-daemon' applets.
Diffstat (limited to 'libbb')
| -rw-r--r-- | libbb/getopt_ulflags.c | 108 |
1 files changed, 72 insertions, 36 deletions
diff --git a/libbb/getopt_ulflags.c b/libbb/getopt_ulflags.c index 2e2ee0b6b..5f35c583c 100644 --- a/libbb/getopt_ulflags.c +++ b/libbb/getopt_ulflags.c | |||
| @@ -197,8 +197,9 @@ Special characters: | |||
| 197 | if (flags & BB_GETOPT_ERROR) | 197 | if (flags & BB_GETOPT_ERROR) |
| 198 | bb_show_usage(); | 198 | bb_show_usage(); |
| 199 | 199 | ||
| 200 | "!" If previous point set BB_GETOPT_ERROR, don`t return and call | 200 | "?" A "ask" as the first char in a bb_opt_complementally group give: |
| 201 | previous example internally | 201 | if previous point set BB_GETOPT_ERROR, don`t return and |
| 202 | call previous example internally | ||
| 202 | 203 | ||
| 203 | "*" A star after a char in bb_opt_complementally means that the | 204 | "*" A star after a char in bb_opt_complementally means that the |
| 204 | option can occur multiple times: | 205 | option can occur multiple times: |
| @@ -218,16 +219,38 @@ Special characters: | |||
| 218 | $ grep -e user -e root /etc/passwd | 219 | $ grep -e user -e root /etc/passwd |
| 219 | root:x:0:0:root:/root:/bin/bash | 220 | root:x:0:0:root:/root:/bin/bash |
| 220 | user:x:500:500::/home/user:/bin/bash | 221 | user:x:500:500::/home/user:/bin/bash |
| 222 | |||
| 223 | "?" 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. | ||
| 225 | For example from "id" applet: | ||
| 226 | |||
| 227 | // Don't allow -n -r -rn -ug -rug -nug -rnug | ||
| 228 | bb_opt_complementally = "?u~g:g~u:r?ug:n?ug"; | ||
| 229 | flags = bb_getopt_ulflags(argc, argv, "rnug"); | ||
| 230 | |||
| 231 | This example allowed only: | ||
| 232 | $ id; id -u; id -g; id -ru; id -nu; id -rg; id -ng; id -rnu; id -rng | ||
| 233 | |||
| 234 | "?" A "ask" between equivalent options in bb_opt_complementally means | ||
| 235 | requires this option always, checked after switch off from | ||
| 236 | complementally logic | ||
| 237 | For example from "start-stop-daemon" applet: | ||
| 238 | |||
| 239 | // Don't allow -KS -SK, but -S or -K required | ||
| 240 | bb_opt_complementally = "?:K?K:S?S:K~S:S~K"; | ||
| 241 | flags = bb_getopt_ulflags(argc, argv, "KS...); | ||
| 242 | |||
| 221 | */ | 243 | */ |
| 222 | 244 | ||
| 223 | const char *bb_opt_complementally; | 245 | const char *bb_opt_complementally; |
| 224 | 246 | ||
| 225 | typedef struct { | 247 | typedef struct { |
| 226 | unsigned char opt; | 248 | int opt; |
| 227 | char list_flg; | 249 | int list_flg; |
| 228 | unsigned long switch_on; | 250 | unsigned long switch_on; |
| 229 | unsigned long switch_off; | 251 | unsigned long switch_off; |
| 230 | unsigned long incongruously; | 252 | unsigned long incongruously; |
| 253 | unsigned long requires; | ||
| 231 | void **optarg; /* char **optarg or llist_t **optarg */ | 254 | void **optarg; /* char **optarg or llist_t **optarg */ |
| 232 | int *counter; | 255 | int *counter; |
| 233 | } t_complementally; | 256 | } t_complementally; |
| @@ -245,17 +268,20 @@ unsigned long | |||
| 245 | bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) | 268 | bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) |
| 246 | { | 269 | { |
| 247 | unsigned long flags = 0; | 270 | unsigned long flags = 0; |
| 271 | unsigned long requires = 0; | ||
| 248 | t_complementally complementally[sizeof(flags) * 8 + 1]; | 272 | t_complementally complementally[sizeof(flags) * 8 + 1]; |
| 249 | int c; | 273 | int c; |
| 250 | const unsigned char *s; | 274 | const unsigned char *s; |
| 251 | t_complementally *on_off; | 275 | t_complementally *on_off; |
| 252 | va_list p; | 276 | va_list p; |
| 253 | const struct option *l_o; | 277 | const struct option *l_o; |
| 254 | char flg_show_usage_if_error = 0; | ||
| 255 | char flg_argv_is_opts = 0; | ||
| 256 | unsigned long trigger; | 278 | unsigned long trigger; |
| 257 | char **pargv = NULL; | 279 | char **pargv = NULL; |
| 258 | 280 | ||
| 281 | #define SHOW_USAGE_IF_ERROR 1 | ||
| 282 | #define ARGV_IS_OPTS 2 | ||
| 283 | int spec_flgs = 0; | ||
| 284 | |||
| 259 | va_start (p, applet_opts); | 285 | va_start (p, applet_opts); |
| 260 | 286 | ||
| 261 | /* skip GNU extension */ | 287 | /* skip GNU extension */ |
| @@ -265,16 +291,13 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) | |||
| 265 | 291 | ||
| 266 | c = 0; | 292 | c = 0; |
| 267 | on_off = complementally; | 293 | on_off = complementally; |
| 294 | memset(on_off, 0, sizeof(complementally)); | ||
| 295 | |||
| 268 | for (; *s; s++) { | 296 | for (; *s; s++) { |
| 269 | if(c >= (int)(sizeof(flags)*8)) | 297 | if(c >= (int)(sizeof(flags)*8)) |
| 270 | break; | 298 | break; |
| 271 | on_off->opt = *s; | 299 | on_off->opt = *s; |
| 272 | on_off->switch_on = (1 << c); | 300 | on_off->switch_on = (1 << c); |
| 273 | on_off->list_flg = 0; | ||
| 274 | on_off->switch_off = 0; | ||
| 275 | on_off->incongruously = 0; | ||
| 276 | on_off->optarg = NULL; | ||
| 277 | on_off->counter = NULL; | ||
| 278 | if (s[1] == ':') { | 301 | if (s[1] == ':') { |
| 279 | on_off->optarg = va_arg (p, void **); | 302 | on_off->optarg = va_arg (p, void **); |
| 280 | do | 303 | do |
| @@ -284,9 +307,10 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) | |||
| 284 | on_off++; | 307 | on_off++; |
| 285 | c++; | 308 | c++; |
| 286 | } | 309 | } |
| 287 | on_off->opt = 0; | ||
| 288 | 310 | ||
| 289 | for(l_o = bb_applet_long_options; l_o->name; l_o++) { | 311 | for(l_o = bb_applet_long_options; l_o->name; l_o++) { |
| 312 | if(l_o->flag) | ||
| 313 | continue; | ||
| 290 | for(on_off = complementally; on_off->opt != 0; on_off++) | 314 | for(on_off = complementally; on_off->opt != 0; on_off++) |
| 291 | if(on_off->opt == l_o->val) | 315 | if(on_off->opt == l_o->val) |
| 292 | break; | 316 | break; |
| @@ -295,16 +319,8 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) | |||
| 295 | break; | 319 | break; |
| 296 | on_off->opt = l_o->val; | 320 | on_off->opt = l_o->val; |
| 297 | on_off->switch_on = (1 << c); | 321 | on_off->switch_on = (1 << c); |
| 298 | on_off->list_flg = 0; | ||
| 299 | on_off->switch_off = 0; | ||
| 300 | on_off->incongruously = 0; | ||
| 301 | on_off->counter = NULL; | ||
| 302 | if(l_o->has_arg != no_argument) | 322 | if(l_o->has_arg != no_argument) |
| 303 | on_off->optarg = va_arg (p, void **); | 323 | on_off->optarg = va_arg (p, void **); |
| 304 | else | ||
| 305 | on_off->optarg = NULL; | ||
| 306 | on_off++; | ||
| 307 | on_off->opt = 0; | ||
| 308 | c++; | 324 | c++; |
| 309 | } | 325 | } |
| 310 | } | 326 | } |
| @@ -318,12 +334,12 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) | |||
| 318 | } | 334 | } |
| 319 | if (c) | 335 | if (c) |
| 320 | continue; | 336 | continue; |
| 321 | if(*s == '!') { | 337 | if(*s == '?') { |
| 322 | flg_show_usage_if_error = '!'; | 338 | spec_flgs |= SHOW_USAGE_IF_ERROR; |
| 323 | continue; | 339 | continue; |
| 324 | } | 340 | } |
| 325 | if(*s == '-') { | 341 | if(*s == '-') { |
| 326 | flg_argv_is_opts = '-'; | 342 | spec_flgs |= ARGV_IS_OPTS; |
| 327 | continue; | 343 | continue; |
| 328 | } | 344 | } |
| 329 | for (on_off = complementally; on_off->opt; on_off++) | 345 | for (on_off = complementally; on_off->opt; on_off++) |
| @@ -331,18 +347,32 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) | |||
| 331 | break; | 347 | break; |
| 332 | pair = on_off; | 348 | pair = on_off; |
| 333 | for(s++; *s && *s != ':'; s++) { | 349 | for(s++; *s && *s != ':'; s++) { |
| 334 | if (*s == '-' || *s == '~') { | 350 | if (*s == '-' || *s == '~' || *s == '?') { |
| 335 | c = *s; | 351 | c = *s; |
| 336 | } else if(*s == '*') { | 352 | } else if(*s == '*') { |
| 337 | pair->list_flg++; | 353 | pair->list_flg++; |
| 338 | } else { | 354 | } else { |
| 339 | unsigned long *pair_switch = &(pair->switch_on); | 355 | unsigned long *pair_switch; |
| 340 | if(c) | 356 | |
| 341 | pair_switch = c == '-' ? &(pair->switch_off) : &(pair->incongruously); | 357 | switch(c) { |
| 358 | case '-': | ||
| 359 | pair_switch = &(pair->switch_off); | ||
| 360 | break; | ||
| 361 | case '~': | ||
| 362 | pair_switch = &(pair->incongruously); | ||
| 363 | break; | ||
| 364 | case '?': | ||
| 365 | pair_switch = &(pair->requires); | ||
| 366 | break; | ||
| 367 | default: | ||
| 368 | pair_switch = &(pair->switch_on); | ||
| 369 | } | ||
| 342 | for (on_off = complementally; on_off->opt; on_off++) | 370 | for (on_off = complementally; on_off->opt; on_off++) |
| 343 | if (on_off->opt == *s) { | 371 | if (on_off->opt == *s) { |
| 344 | if(pair_switch == &(on_off->switch_on)) | 372 | if(pair_switch == &(on_off->switch_on)) |
| 345 | on_off->counter = va_arg (p, int *); | 373 | on_off->counter = va_arg (p, int *); |
| 374 | else if(pair_switch == &(on_off->requires)) | ||
| 375 | requires |= on_off->switch_on; | ||
| 346 | else | 376 | else |
| 347 | *pair_switch |= on_off->switch_on; | 377 | *pair_switch |= on_off->switch_on; |
| 348 | break; | 378 | break; |
| @@ -353,15 +383,16 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) | |||
| 353 | } | 383 | } |
| 354 | 384 | ||
| 355 | while ((c = getopt_long (argc, argv, applet_opts, | 385 | while ((c = getopt_long (argc, argv, applet_opts, |
| 356 | bb_applet_long_options, NULL)) > 0) { | 386 | bb_applet_long_options, NULL)) >= 0) { |
| 357 | 387 | ||
| 358 | loop_arg_is_opt: | 388 | loop_arg_is_opt: |
| 359 | for (on_off = complementally; on_off->opt != c; on_off++) { | 389 | for (on_off = complementally; on_off->opt != c; on_off++) { |
| 360 | if(!on_off->opt) | 390 | /* c==0 if long opt have non NULL flag */ |
| 391 | if(on_off->opt == 0 && c != 0) | ||
| 361 | bb_show_usage (); | 392 | bb_show_usage (); |
| 362 | } | 393 | } |
| 363 | if(flags & on_off->incongruously) { | 394 | if(flags & on_off->incongruously) { |
| 364 | if(flg_show_usage_if_error) | 395 | if((spec_flgs & SHOW_USAGE_IF_ERROR)) |
| 365 | bb_show_usage (); | 396 | bb_show_usage (); |
| 366 | flags |= BB_GETOPT_ERROR; | 397 | flags |= BB_GETOPT_ERROR; |
| 367 | } | 398 | } |
| @@ -377,15 +408,13 @@ loop_arg_is_opt: | |||
| 377 | } else if (on_off->optarg) { | 408 | } else if (on_off->optarg) { |
| 378 | *(char **)(on_off->optarg) = optarg; | 409 | *(char **)(on_off->optarg) = optarg; |
| 379 | } | 410 | } |
| 380 | if(flg_argv_is_opts == 'p') | 411 | if(pargv != NULL) |
| 381 | break; | 412 | break; |
| 382 | } | 413 | } |
| 383 | if(flg_argv_is_opts) { | 414 | if((spec_flgs & ARGV_IS_OPTS)) { |
| 384 | /* process argv is option, for example "ps" applet */ | 415 | /* process argv is option, for example "ps" applet */ |
| 385 | if(flg_argv_is_opts == '-') { | 416 | if(pargv == NULL) |
| 386 | flg_argv_is_opts = 'p'; | ||
| 387 | pargv = argv + optind; | 417 | pargv = argv + optind; |
| 388 | } | ||
| 389 | while(*pargv) { | 418 | while(*pargv) { |
| 390 | c = **pargv; | 419 | c = **pargv; |
| 391 | if(c == '\0') { | 420 | if(c == '\0') { |
| @@ -396,6 +425,13 @@ loop_arg_is_opt: | |||
| 396 | } | 425 | } |
| 397 | } | 426 | } |
| 398 | } | 427 | } |
| 399 | 428 | /* check depending requires for given options */ | |
| 429 | for (on_off = complementally; on_off->opt; on_off++) { | ||
| 430 | if(on_off->requires && (flags & on_off->switch_on) && | ||
| 431 | (flags & on_off->requires) == 0) | ||
| 432 | bb_show_usage (); | ||
| 433 | } | ||
| 434 | if(requires && (flags & requires) == 0) | ||
| 435 | bb_show_usage (); | ||
| 400 | return flags; | 436 | return flags; |
| 401 | } | 437 | } |
