watch: execute command thru shell, not fork/exec. Other fixes
No binary (build failed)
—
(log yok)
| @@ -13,45 +13,66 @@ | |
| #include "busybox.h" | |
| + | // procps 2.0.18: |
| + | // watch [-d] [-n seconds] |
| + | // [--differences[=cumulative]] [--interval=seconds] command |
| + | // |
| + | // procps-3.2.3: |
| + | // watch [-dt] [-n seconds] |
| + | // [--differences[=cumulative]] [--interval=seconds] [--no-title] command |
| + | // |
| + | // (procps 3.x and procps 2.x are forks, not newer/older versions of the same) |
| int watch_main(int argc, char **argv) | |
| { | |
| - | int width, len; |
| + | unsigned opt; |
| unsigned period = 2; | |
| - | char **watched_argv, *header; |
| + | unsigned cmdlen = 1; // 1 for terminal NUL |
| + | char *header = NULL; |
| + | char *cmd; |
| + | char *tmp; |
| + | char **p; |
| - | if (argc < 2) bb_show_usage(); |
| + | opt_complementary = "-1"; // at least one param please |
| + | opt = getopt32(argc, argv, "+dtn:", &tmp); |
| + | //if (opt & 0x1) // -d (ignore) |
| + | //if (opt & 0x2) // -t |
| + | if (opt & 0x4) period = xatou(tmp); |
| + | argv += optind; |
| - | get_terminal_width_height(STDOUT_FILENO, &width, 0); |
| - | header = xzalloc(width--); |
| - | |
| - | /* don't use getopt, because it permutes the arguments */ |
| - | ++argv; |
| - | if ((argc > 3) && argv[0][0] == '-' && argv[0][1] == 'n') { |
| - | period = xatou(argv[1]); |
| - | argv += 2; |
| + | p = argv; |
| + | while (*p) |
| + | cmdlen += strlen(*p++) + 1; |
| + | tmp = cmd = xmalloc(cmdlen); |
| + | while (*argv) { |
| + | tmp += sprintf(tmp, " %s", *argv); |
| + | argv++; |
| } | |
| - | watched_argv = argv; |
| - | |
| - | /* create header */ |
| - | len = snprintf(header, width, "Every %ds:", period); |
| - | while (*argv && len<width) |
| - | snprintf(header+len, width-len, " %s", *(argv++)); |
| + | cmd++; // skip initial space |
| while (1) { | |
| - | char *thyme; |
| - | time_t t; |
| - | |
| - | time(&t); |
| - | thyme = ctime(&t); |
| - | len = strlen(thyme); |
| - | if (len < width) |
| - | header[width-len] = 0; |
| - | bb_printf("\033[H\033[J%s %s\n", header, thyme); |
| + | printf("\033[H\033[J"); |
| + | if (!(opt & 0x2)) { // no -t |
| + | int width, len; |
| + | char *thyme; |
| + | time_t t; |
| - | waitpid(xspawn(watched_argv),0,0); |
| + | get_terminal_width_height(STDOUT_FILENO, &width, 0); |
| + | header = xrealloc(header, width--); |
| + | // We pad with spaces entire length |
| + | snprintf(header, width, "Every %ds: %-*s", period, width, cmd); |
| + | time(&t); |
| + | thyme = ctime(&t); |
| + | len = strlen(thyme); |
| + | if (len < width) |
| + | strcpy(header + width - len, thyme); |
| + | puts(header); |
| + | } |
| + | fflush(stdout); |
| + | // TODO: 'real' watch pipes cmd's output to itself |
| + | // and does not allow it to overflow the screen |
| + | // (taking into account linewrap!) |
| + | system(cmd); |
| sleep(period); | |
| } | |
| - | if (ENABLE_FEATURE_CLEAN_UP) |
| - | free(header); |
| } | |
| @@ -3296,11 +3296,12 @@ USE_FEATURE_START_STOP_DAEMON_FANCY( \ | |
| "\t-a\tLock all VTs" | |
| #define watch_trivial_usage \ | |
| - | "[-n <seconds>] COMMAND..." |
| + | "[-n <seconds>] [-t] COMMAND..." |
| #define watch_full_usage \ | |
| - | "Executes a program periodically.\n" \ |
| + | "Executes a program periodically\n\n" \ |
| "Options:\n" \ | |
| - | "\t-n\tLoop period in seconds - default is 2" |
| + | "\t-n\tLoop period in seconds - default is 2\n" |
| + | "\t-t\tDon't print header" |
| #define watch_example_usage \ | |
| "$ watch date\n" \ | |
| "Mon Dec 17 10:31:40 GMT 2000\n" \ | |