diff options
author | Rob Landley <rob@landley.net> | 2006-05-25 23:02:40 +0000 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2006-05-25 23:02:40 +0000 |
commit | 399d2b5c24aaa059104a89058c7d4c8b97f41629 (patch) | |
tree | 1c6aed143c5dd2ff927190caf83b683c013028cb | |
parent | 69d863b6c609ac0523c546e408cc5d2063073425 (diff) | |
download | busybox-w32-399d2b5c24aaa059104a89058c7d4c8b97f41629.tar.gz busybox-w32-399d2b5c24aaa059104a89058c7d4c8b97f41629.tar.bz2 busybox-w32-399d2b5c24aaa059104a89058c7d4c8b97f41629.zip |
Rich Felker suggested removing dprintf() from watch, and one thing led to
another... This adds bb_xspawn() support, which does vfork/exec. (I don't
know why using a static instead of a local adds ~40 bytes, but using
the local doesn't work...)
-rw-r--r-- | coreutils/watch.c | 82 | ||||
-rw-r--r-- | include/libbb.h | 2 | ||||
-rw-r--r-- | libbb/xfuncs.c | 34 |
3 files changed, 57 insertions, 61 deletions
diff --git a/coreutils/watch.c b/coreutils/watch.c index 9e0c54c7f..b783d34de 100644 --- a/coreutils/watch.c +++ b/coreutils/watch.c | |||
@@ -4,20 +4,7 @@ | |||
4 | * | 4 | * |
5 | * Copyright (C) 2001 by Michael Habermann <mhabermann@gmx.de> | 5 | * Copyright (C) 2001 by Michael Habermann <mhabermann@gmx.de> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | 8 | */ |
22 | 9 | ||
23 | /* BB_AUDIT SUSv3 N/A */ | 10 | /* BB_AUDIT SUSv3 N/A */ |
@@ -41,23 +28,18 @@ | |||
41 | 28 | ||
42 | int watch_main(int argc, char **argv) | 29 | int watch_main(int argc, char **argv) |
43 | { | 30 | { |
44 | const int header_len = 40; | 31 | int width, len; |
45 | time_t t; | ||
46 | pid_t pid; | ||
47 | unsigned period = 2; | 32 | unsigned period = 2; |
48 | int old_stdout; | 33 | char **watched_argv, *header; |
49 | int len, len2; | ||
50 | char **watched_argv; | ||
51 | char header[header_len + 1]; | ||
52 | 34 | ||
53 | if (argc < 2) { | 35 | if (argc < 2) bb_show_usage(); |
54 | bb_show_usage(); | 36 | |
55 | } | 37 | get_terminal_width_height(1, &width, 0); |
38 | header = xzalloc(width--); | ||
56 | 39 | ||
57 | /* don't use getopt, because it permutes the arguments */ | 40 | /* don't use getopt, because it permutes the arguments */ |
58 | ++argv; | 41 | ++argv; |
59 | if ((argc > 3) && !strcmp(*argv, "-n") | 42 | if ((argc > 3) && !strcmp(*argv, "-n")) { |
60 | ) { | ||
61 | period = bb_xgetularg10_bnd(argv[1], 1, UINT_MAX); | 43 | period = bb_xgetularg10_bnd(argv[1], 1, UINT_MAX); |
62 | argv += 2; | 44 | argv += 2; |
63 | } | 45 | } |
@@ -65,44 +47,22 @@ int watch_main(int argc, char **argv) | |||
65 | 47 | ||
66 | /* create header */ | 48 | /* create header */ |
67 | 49 | ||
68 | len = snprintf(header, header_len, "Every %ds:", period); | 50 | len = snprintf(header, width, "Every %ds:", period); |
69 | /* Don't bother checking for len < 0, as it should never happen. | 51 | while (*argv && len<width) |
70 | * But, just to be prepared... */ | 52 | snprintf(header+len, width-len, " %s", *(argv++)); |
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); | ||
81 | |||
82 | header[len] = 0; | ||
83 | |||
84 | /* thanks to lye, who showed me how to redirect stdin/stdout */ | ||
85 | old_stdout = dup(STDOUT_FILENO); | ||
86 | 53 | ||
87 | while (1) { | 54 | while (1) { |
55 | char *thyme; | ||
56 | time_t t; | ||
57 | |||
88 | time(&t); | 58 | time(&t); |
89 | /* Use dprintf to avoid fflush()ing stdout. */ | 59 | thyme = ctime(&t); |
90 | if (dprintf(1, "\033[H\033[J%-*s%s\n", header_len, header, ctime(&t)) < 0) { | 60 | len = strlen(thyme); |
91 | bb_perror_msg_and_die("printf"); | 61 | if (len < width) header[width-len] = 0; |
92 | } | 62 | |
63 | printf("\033[H\033[J%s %s\n", header, thyme); | ||
93 | 64 | ||
94 | pid = vfork(); /* vfork, because of ucLinux */ | 65 | waitpid(bb_xspawn(watched_argv),0,0); |
95 | if (pid > 0) { | 66 | sleep(period); |
96 | //parent | ||
97 | wait(0); | ||
98 | sleep(period); | ||
99 | } else if (0 == pid) { | ||
100 | //child | ||
101 | dup2(old_stdout, STDOUT_FILENO); | ||
102 | execvp(*watched_argv, watched_argv); | ||
103 | bb_perror_msg_and_die("%s", *watched_argv); | ||
104 | } else { | ||
105 | bb_perror_msg_and_die("vfork"); | ||
106 | } | ||
107 | } | 67 | } |
108 | } | 68 | } |
diff --git a/include/libbb.h b/include/libbb.h index ca3afea98..928e25d30 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -146,6 +146,8 @@ extern void bb_fflush_stdout_and_exit(int retval) ATTRIBUTE_NORETURN; | |||
146 | 146 | ||
147 | extern void xstat(const char *filename, struct stat *buf); | 147 | extern void xstat(const char *filename, struct stat *buf); |
148 | extern int bb_xsocket(int domain, int type, int protocol); | 148 | extern int bb_xsocket(int domain, int type, int protocol); |
149 | extern pid_t bb_spawn(char **argv); | ||
150 | extern pid_t bb_xspawn(char **argv); | ||
149 | extern void bb_xdaemon(int nochdir, int noclose); | 151 | extern void bb_xdaemon(int nochdir, int noclose); |
150 | extern void bb_xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen); | 152 | extern void bb_xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen); |
151 | extern void bb_xlisten(int s, int backlog); | 153 | extern void bb_xlisten(int s, int backlog); |
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index d3c9e41e1..2cfafb01a 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c | |||
@@ -182,3 +182,37 @@ void bb_xfflush_stdout(void) | |||
182 | } | 182 | } |
183 | } | 183 | } |
184 | #endif | 184 | #endif |
185 | |||
186 | #ifdef L_spawn | ||
187 | // This does a fork/exec in one call, using vfork(). | ||
188 | pid_t bb_spawn(char **argv) | ||
189 | { | ||
190 | static int failed; | ||
191 | pid_t pid; | ||
192 | |||
193 | // Be nice to nommu machines. | ||
194 | failed = 0; | ||
195 | pid = vfork(); | ||
196 | if (pid < 0) return pid; | ||
197 | if (!pid) { | ||
198 | execvp(*argv, argv); | ||
199 | |||
200 | // We're sharing a stack with blocked parent, let parent know we failed | ||
201 | // and then exit to unblock parent (but don't run atexit() stuff, which | ||
202 | // would screw up parent.) | ||
203 | |||
204 | failed = -1; | ||
205 | _exit(0); | ||
206 | } | ||
207 | return failed ? failed : pid; | ||
208 | } | ||
209 | #endif | ||
210 | |||
211 | #ifdef L_xspawn | ||
212 | pid_t bb_xspawn(char **argv) | ||
213 | { | ||
214 | pid_t pid = bb_spawn(argv); | ||
215 | if (pid < 0) bb_perror_msg_and_die("%s", *argv); | ||
216 | return pid; | ||
217 | } | ||
218 | #endif | ||