www.usr.com/support/gpl/USR9108_release1.5.tar.gz
[bcm963xx.git] / userapps / opensource / busybox / coreutils / watch.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Mini watch implementation for busybox
4  *
5  * Copyright (C) 2001 by Michael Habermann <mhabermann@gmx.de>
6  *
7  * This program is free software; you can redistribute it and/or modify
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  */
22
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  */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <limits.h>
36 #include <time.h>
37 #include <assert.h>
38 #include <unistd.h>
39 #include <sys/wait.h>
40 #include "busybox.h"
41
42 extern int watch_main(int argc, char **argv)
43 {
44         const int header_len = 40;
45         time_t t;
46         pid_t pid;
47         unsigned period = 2;
48         int old_stdout;
49         int len, len2;
50         char **watched_argv;
51         char header[header_len + 1];
52
53         if (argc < 2) {
54                 bb_show_usage();
55         }
56
57         /* don't use getopt, because it permutes the arguments */
58         ++argv;
59         if ((argc > 3) && !strcmp(*argv, "-n")
60         ) {
61                 period = bb_xgetularg10_bnd(argv[1], 1, UINT_MAX);
62                 argv += 2;
63         }
64         watched_argv = argv;
65
66         /* create header */
67
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);
81
82         header[len] = 0;
83
84         /* thanks to lye, who showed me how to redirect stdin/stdout */
85         old_stdout = dup(1);
86
87         while (1) {
88                 time(&t);
89                 /* Use dprintf to avoid fflush()ing stdout. */
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                 }
93
94                 pid = vfork();  /* vfork, because of ucLinux */
95                 if (pid > 0) {
96                         //parent
97                         wait(0);
98                         sleep(period);
99                 } else if (0 == pid) {
100                         //child
101                         close(1);
102                         dup(old_stdout);
103                         if (execvp(*watched_argv, watched_argv)) {
104                                 bb_error_msg_and_die("Couldn't run command\n");
105                         }
106                 } else {
107                         bb_error_msg_and_die("Couldn't vfork\n");
108                 }
109         }
110 }