diff -r 8e55c5c11475 tools/misc/Makefile --- a/tools/misc/Makefile Wed Jul 05 18:48:41 2006 +0100 +++ b/tools/misc/Makefile Fri Jul 07 16:40:48 2006 +0900 @@ -13,10 +13,10 @@ CFLAGS += $(INCLUDES) HDRS = $(wildcard *.h) -TARGETS = xenperf xc_shadow +TARGETS = xenperf xc_shadow xenlogd INSTALL_BIN = $(TARGETS) xencons -INSTALL_SBIN = netfix xm xen-bugtool xend xenperf +INSTALL_SBIN = netfix xm xen-bugtool xend xenperf xenlogd .PHONY: all all: build diff -r 8e55c5c11475 tools/misc/xenlogd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/misc/xenlogd.c Fri Jul 07 16:40:48 2006 +0900 @@ -0,0 +1,299 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define XCDSIZE (32*1024) +#define XENHEAD "(XEN) " +#define PIDFILE "/var/run/xenlogd.pid" + +extern int xc_interface_open(void); +extern int xc_readconsolering(int, char **, int *, int); +static char *cmdname; + +void +quit(int xc, char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsyslog(LOG_KERN|LOG_ALERT, fmt, ap); + va_end(ap); + exit(xc); +} + +int +putsyslog(char *bp, int size) +{ + static char *prsvp = NULL; + static int prsvc = 0; + char *endp; + int offset; + + if ((prsvp == NULL) && ((prsvp = malloc(XCDSIZE)) == NULL)) { + quit(1, "allocate buffer failed"); + } + + bp[size] = '\0'; + + for (endp = bp + size; bp < endp; bp++) { + if (*bp == '\n') { + prsvp[prsvc] = '\0'; + if ((strncmp(prsvp, XENHEAD, strlen(XENHEAD)) == 0)) { + offset = strlen(XENHEAD); + } else { + offset = 0; + } + syslog(LOG_KERN|LOG_ALERT, "%s", prsvp + offset); + prsvc = 0; + } else { + prsvp[prsvc] = *bp; + prsvc++; + } + } + return(prsvc); +} + +static void child_exit(int sig) +{ + while (waitpid(-1, NULL, WNOHANG) > 0); +} + +static void term_daemon(int sig) +{ + unlink(PIDFILE); + quit(0, "logging ended normally."); +} + +void +daemonize(void) +{ + pid_t pid; + int fd; + int len; + int i; + int pfd[2]; + struct sigaction siga; + char buf[1024]; + + if (getppid() == 1) { + return; + } + + signal(SIGPIPE, SIG_IGN); + + if (pipe(pfd) < 0) { + quit(1, "open pipe failed"); + } + + if ((pid = fork()) > 0) { + exit(0); + } + if (pid < 0) { + quit(1, "fork failed: errno = %d", errno); + } + + setsid(); + + if ((pid = fork()) > 0) { + exit(0); + } + if (pid < 0) { + quit(1, "fork failed: errno = %d", errno); + } + + if ((fd = open("/dev/null",O_RDWR)) == -1) { + quit(1, "open /dev/null failed: errno = %d", errno); + } + + for (i = 0; i <= 2; i++) { + close(i); + dup2(fd, i); + } + + close(fd); + umask(027); + + if (chdir("/") < 0) { + quit(1, "change to root dir failed: errno = %d", errno); + } + + pid = getpid(); + snprintf(buf, sizeof(buf), "%s.%d", PIDFILE, pid); + + fd = open(buf, O_RDWR | O_CREAT | O_EXCL); + if (fd < 0) { + quit(1, "open %s failed: errno = %d", buf, errno); + } + + if (link(buf, PIDFILE) < 0) { + unlink(buf); + quit(1, "other logging daemon may keep alive"); + } + unlink(buf); + + len = sprintf(buf, "%d\n", pid); + if (write(fd, buf, len) < 0) { + quit(1, "write %s failed: errno = %d", PIDFILE, errno); + } + + siga.sa_handler = term_daemon; + sigemptyset(&siga.sa_mask); + sigaddset(&siga.sa_mask, SIGTERM); + siga.sa_flags = 0; + + signal(SIGCHLD, child_exit); + signal(SIGTSTP, SIG_IGN); + signal(SIGTTOU, SIG_IGN); + signal(SIGTTIN, SIG_IGN); + sigaction(SIGTERM, &siga, NULL); + + close(pfd[1]); + read(pfd[0], buf, sizeof(buf)); + close(pfd[0]); +} + +void +kill_daemon(void) +{ + int fd, pid, len; + char buf[1024]; + char *comm; + + fd = open(PIDFILE, O_RDWR); + if (fd < 0) { + if (errno == ENOENT) { + fprintf(stderr,"%s: no other daemon exist\n", cmdname); + } else { + perror("open error: "); + } + goto delpidfile; + } + len = read(fd, buf, sizeof(buf)); + if (len < 0) { + perror("read error: "); + goto delpidfile; + } + close(fd); + buf[len] = '\0'; + pid = atoi(buf); + + if (pid) { + snprintf(buf, sizeof(buf), "/proc/%d/stat", pid); + if ((fd = open(buf, O_RDONLY)) >= 0) { + len = read(fd, buf, sizeof(buf)); + strtok(buf, " "); + if (((comm = strtok(NULL, " ")) != NULL) + && (strcmp(comm, "(xenlogd)") == 0)) { + if (kill(pid, SIGTERM) < 0) { + perror("kill error: "); + goto delpidfile; + } + while (kill(pid, SIGTERM) == 0); + if (errno != ESRCH) { + perror("kill error: "); + } + } + } + } + + delpidfile: + if ((fd = open(PIDFILE, O_RDWR)) >= 0) { + close(fd); + unlink(PIDFILE); + fprintf(stderr, "%s: lockfile existed but no daemon alive. it was deleted.\n", cmdname); + } +} + +void usage(void) +{ + fprintf(stderr, "usage: %s [-h] [-n] [-k] [-r]\n", cmdname); + fprintf(stderr, " -h: print help\n"); + fprintf(stderr, " -n: no daemonize\n"); + fprintf(stderr, " -k: kill alive logging daemon\n"); + fprintf(stderr, " -r: restart logging daemon after kill alive one\n"); + exit(0); +} + +int +main(int argc, char *argv[]) +{ + int fd; + int rc; + int bufsize; + int opt; + char *bufaddr; + int no_daemonize = 0; + int kill_d = 0; + int restart_d = 0; + + cmdname = argv[0]; + + while ((opt = getopt(argc, argv, "hnkr")) != -1) { + switch (opt) { + case 'h': + case '?': + default: + usage(); + break; + case 'n': + no_daemonize = 1; + break; + case 'r': + restart_d = 1; + /* fall through */ + case 'k': + kill_d = 1; + break; + } + } + + openlog(XENHEAD, LOG_NDELAY|LOG_CONS, LOG_KERN); + + fd = xc_interface_open(); + if (fd < 0) { + quit(1, "failed to open xen interface"); + } + + if ((bufaddr = malloc(XCDSIZE)) ==NULL) { + quit(1, "allocate buffer failed"); + } + + if (kill_d) { + kill_daemon(); + if (!restart_d) { + exit(0); + } + } + + if (!no_daemonize) { + daemonize(); + } + + syslog(LOG_KERN|LOG_ALERT, "logging has been started."); + + for (;;) { + bufsize = XCDSIZE; + + rc = xc_readconsolering(fd, &bufaddr, &bufsize, -1); + if (rc < 0) { + quit(1, "error: read console ring: %d: errno %d", rc, errno); + } + + if (bufsize) { + if (putsyslog(bufaddr, bufsize)) { + continue; + } + } + sleep(1); + } +}