aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-26 23:22:40 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-26 23:22:40 +0000
commit28e67966f3fc0728fb2f923265a8b2275f410655 (patch)
tree0c522b97ed681180f68d028094bd02b89b292b49
parent572930027d5d86a18ebd68d5f4273150a2f302e1 (diff)
downloadbusybox-w32-28e67966f3fc0728fb2f923265a8b2275f410655.tar.gz
busybox-w32-28e67966f3fc0728fb2f923265a8b2275f410655.tar.bz2
busybox-w32-28e67966f3fc0728fb2f923265a8b2275f410655.zip
hush: make getopt32 usable in builtins. use it in unset.
more uses are expected in the future. function old new delta getopt32 1356 1393 +37 builtin_export 256 266 +10 builtin_unset 418 380 -38
-rw-r--r--libbb/getopt32.c31
-rw-r--r--shell/hush.c42
-rw-r--r--shell/hush_test/hush-vars/unset.right5
3 files changed, 42 insertions, 36 deletions
diff --git a/libbb/getopt32.c b/libbb/getopt32.c
index 5190fa61a..1eb868c97 100644
--- a/libbb/getopt32.c
+++ b/libbb/getopt32.c
@@ -72,6 +72,9 @@ getopt32(char **argv, const char *applet_opts, ...)
72 env -i ls -d / 72 env -i ls -d /
73 Here we want env to process just the '-i', not the '-d'. 73 Here we want env to process just the '-i', not the '-d'.
74 74
75 "!" Report bad option, missing required options,
76 inconsistent options with all-ones return value (instead of abort).
77
75const char *applet_long_options 78const char *applet_long_options
76 79
77 This struct allows you to define long options: 80 This struct allows you to define long options:
@@ -327,6 +330,7 @@ getopt32(char **argv, const char *applet_opts, ...)
327 unsigned flags = 0; 330 unsigned flags = 0;
328 unsigned requires = 0; 331 unsigned requires = 0;
329 t_complementary complementary[33]; /* last stays zero-filled */ 332 t_complementary complementary[33]; /* last stays zero-filled */
333 char first_char;
330 int c; 334 int c;
331 const unsigned char *s; 335 const unsigned char *s;
332 t_complementary *on_off; 336 t_complementary *on_off;
@@ -357,6 +361,11 @@ getopt32(char **argv, const char *applet_opts, ...)
357 on_off = complementary; 361 on_off = complementary;
358 memset(on_off, 0, sizeof(complementary)); 362 memset(on_off, 0, sizeof(complementary));
359 363
364 /* skip bbox extension */
365 first_char = applet_opts[0];
366 if (first_char == '!')
367 applet_opts++;
368
360 /* skip GNU extension */ 369 /* skip GNU extension */
361 s = (const unsigned char *)applet_opts; 370 s = (const unsigned char *)applet_opts;
362 if (*s == '+' || *s == '-') 371 if (*s == '+' || *s == '-')
@@ -549,11 +558,11 @@ getopt32(char **argv, const char *applet_opts, ...)
549 * is always NULL (see above) */ 558 * is always NULL (see above) */
550 if (on_off->opt_char == '\0' /* && c != '\0' */) { 559 if (on_off->opt_char == '\0' /* && c != '\0' */) {
551 /* c is probably '?' - "bad option" */ 560 /* c is probably '?' - "bad option" */
552 bb_show_usage(); 561 goto error;
553 } 562 }
554 } 563 }
555 if (flags & on_off->incongruously) 564 if (flags & on_off->incongruously)
556 bb_show_usage(); 565 goto error;
557 trigger = on_off->switch_on & on_off->switch_off; 566 trigger = on_off->switch_on & on_off->switch_off;
558 flags &= ~(on_off->switch_off ^ trigger); 567 flags &= ~(on_off->switch_off ^ trigger);
559 flags |= on_off->switch_on ^ trigger; 568 flags |= on_off->switch_on ^ trigger;
@@ -577,16 +586,24 @@ getopt32(char **argv, const char *applet_opts, ...)
577 586
578 /* check depending requires for given options */ 587 /* check depending requires for given options */
579 for (on_off = complementary; on_off->opt_char; on_off++) { 588 for (on_off = complementary; on_off->opt_char; on_off++) {
580 if (on_off->requires && (flags & on_off->switch_on) && 589 if (on_off->requires
581 (flags & on_off->requires) == 0) 590 && (flags & on_off->switch_on)
582 bb_show_usage(); 591 && (flags & on_off->requires) == 0
592 ) {
593 goto error;
594 }
583 } 595 }
584 if (requires && (flags & requires) == 0) 596 if (requires && (flags & requires) == 0)
585 bb_show_usage(); 597 goto error;
586 argc -= optind; 598 argc -= optind;
587 if (argc < min_arg || (max_arg >= 0 && argc > max_arg)) 599 if (argc < min_arg || (max_arg >= 0 && argc > max_arg))
588 bb_show_usage(); 600 goto error;
589 601
590 option_mask32 = flags; 602 option_mask32 = flags;
591 return flags; 603 return flags;
604
605 error:
606 if (first_char != '!')
607 bb_show_usage();
608 return (int32_t)-1;
592} 609}
diff --git a/shell/hush.c b/shell/hush.c
index 292b8b2e3..d0819f691 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -6451,7 +6451,11 @@ static int builtin_export(char **argv)
6451 } 6451 }
6452 6452
6453#if ENABLE_HUSH_EXPORT_N 6453#if ENABLE_HUSH_EXPORT_N
6454 opt_unexport = getopt32(argv, "+n"); /* "+": stop at 1st non-option */ 6454 /* "!": do not abort on errors */
6455 /* "+": stop at 1st non-option */
6456 opt_unexport = getopt32(argv, "!+n");
6457 if (opt_unexport == (unsigned)-1)
6458 return EXIT_FAILURE;
6455 argv += optind; 6459 argv += optind;
6456#else 6460#else
6457 opt_unexport = 0; 6461 opt_unexport = 0;
@@ -6918,36 +6922,22 @@ static int builtin_umask(char **argv)
6918static int builtin_unset(char **argv) 6922static int builtin_unset(char **argv)
6919{ 6923{
6920 int ret; 6924 int ret;
6921 char var; 6925 unsigned opts;
6922 char *arg;
6923
6924 if (!*++argv)
6925 return EXIT_SUCCESS;
6926 6926
6927 var = 0; 6927 /* "!": do not abort on errors */
6928 while ((arg = *argv) != NULL && arg[0] == '-') { 6928 /* "+": stop at 1st non-option */
6929 arg++; 6929 opts = getopt32(argv, "!+vf");
6930 do { 6930 if (opts == (unsigned)-1)
6931 switch (*arg) { 6931 return EXIT_FAILURE;
6932 case 'v': 6932 if (opts == 3) {
6933 case 'f': 6933 bb_error_msg("unset: -v and -f are exclusive");
6934 if (var == 0 || var == *arg) { 6934 return EXIT_FAILURE;
6935 var = *arg;
6936 break;
6937 }
6938 /* else: unset -vf, which is illegal.
6939 * fall through */
6940 default:
6941 bb_error_msg("unset: %s: invalid option", *argv);
6942 return EXIT_FAILURE;
6943 }
6944 } while (*++arg);
6945 argv++;
6946 } 6935 }
6936 argv += optind;
6947 6937
6948 ret = EXIT_SUCCESS; 6938 ret = EXIT_SUCCESS;
6949 while (*argv) { 6939 while (*argv) {
6950 if (var != 'f') { 6940 if (!(opts & 2)) { /* not -f */
6951 if (unset_local_var(*argv)) { 6941 if (unset_local_var(*argv)) {
6952 /* unset <nonexistent_var> doesn't fail. 6942 /* unset <nonexistent_var> doesn't fail.
6953 * Error is when one tries to unset RO var. 6943 * Error is when one tries to unset RO var.
diff --git a/shell/hush_test/hush-vars/unset.right b/shell/hush_test/hush-vars/unset.right
index 8dea7c40d..1fbe76a73 100644
--- a/shell/hush_test/hush-vars/unset.right
+++ b/shell/hush_test/hush-vars/unset.right
@@ -1,6 +1,5 @@
1hush: unset: -: invalid option 10
21 2unset: invalid option -- m
3hush: unset: -m: invalid option
41 31
50 40
6___ 5___