xref: /aosp_15_r20/external/toybox/toys/pending/syslogd.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
1*cf5a6c84SAndroid Build Coastguard Worker /* syslogd.c - a system logging utility.
2*cf5a6c84SAndroid Build Coastguard Worker  *
3*cf5a6c84SAndroid Build Coastguard Worker  * Copyright 2013 Madhur Verma <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker  * Copyright 2013 Kyungwan Han <[email protected]>
5*cf5a6c84SAndroid Build Coastguard Worker  *
6*cf5a6c84SAndroid Build Coastguard Worker  * No Standard
7*cf5a6c84SAndroid Build Coastguard Worker 
8*cf5a6c84SAndroid Build Coastguard Worker USE_SYSLOGD(NEWTOY(syslogd,">0l#<1>8=8R:b#<0>99=1s#<0=200m#<0>71582787=20O:p:f:a:nSKLD", TOYFLAG_SBIN|TOYFLAG_STAYROOT))
9*cf5a6c84SAndroid Build Coastguard Worker 
10*cf5a6c84SAndroid Build Coastguard Worker config SYSLOGD
11*cf5a6c84SAndroid Build Coastguard Worker   bool "syslogd"
12*cf5a6c84SAndroid Build Coastguard Worker   default n
13*cf5a6c84SAndroid Build Coastguard Worker   help
14*cf5a6c84SAndroid Build Coastguard Worker     usage: syslogd  [-a socket] [-O logfile] [-f config file] [-m interval]
15*cf5a6c84SAndroid Build Coastguard Worker                     [-p socket] [-s SIZE] [-b N] [-R HOST] [-l N] [-nSLKD]
16*cf5a6c84SAndroid Build Coastguard Worker 
17*cf5a6c84SAndroid Build Coastguard Worker     System logging utility
18*cf5a6c84SAndroid Build Coastguard Worker 
19*cf5a6c84SAndroid Build Coastguard Worker     -a      Extra unix socket for listen
20*cf5a6c84SAndroid Build Coastguard Worker     -O FILE Default log file <DEFAULT: /var/log/messages>
21*cf5a6c84SAndroid Build Coastguard Worker     -f FILE Config file <DEFAULT: /etc/syslog.conf>
22*cf5a6c84SAndroid Build Coastguard Worker     -p      Alternative unix domain socket <DEFAULT : /dev/log>
23*cf5a6c84SAndroid Build Coastguard Worker     -n      Avoid auto-backgrounding
24*cf5a6c84SAndroid Build Coastguard Worker     -S      Smaller output
25*cf5a6c84SAndroid Build Coastguard Worker     -m MARK interval <DEFAULT: 20 minutes> (RANGE: 0 to 71582787)
26*cf5a6c84SAndroid Build Coastguard Worker     -R HOST Log to IP or hostname on PORT (default PORT=514/UDP)"
27*cf5a6c84SAndroid Build Coastguard Worker     -L      Log locally and via network (default is network only if -R)"
28*cf5a6c84SAndroid Build Coastguard Worker     -s SIZE Max size (KB) before rotation (default:200KB, 0=off)
29*cf5a6c84SAndroid Build Coastguard Worker     -b N    rotated logs to keep (default:1, max=99, 0=purge)
30*cf5a6c84SAndroid Build Coastguard Worker     -K      Log to kernel printk buffer (use dmesg to read it)
31*cf5a6c84SAndroid Build Coastguard Worker     -l N    Log only messages more urgent than prio(default:8 max:8 min:1)
32*cf5a6c84SAndroid Build Coastguard Worker     -D      Drop duplicates
33*cf5a6c84SAndroid Build Coastguard Worker */
34*cf5a6c84SAndroid Build Coastguard Worker 
35*cf5a6c84SAndroid Build Coastguard Worker #define FOR_syslogd
36*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
37*cf5a6c84SAndroid Build Coastguard Worker 
38*cf5a6c84SAndroid Build Coastguard Worker // UNIX Sockets for listening
39*cf5a6c84SAndroid Build Coastguard Worker struct unsocks {
40*cf5a6c84SAndroid Build Coastguard Worker   struct unsocks *next;
41*cf5a6c84SAndroid Build Coastguard Worker   char *path;
42*cf5a6c84SAndroid Build Coastguard Worker   struct sockaddr_un sdu;
43*cf5a6c84SAndroid Build Coastguard Worker   int sd;
44*cf5a6c84SAndroid Build Coastguard Worker };
45*cf5a6c84SAndroid Build Coastguard Worker 
46*cf5a6c84SAndroid Build Coastguard Worker // Log file entry to log into.
47*cf5a6c84SAndroid Build Coastguard Worker struct logfile {
48*cf5a6c84SAndroid Build Coastguard Worker   struct logfile *next;
49*cf5a6c84SAndroid Build Coastguard Worker   char *filename;
50*cf5a6c84SAndroid Build Coastguard Worker   uint32_t facility[8];
51*cf5a6c84SAndroid Build Coastguard Worker   uint8_t level[LOG_NFACILITIES];
52*cf5a6c84SAndroid Build Coastguard Worker   int logfd;
53*cf5a6c84SAndroid Build Coastguard Worker   struct sockaddr_in saddr;
54*cf5a6c84SAndroid Build Coastguard Worker };
55*cf5a6c84SAndroid Build Coastguard Worker 
GLOBALS(char * socket;char * config_file;char * unix_socket;char * logfile;long interval;long rot_size;long rot_count;char * remote_log;long log_prio;struct unsocks * lsocks;struct logfile * lfiles;int sigfd[2];)56*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
57*cf5a6c84SAndroid Build Coastguard Worker   char *socket;
58*cf5a6c84SAndroid Build Coastguard Worker   char *config_file;
59*cf5a6c84SAndroid Build Coastguard Worker   char *unix_socket;
60*cf5a6c84SAndroid Build Coastguard Worker   char *logfile;
61*cf5a6c84SAndroid Build Coastguard Worker   long interval;
62*cf5a6c84SAndroid Build Coastguard Worker   long rot_size;
63*cf5a6c84SAndroid Build Coastguard Worker   long rot_count;
64*cf5a6c84SAndroid Build Coastguard Worker   char *remote_log;
65*cf5a6c84SAndroid Build Coastguard Worker   long log_prio;
66*cf5a6c84SAndroid Build Coastguard Worker 
67*cf5a6c84SAndroid Build Coastguard Worker   struct unsocks *lsocks;  // list of listen sockets
68*cf5a6c84SAndroid Build Coastguard Worker   struct logfile *lfiles;  // list of write logfiles
69*cf5a6c84SAndroid Build Coastguard Worker   int sigfd[2];
70*cf5a6c84SAndroid Build Coastguard Worker )
71*cf5a6c84SAndroid Build Coastguard Worker 
72*cf5a6c84SAndroid Build Coastguard Worker // Lookup numerical code from name
73*cf5a6c84SAndroid Build Coastguard Worker // Also used in logger
74*cf5a6c84SAndroid Build Coastguard Worker int logger_lookup(int where, char *key)
75*cf5a6c84SAndroid Build Coastguard Worker {
76*cf5a6c84SAndroid Build Coastguard Worker   CODE *w = ((CODE *[]){facilitynames, prioritynames})[where];
77*cf5a6c84SAndroid Build Coastguard Worker 
78*cf5a6c84SAndroid Build Coastguard Worker   for (; w->c_name; w++)
79*cf5a6c84SAndroid Build Coastguard Worker     if (!strcasecmp(key, w->c_name)) return w->c_val;
80*cf5a6c84SAndroid Build Coastguard Worker 
81*cf5a6c84SAndroid Build Coastguard Worker   return -1;
82*cf5a6c84SAndroid Build Coastguard Worker }
83*cf5a6c84SAndroid Build Coastguard Worker 
84*cf5a6c84SAndroid Build Coastguard Worker //search the given name and return its value
dec(int val,CODE * clist,char * buf)85*cf5a6c84SAndroid Build Coastguard Worker static char *dec(int val, CODE *clist, char *buf)
86*cf5a6c84SAndroid Build Coastguard Worker {
87*cf5a6c84SAndroid Build Coastguard Worker   for (; clist->c_name; clist++)
88*cf5a6c84SAndroid Build Coastguard Worker     if (val == clist->c_val) return clist->c_name;
89*cf5a6c84SAndroid Build Coastguard Worker   sprintf(buf, "%u", val);
90*cf5a6c84SAndroid Build Coastguard Worker 
91*cf5a6c84SAndroid Build Coastguard Worker   return buf;
92*cf5a6c84SAndroid Build Coastguard Worker }
93*cf5a6c84SAndroid Build Coastguard Worker 
94*cf5a6c84SAndroid Build Coastguard Worker /*
95*cf5a6c84SAndroid Build Coastguard Worker  * recurses the logfile list and resolves config
96*cf5a6c84SAndroid Build Coastguard Worker  * for evry file and updates facilty and log level bits.
97*cf5a6c84SAndroid Build Coastguard Worker  */
resolve_config(struct logfile * file,char * config)98*cf5a6c84SAndroid Build Coastguard Worker static int resolve_config(struct logfile *file, char *config)
99*cf5a6c84SAndroid Build Coastguard Worker {
100*cf5a6c84SAndroid Build Coastguard Worker   char *tk;
101*cf5a6c84SAndroid Build Coastguard Worker 
102*cf5a6c84SAndroid Build Coastguard Worker   for (tk = strtok(config, "; \0"); tk; tk = strtok(NULL, "; \0")) {
103*cf5a6c84SAndroid Build Coastguard Worker     char *fac = tk, *lvl;
104*cf5a6c84SAndroid Build Coastguard Worker     int i = 0;
105*cf5a6c84SAndroid Build Coastguard Worker     unsigned facval = 0;
106*cf5a6c84SAndroid Build Coastguard Worker     uint8_t set, levval, bits = 0;
107*cf5a6c84SAndroid Build Coastguard Worker 
108*cf5a6c84SAndroid Build Coastguard Worker     tk = strchr(fac, '.');
109*cf5a6c84SAndroid Build Coastguard Worker     if (!tk) return -1;
110*cf5a6c84SAndroid Build Coastguard Worker     *tk = '\0';
111*cf5a6c84SAndroid Build Coastguard Worker     lvl = tk + 1;
112*cf5a6c84SAndroid Build Coastguard Worker 
113*cf5a6c84SAndroid Build Coastguard Worker     for (;;) {
114*cf5a6c84SAndroid Build Coastguard Worker       char *nfac = strchr(fac, ',');
115*cf5a6c84SAndroid Build Coastguard Worker 
116*cf5a6c84SAndroid Build Coastguard Worker       if (nfac) *nfac = '\0';
117*cf5a6c84SAndroid Build Coastguard Worker       if (*fac == '*') {
118*cf5a6c84SAndroid Build Coastguard Worker         facval = 0xFFFFFFFF;
119*cf5a6c84SAndroid Build Coastguard Worker         if (fac[1]) return -1;
120*cf5a6c84SAndroid Build Coastguard Worker       } else {
121*cf5a6c84SAndroid Build Coastguard Worker         if ((i = logger_lookup(0, fac)) == -1) return -1;
122*cf5a6c84SAndroid Build Coastguard Worker         facval |= (1 << LOG_FAC(i));
123*cf5a6c84SAndroid Build Coastguard Worker       }
124*cf5a6c84SAndroid Build Coastguard Worker       if (nfac) fac = nfac + 1;
125*cf5a6c84SAndroid Build Coastguard Worker       else break;
126*cf5a6c84SAndroid Build Coastguard Worker     }
127*cf5a6c84SAndroid Build Coastguard Worker 
128*cf5a6c84SAndroid Build Coastguard Worker     levval = 0;
129*cf5a6c84SAndroid Build Coastguard Worker     for (tk = "!=*"; *tk; tk++, bits <<= 1) {
130*cf5a6c84SAndroid Build Coastguard Worker       if (*lvl == *tk) {
131*cf5a6c84SAndroid Build Coastguard Worker         bits++;
132*cf5a6c84SAndroid Build Coastguard Worker         lvl++;
133*cf5a6c84SAndroid Build Coastguard Worker       }
134*cf5a6c84SAndroid Build Coastguard Worker     }
135*cf5a6c84SAndroid Build Coastguard Worker     if (bits & 2) levval = 0xff;
136*cf5a6c84SAndroid Build Coastguard Worker     if (*lvl) {
137*cf5a6c84SAndroid Build Coastguard Worker       if ((i = logger_lookup(1, lvl)) == -1) return -1;
138*cf5a6c84SAndroid Build Coastguard Worker       levval |= (bits & 4) ? LOG_MASK(i) : LOG_UPTO(i);
139*cf5a6c84SAndroid Build Coastguard Worker       if (bits & 8) levval = ~levval;
140*cf5a6c84SAndroid Build Coastguard Worker     }
141*cf5a6c84SAndroid Build Coastguard Worker 
142*cf5a6c84SAndroid Build Coastguard Worker     for (i = 0, set = levval; set; set >>= 1, i++)
143*cf5a6c84SAndroid Build Coastguard Worker       if (set & 0x1) file->facility[i] |= ~facval;
144*cf5a6c84SAndroid Build Coastguard Worker     for (i = 0; i < LOG_NFACILITIES; facval >>= 1, i++)
145*cf5a6c84SAndroid Build Coastguard Worker       if (facval & 0x1) file->level[i] |= ~levval;
146*cf5a6c84SAndroid Build Coastguard Worker   }
147*cf5a6c84SAndroid Build Coastguard Worker 
148*cf5a6c84SAndroid Build Coastguard Worker   return 0;
149*cf5a6c84SAndroid Build Coastguard Worker }
150*cf5a6c84SAndroid Build Coastguard Worker 
151*cf5a6c84SAndroid Build Coastguard Worker // Parse config file and update the log file list.
parse_config_file(void)152*cf5a6c84SAndroid Build Coastguard Worker static int parse_config_file(void)
153*cf5a6c84SAndroid Build Coastguard Worker {
154*cf5a6c84SAndroid Build Coastguard Worker   struct logfile *file;
155*cf5a6c84SAndroid Build Coastguard Worker   FILE *fp;
156*cf5a6c84SAndroid Build Coastguard Worker   char *confline, *tk[2];
157*cf5a6c84SAndroid Build Coastguard Worker   int len, lineno = 0;
158*cf5a6c84SAndroid Build Coastguard Worker   size_t linelen;
159*cf5a6c84SAndroid Build Coastguard Worker   /*
160*cf5a6c84SAndroid Build Coastguard Worker    * if -K then open only /dev/kmsg
161*cf5a6c84SAndroid Build Coastguard Worker    * all other log files are neglected
162*cf5a6c84SAndroid Build Coastguard Worker    * thus no need to open config either.
163*cf5a6c84SAndroid Build Coastguard Worker    */
164*cf5a6c84SAndroid Build Coastguard Worker   if (toys.optflags & FLAG_K) {
165*cf5a6c84SAndroid Build Coastguard Worker     file = xzalloc(sizeof(struct logfile));
166*cf5a6c84SAndroid Build Coastguard Worker     file->filename = xstrdup("/dev/kmsg");
167*cf5a6c84SAndroid Build Coastguard Worker     TT.lfiles = file;
168*cf5a6c84SAndroid Build Coastguard Worker     return 0;
169*cf5a6c84SAndroid Build Coastguard Worker   }
170*cf5a6c84SAndroid Build Coastguard Worker   /*
171*cf5a6c84SAndroid Build Coastguard Worker    * if -R then add remote host to log list
172*cf5a6c84SAndroid Build Coastguard Worker    * if -L is not provided all other log
173*cf5a6c84SAndroid Build Coastguard Worker    * files are neglected thus no need to
174*cf5a6c84SAndroid Build Coastguard Worker    * open config either so just return.
175*cf5a6c84SAndroid Build Coastguard Worker    */
176*cf5a6c84SAndroid Build Coastguard Worker   if (toys.optflags & FLAG_R) {
177*cf5a6c84SAndroid Build Coastguard Worker     file = xzalloc(sizeof(struct logfile));
178*cf5a6c84SAndroid Build Coastguard Worker     file->filename = xmprintf("@%s",TT.remote_log);
179*cf5a6c84SAndroid Build Coastguard Worker     TT.lfiles = file;
180*cf5a6c84SAndroid Build Coastguard Worker     if (!(toys.optflags & FLAG_L)) return 0;
181*cf5a6c84SAndroid Build Coastguard Worker   }
182*cf5a6c84SAndroid Build Coastguard Worker   /*
183*cf5a6c84SAndroid Build Coastguard Worker    * Read config file and add logfiles to the list
184*cf5a6c84SAndroid Build Coastguard Worker    * with their configuration.
185*cf5a6c84SAndroid Build Coastguard Worker    */
186*cf5a6c84SAndroid Build Coastguard Worker   if (!(fp = fopen(TT.config_file, "r")) && (toys.optflags & FLAG_f))
187*cf5a6c84SAndroid Build Coastguard Worker     perror_exit("can't open '%s'", TT.config_file);
188*cf5a6c84SAndroid Build Coastguard Worker 
189*cf5a6c84SAndroid Build Coastguard Worker   for (linelen = 0; fp;) {
190*cf5a6c84SAndroid Build Coastguard Worker     confline = NULL;
191*cf5a6c84SAndroid Build Coastguard Worker     len = getline(&confline, &linelen, fp);
192*cf5a6c84SAndroid Build Coastguard Worker     if (len <= 0) break;
193*cf5a6c84SAndroid Build Coastguard Worker     lineno++;
194*cf5a6c84SAndroid Build Coastguard Worker     for (; *confline == ' '; confline++, len--) ;
195*cf5a6c84SAndroid Build Coastguard Worker     if ((confline[0] == '#') || (confline[0] == '\n')) continue;
196*cf5a6c84SAndroid Build Coastguard Worker     tk[0] = confline;
197*cf5a6c84SAndroid Build Coastguard Worker     for (; len && !(*tk[0]==' ' || *tk[0]=='\t'); tk[0]++, len--);
198*cf5a6c84SAndroid Build Coastguard Worker     for (tk[1] = tk[0]; len && (*tk[1]==' ' || *tk[1]=='\t'); tk[1]++, len--);
199*cf5a6c84SAndroid Build Coastguard Worker     if (!len || (len == 1 && *tk[1] == '\n')) {
200*cf5a6c84SAndroid Build Coastguard Worker       error_msg("error in '%s' at line %d", TT.config_file, lineno);
201*cf5a6c84SAndroid Build Coastguard Worker       return -1;
202*cf5a6c84SAndroid Build Coastguard Worker     }
203*cf5a6c84SAndroid Build Coastguard Worker     else if (*(tk[1] + len - 1) == '\n') *(tk[1] + len - 1) = '\0';
204*cf5a6c84SAndroid Build Coastguard Worker     *tk[0] = '\0';
205*cf5a6c84SAndroid Build Coastguard Worker     if (*tk[1] != '*') {
206*cf5a6c84SAndroid Build Coastguard Worker       file = TT.lfiles;
207*cf5a6c84SAndroid Build Coastguard Worker       while (file && strcmp(file->filename, tk[1])) file = file->next;
208*cf5a6c84SAndroid Build Coastguard Worker       if (!file) {
209*cf5a6c84SAndroid Build Coastguard Worker         file = xzalloc(sizeof(struct logfile));
210*cf5a6c84SAndroid Build Coastguard Worker         file->filename = xstrdup(tk[1]);
211*cf5a6c84SAndroid Build Coastguard Worker         file->next = TT.lfiles;
212*cf5a6c84SAndroid Build Coastguard Worker         TT.lfiles = file;
213*cf5a6c84SAndroid Build Coastguard Worker       }
214*cf5a6c84SAndroid Build Coastguard Worker       if (resolve_config(file, confline) == -1) {
215*cf5a6c84SAndroid Build Coastguard Worker         error_msg("error in '%s' at line %d", TT.config_file, lineno);
216*cf5a6c84SAndroid Build Coastguard Worker         return -1;
217*cf5a6c84SAndroid Build Coastguard Worker       }
218*cf5a6c84SAndroid Build Coastguard Worker     }
219*cf5a6c84SAndroid Build Coastguard Worker     free(confline);
220*cf5a6c84SAndroid Build Coastguard Worker   }
221*cf5a6c84SAndroid Build Coastguard Worker   /*
222*cf5a6c84SAndroid Build Coastguard Worker    * Can't open config file or support is not enabled
223*cf5a6c84SAndroid Build Coastguard Worker    * adding default logfile to the head of list.
224*cf5a6c84SAndroid Build Coastguard Worker    */
225*cf5a6c84SAndroid Build Coastguard Worker   if (!fp){
226*cf5a6c84SAndroid Build Coastguard Worker     file = xzalloc(sizeof(struct logfile));
227*cf5a6c84SAndroid Build Coastguard Worker     file->filename = xstrdup((toys.optflags & FLAG_O) ?
228*cf5a6c84SAndroid Build Coastguard Worker                      TT.logfile : "/var/log/messages"); //DEFLOGFILE
229*cf5a6c84SAndroid Build Coastguard Worker     file->next = TT.lfiles;
230*cf5a6c84SAndroid Build Coastguard Worker     TT.lfiles = file;
231*cf5a6c84SAndroid Build Coastguard Worker   } else fclose(fp);
232*cf5a6c84SAndroid Build Coastguard Worker   return 0;
233*cf5a6c84SAndroid Build Coastguard Worker }
234*cf5a6c84SAndroid Build Coastguard Worker 
235*cf5a6c84SAndroid Build Coastguard Worker // open every log file in list.
open_logfiles(void)236*cf5a6c84SAndroid Build Coastguard Worker static void open_logfiles(void)
237*cf5a6c84SAndroid Build Coastguard Worker {
238*cf5a6c84SAndroid Build Coastguard Worker   struct logfile *tfd;
239*cf5a6c84SAndroid Build Coastguard Worker 
240*cf5a6c84SAndroid Build Coastguard Worker   for (tfd = TT.lfiles; tfd; tfd = tfd->next) {
241*cf5a6c84SAndroid Build Coastguard Worker     char *p, *tmpfile;
242*cf5a6c84SAndroid Build Coastguard Worker     long port = 514;
243*cf5a6c84SAndroid Build Coastguard Worker 
244*cf5a6c84SAndroid Build Coastguard Worker     if (*tfd->filename == '@') { // network
245*cf5a6c84SAndroid Build Coastguard Worker       struct addrinfo *info, rp;
246*cf5a6c84SAndroid Build Coastguard Worker 
247*cf5a6c84SAndroid Build Coastguard Worker       tmpfile = xstrdup(tfd->filename + 1);
248*cf5a6c84SAndroid Build Coastguard Worker       if ((p = strchr(tmpfile, ':'))) {
249*cf5a6c84SAndroid Build Coastguard Worker         char *endptr;
250*cf5a6c84SAndroid Build Coastguard Worker 
251*cf5a6c84SAndroid Build Coastguard Worker         *p = '\0';
252*cf5a6c84SAndroid Build Coastguard Worker         port = strtol(++p, &endptr, 10);
253*cf5a6c84SAndroid Build Coastguard Worker         if (*endptr || endptr == p || port < 0 || port > 65535)
254*cf5a6c84SAndroid Build Coastguard Worker           error_exit("bad port in %s", tfd->filename);
255*cf5a6c84SAndroid Build Coastguard Worker       }
256*cf5a6c84SAndroid Build Coastguard Worker       memset(&rp, 0, sizeof(rp));
257*cf5a6c84SAndroid Build Coastguard Worker       rp.ai_family = AF_INET;
258*cf5a6c84SAndroid Build Coastguard Worker       rp.ai_socktype = SOCK_DGRAM;
259*cf5a6c84SAndroid Build Coastguard Worker       rp.ai_protocol = IPPROTO_UDP;
260*cf5a6c84SAndroid Build Coastguard Worker 
261*cf5a6c84SAndroid Build Coastguard Worker       if (getaddrinfo(tmpfile, NULL, &rp, &info) || !info)
262*cf5a6c84SAndroid Build Coastguard Worker         perror_exit("BAD ADDRESS: can't find : %s ", tmpfile);
263*cf5a6c84SAndroid Build Coastguard Worker       ((struct sockaddr_in*)info->ai_addr)->sin_port = htons(port);
264*cf5a6c84SAndroid Build Coastguard Worker       memcpy(&tfd->saddr, info->ai_addr, info->ai_addrlen);
265*cf5a6c84SAndroid Build Coastguard Worker       freeaddrinfo(info);
266*cf5a6c84SAndroid Build Coastguard Worker 
267*cf5a6c84SAndroid Build Coastguard Worker       tfd->logfd = xsocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
268*cf5a6c84SAndroid Build Coastguard Worker       free(tmpfile);
269*cf5a6c84SAndroid Build Coastguard Worker     } else tfd->logfd = open(tfd->filename, O_CREAT | O_WRONLY | O_APPEND, 0666);
270*cf5a6c84SAndroid Build Coastguard Worker     if (tfd->logfd < 0) {
271*cf5a6c84SAndroid Build Coastguard Worker       tfd->filename = "/dev/console";
272*cf5a6c84SAndroid Build Coastguard Worker       tfd->logfd = open(tfd->filename, O_APPEND);
273*cf5a6c84SAndroid Build Coastguard Worker     }
274*cf5a6c84SAndroid Build Coastguard Worker   }
275*cf5a6c84SAndroid Build Coastguard Worker }
276*cf5a6c84SAndroid Build Coastguard Worker 
277*cf5a6c84SAndroid Build Coastguard Worker //write to file with rotation
write_rotate(struct logfile * tf,int len)278*cf5a6c84SAndroid Build Coastguard Worker static int write_rotate(struct logfile *tf, int len)
279*cf5a6c84SAndroid Build Coastguard Worker {
280*cf5a6c84SAndroid Build Coastguard Worker   int size, isreg;
281*cf5a6c84SAndroid Build Coastguard Worker   struct stat statf;
282*cf5a6c84SAndroid Build Coastguard Worker   isreg = (!fstat(tf->logfd, &statf) && S_ISREG(statf.st_mode));
283*cf5a6c84SAndroid Build Coastguard Worker   size = statf.st_size;
284*cf5a6c84SAndroid Build Coastguard Worker 
285*cf5a6c84SAndroid Build Coastguard Worker   if ((toys.optflags & FLAG_s) || (toys.optflags & FLAG_b)) {
286*cf5a6c84SAndroid Build Coastguard Worker     if (TT.rot_size && isreg && (size + len) > (TT.rot_size*1024)) {
287*cf5a6c84SAndroid Build Coastguard Worker       if (TT.rot_count) { /* always 0..99 */
288*cf5a6c84SAndroid Build Coastguard Worker         int i = strlen(tf->filename) + 3 + 1;
289*cf5a6c84SAndroid Build Coastguard Worker         char old_file[i];
290*cf5a6c84SAndroid Build Coastguard Worker         char new_file[i];
291*cf5a6c84SAndroid Build Coastguard Worker         i = TT.rot_count - 1;
292*cf5a6c84SAndroid Build Coastguard Worker         while (1) {
293*cf5a6c84SAndroid Build Coastguard Worker           sprintf(new_file, "%s.%d", tf->filename, i);
294*cf5a6c84SAndroid Build Coastguard Worker           if (!i) break;
295*cf5a6c84SAndroid Build Coastguard Worker           sprintf(old_file, "%s.%d", tf->filename, --i);
296*cf5a6c84SAndroid Build Coastguard Worker           rename(old_file, new_file);
297*cf5a6c84SAndroid Build Coastguard Worker         }
298*cf5a6c84SAndroid Build Coastguard Worker         rename(tf->filename, new_file);
299*cf5a6c84SAndroid Build Coastguard Worker         unlink(tf->filename);
300*cf5a6c84SAndroid Build Coastguard Worker         close(tf->logfd);
301*cf5a6c84SAndroid Build Coastguard Worker         tf->logfd = open(tf->filename, O_CREAT | O_WRONLY | O_APPEND, 0666);
302*cf5a6c84SAndroid Build Coastguard Worker         if (tf->logfd < 0) {
303*cf5a6c84SAndroid Build Coastguard Worker           perror_msg("can't open %s", tf->filename);
304*cf5a6c84SAndroid Build Coastguard Worker           return -1;
305*cf5a6c84SAndroid Build Coastguard Worker         }
306*cf5a6c84SAndroid Build Coastguard Worker       }
307*cf5a6c84SAndroid Build Coastguard Worker       ftruncate(tf->logfd, 0);
308*cf5a6c84SAndroid Build Coastguard Worker     }
309*cf5a6c84SAndroid Build Coastguard Worker   }
310*cf5a6c84SAndroid Build Coastguard Worker   return write(tf->logfd, toybuf, len);
311*cf5a6c84SAndroid Build Coastguard Worker }
312*cf5a6c84SAndroid Build Coastguard Worker 
313*cf5a6c84SAndroid Build Coastguard Worker //Parse message and write to file.
logmsg(char * msg,int len)314*cf5a6c84SAndroid Build Coastguard Worker static void logmsg(char *msg, int len)
315*cf5a6c84SAndroid Build Coastguard Worker {
316*cf5a6c84SAndroid Build Coastguard Worker   time_t now;
317*cf5a6c84SAndroid Build Coastguard Worker   char *p, *ts, *lvlstr, *facstr;
318*cf5a6c84SAndroid Build Coastguard Worker   struct utsname uts;
319*cf5a6c84SAndroid Build Coastguard Worker   int pri = 0;
320*cf5a6c84SAndroid Build Coastguard Worker   struct logfile *tf = TT.lfiles;
321*cf5a6c84SAndroid Build Coastguard Worker 
322*cf5a6c84SAndroid Build Coastguard Worker   char *omsg = msg;
323*cf5a6c84SAndroid Build Coastguard Worker   int olen = len, fac, lvl;
324*cf5a6c84SAndroid Build Coastguard Worker 
325*cf5a6c84SAndroid Build Coastguard Worker   if (*msg == '<') { // Extract the priority no.
326*cf5a6c84SAndroid Build Coastguard Worker     pri = (int) strtoul(msg + 1, &p, 10);
327*cf5a6c84SAndroid Build Coastguard Worker     if (*p == '>') msg = p + 1;
328*cf5a6c84SAndroid Build Coastguard Worker   }
329*cf5a6c84SAndroid Build Coastguard Worker   /* Jan 18 00:11:22 msg...
330*cf5a6c84SAndroid Build Coastguard Worker    * 01234567890123456
331*cf5a6c84SAndroid Build Coastguard Worker    */
332*cf5a6c84SAndroid Build Coastguard Worker   if (len < 16 || msg[3] != ' ' || msg[6] != ' ' || msg[9] != ':'
333*cf5a6c84SAndroid Build Coastguard Worker       || msg[12] != ':' || msg[15] != ' ') {
334*cf5a6c84SAndroid Build Coastguard Worker     time(&now);
335*cf5a6c84SAndroid Build Coastguard Worker     ts = ctime(&now) + 4; /* skip day of week */
336*cf5a6c84SAndroid Build Coastguard Worker   } else {
337*cf5a6c84SAndroid Build Coastguard Worker     now = 0;
338*cf5a6c84SAndroid Build Coastguard Worker     ts = msg;
339*cf5a6c84SAndroid Build Coastguard Worker     msg += 16;
340*cf5a6c84SAndroid Build Coastguard Worker   }
341*cf5a6c84SAndroid Build Coastguard Worker   ts[15] = '\0';
342*cf5a6c84SAndroid Build Coastguard Worker   fac = LOG_FAC(pri);
343*cf5a6c84SAndroid Build Coastguard Worker   lvl = LOG_PRI(pri);
344*cf5a6c84SAndroid Build Coastguard Worker 
345*cf5a6c84SAndroid Build Coastguard Worker   if (toys.optflags & FLAG_K) len = sprintf(toybuf, "<%d> %s", pri, msg);
346*cf5a6c84SAndroid Build Coastguard Worker   else {
347*cf5a6c84SAndroid Build Coastguard Worker     char facbuf[12], pribuf[12];
348*cf5a6c84SAndroid Build Coastguard Worker 
349*cf5a6c84SAndroid Build Coastguard Worker     facstr = dec(pri & LOG_FACMASK, facilitynames, facbuf);
350*cf5a6c84SAndroid Build Coastguard Worker     lvlstr = dec(LOG_PRI(pri), prioritynames, pribuf);
351*cf5a6c84SAndroid Build Coastguard Worker 
352*cf5a6c84SAndroid Build Coastguard Worker     p = "local";
353*cf5a6c84SAndroid Build Coastguard Worker     if (!uname(&uts)) p = uts.nodename;
354*cf5a6c84SAndroid Build Coastguard Worker     if (toys.optflags & FLAG_S) len = sprintf(toybuf, "%s %s", ts, msg);
355*cf5a6c84SAndroid Build Coastguard Worker     else len = sprintf(toybuf, "%s %s %s.%s %s", ts, p, facstr, lvlstr, msg);
356*cf5a6c84SAndroid Build Coastguard Worker   }
357*cf5a6c84SAndroid Build Coastguard Worker   if (lvl >= TT.log_prio) return;
358*cf5a6c84SAndroid Build Coastguard Worker 
359*cf5a6c84SAndroid Build Coastguard Worker   for (; tf; tf = tf->next) {
360*cf5a6c84SAndroid Build Coastguard Worker     if (tf->logfd > 0) {
361*cf5a6c84SAndroid Build Coastguard Worker       if (!((tf->facility[lvl] & (1 << fac)) || (tf->level[fac] & (1<<lvl)))) {
362*cf5a6c84SAndroid Build Coastguard Worker         int wlen, isNetwork = *tf->filename == '@';
363*cf5a6c84SAndroid Build Coastguard Worker         if (isNetwork)
364*cf5a6c84SAndroid Build Coastguard Worker           wlen = sendto(tf->logfd, omsg, olen, 0, (struct sockaddr*)&tf->saddr, sizeof(tf->saddr));
365*cf5a6c84SAndroid Build Coastguard Worker         else wlen = write_rotate(tf, len);
366*cf5a6c84SAndroid Build Coastguard Worker         if (wlen < 0) perror_msg("write failed file : %s ", tf->filename + isNetwork);
367*cf5a6c84SAndroid Build Coastguard Worker       }
368*cf5a6c84SAndroid Build Coastguard Worker     }
369*cf5a6c84SAndroid Build Coastguard Worker   }
370*cf5a6c84SAndroid Build Coastguard Worker }
371*cf5a6c84SAndroid Build Coastguard Worker 
372*cf5a6c84SAndroid Build Coastguard Worker /*
373*cf5a6c84SAndroid Build Coastguard Worker  * closes all read and write fds
374*cf5a6c84SAndroid Build Coastguard Worker  * and frees all nodes and lists
375*cf5a6c84SAndroid Build Coastguard Worker  */
cleanup(void)376*cf5a6c84SAndroid Build Coastguard Worker static void cleanup(void)
377*cf5a6c84SAndroid Build Coastguard Worker {
378*cf5a6c84SAndroid Build Coastguard Worker   while (TT.lsocks) {
379*cf5a6c84SAndroid Build Coastguard Worker     struct unsocks *fnode = TT.lsocks;
380*cf5a6c84SAndroid Build Coastguard Worker 
381*cf5a6c84SAndroid Build Coastguard Worker     if (fnode->sd >= 0) {
382*cf5a6c84SAndroid Build Coastguard Worker       close(fnode->sd);
383*cf5a6c84SAndroid Build Coastguard Worker       unlink(fnode->path);
384*cf5a6c84SAndroid Build Coastguard Worker     }
385*cf5a6c84SAndroid Build Coastguard Worker     TT.lsocks = fnode->next;
386*cf5a6c84SAndroid Build Coastguard Worker     free(fnode);
387*cf5a6c84SAndroid Build Coastguard Worker   }
388*cf5a6c84SAndroid Build Coastguard Worker 
389*cf5a6c84SAndroid Build Coastguard Worker   while (TT.lfiles) {
390*cf5a6c84SAndroid Build Coastguard Worker     struct logfile *fnode = TT.lfiles;
391*cf5a6c84SAndroid Build Coastguard Worker 
392*cf5a6c84SAndroid Build Coastguard Worker     free(fnode->filename);
393*cf5a6c84SAndroid Build Coastguard Worker     if (fnode->logfd >= 0) close(fnode->logfd);
394*cf5a6c84SAndroid Build Coastguard Worker     TT.lfiles = fnode->next;
395*cf5a6c84SAndroid Build Coastguard Worker     free(fnode);
396*cf5a6c84SAndroid Build Coastguard Worker   }
397*cf5a6c84SAndroid Build Coastguard Worker }
398*cf5a6c84SAndroid Build Coastguard Worker 
signal_handler(int sig)399*cf5a6c84SAndroid Build Coastguard Worker static void signal_handler(int sig)
400*cf5a6c84SAndroid Build Coastguard Worker {
401*cf5a6c84SAndroid Build Coastguard Worker   unsigned char ch = sig;
402*cf5a6c84SAndroid Build Coastguard Worker   if (write(TT.sigfd[1], &ch, 1) != 1) error_msg("can't send signal");
403*cf5a6c84SAndroid Build Coastguard Worker }
404*cf5a6c84SAndroid Build Coastguard Worker 
syslogd_main(void)405*cf5a6c84SAndroid Build Coastguard Worker void syslogd_main(void)
406*cf5a6c84SAndroid Build Coastguard Worker {
407*cf5a6c84SAndroid Build Coastguard Worker   struct unsocks *tsd;
408*cf5a6c84SAndroid Build Coastguard Worker   int nfds, retval, last_len=0;
409*cf5a6c84SAndroid Build Coastguard Worker   struct timeval tv;
410*cf5a6c84SAndroid Build Coastguard Worker   fd_set rfds;        // fds for reading
411*cf5a6c84SAndroid Build Coastguard Worker   char *temp, *buffer = (toybuf +2048), *last_buf = (toybuf + 3072); //these two buffs are of 1K each
412*cf5a6c84SAndroid Build Coastguard Worker 
413*cf5a6c84SAndroid Build Coastguard Worker   if ((toys.optflags & FLAG_p) && (strlen(TT.unix_socket) > 108))
414*cf5a6c84SAndroid Build Coastguard Worker     error_exit("Socket path should not be more than 108");
415*cf5a6c84SAndroid Build Coastguard Worker 
416*cf5a6c84SAndroid Build Coastguard Worker   TT.config_file = (toys.optflags & FLAG_f) ?
417*cf5a6c84SAndroid Build Coastguard Worker                    TT.config_file : "/etc/syslog.conf"; //DEFCONFFILE
418*cf5a6c84SAndroid Build Coastguard Worker init_jumpin:
419*cf5a6c84SAndroid Build Coastguard Worker   tsd = xzalloc(sizeof(struct unsocks));
420*cf5a6c84SAndroid Build Coastguard Worker 
421*cf5a6c84SAndroid Build Coastguard Worker   tsd->path = (toys.optflags & FLAG_p) ? TT.unix_socket : "/dev/log"; // DEFLOGSOCK
422*cf5a6c84SAndroid Build Coastguard Worker   TT.lsocks = tsd;
423*cf5a6c84SAndroid Build Coastguard Worker 
424*cf5a6c84SAndroid Build Coastguard Worker   if (toys.optflags & FLAG_a) {
425*cf5a6c84SAndroid Build Coastguard Worker     for (temp = strtok(TT.socket, ":"); temp; temp = strtok(NULL, ":")) {
426*cf5a6c84SAndroid Build Coastguard Worker       if (strlen(temp) > 107) temp[108] = '\0';
427*cf5a6c84SAndroid Build Coastguard Worker       tsd = xzalloc(sizeof(struct unsocks));
428*cf5a6c84SAndroid Build Coastguard Worker       tsd->path = temp;
429*cf5a6c84SAndroid Build Coastguard Worker       tsd->next = TT.lsocks;
430*cf5a6c84SAndroid Build Coastguard Worker       TT.lsocks = tsd;
431*cf5a6c84SAndroid Build Coastguard Worker     }
432*cf5a6c84SAndroid Build Coastguard Worker   }
433*cf5a6c84SAndroid Build Coastguard Worker   /*
434*cf5a6c84SAndroid Build Coastguard Worker    * initializes unsock_t structure
435*cf5a6c84SAndroid Build Coastguard Worker    * and opens socket for reading
436*cf5a6c84SAndroid Build Coastguard Worker    * and adds to global lsock list.
437*cf5a6c84SAndroid Build Coastguard Worker   */
438*cf5a6c84SAndroid Build Coastguard Worker   nfds = 0;
439*cf5a6c84SAndroid Build Coastguard Worker   for (tsd = TT.lsocks; tsd; tsd = tsd->next) {
440*cf5a6c84SAndroid Build Coastguard Worker     tsd->sdu.sun_family = AF_UNIX;
441*cf5a6c84SAndroid Build Coastguard Worker     strcpy(tsd->sdu.sun_path, tsd->path);
442*cf5a6c84SAndroid Build Coastguard Worker     tsd->sd = socket(AF_UNIX, SOCK_DGRAM, 0);
443*cf5a6c84SAndroid Build Coastguard Worker     if (tsd->sd < 0) {
444*cf5a6c84SAndroid Build Coastguard Worker       perror_msg("OPEN SOCKS : failed");
445*cf5a6c84SAndroid Build Coastguard Worker       continue;
446*cf5a6c84SAndroid Build Coastguard Worker     }
447*cf5a6c84SAndroid Build Coastguard Worker     unlink(tsd->sdu.sun_path);
448*cf5a6c84SAndroid Build Coastguard Worker     if (bind(tsd->sd, (struct sockaddr *) &tsd->sdu, sizeof(tsd->sdu))) {
449*cf5a6c84SAndroid Build Coastguard Worker       perror_msg("BIND SOCKS : failed sock : %s", tsd->sdu.sun_path);
450*cf5a6c84SAndroid Build Coastguard Worker       close(tsd->sd);
451*cf5a6c84SAndroid Build Coastguard Worker       continue;
452*cf5a6c84SAndroid Build Coastguard Worker     }
453*cf5a6c84SAndroid Build Coastguard Worker     chmod(tsd->path, 0777);
454*cf5a6c84SAndroid Build Coastguard Worker     nfds++;
455*cf5a6c84SAndroid Build Coastguard Worker   }
456*cf5a6c84SAndroid Build Coastguard Worker   if (!nfds) {
457*cf5a6c84SAndroid Build Coastguard Worker     error_msg("Can't open single socket for listening.");
458*cf5a6c84SAndroid Build Coastguard Worker     goto clean_and_exit;
459*cf5a6c84SAndroid Build Coastguard Worker   }
460*cf5a6c84SAndroid Build Coastguard Worker 
461*cf5a6c84SAndroid Build Coastguard Worker   // Setup signals
462*cf5a6c84SAndroid Build Coastguard Worker   xpipe(TT.sigfd);
463*cf5a6c84SAndroid Build Coastguard Worker 
464*cf5a6c84SAndroid Build Coastguard Worker   fcntl(TT.sigfd[1] , F_SETFD, FD_CLOEXEC);
465*cf5a6c84SAndroid Build Coastguard Worker   fcntl(TT.sigfd[0] , F_SETFD, FD_CLOEXEC);
466*cf5a6c84SAndroid Build Coastguard Worker   int flags = fcntl(TT.sigfd[1], F_GETFL);
467*cf5a6c84SAndroid Build Coastguard Worker   fcntl(TT.sigfd[1], F_SETFL, flags | O_NONBLOCK);
468*cf5a6c84SAndroid Build Coastguard Worker   signal(SIGHUP, signal_handler);
469*cf5a6c84SAndroid Build Coastguard Worker   signal(SIGTERM, signal_handler);
470*cf5a6c84SAndroid Build Coastguard Worker   signal(SIGINT, signal_handler);
471*cf5a6c84SAndroid Build Coastguard Worker   signal(SIGQUIT, signal_handler);
472*cf5a6c84SAndroid Build Coastguard Worker 
473*cf5a6c84SAndroid Build Coastguard Worker   if (parse_config_file() == -1) goto clean_and_exit;
474*cf5a6c84SAndroid Build Coastguard Worker   open_logfiles();
475*cf5a6c84SAndroid Build Coastguard Worker   if (!(toys.optflags & FLAG_n)) {
476*cf5a6c84SAndroid Build Coastguard Worker     daemon(0, 0);
477*cf5a6c84SAndroid Build Coastguard Worker     //don't daemonize again if SIGHUP received.
478*cf5a6c84SAndroid Build Coastguard Worker     toys.optflags |= FLAG_n;
479*cf5a6c84SAndroid Build Coastguard Worker   }
480*cf5a6c84SAndroid Build Coastguard Worker   xpidfile("syslogd");
481*cf5a6c84SAndroid Build Coastguard Worker 
482*cf5a6c84SAndroid Build Coastguard Worker   logmsg("<46>Toybox: syslogd started", 27); //27 : the length of message
483*cf5a6c84SAndroid Build Coastguard Worker   for (;;) {
484*cf5a6c84SAndroid Build Coastguard Worker     // Add opened socks to rfds for select()
485*cf5a6c84SAndroid Build Coastguard Worker     FD_ZERO(&rfds);
486*cf5a6c84SAndroid Build Coastguard Worker     for (tsd = TT.lsocks; tsd; tsd = tsd->next) FD_SET(tsd->sd, &rfds);
487*cf5a6c84SAndroid Build Coastguard Worker     FD_SET(TT.sigfd[0], &rfds);
488*cf5a6c84SAndroid Build Coastguard Worker     tv.tv_usec = 0;
489*cf5a6c84SAndroid Build Coastguard Worker     tv.tv_sec = TT.interval*60;
490*cf5a6c84SAndroid Build Coastguard Worker 
491*cf5a6c84SAndroid Build Coastguard Worker     retval = select(TT.sigfd[0] + 1, &rfds, NULL, NULL, (TT.interval)?&tv:NULL);
492*cf5a6c84SAndroid Build Coastguard Worker     if (retval < 0) {
493*cf5a6c84SAndroid Build Coastguard Worker       if (errno != EINTR) perror_msg("Error in select ");
494*cf5a6c84SAndroid Build Coastguard Worker     }
495*cf5a6c84SAndroid Build Coastguard Worker     else if (!retval) logmsg("<46>-- MARK --", 14);
496*cf5a6c84SAndroid Build Coastguard Worker     else if (FD_ISSET(TT.sigfd[0], &rfds)) { /* May be a signal */
497*cf5a6c84SAndroid Build Coastguard Worker       unsigned char sig;
498*cf5a6c84SAndroid Build Coastguard Worker 
499*cf5a6c84SAndroid Build Coastguard Worker       if (read(TT.sigfd[0], &sig, 1) != 1) {
500*cf5a6c84SAndroid Build Coastguard Worker         error_msg("signal read failed.\n");
501*cf5a6c84SAndroid Build Coastguard Worker         continue;
502*cf5a6c84SAndroid Build Coastguard Worker       }
503*cf5a6c84SAndroid Build Coastguard Worker       switch(sig) {
504*cf5a6c84SAndroid Build Coastguard Worker         case SIGTERM:    /* FALLTHROUGH */
505*cf5a6c84SAndroid Build Coastguard Worker         case SIGINT:     /* FALLTHROUGH */
506*cf5a6c84SAndroid Build Coastguard Worker         case SIGQUIT:
507*cf5a6c84SAndroid Build Coastguard Worker           logmsg("<46>syslogd exiting", 19);
508*cf5a6c84SAndroid Build Coastguard Worker           if (CFG_TOYBOX_FREE ) cleanup();
509*cf5a6c84SAndroid Build Coastguard Worker           signal(sig, SIG_DFL);
510*cf5a6c84SAndroid Build Coastguard Worker           sigset_t ss;
511*cf5a6c84SAndroid Build Coastguard Worker           sigemptyset(&ss);
512*cf5a6c84SAndroid Build Coastguard Worker           sigaddset(&ss, sig);
513*cf5a6c84SAndroid Build Coastguard Worker           sigprocmask(SIG_UNBLOCK, &ss, NULL);
514*cf5a6c84SAndroid Build Coastguard Worker           raise(sig);
515*cf5a6c84SAndroid Build Coastguard Worker           _exit(1);  /* Should not reach it */
516*cf5a6c84SAndroid Build Coastguard Worker           break;
517*cf5a6c84SAndroid Build Coastguard Worker         case SIGHUP:
518*cf5a6c84SAndroid Build Coastguard Worker           logmsg("<46>syslogd exiting", 19);
519*cf5a6c84SAndroid Build Coastguard Worker           cleanup(); //cleanup is done, as we restart syslog.
520*cf5a6c84SAndroid Build Coastguard Worker           goto init_jumpin;
521*cf5a6c84SAndroid Build Coastguard Worker         default: break;
522*cf5a6c84SAndroid Build Coastguard Worker       }
523*cf5a6c84SAndroid Build Coastguard Worker     } else { /* Some activity on listen sockets. */
524*cf5a6c84SAndroid Build Coastguard Worker       for (tsd = TT.lsocks; tsd; tsd = tsd->next) {
525*cf5a6c84SAndroid Build Coastguard Worker         int sd = tsd->sd;
526*cf5a6c84SAndroid Build Coastguard Worker         if (FD_ISSET(sd, &rfds)) {
527*cf5a6c84SAndroid Build Coastguard Worker           // Buffer is of 1 KiB, hence reading only 1022 bytes, reserving 1
528*cf5a6c84SAndroid Build Coastguard Worker           // for '\n' and 1 for '\0'
529*cf5a6c84SAndroid Build Coastguard Worker           int len = read(sd, buffer, 1022);
530*cf5a6c84SAndroid Build Coastguard Worker 
531*cf5a6c84SAndroid Build Coastguard Worker           // The syslog function's documentation says that a trailing '\n' is
532*cf5a6c84SAndroid Build Coastguard Worker           // optional. We trim any that are present, and then append one.
533*cf5a6c84SAndroid Build Coastguard Worker           while (len > 0 &&
534*cf5a6c84SAndroid Build Coastguard Worker                  (buffer[len - 1] == '\n' || buffer[len - 1] == '\0')) {
535*cf5a6c84SAndroid Build Coastguard Worker             --len;
536*cf5a6c84SAndroid Build Coastguard Worker           }
537*cf5a6c84SAndroid Build Coastguard Worker 
538*cf5a6c84SAndroid Build Coastguard Worker           if (len > 0) {
539*cf5a6c84SAndroid Build Coastguard Worker             buffer[len++] = '\n';
540*cf5a6c84SAndroid Build Coastguard Worker             buffer[len] = '\0';
541*cf5a6c84SAndroid Build Coastguard Worker             if((toys.optflags & FLAG_D) && (len == last_len))
542*cf5a6c84SAndroid Build Coastguard Worker               if (!memcmp(last_buf, buffer, len)) break;
543*cf5a6c84SAndroid Build Coastguard Worker 
544*cf5a6c84SAndroid Build Coastguard Worker             memcpy(last_buf, buffer, len);
545*cf5a6c84SAndroid Build Coastguard Worker             last_len = len;
546*cf5a6c84SAndroid Build Coastguard Worker             logmsg(buffer, len);
547*cf5a6c84SAndroid Build Coastguard Worker           }
548*cf5a6c84SAndroid Build Coastguard Worker           break;
549*cf5a6c84SAndroid Build Coastguard Worker         }
550*cf5a6c84SAndroid Build Coastguard Worker       }
551*cf5a6c84SAndroid Build Coastguard Worker     }
552*cf5a6c84SAndroid Build Coastguard Worker   }
553*cf5a6c84SAndroid Build Coastguard Worker clean_and_exit:
554*cf5a6c84SAndroid Build Coastguard Worker   logmsg("<46>syslogd exiting", 19);
555*cf5a6c84SAndroid Build Coastguard Worker   if (CFG_TOYBOX_FREE ) cleanup();
556*cf5a6c84SAndroid Build Coastguard Worker }
557