[PATCH 1/2] env: use getopt_long instead of getopt32long
Marc Kewitz
herderkewitz at googlemail.com
Mon Apr 7 10:08:03 UTC 2025
getopt32long does not allow handling options iteratively
this is in preparation of adding an option to split strings
which can be used for shebangs
---
coreutils/env.c | 75 ++++++++++++++++++++++++++++++++++---------------
1 file changed, 53 insertions(+), 22 deletions(-)
diff --git a/coreutils/env.c b/coreutils/env.c
index e9d3e883e..9ca1fad2d 100644
--- a/coreutils/env.c
+++ b/coreutils/env.c
@@ -50,51 +50,82 @@
//usage: "\n -u NAME Remove variable from environment"
#include "libbb.h"
+#include <getopt.h>
+
+static struct option const long_options[] = {
+ {"ignore-environment", no_argument, 0, 'i' },
+ {"null", no_argument, 0, '0' },
+ {"unset", required_argument, 0, 'u' },
+ {0, 0, 0, 0 }
+};
+
+static char const short_options[] = "+iu:0";
+
+static char const **unset_vars;
+static int num_unset_vars;
+
+static void add_unset_var (char const *var)
+{
+ unset_vars = xrealloc(unset_vars, num_unset_vars + 1);
+ unset_vars[num_unset_vars++] = var;
+}
int env_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int env_main(int argc UNUSED_PARAM, char **argv)
+int env_main(int argc, char **argv)
{
unsigned opts;
- llist_t *unset_env = NULL;
-
- opts = getopt32long(argv, "+i0u:*",
- "ignore-environment\0" No_argument "i"
- "null\0" No_argument "0"
- "unset\0" Required_argument "u"
- , &unset_env
- );
- argv += optind;
- if (argv[0] && LONE_DASH(argv[0])) {
- opts |= 1;
- ++argv;
+ int optc;
+ bool ignore_environment = false;
+ bool null_terminate_output = false;
+
+ while ((optc = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) {
+ switch (optc)
+ {
+ case 'i':
+ ignore_environment = true;
+ break;
+ case 'u':
+ add_unset_var(optarg);
+ break;
+ case '0':
+ null_terminate_output = true;
+ break;
+ default:
+ exit(EXIT_FAILURE);
+ }
}
- if (opts & 1) {
+
+ if (optind < argc && LONE_DASH(argv[optind])) {
+ ignore_environment = true;
+ ++optind;
+ }
+ if (ignore_environment) {
clearenv();
}
- while (unset_env) {
- char *var = llist_pop(&unset_env);
+
+ for (int i = 0; i < num_unset_vars; ++i) {
/* This does not handle -uVAR=VAL
* (coreutils _sets_ the variable in that case): */
/*unsetenv(var);*/
/* This does, but uses somewhan undocumented feature that
* putenv("name_without_equal_sign") unsets the variable: */
- putenv(var);
+ putenv(unset_vars[i]);
}
- while (*argv && (strchr(*argv, '=') != NULL)) {
+ while (optind < argc && (strchr(argv[optind], '=') != NULL)) {
if (putenv(*argv) < 0) {
bb_simple_perror_msg_and_die("putenv");
}
- ++argv;
+ ++optind;
}
- if (argv[0]) {
- BB_EXECVP_or_die(argv);
+ if (optind < argc) {
+ BB_EXECVP_or_die(&argv[optind]);
}
if (environ) { /* clearenv() may set environ == NULL! */
char **ep;
- opts = (opts & 2) ? 0 : '\n';
+ opts = null_terminate_output ? 0 : '\n';
for (ep = environ; *ep; ep++) {
printf("%s%c", *ep, opts);
}
--
2.30.2
More information about the busybox
mailing list