Signed-off-by: Mike Frysinger <[EMAIL PROTECTED]>
---
 user/Kconfig               |    5 +
 user/Makefile              |    1 +
 user/watchdogd/Makefile    |   12 +++
 user/watchdogd/watchdogd.c |  200 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 218 insertions(+), 0 deletions(-)
 create mode 100644 user/watchdogd/Makefile
 create mode 100644 user/watchdogd/watchdogd.c

diff --git a/user/Kconfig b/user/Kconfig
index 688fca6..f78e94d 100644
--- a/user/Kconfig
+++ b/user/Kconfig
@@ -3361,6 +3361,11 @@ config USER_UNZOO_UNZOO
          The unzoo archive decompression and extraction program.
          Can only extract and view contents of zoo archives.
 
+config USER_WATCHDOGD
+       bool "watchdogd"
+       help
+         A simple watchdog daemon.
+
 config USER_LRZSZ_LRZSZ
        bool "zmodem utils"
 
diff --git a/user/Makefile b/user/Makefile
index d452260..4dfd206 100644
--- a/user/Makefile
+++ b/user/Makefile
@@ -417,6 +417,7 @@ dir_$(CONFIG_USER_VPLAY_MIXER)              += vplay
 dir_$(CONFIG_USER_VPNLED_VPNLED)            += vpnled
 dir_$(CONFIG_USER_W3CAM_VIDCAT)             += w3cam
 dir_$(CONFIG_USER_W3CAM_W3CAMD)             += w3cam
+dir_$(CONFIG_USER_WATCHDOGD)                += watchdogd
 dir_$(CONFIG_USER_WGET)                     += wget
 dir_$(CONFIG_USER_WHETSTONE_WHETSTONE)      += whetstone
 dir_$(CONFIG_USER_WIRELESS_TOOLS)           += wireless_tools
diff --git a/user/watchdogd/Makefile b/user/watchdogd/Makefile
new file mode 100644
index 0000000..d76bd7c
--- /dev/null
+++ b/user/watchdogd/Makefile
@@ -0,0 +1,12 @@
+CFLAGS += -Wall
+
+all: watchdogd
+
+romfs:
+       $(ROMFSINST) -e CONFIG_USER_WATCHDOGD /bin/$(EXEC)
+       $(ROMFSINST) -e CONFIG_USER_WATCHDOGD -a 
"watchdogd:unknown:/bin/watchdogd -f -s" /etc/inittab
+
+clean:
+       -rm -f $(EXEC) *.elf *.gdb *.o
+
+.PHONY: all clean romfs
diff --git a/user/watchdogd/watchdogd.c b/user/watchdogd/watchdogd.c
new file mode 100644
index 0000000..d25aa1e
--- /dev/null
+++ b/user/watchdogd/watchdogd.c
@@ -0,0 +1,200 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+#include <signal.h>
+#include <paths.h>
+
+int fd = -1;
+
+/*
+ * This function simply sends an IOCTL to the driver, which in turn ticks
+ * the PC Watchdog card to reset its internal timer so it doesn't trigger
+ * a computer reset.
+ */
+void keep_alive(void)
+{
+       int dummy;
+
+       ioctl(fd, WDIOC_KEEPALIVE, &dummy);
+}
+
+void safe_exit()
+{
+       if (fd != -1) {
+               write(fd, "V", 1);
+               close(fd);
+       }
+       exit(0);
+}
+
+int set_wd_counter(int count)
+{
+       return ioctl(fd, WDIOC_SETTIMEOUT, &count);
+}
+
+int get_wd_counter()
+{
+       int count;
+       int err;
+       if ((err = ioctl(fd, WDIOC_GETTIMEOUT, &count))) {
+               count = err;
+       }
+       return count;
+}
+
+#define FOREGROUND_FLAG "-f"
+
+#define _PATH_DEVNULL "/dev/null"
+
+void vfork_daemon_rexec(int nochdir, int noclose, int argc, char **argv, char 
*foreground_opt)
+{
+       int f;
+       char **vfork_args;
+       int a = 0;
+
+       setsid();
+
+       if (!nochdir)
+               chdir("/");
+
+       if (!noclose && (f = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+               dup2(f, STDIN_FILENO);
+               dup2(f, STDOUT_FILENO);
+               dup2(f, STDERR_FILENO);
+               if (f > 2)
+                       close(f);
+       }
+
+       vfork_args = malloc(sizeof(char *) * (argc + 2));
+       while (*argv) {
+               vfork_args[a++] = *argv;
+               argv++;
+       }
+       vfork_args[a++] = foreground_opt;
+       vfork_args[a++] = NULL;
+       switch (vfork()) {
+       case 0:         /* child */
+               /* Make certain we are not a session leader, or else we
+                * might reacquire a controlling terminal */
+               if (vfork())
+                       _exit(0);
+               execvp(vfork_args[0], vfork_args);
+               perror("execv");
+               exit(-1);
+       case -1:                /* error */
+               perror("vfork");
+               exit(-1);
+       default:                /* parent */
+               exit(0);
+       }
+}
+
+static void usage(char *argv[])
+{
+       printf(
+               "%s [-f] [-w <sec>] [-k <sec>] [-s] [-h|--help]\n"
+               "A simple watchdog deamon that send WDIOC_KEEPALIVE ioctl every 
some\n"
+               "\"heartbeat of keepalives\" seconds.\n"
+               "Options:\n"
+               "\t-f        start in foreground (background is default)\n"
+               "\t-w <sec>  set the watchdog counter to <sec> in seconds\n"
+               "\t-k <sec>  set the \"heartbeat of keepalives\" to <sec> in 
seconds\n"
+               "\t-s        safe exit (disable Watchdog) for CTRL-c and kill 
-SIGTERM signals\n"
+               "\t--help|-h write this help message and exit\n",
+               argv[0]);
+}
+
+/*
+ * The main program.
+ */
+int main(int argc, char *argv[])
+{
+       int wd_count = 20;
+       int real_wd_count = 0;
+       int wd_keep_alive = wd_count / 2;
+       struct sigaction sa;
+       int background = 1;
+       int ac = argc;
+       char **av = argv;
+
+       memset(&sa, 0, sizeof(sa));
+
+       /* TODO: rewrite this to use getopt() */
+       while (--ac) {
+               ++av;
+               if (strcmp(*av, "-w") == 0) {
+                       if (--ac) {
+                               wd_count = atoi(*++av);
+                               printf("-w switch: set watchdog counter to %d 
sec.\n", wd_count);
+                       } else {
+                               fprintf(stderr, "-w switch must be followed to 
seconds of watchdog counter.\n");
+                               fflush(stderr);
+                               break;
+                       }
+               } else if (strcmp(*av, "-k") == 0) {
+                       if (--ac) {
+                               wd_keep_alive = atoi(*++av);
+                               printf("-k switch: set the heartbeat of 
keepalives in %d sec.\n", wd_keep_alive);
+                       } else {
+                               fprintf(stderr, "-k switch must be followed to 
seconds of heartbeat of keepalives.\n");
+                               fflush(stderr);
+                               break;
+                       }
+               } else if (strcmp(*av, "-s") == 0) {
+                       printf("-s switch: safe exit (CTRL-C and kill).\n");
+                       sa.sa_handler = safe_exit;
+                       sigaction(SIGINT, &sa, NULL);
+                       sigaction(SIGTERM, &sa, NULL);
+               } else if (strcmp(*av, FOREGROUND_FLAG) == 0) {
+                       background = 0;
+                       printf("Start in foreground mode.\n");
+               } else if ((strcmp(*av, "-h") == 0) || (strcmp(*av, "--help") 
== 0)) {
+                       usage(argv);
+                       exit(0);
+               } else {
+                       fprintf(stderr, "Unrecognized option \"%s\".\n", *av);
+                       usage(argv);
+                       exit(1);
+               }
+       }
+
+       if (background) {
+               printf("Start in deamon mode.\n");
+               vfork_daemon_rexec(1, 0, argc, argv, FOREGROUND_FLAG);
+       }
+
+       fd = open("/dev/watchdog", O_WRONLY);
+
+       if (fd == -1) {
+               perror("Watchdog device not enabled");
+               fflush(stderr);
+               exit(-1);
+       }
+
+       if (set_wd_counter(wd_count)) {
+               fprintf(stderr, "-w switch: wrong value. Please look at kernel 
log for more dettails.\n Continue with the old value\n");
+               fflush(stderr);
+       }
+
+       real_wd_count = get_wd_counter();
+       if (real_wd_count < 0) {
+               perror("Error while issue IOCTL WDIOC_GETTIMEOUT");
+       } else {
+               if (real_wd_count <= wd_keep_alive) {
+                       fprintf(stderr,
+                               "Warning watchdog counter less or equal to the 
heartbeat of keepalives: %d <= %d\n",
+                               real_wd_count, wd_keep_alive);
+                       fflush(stderr);
+               }
+       }
+
+       while (1) {
+               keep_alive();
+               sleep(wd_keep_alive);
+       }
+}
-- 
1.5.5

_______________________________________________
uClinux-dev mailing list
uClinux-dev@uclinux.org
http://mailman.uclinux.org/mailman/listinfo/uclinux-dev
This message was resent by uclinux-dev@uclinux.org
To unsubscribe see:
http://mailman.uclinux.org/mailman/options/uclinux-dev

Reply via email to