libbb: GETOPT_RESET macro
No binary (build failed)
—
(log yok)
| @@ -1178,6 +1178,28 @@ extern uint32_t option_mask32; | |
| extern uint32_t getopt32(char **argv, const char *applet_opts, ...) FAST_FUNC; | |
| + | /* BSD-derived getopt() functions require that optind be set to 1 in |
| + | * order to reset getopt() state. This used to be generally accepted |
| + | * way of resetting getopt(). However, glibc's getopt() |
| + | * has additional getopt() state beyond optind (specifically, glibc |
| + | * extensions ('+' and '-' at the start of the string), and requires |
| + | * that optind be set to zero to reset its state. BSD-derived versions |
| + | * of getopt() misbehaved if optind is set to 0 in order to reset getopt(), |
| + | * and glibc's getopt() used to coredump if optind is set 1 in order |
| + | * to reset getopt(). |
| + | * Then BSD introduced additional variable "optreset" which |
| + | * be set to 1 in order to reset getopt(). Sigh. Standards, anyone? |
| + | * |
| + | * By ~2008, OpenBSD 3.4 was changed to survive glibc-like optind = 0 |
| + | * (to interpret it as if optreset was set). |
| + | */ |
| + | #ifdef __GLIBC__ |
| + | #define GETOPT_RESET() (optind = 0) |
| + | #else /* BSD style */ |
| + | #define GETOPT_RESET() (optind = 1) |
| + | #endif |
| + | |
| + | |
| /* Having next pointer as a first member allows easy creation | |
| * of "llist-compatible" structs, and using llist_FOO functions | |
| * on them. | |
| @@ -576,13 +576,7 @@ getopt32(char **argv, const char *applet_opts, ...) | |
| * run_nofork_applet() does this, but we might end up here | |
| * also via gunzip_main() -> gzip_main(). Play safe. | |
| */ | |
| - | #ifdef __GLIBC__ |
| - | optind = 0; |
| - | #else /* BSD style */ |
| - | optind = 1; |
| - | /* optreset = 1; */ |
| - | #endif |
| - | /* optarg = NULL; opterr = 0; optopt = 0; - do we need this?? */ |
| + | GETOPT_RESET(); |
| /* Note: just "getopt() <= 0" will not work well for | |
| * "fake" short options, like this one: | |
| @@ -121,28 +121,8 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv) | |
| /* In case getopt() or getopt32() was already called: | |
| * reset the libc getopt() function, which keeps internal state. | |
| - | * |
| - | * BSD-derived getopt() functions require that optind be set to 1 in |
| - | * order to reset getopt() state. This used to be generally accepted |
| - | * way of resetting getopt(). However, glibc's getopt() |
| - | * has additional getopt() state beyond optind, and requires that |
| - | * optind be set to zero to reset its state. So the unfortunate state of |
| - | * affairs is that BSD-derived versions of getopt() misbehave if |
| - | * optind is set to 0 in order to reset getopt(), and glibc's getopt() |
| - | * will core dump if optind is set 1 in order to reset getopt(). |
| - | * |
| - | * More modern versions of BSD require that optreset be set to 1 in |
| - | * order to reset getopt(). Sigh. Standards, anyone? |
| */ | |
| - | #ifdef __GLIBC__ |
| - | optind = 0; |
| - | #else /* BSD style */ |
| - | optind = 1; |
| - | /* optreset = 1; */ |
| - | #endif |
| - | /* optarg = NULL; opterr = 1; optopt = 63; - do we need this too? */ |
| - | /* (values above are what they initialized to in glibc and uclibc) */ |
| - | /* option_mask32 = 0; - not needed, no applet depends on it being 0 */ |
| + | GETOPT_RESET(); |
| argc = 1; | |
| while (argv[argc]) | |
| @@ -167,11 +147,7 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv) | |
| restore_nofork_data(&old); | |
| /* Other globals can be simply reset to defaults */ | |
| - | #ifdef __GLIBC__ |
| - | optind = 0; |
| - | #else /* BSD style */ |
| - | optind = 1; |
| - | #endif |
| + | GETOPT_RESET(); |
| return rc & 0xff; /* don't confuse people with "exitcodes" >255 */ | |
| } | |
| @@ -688,12 +688,7 @@ int svc_main(int argc UNUSED_PARAM, char **argv) | |
| /* getopt32() was already called: | |
| * reset the libc getopt() function, which keeps internal state. | |
| */ | |
| - | #ifdef __GLIBC__ |
| - | optind = 0; |
| - | #else /* BSD style */ |
| - | optind = 1; |
| - | /* optreset = 1; */ |
| - | #endif |
| + | GETOPT_RESET(); |
| do { | |
| if (opts & 1) { | |
| @@ -401,13 +401,7 @@ shell_builtin_ulimit(char **argv) | |
| /* In case getopt was already called: | |
| * reset the libc getopt() function, which keeps internal state. | |
| */ | |
| - | #ifdef __GLIBC__ |
| - | optind = 0; |
| - | #else /* BSD style */ |
| - | optind = 1; |
| - | /* optreset = 1; */ |
| - | #endif |
| - | /* optarg = NULL; opterr = 0; optopt = 0; - do we need this?? */ |
| + | GETOPT_RESET(); |
| argc = 1; | |
| while (argv[argc]) | |
| @@ -246,12 +246,7 @@ static int generate_output(char **argv, int argc, const char *optstr, const stru | |
| /* We used it already in main() in getopt32(), | |
| * we *must* reset getopt(3): */ | |
| - | #ifdef __GLIBC__ |
| - | optind = 0; |
| - | #else /* BSD style */ |
| - | optind = 1; |
| - | /* optreset = 1; */ |
| - | #endif |
| + | GETOPT_RESET(); |
| while (1) { | |
| #if ENABLE_FEATURE_GETOPT_LONG | |