e040c64fdcb867af7d903e0b4f1de54dfa8941ae
[oweals/busybox.git] / 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 ATTRIBUTE_UNUSED sig) ATTRIBUTE_NORETURN;
17 static void watchdog_shutdown(int ATTRIBUTE_UNUSED sig)
18 {
19         static const char V = 'V';
20
21         write(3, &V, 1);        /* Magic, see watchdog-api.txt in kernel */
22         if (ENABLE_FEATURE_CLEAN_UP)
23                 close(3);
24         exit(0);
25 }
26
27 int watchdog_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
28 int watchdog_main(int argc, char **argv)
29 {
30         unsigned opts;
31         unsigned timer_duration = 30000; /* Userspace timer duration, in milliseconds */
32         char *t_arg;
33
34         opt_complementary = "=1"; /* must have 1 argument */
35         opts = getopt32(argv, "Ft:", &t_arg);
36
37         if (opts & OPT_TIMER) {
38                 static const struct suffix_mult suffixes[] = {
39                         { "ms", 1 },
40                         { "", 1000 },
41                         { }
42                 };
43                 timer_duration = xatou_sfx(t_arg, suffixes);
44         }
45
46         if (!(opts & OPT_FOREGROUND)) {
47                 bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv);
48         }
49
50         signal(SIGHUP, watchdog_shutdown);
51         signal(SIGINT, watchdog_shutdown);
52
53         /* Use known fd # - avoid needing global 'int fd' */
54         xmove_fd(xopen(argv[argc - 1], O_WRONLY), 3);
55
56         while (1) {
57                 /*
58                  * Make sure we clear the counter before sleeping, as the counter value
59                  * is undefined at this point -- PFM
60                  */
61                 write(3, "", 1); /* write zero byte */
62                 usleep(timer_duration * 1000L);
63         }
64         return EXIT_SUCCESS; /* - not reached, but gcc 4.2.1 is too dumb! */
65 }