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