source: projects/initscripts/tags/initscripts-8.91.3/src/minilogd.c @ 1108

Revision 1108, 4.9 KB checked in by daisuke, 14 years ago (diff)

import initscripts-8.90.6 from internal cvs repository

Line 
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 program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License, version 2,
10 * as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 *
21 */
22
23#include <errno.h>
24#include <fcntl.h>
25#include <signal.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <syslog.h>
29#include <unistd.h>
30
31#include <sys/poll.h>
32#include <sys/socket.h>
33#include <sys/stat.h>
34#include <sys/un.h>
35
36static int we_own_log=0;
37static char **buffer=NULL;
38static int buflines=0;
39
40int debug;
41
42int recvsock;
43
44void alarm_handler(int x) {
45        alarm(0);
46        close(recvsock);
47        recvsock = -1;
48}
49
50void freeBuffer() {
51   struct sockaddr_un addr;
52   int sock;
53   int x=0,conn;
54   
55   bzero(&addr,sizeof(addr));
56   addr.sun_family = AF_LOCAL;
57   strncpy(addr.sun_path,_PATH_LOG,sizeof(addr.sun_path)-1);
58   /* wait for klogd to hit syslog */
59   sleep(2);
60   sock = socket(AF_LOCAL, SOCK_DGRAM,0);
61   conn=connect(sock,(struct sockaddr *) &addr,sizeof(addr));
62   while (x<buflines) {
63      if (!conn) write(sock,buffer[x],strlen(buffer[x])+1);
64      free(buffer[x]);
65      x++;
66   }
67}
68
69void cleanup(int exitcode) {
70   /* If we own the log, unlink it before trying to free our buffer.
71    * Otherwise, sending the buffer to /dev/log doesn't make much sense.... */
72   if (we_own_log) {
73      perror("wol");
74      unlink(_PATH_LOG);
75   }
76   /* Don't try to free buffer if we were called from a signal handler */
77   if (exitcode<=0) {
78       if (buffer) freeBuffer();
79       exit(exitcode);
80   } else
81      exit(exitcode+128);
82}
83
84void runDaemon(int sock) {
85   struct sockaddr_un addr;
86   int x,len,done=0;
87   int addrlen = sizeof(struct sockaddr_un);
88   char *message;
89   struct stat s1,s2;
90   struct pollfd pfds;
91   
92    daemon(0,-1);
93    /* try not to leave stale sockets lying around */
94    /* Hopefully, we won't actually get any of these */
95    signal(SIGHUP,cleanup);
96    signal(SIGINT,cleanup);
97    signal(SIGQUIT,cleanup);
98    signal(SIGILL,cleanup);
99    signal(SIGABRT,cleanup);
100    signal(SIGFPE,cleanup);
101    signal(SIGSEGV,cleanup);
102    signal(SIGPIPE,cleanup);
103    signal(SIGBUS,cleanup);
104    signal(SIGTERM,cleanup);
105   done = 0;
106   /* Get stat info on /dev/log so we can later check to make sure we
107    * still own it... */
108   if (stat(_PATH_LOG,&s1) != 0)
109          memset(&s1, '\0', sizeof(struct stat));
110   while (!done) {
111      pfds.fd = sock;
112      pfds.events = POLLIN|POLLPRI;
113      if ( ( (x=poll(&pfds,1,500))==-1) && errno !=EINTR) {
114         perror("poll");
115         cleanup(-1);
116      }
117      if ( (x>0) && pfds.revents & (POLLIN | POLLPRI)) {
118         message = calloc(8192,sizeof(char));
119         addrlen = sizeof(struct sockaddr_un);
120         recvsock = accept(sock,(struct sockaddr *) &addr, &addrlen);
121         if (recvsock == -1)
122                      continue;
123         alarm(2);
124         signal(SIGALRM, alarm_handler);
125         len = recv(recvsock,message,8192,0);
126         alarm(0);
127         close(recvsock);
128         if (len>0) {
129                 if (buflines < 200000) {
130                         if (buffer)
131                           buffer = realloc(buffer,(buflines+1)*sizeof(char *));
132                         else
133                           buffer = malloc(sizeof(char *));
134                         message[strlen(message)]='\n';
135                         buffer[buflines]=message;
136                         buflines++;
137                 }
138         }
139         else {
140            recvsock=-1;
141         }
142      }
143      if ( (x>0) && ( pfds.revents & (POLLHUP | POLLNVAL)) )
144        done = 1;
145      /* Check to see if syslogd's yanked our socket out from under us */
146      if ( (stat(_PATH_LOG,&s2)!=0) ||
147            (s1.st_ino != s2.st_ino ) || (s1.st_ctime != s2.st_ctime) ||
148            (s1.st_mtime != s2.st_mtime) ) {
149         done = 1;
150         we_own_log = 0;
151      }
152   }
153   cleanup(0);
154}
155
156int main(int argc, char **argv) {
157   struct sockaddr_un addr;
158   int sock;
159   int pid;
160   
161   /* option processing made simple... */
162   if (argc>1) debug=1;
163   /* just in case */
164   sock = open("/dev/null",O_RDWR);
165   dup2(sock,0);
166   dup2(sock,1);
167   dup2(sock,2);
168   close(sock);
169       
170   bzero(&addr, sizeof(addr));
171   addr.sun_family = AF_LOCAL;
172   strncpy(addr.sun_path,_PATH_LOG,sizeof(addr.sun_path)-1);
173   sock = socket(AF_LOCAL, SOCK_STREAM,0);
174   unlink(_PATH_LOG);
175   /* Bind socket before forking, so we know if the server started */
176   if (!bind(sock,(struct sockaddr *) &addr, sizeof(addr))) {
177      we_own_log = 1;
178      listen(sock,5);
179      if ((pid=fork())==-1) {
180         perror("fork");
181         exit(3);
182      }
183      if (pid) {
184         exit(0);
185      } else {
186          runDaemon(sock);
187          /* shouldn't get back here... */
188          exit(4);
189      }
190   } else {
191      exit(5);
192   }
193}
Note: See TracBrowser for help on using the repository browser.