diff options
Diffstat (limited to 'release/src/router/busybox/miscutils/watchdog.c')
-rw-r--r-- | release/src/router/busybox/miscutils/watchdog.c | 118 |
1 files changed, 61 insertions, 57 deletions
diff --git a/release/src/router/busybox/miscutils/watchdog.c b/release/src/router/busybox/miscutils/watchdog.c index b1167dc9..f85138e1 100644 --- a/release/src/router/busybox/miscutils/watchdog.c +++ b/release/src/router/busybox/miscutils/watchdog.c @@ -3,79 +3,83 @@ * Mini watchdog implementation for busybox * * Copyright (C) 2003 Paul Mundt <lethal@linux-sh.org> + * Copyright (C) 2006 Bernhard Reutner-Fischer <busybox@busybox.net> + * Copyright (C) 2008 Darius Augulis <augulis.darius@gmail.com> * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. */ -#include <stdio.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdlib.h> -#include <signal.h> -#include "busybox.h" +#include "libbb.h" +#include "linux/types.h" /* for __u32 */ +#include "linux/watchdog.h" -/* Userspace timer duration, in seconds */ -static unsigned int timer_duration = 30; +#define OPT_FOREGROUND (1 << 0) +#define OPT_STIMER (1 << 1) +#define OPT_HTIMER (1 << 2) -/* Watchdog file descriptor */ -static int fd; - -static void watchdog_shutdown(int unused) +static void watchdog_shutdown(int sig UNUSED_PARAM) { - write(fd, "V", 1); /* Magic */ - close(fd); - exit(0); + static const char V = 'V'; + + write(3, &V, 1); /* Magic, see watchdog-api.txt in kernel */ + if (ENABLE_FEATURE_CLEAN_UP) + close(3); + exit(EXIT_SUCCESS); } -extern int watchdog_main(int argc, char **argv) +int watchdog_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int watchdog_main(int argc, char **argv) { - int opt; + static const struct suffix_mult suffixes[] = { + { "ms", 1 }, + { "", 1000 }, + { } + }; - while ((opt = getopt(argc, argv, "t:")) > 0) { - switch (opt) { - case 't': - timer_duration = bb_xgetlarg(optarg, 10, 0, INT_MAX); - break; - default: - bb_show_usage(); - } - } + unsigned opts; + unsigned stimer_duration; /* how often to restart */ + unsigned htimer_duration = 60000; /* reboots after N ms if not restarted */ + char *st_arg; + char *ht_arg; - /* We're only interested in the watchdog device .. */ - if (optind < argc - 1 || argc == 1) - bb_show_usage(); + opt_complementary = "=1"; /* must have exactly 1 argument */ + opts = getopt32(argv, "Ft:T:", &st_arg, &ht_arg); - if (daemon(0, 1) < 0) - bb_perror_msg_and_die("Failed forking watchdog daemon"); + if (opts & OPT_HTIMER) + htimer_duration = xatou_sfx(ht_arg, suffixes); + stimer_duration = htimer_duration / 2; + if (opts & OPT_STIMER) + stimer_duration = xatou_sfx(st_arg, suffixes); - signal(SIGHUP, watchdog_shutdown); - signal(SIGINT, watchdog_shutdown); + bb_signals(BB_FATAL_SIGS, watchdog_shutdown); - fd = bb_xopen(argv[argc - 1], O_WRONLY); + /* Use known fd # - avoid needing global 'int fd' */ + xmove_fd(xopen(argv[argc - 1], O_WRONLY), 3); + + /* WDIOC_SETTIMEOUT takes seconds, not milliseconds */ + htimer_duration = htimer_duration / 1000; +#ifndef WDIOC_SETTIMEOUT +#error WDIOC_SETTIMEOUT is not defined, cannot compile watchdog applet +#else + ioctl_or_warn(3, WDIOC_SETTIMEOUT, &htimer_duration); +#endif +#if 0 + ioctl_or_warn(3, WDIOC_GETTIMEOUT, &htimer_duration); + printf("watchdog: SW timer is %dms, HW timer is %dms\n", + stimer_duration, htimer_duration * 1000); +#endif + + if (!(opts & OPT_FOREGROUND)) { + bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); + } while (1) { - /* - * Make sure we clear the counter before sleeping, as the counter value - * is undefined at this point -- PFM + /* + * Make sure we clear the counter before sleeping, + * as the counter value is undefined at this point -- PFM */ - write(fd, "\0", 1); - sleep(timer_duration); + write(3, "", 1); /* write zero byte */ + usleep(stimer_duration * 1000L); } - - watchdog_shutdown(0); - - return EXIT_SUCCESS; + return EXIT_SUCCESS; /* - not reached, but gcc 4.2.1 is too dumb! */ } |