aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2019-03-10 23:05:24 -0500
committerRob Landley <rob@landley.net>2019-03-10 23:05:24 -0500
commit677cd8cea214ef73bbbed965580575c9abaa048e (patch)
tree09f113fdd434384c58c15eebd663b1b1be01d805
parent502b10c2ab6bb273bf280ba355fa30869b955d56 (diff)
downloadtoybox-677cd8cea214ef73bbbed965580575c9abaa048e.tar.gz
Add TOYFLAG_ARGFAIL() to allow argument parsing failures to exit with value.
-rw-r--r--lib/args.c4
-rw-r--r--lib/toyflags.h3
-rw-r--r--lib/xwrap.c2
-rw-r--r--toys.h2
-rw-r--r--toys/other/timeout.c15
5 files changed, 12 insertions, 14 deletions
diff --git a/lib/args.c b/lib/args.c
index 54106c25..1ebc4f2d 100644
--- a/lib/args.c
+++ b/lib/args.c
@@ -388,6 +388,8 @@ void get_optflags(void)
// Option parsing is a two stage process: parse the option string into
// a struct opts list, then use that list to process argv[];
+ toys.exitval = toys.which->flags >> 24;
+
// Allocate memory for optargs
saveflags = 0;
while (toys.argv[saveflags++]);
@@ -495,6 +497,8 @@ notflag:
help_exit("Needs %s-%s", s[1] ? "one of " : "", needs);
}
+ toys.exitval = 0;
+
if (CFG_TOYBOX_FREE) {
llist_traverse(gof.opts, free);
llist_traverse(gof.longopts, free);
diff --git a/lib/toyflags.h b/lib/toyflags.h
index bec8078b..408c3ec6 100644
--- a/lib/toyflags.h
+++ b/lib/toyflags.h
@@ -31,6 +31,9 @@
// Suppress default --help processing
#define TOYFLAG_NOHELP (1<<9)
+// Error code to return if argument parsing fails (default 1)
+#define TOYFLAG_ARGFAIL(x) (x<<24)
+
#if CFG_TOYBOX_PEDANTIC_ARGS
#define NO_ARGS ">0"
#else
diff --git a/lib/xwrap.c b/lib/xwrap.c
index 223356b3..d7b06c5a 100644
--- a/lib/xwrap.c
+++ b/lib/xwrap.c
@@ -210,8 +210,8 @@ void xexec(char **argv)
toy_exec(argv);
execvp(argv[0], argv);
+ toys.exitval = 126+(errno == ENOENT);
perror_msg("exec %s", argv[0]);
- toys.exitval = 127;
if (!toys.stacktop) _exit(toys.exitval);
xexit();
}
diff --git a/toys.h b/toys.h
index 9e49900b..79d0a905 100644
--- a/toys.h
+++ b/toys.h
@@ -89,7 +89,7 @@ extern struct toy_list {
char *name;
void (*toy_main)(void);
char *options;
- int flags;
+ unsigned flags;
} toy_list[];
// Global context shared by all commands.
diff --git a/toys/other/timeout.c b/toys/other/timeout.c
index 20722b7e..d6715a5f 100644
--- a/toys/other/timeout.c
+++ b/toys/other/timeout.c
@@ -4,7 +4,7 @@
*
* No standard
-USE_TIMEOUT(NEWTOY(timeout, "<2^(foreground)(preserve-status)vk:s(signal):", TOYFLAG_USR|TOYFLAG_BIN))
+USE_TIMEOUT(NEWTOY(timeout, "<2^(foreground)(preserve-status)vk:s(signal):", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(125)))
config TIMEOUT
bool "timeout"
@@ -66,9 +66,6 @@ void xparsetimeval(char *s, struct timeval *tv)
void timeout_main(void)
{
- // If timeout fails to parse its arguments, it exits with 125.
- // TODO: this and grep both have a bug where built-in error checking like
- // "too few arguments" will exit 1 instead of the custom value.
toys.exitval = 125;
// Parse early to get any errors out of the way.
@@ -81,14 +78,8 @@ void timeout_main(void)
if (!FLAG(foreground)) setpgid(0, 0);
- if (!(TT.pid = XVFORK())) {
- char **argv = toys.optargs+1;
-
- execvp(argv[0], argv);
- perror_msg("failed to run '%s'", argv[0]);
- toys.exitval = (errno == ENOENT) ? 127 : 126;
- _xexit();
- } else {
+ if (!(TT.pid = XVFORK())) xexec(toys.optargs+1);
+ else {
int status;
xsignal(SIGALRM, handler);