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
This commit is contained in:
parent
572930027d
commit
28e67966f3
@ -72,6 +72,9 @@ getopt32(char **argv, const char *applet_opts, ...)
|
|||||||
env -i ls -d /
|
env -i ls -d /
|
||||||
Here we want env to process just the '-i', not the '-d'.
|
Here we want env to process just the '-i', not the '-d'.
|
||||||
|
|
||||||
|
"!" Report bad option, missing required options,
|
||||||
|
inconsistent options with all-ones return value (instead of abort).
|
||||||
|
|
||||||
const char *applet_long_options
|
const char *applet_long_options
|
||||||
|
|
||||||
This struct allows you to define long options:
|
This struct allows you to define long options:
|
||||||
@ -327,6 +330,7 @@ getopt32(char **argv, const char *applet_opts, ...)
|
|||||||
unsigned flags = 0;
|
unsigned flags = 0;
|
||||||
unsigned requires = 0;
|
unsigned requires = 0;
|
||||||
t_complementary complementary[33]; /* last stays zero-filled */
|
t_complementary complementary[33]; /* last stays zero-filled */
|
||||||
|
char first_char;
|
||||||
int c;
|
int c;
|
||||||
const unsigned char *s;
|
const unsigned char *s;
|
||||||
t_complementary *on_off;
|
t_complementary *on_off;
|
||||||
@ -357,6 +361,11 @@ getopt32(char **argv, const char *applet_opts, ...)
|
|||||||
on_off = complementary;
|
on_off = complementary;
|
||||||
memset(on_off, 0, sizeof(complementary));
|
memset(on_off, 0, sizeof(complementary));
|
||||||
|
|
||||||
|
/* skip bbox extension */
|
||||||
|
first_char = applet_opts[0];
|
||||||
|
if (first_char == '!')
|
||||||
|
applet_opts++;
|
||||||
|
|
||||||
/* skip GNU extension */
|
/* skip GNU extension */
|
||||||
s = (const unsigned char *)applet_opts;
|
s = (const unsigned char *)applet_opts;
|
||||||
if (*s == '+' || *s == '-')
|
if (*s == '+' || *s == '-')
|
||||||
@ -549,11 +558,11 @@ getopt32(char **argv, const char *applet_opts, ...)
|
|||||||
* is always NULL (see above) */
|
* is always NULL (see above) */
|
||||||
if (on_off->opt_char == '\0' /* && c != '\0' */) {
|
if (on_off->opt_char == '\0' /* && c != '\0' */) {
|
||||||
/* c is probably '?' - "bad option" */
|
/* c is probably '?' - "bad option" */
|
||||||
bb_show_usage();
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (flags & on_off->incongruously)
|
if (flags & on_off->incongruously)
|
||||||
bb_show_usage();
|
goto error;
|
||||||
trigger = on_off->switch_on & on_off->switch_off;
|
trigger = on_off->switch_on & on_off->switch_off;
|
||||||
flags &= ~(on_off->switch_off ^ trigger);
|
flags &= ~(on_off->switch_off ^ trigger);
|
||||||
flags |= on_off->switch_on ^ trigger;
|
flags |= on_off->switch_on ^ trigger;
|
||||||
@ -577,16 +586,24 @@ getopt32(char **argv, const char *applet_opts, ...)
|
|||||||
|
|
||||||
/* check depending requires for given options */
|
/* check depending requires for given options */
|
||||||
for (on_off = complementary; on_off->opt_char; on_off++) {
|
for (on_off = complementary; on_off->opt_char; on_off++) {
|
||||||
if (on_off->requires && (flags & on_off->switch_on) &&
|
if (on_off->requires
|
||||||
(flags & on_off->requires) == 0)
|
&& (flags & on_off->switch_on)
|
||||||
bb_show_usage();
|
&& (flags & on_off->requires) == 0
|
||||||
|
) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (requires && (flags & requires) == 0)
|
if (requires && (flags & requires) == 0)
|
||||||
bb_show_usage();
|
goto error;
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
if (argc < min_arg || (max_arg >= 0 && argc > max_arg))
|
if (argc < min_arg || (max_arg >= 0 && argc > max_arg))
|
||||||
bb_show_usage();
|
goto error;
|
||||||
|
|
||||||
option_mask32 = flags;
|
option_mask32 = flags;
|
||||||
return flags;
|
return flags;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (first_char != '!')
|
||||||
|
bb_show_usage();
|
||||||
|
return (int32_t)-1;
|
||||||
}
|
}
|
||||||
|
42
shell/hush.c
42
shell/hush.c
@ -6451,7 +6451,11 @@ static int builtin_export(char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_HUSH_EXPORT_N
|
#if ENABLE_HUSH_EXPORT_N
|
||||||
opt_unexport = getopt32(argv, "+n"); /* "+": stop at 1st non-option */
|
/* "!": do not abort on errors */
|
||||||
|
/* "+": stop at 1st non-option */
|
||||||
|
opt_unexport = getopt32(argv, "!+n");
|
||||||
|
if (opt_unexport == (unsigned)-1)
|
||||||
|
return EXIT_FAILURE;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
#else
|
#else
|
||||||
opt_unexport = 0;
|
opt_unexport = 0;
|
||||||
@ -6918,36 +6922,22 @@ static int builtin_umask(char **argv)
|
|||||||
static int builtin_unset(char **argv)
|
static int builtin_unset(char **argv)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char var;
|
unsigned opts;
|
||||||
char *arg;
|
|
||||||
|
|
||||||
if (!*++argv)
|
/* "!": do not abort on errors */
|
||||||
return EXIT_SUCCESS;
|
/* "+": stop at 1st non-option */
|
||||||
|
opts = getopt32(argv, "!+vf");
|
||||||
var = 0;
|
if (opts == (unsigned)-1)
|
||||||
while ((arg = *argv) != NULL && arg[0] == '-') {
|
return EXIT_FAILURE;
|
||||||
arg++;
|
if (opts == 3) {
|
||||||
do {
|
bb_error_msg("unset: -v and -f are exclusive");
|
||||||
switch (*arg) {
|
return EXIT_FAILURE;
|
||||||
case 'v':
|
|
||||||
case 'f':
|
|
||||||
if (var == 0 || var == *arg) {
|
|
||||||
var = *arg;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* else: unset -vf, which is illegal.
|
|
||||||
* fall through */
|
|
||||||
default:
|
|
||||||
bb_error_msg("unset: %s: invalid option", *argv);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
} while (*++arg);
|
|
||||||
argv++;
|
|
||||||
}
|
}
|
||||||
|
argv += optind;
|
||||||
|
|
||||||
ret = EXIT_SUCCESS;
|
ret = EXIT_SUCCESS;
|
||||||
while (*argv) {
|
while (*argv) {
|
||||||
if (var != 'f') {
|
if (!(opts & 2)) { /* not -f */
|
||||||
if (unset_local_var(*argv)) {
|
if (unset_local_var(*argv)) {
|
||||||
/* unset <nonexistent_var> doesn't fail.
|
/* unset <nonexistent_var> doesn't fail.
|
||||||
* Error is when one tries to unset RO var.
|
* Error is when one tries to unset RO var.
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
hush: unset: -: invalid option
|
0
|
||||||
1
|
unset: invalid option -- m
|
||||||
hush: unset: -m: invalid option
|
|
||||||
1
|
1
|
||||||
0
|
0
|
||||||
___
|
___
|
||||||
|
Loading…
Reference in New Issue
Block a user