]> git.pld-linux.org Git - projects/rc-scripts.git/blame - src/minilogd.c
- todo from arekm
[projects/rc-scripts.git] / src / minilogd.c
CommitLineData
35111b89
JR
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
30static int we_own_log=0;
31static char **buffer=NULL;
32static int buflines=0;
33
34int debug;
35
36int recvsock;
37
38void alarm_handler(int x) {
39 alarm(0);
40 close(recvsock);
41 recvsock = -1;
42}
43
44void 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
63void 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
78void runDaemon(int sock) {
79 struct sockaddr_un addr;
9628cdf1
ER
80 int x,len,done=0;
81 int addrlen = sizeof(struct sockaddr_un);
35111b89
JR
82 char *message;
83 struct stat s1,s2;
84 struct pollfd pfds;
85
86 daemon(0,-1);
87 /* try not to leave stale sockets lying around */
88 /* Hopefully, we won't actually get any of these */
89 signal(SIGHUP,cleanup);
90 signal(SIGINT,cleanup);
91 signal(SIGQUIT,cleanup);
92 signal(SIGILL,cleanup);
93 signal(SIGABRT,cleanup);
94 signal(SIGFPE,cleanup);
95 signal(SIGSEGV,cleanup);
96 signal(SIGPIPE,cleanup);
97 signal(SIGBUS,cleanup);
98 signal(SIGTERM,cleanup);
99 done = 0;
100 /* Get stat info on /dev/log so we can later check to make sure we
101 * still own it... */
102 if (stat(_PATH_LOG,&s1) != 0)
103 memset(&s1, '\0', sizeof(struct stat));
104 while (!done) {
105 pfds.fd = sock;
106 pfds.events = POLLIN|POLLPRI;
107 if ( ( (x=poll(&pfds,1,500))==-1) && errno !=EINTR) {
108 perror("poll");
109 cleanup(-1);
110 }
111 if ( (x>0) && pfds.revents & (POLLIN | POLLPRI)) {
112 message = calloc(8192,sizeof(char));
9628cdf1 113 addrlen = sizeof(struct sockaddr_un);
35111b89 114 recvsock = accept(sock,(struct sockaddr *) &addr, &addrlen);
9628cdf1
ER
115 if (recvsock == -1)
116 continue;
35111b89
JR
117 alarm(2);
118 signal(SIGALRM, alarm_handler);
9628cdf1 119 len = recv(recvsock,message,8192,0);
35111b89
JR
120 alarm(0);
121 close(recvsock);
122 if (len>0) {
123 if (buflines < 200000) {
124 if (buffer)
125 buffer = realloc(buffer,(buflines+1)*sizeof(char *));
126 else
127 buffer = malloc(sizeof(char *));
128 message[strlen(message)]='\n';
129 buffer[buflines]=message;
130 buflines++;
131 }
132 }
133 else {
134 recvsock=-1;
135 }
136 }
137 if ( (x>0) && ( pfds.revents & (POLLHUP | POLLNVAL)) )
138 done = 1;
139 /* Check to see if syslogd's yanked our socket out from under us */
140 if ( (stat(_PATH_LOG,&s2)!=0) ||
141 (s1.st_ino != s2.st_ino ) || (s1.st_ctime != s2.st_ctime) ||
9628cdf1 142 (s1.st_mtime != s2.st_mtime) ) {
35111b89
JR
143 done = 1;
144 we_own_log = 0;
145 }
146 }
147 cleanup(0);
148}
149
150int main(int argc, char **argv) {
151 struct sockaddr_un addr;
152 int sock;
153 int pid;
154
155 /* option processing made simple... */
156 if (argc>1) debug=1;
157 /* just in case */
158 sock = open("/dev/null",O_RDWR);
159 dup2(sock,0);
160 dup2(sock,1);
161 dup2(sock,2);
162 close(sock);
163
164 bzero(&addr, sizeof(addr));
165 addr.sun_family = AF_LOCAL;
166 strncpy(addr.sun_path,_PATH_LOG,sizeof(addr.sun_path)-1);
167 sock = socket(AF_LOCAL, SOCK_STREAM,0);
168 unlink(_PATH_LOG);
169 /* Bind socket before forking, so we know if the server started */
170 if (!bind(sock,(struct sockaddr *) &addr, sizeof(addr))) {
171 we_own_log = 1;
172 listen(sock,5);
173 if ((pid=fork())==-1) {
174 perror("fork");
175 exit(3);
176 }
177 if (pid) {
178 exit(0);
179 } else {
180 runDaemon(sock);
181 /* shouldn't get back here... */
182 exit(4);
183 }
184 } else {
185 exit(5);
186 }
187}
This page took 0.095731 seconds and 4 git commands to generate.