diff options
author | Judd Vinet <judd@archlinux.org> | 2003-12-21 00:48:23 +0000 |
---|---|---|
committer | Judd Vinet <judd@archlinux.org> | 2003-12-21 00:48:23 +0000 |
commit | a71e42c461da1672582143a829654049399616e7 (patch) | |
tree | 5a3c3e41a80a1781198159988e2ddf44a8395edb /minilogd.c | |
parent | 53ae13821436183990e40cffefa8c9cff4b4f2ae (diff) |
upgpkg: initscripts 0.6
Diffstat (limited to 'minilogd.c')
-rw-r--r-- | minilogd.c | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/minilogd.c b/minilogd.c new file mode 100644 index 0000000..76e4a9c --- /dev/null +++ b/minilogd.c @@ -0,0 +1,184 @@ + +/* minilogd.c + * + * A pale imitation of syslogd. Most notably, doesn't write anything + * anywhere except possibly back to syslogd. + * + */ + +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <syslog.h> +#include <unistd.h> + +#include <sys/poll.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/un.h> + +static int we_own_log=0; +static char **buffer=NULL; +static int buflines=0; + +int debug; + +int recvsock; + +void alarm_handler(int x) { + alarm(0); + close(recvsock); + recvsock = -1; +} + +void freeBuffer() { + struct sockaddr_un addr; + int sock; + int x=0,conn; + + bzero(&addr,sizeof(addr)); + addr.sun_family = AF_LOCAL; + strncpy(addr.sun_path,_PATH_LOG,sizeof(addr.sun_path)-1); + /* wait for klogd to hit syslog */ + sleep(2); + sock = socket(AF_LOCAL, SOCK_DGRAM,0); + conn=connect(sock,(struct sockaddr *) &addr,sizeof(addr)); + while (x<buflines) { + if (!conn) { + /*printf("to syslog: %s\n", buffer[x]);*/ + write(sock,buffer[x],strlen(buffer[x])+1); + } + free(buffer[x]); + x++; + } +} + +void cleanup(int exitcode) { + /* If we own the log, unlink it before trying to free our buffer. + * Otherwise, sending the buffer to /dev/log doesn't make much sense.... */ + if (we_own_log) { + perror("wol"); + unlink(_PATH_LOG); + } + /* Don't try to free buffer if we were called from a signal handler */ + if (exitcode<=0) { + if (buffer) freeBuffer(); + exit(exitcode); + } else + exit(exitcode+128); +} + +void runDaemon(int sock) { + struct sockaddr_un addr; + int x,len,addrlen,done=0; + char *message; + struct stat s1,s2; + struct pollfd pfds; + + daemon(0,-1); + /* try not to leave stale sockets lying around */ + /* Hopefully, we won't actually get any of these */ + signal(SIGHUP,cleanup); + signal(SIGINT,cleanup); + signal(SIGQUIT,cleanup); + signal(SIGILL,cleanup); + signal(SIGABRT,cleanup); + signal(SIGFPE,cleanup); + signal(SIGSEGV,cleanup); + signal(SIGPIPE,cleanup); + signal(SIGBUS,cleanup); + signal(SIGTERM,cleanup); + done = 0; + /* Get stat info on /dev/log so we can later check to make sure we + * still own it... */ + if (stat(_PATH_LOG,&s1) != 0) + memset(&s1, '\0', sizeof(struct stat)); + while (!done) { + pfds.fd = sock; + pfds.events = POLLIN|POLLPRI; + if ( ( (x=poll(&pfds,1,500))==-1) && errno !=EINTR) { + perror("poll"); + cleanup(-1); + } + if ( (x>0) && pfds.revents & (POLLIN | POLLPRI)) { + message = calloc(8192,sizeof(char)); + recvsock = accept(sock,(struct sockaddr *) &addr, &addrlen); + alarm(2); + signal(SIGALRM, alarm_handler); + len = read(recvsock,message,8192); + alarm(0); + close(recvsock); + if (len>0) { + /*printf("line recv'd: %s\n", message);*/ + if (buflines < 200000) { + if (buffer) + buffer = realloc(buffer,(buflines+1)*sizeof(char *)); + else + buffer = malloc(sizeof(char *)); + message[strlen(message)]='\n'; + buffer[buflines]=message; + buflines++; + } + } + else { + recvsock=-1; + } + } + if ( (x>0) && ( pfds.revents & (POLLHUP | POLLNVAL)) ) + done = 1; + /* Check to see if syslogd's yanked our socket out from under us */ + if ( (stat(_PATH_LOG,&s2)!=0) || + (s1.st_ino != s2.st_ino ) || (s1.st_ctime != s2.st_ctime) || + (s1.st_mtime != s2.st_mtime) ) { /*|| (s1.st_atime != s2.st_atime) ) {*/ + done = 1; + we_own_log = 0; + /*printf("someone stole our %s\n", _PATH_LOG); + printf("st_ino: %d %d\n", s1.st_ino, s2.st_ino); + printf("st_ctime: %d %d\n", s1.st_ctime, s2.st_ctime); + printf("st_atime: %d %d\n", s1.st_atime, s2.st_atime); + printf("st_mtime: %d %d\n", s1.st_mtime, s2.st_mtime);*/ + } + } + cleanup(0); +} + +int main(int argc, char **argv) { + struct sockaddr_un addr; + int sock; + int pid; + + /* option processing made simple... */ + if (argc>1) debug=1; + /* just in case */ + sock = open("/dev/null",O_RDWR); + dup2(sock,0); + dup2(sock,1); + dup2(sock,2); + + bzero(&addr, sizeof(addr)); + addr.sun_family = AF_LOCAL; + strncpy(addr.sun_path,_PATH_LOG,sizeof(addr.sun_path)-1); + sock = socket(AF_LOCAL, SOCK_STREAM,0); + unlink(_PATH_LOG); + /* Bind socket before forking, so we know if the server started */ + if (!bind(sock,(struct sockaddr *) &addr, sizeof(addr))) { + we_own_log = 1; + listen(sock,5); + if ((pid=fork())==-1) { + perror("fork"); + exit(3); + } + if (pid) { + exit(0); + } else { + /*printf("starting daemon...\n");*/ + runDaemon(sock); + /* shouldn't get back here... */ + exit(4); + } + } else { + exit(5); + } +} |