#include "wdt.h" #include #include #include #include #include #include #include #include #include #define WDT_DEVICE "/dev/watchdog" #define WDT_MAX_TIMEOUT 40 /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int watchdog_announce(char* name, int timeout) { int fd; unsigned char* buf; if ((timeout < 0) || (timeout > WDT_MAX_TIMEOUT)) return WDT_INVALID_TIMEOUT; fd = open(WDT_DEVICE, O_RDWR); if (fd < 0) return WDT_ALREADY_REGISTERED; buf = malloc(strlen("start") + 2 + strlen(name)); if (buf == NULL) return WDT_RESOURCE_ERROR; strcpy(buf, "start "); strcat(buf, name); if (write(fd, buf, strlen("start") + 2 + strlen(name)) < 0) switch (errno) { case EBADF: free(buf); return WDT_UNKNOWN_HANDLE; default: free(buf); return WDT_RESOURCE_ERROR; } free(buf); watchdog_settimeout(fd, timeout); close(fd); return WDT_OK; } #if 0 /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int watchdog_log(const char * __restrict format, ...) { FILE *fd; va_list arg; fd = fopen("/var/wdtlog", "a+"); va_start(arg, format); vfprintf(fd, format, arg); va_end(arg); fclose(fd); } #endif /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int watchdog_register(char* name) { int fd; unsigned char* buf; fd = open(WDT_DEVICE, O_RDWR); if (fd < 0) { return WDT_ALREADY_REGISTERED; } buf = malloc(strlen("register") + 2 + strlen(name)); if (buf == NULL) { return WDT_RESOURCE_ERROR; } strcpy(buf, "register "); strcat(buf, name); if (write(fd, buf, strlen("register") + 2 + strlen(name)) < 0) { switch (errno) { case EBADF: free(buf); return WDT_UNKNOWN_HANDLE; default: free(buf); return WDT_RESOURCE_ERROR; } } free(buf); return fd + 1; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int watchdog_get_fd(int handle) { return handle - 1; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int watchdog_release(int handle) { unsigned char *buf; handle--; buf = malloc(strlen("release") + 1); if (buf == NULL) return WDT_RESOURCE_ERROR; strcpy(buf, "release"); if (write(handle, buf, strlen("release") + 1) < 0) { switch (errno) { case EBADF: free(buf); return WDT_UNKNOWN_HANDLE; default: free(buf); return WDT_RESOURCE_ERROR; } } free(buf); close(handle); return WDT_OK; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int watchdog_settimeout(int handle, int timeout) { unsigned char *buf; handle--; if ((timeout <= 0) || (timeout > WDT_MAX_TIMEOUT)) return WDT_INVALID_TIMEOUT; buf = malloc(strlen("timeout") + 5); if (buf == NULL) return WDT_RESOURCE_ERROR; sprintf(buf, "timeout %d", timeout); if (write(handle, buf, strlen(buf)) < 0) switch (errno) { case EBADF: free(buf); return WDT_UNKNOWN_HANDLE; default: free(buf); return WDT_RESOURCE_ERROR; } free(buf); return WDT_OK; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int watchdog_trigger(int handle) { handle--; if (write(handle, "trigger", strlen("trigger")) < 0) switch (errno) { case EBADF: return WDT_UNKNOWN_HANDLE; default: return WDT_RESOURCE_ERROR; } return WDT_OK; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int watchdog_set_non_blocking(int fd) { int flags; flags = fcntl(fd, F_GETFL); if (flags == -1) { switch (errno) { case EBADF: return WDT_UNKNOWN_HANDLE; default: return WDT_RESOURCE_ERROR; } } if ((flags & O_NONBLOCK)) return WDT_OK; flags |= O_NONBLOCK; if (fcntl(fd, F_SETFL, flags)) { switch (errno) { case EBADF: return WDT_UNKNOWN_HANDLE; default: return WDT_RESOURCE_ERROR; } } return WDT_OK; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int watchdog_set_blocking(int fd) { int flags; flags = fcntl(fd, F_GETFL); if (flags == -1) { switch (errno) { case EBADF: return WDT_UNKNOWN_HANDLE; default: return WDT_RESOURCE_ERROR; } } if ((flags & O_NONBLOCK) == 0) return WDT_OK; flags &= ~O_NONBLOCK; if (fcntl(fd, F_SETFL, flags)) { switch (errno) { case EBADF: return WDT_UNKNOWN_HANDLE; default: return WDT_RESOURCE_ERROR; } } return WDT_OK; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int watchdog_wait(int handle) { char c; int ret; handle--; watchdog_set_blocking(handle); ret = read(handle, (void*)&c, 1); if (ret < 0) switch (errno) { case EBADF: return WDT_UNKNOWN_HANDLE; default: return WDT_RESOURCE_ERROR; } return WDT_REQUEST; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int watchdog_poll(int handle) { char c; int ret; handle--; watchdog_set_non_blocking(handle); ret = read(handle, (void*)&c, 1); if (ret < 0) switch (errno) { case EBADF: return WDT_UNKNOWN_HANDLE; case EAGAIN: return WDT_OK; default: return WDT_RESOURCE_ERROR; } return WDT_REQUEST; }