Initial public busybox upstream commit
[busybox4maemo] / miscutils / watchdog.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Mini watchdog implementation for busybox
4  *
5  * Copyright (C) 2003  Paul Mundt <lethal@linux-sh.org>
6  * Copyright (C) 2006  Bernhard Fischer <busybox@busybox.net>
7  *
8  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
9  */
10
11 #include "libbb.h"
12
13 #define OPT_FOREGROUND 0x01
14 #define OPT_TIMER      0x02
15
16 static void watchdog_shutdown(int sig ATTRIBUTE_UNUSED)
17 {
18         static const char V = 'V';
19
20         write(3, &V, 1);        /* Magic, see watchdog-api.txt in kernel */
21         if (ENABLE_FEATURE_CLEAN_UP)
22                 close(3);
23         exit(0);
24 }
25
26 int watchdog_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
27 int watchdog_main(int argc, char **argv)
28 {
29         unsigned opts;
30         unsigned timer_duration = 30000; /* Userspace timer duration, in milliseconds */
31         char *t_arg;
32
33         opt_complementary = "=1"; /* must have 1 argument */
34         opts = getopt32(argv, "Ft:", &t_arg);
35
36         if (opts & OPT_TIMER) {
37                 static const struct suffix_mult suffixes[] = {
38                         { "ms", 1 },
39                         { "", 1000 },
40                         { }
41                 };
42                 timer_duration = xatou_sfx(t_arg, suffixes);
43         }
44
45         if (!(opts & OPT_FOREGROUND)) {
46                 bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv);
47         }
48
49         bb_signals(BB_FATAL_SIGS, watchdog_shutdown);
50
51         /* Use known fd # - avoid needing global 'int fd' */
52         xmove_fd(xopen(argv[argc - 1], O_WRONLY), 3);
53
54 // TODO?
55 //      if (!(opts & OPT_TIMER)) {
56 //              if (ioctl(fd, WDIOC_GETTIMEOUT, &timer_duration) == 0)
57 //                      timer_duration *= 500;
58 //              else
59 //                      timer_duration = 30000;
60 //      }
61
62         while (1) {
63                 /*
64                  * Make sure we clear the counter before sleeping, as the counter value
65                  * is undefined at this point -- PFM
66                  */
67                 write(3, "", 1); /* write zero byte */
68                 usleep(timer_duration * 1000L);
69         }
70         return EXIT_SUCCESS; /* - not reached, but gcc 4.2.1 is too dumb! */
71 }