]> git.pld-linux.org Git - projects/rc-scripts.git/blob - src/minilogd.c
manuals in doc
[projects/rc-scripts.git] / src / minilogd.c
1
2 /* minilogd.c
3  * 
4  * A pale imitation of syslogd. Most notably, doesn't write anything
5  * anywhere except possibly back to syslogd.
6  * 
7  */
8
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <signal.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <syslog.h>
15 #include <unistd.h>
16
17 #include <sys/poll.h>
18 #include <sys/socket.h>
19 #include <sys/stat.h>
20 #include <sys/un.h>
21
22 static int we_own_log=0;
23 static char **buffer=NULL;
24 static int buflines=0;
25
26 int debug;
27
28 void freeBuffer() {
29    struct sockaddr_un addr;
30    int sock;
31    int x=0,conn;
32    
33    bzero(&addr,sizeof(addr));
34    addr.sun_family = AF_LOCAL;
35    strncpy(addr.sun_path,_PATH_LOG,sizeof(addr.sun_path)-1);
36    /* wait for klogd to hit syslog */
37    sleep(1);
38    sock = socket(AF_LOCAL, SOCK_STREAM,0);
39    conn=connect(sock,(struct sockaddr *) &addr,sizeof(addr));
40    while (x<buflines) {
41       if (!conn) write(sock,buffer[x],strlen(buffer[x])+1);
42       free(buffer[x]);
43       x++;
44    }
45 }
46
47 void cleanup(int exitcode) {
48    /* If we own the log, unlink it before trying to free our buffer.
49     * Otherwise, sending the buffer to /dev/log doesn't make much sense.... */
50    if (we_own_log) {
51       perror("wol");
52       unlink(_PATH_LOG);
53    }
54    /* Don't try to free buffer if we were called from a signal handler */
55    if (exitcode<=0) {
56        if (buffer) freeBuffer();
57        exit(exitcode);
58    } else
59       exit(exitcode+128);
60 }
61
62 void runDaemon(int sock) {
63    struct sockaddr_un addr;
64    int x,len,addrlen,recvsock,done=0;
65    char *message;
66    struct stat s1,s2;
67    struct pollfd pfds;
68     
69     daemon(0,-1);
70     /* try not to leave stale sockets lying around */
71     /* Hopefully, we won't actually get any of these */
72     signal(SIGHUP,cleanup);
73     signal(SIGINT,cleanup);
74     signal(SIGQUIT,cleanup);
75     signal(SIGILL,cleanup);
76     signal(SIGABRT,cleanup);
77     signal(SIGFPE,cleanup);
78     signal(SIGSEGV,cleanup);
79     signal(SIGPIPE,cleanup);
80     signal(SIGBUS,cleanup);
81     signal(SIGTERM,cleanup);
82    done = 0;
83    /* Get stat info on /dev/log so we can later check to make sure we
84     * still own it... */
85    stat(_PATH_LOG,&s1);
86    while (!done) {
87       pfds.fd = sock;
88       pfds.events = POLLIN|POLLPRI;
89       if ( ( (x=poll(&pfds,1,500))==-1) && errno !=EINTR) {
90          perror("poll");
91          cleanup(-1);
92       }
93       if ( (x>0) && pfds.revents & (POLLIN | POLLPRI)) {
94          message = calloc(8192,sizeof(char));
95          recvsock = accept(sock,(struct sockaddr *) &addr, &addrlen);
96          len = read(recvsock,message,8192);
97          if (buffer)
98            buffer = realloc(buffer,(buflines+1)*sizeof(char *));
99          else
100            buffer = malloc(sizeof(char *));
101          if (len>0) {
102              message[strlen(message)]='\n';
103             buffer[buflines]=message;
104             buflines++;
105             close(recvsock);
106          }
107          else {
108             close(recvsock);
109             recvsock=-1;
110          }
111       }
112       if ( (x>0) && ( pfds.revents & (POLLHUP | POLLNVAL)) )
113         done = 1;
114       /* Check to see if syslogd's yanked our socket out from under us */
115       if ( (stat(_PATH_LOG,&s2)!=0) ||
116             (s1.st_ino != s2.st_ino ) || (s1.st_ctime != s2.st_ctime) ||
117             (s1.st_mtime != s2.st_mtime) || (s1.st_atime != s2.st_atime) ) {
118          done = 1;
119          we_own_log = 0;
120       }
121    }
122    cleanup(0);
123 }
124
125 int main(int argc, char **argv) {
126    struct sockaddr_un addr;
127    int sock;
128    int pid;
129     
130    /* option processing made simple... */
131    if (argc>1) debug=1;
132    /* just in case */
133    sock = open("/dev/null",O_RDWR);
134    dup2(sock,0);
135    dup2(sock,1);
136    dup2(sock,2);
137         
138    bzero(&addr, sizeof(addr));
139    addr.sun_family = AF_LOCAL;
140    strncpy(addr.sun_path,_PATH_LOG,sizeof(addr.sun_path)-1);
141    sock = socket(AF_LOCAL, SOCK_STREAM,0);
142    unlink(_PATH_LOG);
143    /* Bind socket before forking, so we know if the server started */
144    if (!bind(sock,(struct sockaddr *) &addr, sizeof(addr))) {
145       we_own_log = 1;
146       listen(sock,5);
147       if ((pid=fork())==-1) {
148          perror("fork");
149          exit(3);
150       }
151       if (pid) {
152          exit(0);
153       } else {
154           runDaemon(sock);
155           /* shouldn't get back here... */
156           exit(4);
157       }
158    } else {
159       exit(5);
160    }
161 }
This page took 0.046375 seconds and 3 git commands to generate.