[git commit] watch: implement -x

Denys Vlasenko vda.linux at googlemail.com
Thu Feb 5 11:23:32 UTC 2026


commit: https://git.busybox.net/busybox/commit/?id=3d572a8cc3d71b43877db2776882e91303a0532d
branch: https://git.busybox.net/busybox/log/?h=master

function                                             old     new   delta
packed_usage                                       35949   36009     +60
watch_main                                           229     269     +40
.rodata                                           107008  107009      +1
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/0 up/down: 101/0)             Total: 101 bytes

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 procps/watch.c | 27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/procps/watch.c b/procps/watch.c
index 05b72723c..b376fdc33 100644
--- a/procps/watch.c
+++ b/procps/watch.c
@@ -19,11 +19,12 @@
 //kbuild:lib-$(CONFIG_WATCH) += watch.o
 
 //usage:#define watch_trivial_usage
-//usage:       "[-n SEC] [-t] PROG ARGS"
+//usage:       "[-n SEC] [-tx] PROG ARGS"
 //usage:#define watch_full_usage "\n\n"
 //usage:       "Run PROG periodically\n"
 //usage:     "\n	-n SEC	Period (default 2)"
 //usage:     "\n	-t	Don't print header"
+//usage:     "\n	-x	exec(PROG,ARGS) instead of sh -c 'PROG ARGS'"
 //usage:
 //usage:#define watch_example_usage
 //usage:       "$ watch date\n"
@@ -56,6 +57,7 @@ int watch_main(int argc UNUSED_PARAM, char **argv)
 	unsigned opt;
 	unsigned width, new_width;
 	char *header;
+	char **argv0;
 	char *cmd;
 
 #if 0 // maybe ENABLE_DESKTOP?
@@ -66,20 +68,28 @@ int watch_main(int argc UNUSED_PARAM, char **argv)
 
 	// "+": stop at first non-option (procps 3.x only); -n NUM
 	// at least one param
-	opt = getopt32(argv, "^+" "dtn:" "\0" "-1", &period_str);
+	opt = getopt32(argv, "^+" "dtn:x" "\0" "-1", &period_str);
 	argv += optind;
 
-	// watch from both procps 2.x and 3.x does concatenation. Example:
-	// watch ls -l "a /tmp" "2>&1" - ls won't see "a /tmp" as one param
+	// watch from both procps 2.x and 3.x concatenates (unless -x).
+	// Example:
+	// watch ls -l "a /tmp" "2>&1" - ls won't see "a /tmp" as one param.
+	argv0 = argv;
+	// If -x, cmd is only used for printing header
 	cmd = *argv;
 	while (*++argv)
-		cmd = xasprintf("%s %s", cmd, *argv); // leaks cmd
+		cmd = xasprintf("%s %s", cmd, *argv);
+//leaks cmd ^^^
+//TODO: create and use xasprintf_inplace(DST, fmt, args_one_of_which_is_DST)
+//which frees old DST?
+	if (opt & (1 << 3))
+		argv = argv0; // If -x, restore argv[0] to !NULL
 
 	period = parse_duration_str(period_str);
 	width = (unsigned)-1; // make sure first time new_width != width
 	header = NULL;
 	while (1) {
-		/* home; clear to the end of screen */
+		// home; clear to the end of screen
 		printf(ESC"[H" ESC"[J");
 		if (!(opt & 0x2)) { // no -t
 			const unsigned time_len = sizeof("1234-67-90 23:56:89");
@@ -112,7 +122,10 @@ int watch_main(int argc UNUSED_PARAM, char **argv)
 		// TODO: 'real' watch pipes cmd's output to itself
 		// and does not allow it to overflow the screen
 		// (taking into account linewrap!)
-		system(cmd);
+		if (argv[0]) // -x?
+			spawn_and_wait(argv); // yes
+		else
+			system(cmd);
 		sleep_for_duration(period);
 	}
 	return 0; // gcc thinks we can reach this :)


More information about the busybox-cvs mailing list