diff options
Diffstat (limited to 'coreutils/watch.c')
-rw-r--r-- | coreutils/watch.c | 91 |
1 files changed, 49 insertions, 42 deletions
diff --git a/coreutils/watch.c b/coreutils/watch.c index c275f3bb3..f9f40189e 100644 --- a/coreutils/watch.c +++ b/coreutils/watch.c | |||
@@ -20,67 +20,76 @@ | |||
20 | * | 20 | * |
21 | */ | 21 | */ |
22 | 22 | ||
23 | /* getopt not needed */ | 23 | /* BB_AUDIT SUSv3 N/A */ |
24 | /* BB_AUDIT GNU defects -- only option -n is supported. */ | ||
25 | |||
26 | /* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) | ||
27 | * | ||
28 | * Removed dependency on date_main(), added proper error checking, and | ||
29 | * reduced size. | ||
30 | */ | ||
24 | 31 | ||
25 | #include <stdio.h> | 32 | #include <stdio.h> |
26 | #include <errno.h> | ||
27 | #include <unistd.h> | ||
28 | #include <stdlib.h> | 33 | #include <stdlib.h> |
29 | #include <string.h> | 34 | #include <string.h> |
35 | #include <limits.h> | ||
36 | #include <time.h> | ||
37 | #include <assert.h> | ||
38 | #include <unistd.h> | ||
30 | #include <sys/wait.h> | 39 | #include <sys/wait.h> |
31 | #include "busybox.h" | 40 | #include "busybox.h" |
32 | 41 | ||
33 | extern int watch_main(int argc, char **argv) | 42 | extern int watch_main(int argc, char **argv) |
34 | { | 43 | { |
35 | const char date_argv[2][10] = { "date", "" }; | ||
36 | const int header_len = 40; | 44 | const int header_len = 40; |
37 | char header[header_len + 1]; | 45 | time_t t; |
38 | int period = 2; | ||
39 | char **cargv; | ||
40 | int cargc; | ||
41 | pid_t pid; | 46 | pid_t pid; |
47 | unsigned period = 2; | ||
42 | int old_stdout; | 48 | int old_stdout; |
43 | int i; | 49 | int len, len2; |
50 | char **watched_argv; | ||
51 | char header[header_len + 1]; | ||
44 | 52 | ||
45 | if (argc < 2) { | 53 | if (argc < 2) { |
46 | show_usage(); | 54 | bb_show_usage(); |
47 | } else { | ||
48 | cargv = argv + 1; | ||
49 | cargc = argc - 1; | ||
50 | |||
51 | /* don't use getopt, because it permutes the arguments */ | ||
52 | if (argc >= 3 && !strcmp(argv[1], "-n")) { | ||
53 | period = strtol(argv[2], NULL, 10); | ||
54 | if (period < 1) | ||
55 | show_usage(); | ||
56 | cargv += 2; | ||
57 | cargc -= 2; | ||
58 | } | ||
59 | } | 55 | } |
60 | 56 | ||
61 | 57 | /* don't use getopt, because it permutes the arguments */ | |
62 | /* create header */ | 58 | ++argv; |
63 | snprintf(header, header_len, "Every %ds: ", period); | 59 | if ((argc > 3) && !strcmp(*argv, "-n") |
64 | for (i = 0; i < cargc && (strlen(header) + strlen(cargv[i]) < header_len); | 60 | ) { |
65 | i++) { | 61 | period = bb_xgetularg10_bnd(argv[1], 1, UINT_MAX); |
66 | strcat(header, cargv[i]); | 62 | argv += 2; |
67 | strcat(header, " "); | ||
68 | } | 63 | } |
64 | watched_argv = argv; | ||
69 | 65 | ||
70 | /* fill with blanks */ | 66 | /* create header */ |
71 | for (i = strlen(header); i < header_len; i++) | ||
72 | header[i] = ' '; | ||
73 | 67 | ||
74 | header[header_len - 1] = '\0'; | 68 | len = snprintf(header, header_len, "Every %ds:", period); |
69 | /* Don't bother checking for len < 0, as it should never happen. | ||
70 | * But, just to be prepared... */ | ||
71 | assert(len >= 0); | ||
72 | do { | ||
73 | len2 = strlen(*argv); | ||
74 | if (len + len2 >= header_len-1) { | ||
75 | break; | ||
76 | } | ||
77 | header[len] = ' '; | ||
78 | memcpy(header+len+1, *argv, len2); | ||
79 | len += len2+1; | ||
80 | } while (*++argv); | ||
75 | 81 | ||
82 | header[len] = 0; | ||
76 | 83 | ||
77 | /* thanks to lye, who showed me how to redirect stdin/stdout */ | 84 | /* thanks to lye, who showed me how to redirect stdin/stdout */ |
78 | old_stdout = dup(1); | 85 | old_stdout = dup(1); |
79 | 86 | ||
80 | while (1) { | 87 | while (1) { |
81 | printf("\033[H\033[J%s", header); | 88 | time(&t); |
82 | date_main(1, (char **) date_argv); | 89 | /* Use dprintf to avoid fflush()ing stdout. */ |
83 | printf("\n"); | 90 | if (dprintf(1, "\033[H\033[J%-*s%s\n", header_len, header, ctime(&t)) < 0) { |
91 | bb_perror_msg_and_die("printf"); | ||
92 | } | ||
84 | 93 | ||
85 | pid = vfork(); /* vfork, because of ucLinux */ | 94 | pid = vfork(); /* vfork, because of ucLinux */ |
86 | if (pid > 0) { | 95 | if (pid > 0) { |
@@ -91,13 +100,11 @@ extern int watch_main(int argc, char **argv) | |||
91 | //child | 100 | //child |
92 | close(1); | 101 | close(1); |
93 | dup(old_stdout); | 102 | dup(old_stdout); |
94 | if (execvp(*cargv, cargv)) | 103 | if (execvp(*watched_argv, watched_argv)) { |
95 | error_msg_and_die("Couldn't run command\n"); | 104 | bb_error_msg_and_die("Couldn't run command\n"); |
105 | } | ||
96 | } else { | 106 | } else { |
97 | error_msg_and_die("Couldn't vfork\n"); | 107 | bb_error_msg_and_die("Couldn't vfork\n"); |
98 | } | 108 | } |
99 | } | 109 | } |
100 | |||
101 | |||
102 | return EXIT_SUCCESS; | ||
103 | } | 110 | } |