]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/syslogd/syslogd.c
Add more #ifdef INET and INET6.
[FreeBSD/FreeBSD.git] / usr.sbin / syslogd / syslogd.c
1 /*
2  * Copyright (c) 1983, 1988, 1993, 1994
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 4. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #ifndef lint
31 static const char copyright[] =
32 "@(#) Copyright (c) 1983, 1988, 1993, 1994\n\
33         The Regents of the University of California.  All rights reserved.\n";
34 #endif /* not lint */
35
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)syslogd.c   8.3 (Berkeley) 4/4/94";
39 #endif
40 #endif /* not lint */
41
42 #include <sys/cdefs.h>
43 __FBSDID("$FreeBSD$");
44
45 /*
46  *  syslogd -- log system messages
47  *
48  * This program implements a system log. It takes a series of lines.
49  * Each line may have a priority, signified as "<n>" as
50  * the first characters of the line.  If this is
51  * not present, a default priority is used.
52  *
53  * To kill syslogd, send a signal 15 (terminate).  A signal 1 (hup) will
54  * cause it to reread its configuration file.
55  *
56  * Defined Constants:
57  *
58  * MAXLINE -- the maximum line length that can be handled.
59  * DEFUPRI -- the default priority for user messages
60  * DEFSPRI -- the default priority for kernel messages
61  *
62  * Author: Eric Allman
63  * extensive changes by Ralph Campbell
64  * more extensive changes by Eric Allman (again)
65  * Extension to log by program name as well as facility and priority
66  *   by Peter da Silva.
67  * -u and -v by Harlan Stenn.
68  * Priority comparison code by Harlan Stenn.
69  */
70
71 #define MAXLINE         1024            /* maximum line length */
72 #define MAXSVLINE       MAXLINE         /* maximum saved line length */
73 #define DEFUPRI         (LOG_USER|LOG_NOTICE)
74 #define DEFSPRI         (LOG_KERN|LOG_CRIT)
75 #define TIMERINTVL      30              /* interval for checking flush, mark */
76 #define TTYMSGTIME      1               /* timeout passed to ttymsg */
77 #define RCVBUF_MINSIZE  (80 * 1024)     /* minimum size of dgram rcv buffer */
78
79 #include <sys/param.h>
80 #include <sys/ioctl.h>
81 #include <sys/mman.h>
82 #include <sys/stat.h>
83 #include <sys/wait.h>
84 #include <sys/socket.h>
85 #include <sys/queue.h>
86 #include <sys/uio.h>
87 #include <sys/un.h>
88 #include <sys/time.h>
89 #include <sys/resource.h>
90 #include <sys/syslimits.h>
91
92 #if defined(INET) || defined(INET6) 
93 #include <netinet/in.h>
94 #include <arpa/inet.h>
95 #endif
96 #include <netdb.h>
97
98 #include <ctype.h>
99 #include <dirent.h>
100 #include <err.h>
101 #include <errno.h>
102 #include <fcntl.h>
103 #include <fnmatch.h>
104 #include <libutil.h>
105 #include <limits.h>
106 #include <paths.h>
107 #include <signal.h>
108 #include <stdio.h>
109 #include <stdlib.h>
110 #include <string.h>
111 #include <sysexits.h>
112 #include <unistd.h>
113 #include <utmpx.h>
114
115 #include "pathnames.h"
116 #include "ttymsg.h"
117
118 #define SYSLOG_NAMES
119 #include <sys/syslog.h>
120
121 static const char *ConfFile = _PATH_LOGCONF;
122 static const char *PidFile = _PATH_LOGPID;
123 static const char ctty[] = _PATH_CONSOLE;
124 static const char include_str[] = "include";
125 static const char include_ext[] = ".conf";
126
127 #define dprintf         if (Debug) printf
128
129 #define MAXUNAMES       20      /* maximum number of user names */
130
131 #define sstosa(ss)      ((struct sockaddr *)(ss))
132 #ifdef INET
133 #define sstosin(ss)     ((struct sockaddr_in *)(void *)(ss))
134 #define satosin(sa)     ((struct sockaddr_in *)(void *)(sa))
135 #endif
136 #ifdef INET6
137 #define sstosin6(ss)    ((struct sockaddr_in6 *)(void *)(ss))
138 #define satosin6(sa)    ((struct sockaddr_in6 *)(void *)(sa))
139 #define s6_addr32       __u6_addr.__u6_addr32
140 #define IN6_ARE_MASKED_ADDR_EQUAL(d, a, m)      (       \
141         (((d)->s6_addr32[0] ^ (a)->s6_addr32[0]) & (m)->s6_addr32[0]) == 0 && \
142         (((d)->s6_addr32[1] ^ (a)->s6_addr32[1]) & (m)->s6_addr32[1]) == 0 && \
143         (((d)->s6_addr32[2] ^ (a)->s6_addr32[2]) & (m)->s6_addr32[2]) == 0 && \
144         (((d)->s6_addr32[3] ^ (a)->s6_addr32[3]) & (m)->s6_addr32[3]) == 0 )
145 #endif
146 /*
147  * List of peers and sockets for binding.
148  */
149 struct peer {
150         const char      *pe_name;
151         const char      *pe_serv;
152         mode_t          pe_mode;
153         STAILQ_ENTRY(peer)      next;
154 };
155 static STAILQ_HEAD(, peer) pqueue = STAILQ_HEAD_INITIALIZER(pqueue);
156
157 struct socklist {
158         struct sockaddr_storage sl_ss;
159         int                     sl_socket;
160         struct peer             *sl_peer;
161         int                     (*sl_recv)(struct socklist *);
162         STAILQ_ENTRY(socklist)  next;
163 };
164 static STAILQ_HEAD(, socklist) shead = STAILQ_HEAD_INITIALIZER(shead);
165
166 /*
167  * Flags to logmsg().
168  */
169
170 #define IGN_CONS        0x001   /* don't print on console */
171 #define SYNC_FILE       0x002   /* do fsync on file after printing */
172 #define ADDDATE         0x004   /* add a date to the message */
173 #define MARK            0x008   /* this message is a mark */
174 #define ISKERNEL        0x010   /* kernel generated message */
175
176 /*
177  * This structure represents the files that will have log
178  * copies printed.
179  * We require f_file to be valid if f_type is F_FILE, F_CONSOLE, F_TTY
180  * or if f_type if F_PIPE and f_pid > 0.
181  */
182
183 struct filed {
184         STAILQ_ENTRY(filed)     next;   /* next in linked list */
185         short   f_type;                 /* entry type, see below */
186         short   f_file;                 /* file descriptor */
187         time_t  f_time;                 /* time this was last written */
188         char    *f_host;                /* host from which to recd. */
189         u_char  f_pmask[LOG_NFACILITIES+1];     /* priority mask */
190         u_char  f_pcmp[LOG_NFACILITIES+1];      /* compare priority */
191 #define PRI_LT  0x1
192 #define PRI_EQ  0x2
193 #define PRI_GT  0x4
194         char    *f_program;             /* program this applies to */
195         union {
196                 char    f_uname[MAXUNAMES][MAXLOGNAME];
197                 struct {
198                         char    f_hname[MAXHOSTNAMELEN];
199                         struct addrinfo *f_addr;
200
201                 } f_forw;               /* forwarding address */
202                 char    f_fname[MAXPATHLEN];
203                 struct {
204                         char    f_pname[MAXPATHLEN];
205                         pid_t   f_pid;
206                 } f_pipe;
207         } f_un;
208 #define fu_uname        f_un.f_uname
209 #define fu_forw_hname   f_un.f_forw.f_hname
210 #define fu_forw_addr    f_un.f_forw.f_addr
211 #define fu_fname        f_un.f_fname
212 #define fu_pipe_pname   f_un.f_pipe.f_pname
213 #define fu_pipe_pid     f_un.f_pipe.f_pid
214         char    f_prevline[MAXSVLINE];          /* last message logged */
215         char    f_lasttime[16];                 /* time of last occurrence */
216         char    f_prevhost[MAXHOSTNAMELEN];     /* host from which recd. */
217         int     f_prevpri;                      /* pri of f_prevline */
218         int     f_prevlen;                      /* length of f_prevline */
219         int     f_prevcount;                    /* repetition cnt of prevline */
220         u_int   f_repeatcount;                  /* number of "repeated" msgs */
221         int     f_flags;                        /* file-specific flags */
222 #define FFLAG_SYNC 0x01
223 #define FFLAG_NEEDSYNC  0x02
224 };
225
226 /*
227  * Queue of about-to-be dead processes we should watch out for.
228  */
229 struct deadq_entry {
230         pid_t                           dq_pid;
231         int                             dq_timeout;
232         TAILQ_ENTRY(deadq_entry)        dq_entries;
233 };
234 static TAILQ_HEAD(, deadq_entry) deadq_head =
235     TAILQ_HEAD_INITIALIZER(deadq_head);
236
237 /*
238  * The timeout to apply to processes waiting on the dead queue.  Unit
239  * of measure is `mark intervals', i.e. 20 minutes by default.
240  * Processes on the dead queue will be terminated after that time.
241  */
242
243 #define  DQ_TIMO_INIT   2
244
245 /*
246  * Struct to hold records of network addresses that are allowed to log
247  * to us.
248  */
249 struct allowedpeer {
250         int isnumeric;
251         u_short port;
252         union {
253                 struct {
254                         struct sockaddr_storage addr;
255                         struct sockaddr_storage mask;
256                 } numeric;
257                 char *name;
258         } u;
259 #define a_addr u.numeric.addr
260 #define a_mask u.numeric.mask
261 #define a_name u.name
262         STAILQ_ENTRY(allowedpeer)       next;
263 };
264 static STAILQ_HEAD(, allowedpeer) aphead = STAILQ_HEAD_INITIALIZER(aphead);
265
266
267 /*
268  * Intervals at which we flush out "message repeated" messages,
269  * in seconds after previous message is logged.  After each flush,
270  * we move to the next interval until we reach the largest.
271  */
272 static int repeatinterval[] = { 30, 120, 600 }; /* # of secs before flush */
273 #define MAXREPEAT       (nitems(repeatinterval) - 1)
274 #define REPEATTIME(f)   ((f)->f_time + repeatinterval[(f)->f_repeatcount])
275 #define BACKOFF(f)      do {                                            \
276                                 if (++(f)->f_repeatcount > MAXREPEAT)   \
277                                         (f)->f_repeatcount = MAXREPEAT; \
278                         } while (0)
279
280 /* values for f_type */
281 #define F_UNUSED        0               /* unused entry */
282 #define F_FILE          1               /* regular file */
283 #define F_TTY           2               /* terminal */
284 #define F_CONSOLE       3               /* console terminal */
285 #define F_FORW          4               /* remote machine */
286 #define F_USERS         5               /* list of users */
287 #define F_WALL          6               /* everyone logged on */
288 #define F_PIPE          7               /* pipe to program */
289
290 static const char *TypeNames[8] = {
291         "UNUSED",       "FILE",         "TTY",          "CONSOLE",
292         "FORW",         "USERS",        "WALL",         "PIPE"
293 };
294
295 static STAILQ_HEAD(, filed) fhead =
296     STAILQ_HEAD_INITIALIZER(fhead);     /* Log files that we write to */
297 static struct filed consfile;   /* Console */
298
299 static int      Debug;          /* debug flag */
300 static int      Foreground = 0; /* Run in foreground, instead of daemonizing */
301 static int      resolve = 1;    /* resolve hostname */
302 static char     LocalHostName[MAXHOSTNAMELEN];  /* our hostname */
303 static const char *LocalDomain; /* our local domain name */
304 static int      Initialized;    /* set when we have initialized ourselves */
305 static int      MarkInterval = 20 * 60; /* interval between marks in seconds */
306 static int      MarkSeq;        /* mark sequence number */
307 static int      NoBind;         /* don't bind() as suggested by RFC 3164 */
308 static int      SecureMode;     /* when true, receive only unix domain socks */
309 #ifdef INET6
310 static int      family = PF_UNSPEC; /* protocol family (IPv4, IPv6 or both) */
311 #else
312 static int      family = PF_INET; /* protocol family (IPv4 only) */
313 #endif
314 static int      mask_C1 = 1;    /* mask characters from 0x80 - 0x9F */
315 static int      send_to_all;    /* send message to all IPv4/IPv6 addresses */
316 static int      use_bootfile;   /* log entire bootfile for every kern msg */
317 static int      no_compress;    /* don't compress messages (1=pipes, 2=all) */
318 static int      logflags = O_WRONLY|O_APPEND; /* flags used to open log files */
319
320 static char     bootfile[MAXLINE+1]; /* booted kernel file */
321
322 static int      RemoteAddDate;  /* Always set the date on remote messages */
323
324 static int      UniquePriority; /* Only log specified priority? */
325 static int      LogFacPri;      /* Put facility and priority in log message: */
326                                 /* 0=no, 1=numeric, 2=names */
327 static int      KeepKernFac;    /* Keep remotely logged kernel facility */
328 static int      needdofsync = 0; /* Are any file(s) waiting to be fsynced? */
329 static struct pidfh *pfh;
330 static int      sigpipe[2];     /* Pipe to catch a signal during select(). */
331
332 static volatile sig_atomic_t MarkSet, WantDie, WantInitialize, WantReapchild;
333
334 static int      allowaddr(char *);
335 static int      addfile(struct filed *);
336 static int      addpeer(struct peer *);
337 static int      addsock(struct sockaddr *, socklen_t, struct socklist *);
338 static struct filed *cfline(const char *, const char *, const char *);
339 static const char *cvthname(struct sockaddr *);
340 static void     deadq_enter(pid_t, const char *);
341 static int      deadq_remove(struct deadq_entry *);
342 static int      deadq_removebypid(pid_t);
343 static int      decode(const char *, const CODE *);
344 static void     die(int) __dead2;
345 static void     dodie(int);
346 static void     dofsync(void);
347 static void     domark(int);
348 static void     fprintlog(struct filed *, int, const char *);
349 static void     init(int);
350 static void     logerror(const char *);
351 static void     logmsg(int, const char *, const char *, int);
352 static void     log_deadchild(pid_t, int, const char *);
353 static void     markit(void);
354 static int      socksetup(struct peer *);
355 static int      socklist_recv_file(struct socklist *);
356 static int      socklist_recv_sock(struct socklist *);
357 static int      socklist_recv_signal(struct socklist *);
358 static void     sighandler(int);
359 static int      skip_message(const char *, const char *, int);
360 static void     printline(const char *, char *, int);
361 static void     printsys(char *);
362 static int      p_open(const char *, pid_t *);
363 static void     reapchild(int);
364 static const char *ttymsg_check(struct iovec *, int, char *, int);
365 static void     usage(void);
366 static int      validate(struct sockaddr *, const char *);
367 static void     unmapped(struct sockaddr *);
368 static void     wallmsg(struct filed *, struct iovec *, const int iovlen);
369 static int      waitdaemon(int);
370 static void     timedout(int);
371 static void     increase_rcvbuf(int);
372
373 static void
374 close_filed(struct filed *f)
375 {
376
377         if (f == NULL || f->f_file == -1)
378                 return;
379
380         switch (f->f_type) {
381         case F_FILE:
382         case F_TTY:
383         case F_CONSOLE:
384         case F_FORW:
385                 f->f_type = F_UNUSED;
386                 break;
387         case F_PIPE:
388                 f->fu_pipe_pid = 0;
389                 break;
390         }
391         (void)close(f->f_file);
392         f->f_file = -1;
393 }
394
395 static int
396 addfile(struct filed *f0)
397 {
398         struct filed *f;
399
400         f = calloc(1, sizeof(*f));
401         if (f == NULL)
402                 err(1, "malloc failed");
403         *f = *f0;
404         STAILQ_INSERT_TAIL(&fhead, f, next);
405
406         return (0);
407 }
408
409 static int
410 addpeer(struct peer *pe0)
411 {
412         struct peer *pe;
413
414         pe = calloc(1, sizeof(*pe));
415         if (pe == NULL)
416                 err(1, "malloc failed");
417         *pe = *pe0;
418         STAILQ_INSERT_TAIL(&pqueue, pe, next);
419
420         return (0);
421 }
422
423 static int
424 addsock(struct sockaddr *sa, socklen_t sa_len, struct socklist *sl0)
425 {
426         struct socklist *sl;
427
428         sl = calloc(1, sizeof(*sl));
429         if (sl == NULL)
430                 err(1, "malloc failed");
431         *sl = *sl0;
432         if (sa != NULL && sa_len > 0)
433                 memcpy(&sl->sl_ss, sa, sa_len);
434         STAILQ_INSERT_TAIL(&shead, sl, next);
435
436         return (0);
437 }
438
439 int
440 main(int argc, char *argv[])
441 {
442         int ch, i, s, fdsrmax = 0, bflag = 0, pflag = 0, Sflag = 0;
443         fd_set *fdsr = NULL;
444         struct timeval tv, *tvp;
445         struct peer *pe;
446         struct socklist *sl;
447         pid_t ppid = 1, spid;
448         char *p;
449
450         if (madvise(NULL, 0, MADV_PROTECT) != 0)
451                 dprintf("madvise() failed: %s\n", strerror(errno));
452
453         while ((ch = getopt(argc, argv, "468Aa:b:cCdf:Fkl:m:nNop:P:sS:Tuv"))
454             != -1)
455                 switch (ch) {
456 #ifdef INET
457                 case '4':
458                         family = PF_INET;
459                         break;
460 #endif
461 #ifdef INET6
462                 case '6':
463                         family = PF_INET6;
464                         break;
465 #endif
466                 case '8':
467                         mask_C1 = 0;
468                         break;
469                 case 'A':
470                         send_to_all++;
471                         break;
472                 case 'a':               /* allow specific network addresses only */
473                         if (allowaddr(optarg) == -1)
474                                 usage();
475                         break;
476                 case 'b':
477                         bflag = 1;
478                         if ((p = strchr(optarg, ':')) == NULL) {
479                                 /* A hostname or filename only. */
480                                 addpeer(&(struct peer){
481                                         .pe_name = optarg,
482                                         .pe_serv = "syslog"
483                                 });
484                         } else {
485                                 /* The case of "name:service". */
486                                 *p++ = '\0';
487                                 addpeer(&(struct peer){
488                                         .pe_serv = p,
489                                         .pe_name = (strlen(optarg) == 0) ?
490                                             NULL : optarg,
491                                 });
492                         }
493                         break;
494                 case 'c':
495                         no_compress++;
496                         break;
497                 case 'C':
498                         logflags |= O_CREAT;
499                         break;
500                 case 'd':               /* debug */
501                         Debug++;
502                         break;
503                 case 'f':               /* configuration file */
504                         ConfFile = optarg;
505                         break;
506                 case 'F':               /* run in foreground instead of daemon */
507                         Foreground++;
508                         break;
509                 case 'k':               /* keep remote kern fac */
510                         KeepKernFac = 1;
511                         break;
512                 case 'l':
513                 case 'p':
514                 case 'S':
515                     {
516                         long    perml;
517                         mode_t  mode;
518                         char    *name, *ep;
519
520                         if (ch == 'l')
521                                 mode = DEFFILEMODE;
522                         else if (ch == 'p') {
523                                 mode = DEFFILEMODE;
524                                 pflag = 1;
525                         } else if (ch == 'S') {
526                                 mode = S_IRUSR | S_IWUSR;
527                                 Sflag = 1;
528                         }
529                         if (optarg[0] == '/')
530                                 name = optarg;
531                         else if ((name = strchr(optarg, ':')) != NULL) {
532                                 *name++ = '\0';
533                                 if (name[0] != '/')
534                                         errx(1, "socket name must be absolute "
535                                             "path");
536                                 if (isdigit(*optarg)) {
537                                         perml = strtol(optarg, &ep, 8);
538                                     if (*ep || perml < 0 ||
539                                         perml & ~(S_IRWXU|S_IRWXG|S_IRWXO))
540                                             errx(1, "invalid mode %s, exiting",
541                                                 optarg);
542                                     mode = (mode_t )perml;
543                                 } else
544                                         errx(1, "invalid mode %s, exiting",
545                                             optarg);
546                         } else
547                                 errx(1, "invalid filename %s, exiting",
548                                     optarg);
549                         addpeer(&(struct peer){
550                                 .pe_name = name,
551                                 .pe_mode = mode
552                         });
553                         break;
554                    }
555                 case 'm':               /* mark interval */
556                         MarkInterval = atoi(optarg) * 60;
557                         break;
558                 case 'N':
559                         NoBind = 1;
560                         SecureMode = 1;
561                         break;
562                 case 'n':
563                         resolve = 0;
564                         break;
565                 case 'o':
566                         use_bootfile = 1;
567                         break;
568                 case 'P':               /* path for alt. PID */
569                         PidFile = optarg;
570                         break;
571                 case 's':               /* no network mode */
572                         SecureMode++;
573                         break;
574                 case 'T':
575                         RemoteAddDate = 1;
576                         break;
577                 case 'u':               /* only log specified priority */
578                         UniquePriority++;
579                         break;
580                 case 'v':               /* log facility and priority */
581                         LogFacPri++;
582                         break;
583                 default:
584                         usage();
585                 }
586         if ((argc -= optind) != 0)
587                 usage();
588
589         /* Pipe to catch a signal during select(). */
590         s = pipe2(sigpipe, O_CLOEXEC);
591         if (s < 0) {
592                 err(1, "cannot open a pipe for signals");
593         } else {
594                 addsock(NULL, 0, &(struct socklist){
595                     .sl_socket = sigpipe[0],
596                     .sl_recv = socklist_recv_signal
597                 });
598         }
599
600         /* Listen by default: /dev/klog. */
601         s = open(_PATH_KLOG, O_RDONLY | O_NONBLOCK | O_CLOEXEC, 0);
602         if (s < 0) {
603                 dprintf("can't open %s (%d)\n", _PATH_KLOG, errno);
604         } else {
605                 addsock(NULL, 0, &(struct socklist){
606                         .sl_socket = s,
607                         .sl_recv = socklist_recv_file,
608                 });
609         }
610         /* Listen by default: *:514 if no -b flag. */
611         if (bflag == 0)
612                 addpeer(&(struct peer){
613                         .pe_serv = "syslog"
614                 });
615         /* Listen by default: /var/run/log if no -p flag. */
616         if (pflag == 0)
617                 addpeer(&(struct peer){
618                         .pe_name = _PATH_LOG,
619                         .pe_mode = DEFFILEMODE,
620                 });
621         /* Listen by default: /var/run/logpriv if no -S flag. */
622         if (Sflag == 0)
623                 addpeer(&(struct peer){
624                         .pe_name = _PATH_LOG_PRIV,
625                         .pe_mode = S_IRUSR | S_IWUSR,
626                 });
627         STAILQ_FOREACH(pe, &pqueue, next)
628                 socksetup(pe);
629
630         pfh = pidfile_open(PidFile, 0600, &spid);
631         if (pfh == NULL) {
632                 if (errno == EEXIST)
633                         errx(1, "syslogd already running, pid: %d", spid);
634                 warn("cannot open pid file");
635         }
636
637         if ((!Foreground) && (!Debug)) {
638                 ppid = waitdaemon(30);
639                 if (ppid < 0) {
640                         warn("could not become daemon");
641                         pidfile_remove(pfh);
642                         exit(1);
643                 }
644         } else if (Debug)
645                 setlinebuf(stdout);
646
647         consfile.f_type = F_CONSOLE;
648         (void)strlcpy(consfile.fu_fname, ctty + sizeof _PATH_DEV - 1,
649             sizeof(consfile.fu_fname));
650         (void)strlcpy(bootfile, getbootfile(), sizeof(bootfile));
651         (void)signal(SIGTERM, dodie);
652         (void)signal(SIGINT, Debug ? dodie : SIG_IGN);
653         (void)signal(SIGQUIT, Debug ? dodie : SIG_IGN);
654         (void)signal(SIGHUP, sighandler);
655         (void)signal(SIGCHLD, sighandler);
656         (void)signal(SIGALRM, domark);
657         (void)signal(SIGPIPE, SIG_IGN); /* We'll catch EPIPE instead. */
658         (void)alarm(TIMERINTVL);
659
660         /* tuck my process id away */
661         pidfile_write(pfh);
662
663         dprintf("off & running....\n");
664
665         tvp = &tv;
666         tv.tv_sec = tv.tv_usec = 0;
667
668         STAILQ_FOREACH(sl, &shead, next) {
669                 if (sl->sl_socket > fdsrmax)
670                         fdsrmax = sl->sl_socket;
671         }
672         fdsr = (fd_set *)calloc(howmany(fdsrmax+1, NFDBITS),
673             sizeof(fd_mask));
674         if (fdsr == NULL)
675                 errx(1, "calloc fd_set");
676
677         for (;;) {
678                 if (Initialized == 0)
679                         init(0);
680                 else if (WantInitialize)
681                         init(WantInitialize);
682                 if (WantReapchild)
683                         reapchild(WantReapchild);
684                 if (MarkSet)
685                         markit();
686                 if (WantDie)
687                         die(WantDie);
688
689                 bzero(fdsr, howmany(fdsrmax+1, NFDBITS) *
690                     sizeof(fd_mask));
691
692                 STAILQ_FOREACH(sl, &shead, next) {
693                         if (sl->sl_socket != -1)
694                                 FD_SET(sl->sl_socket, fdsr);
695                 }
696                 i = select(fdsrmax + 1, fdsr, NULL, NULL,
697                     needdofsync ? &tv : tvp);
698                 switch (i) {
699                 case 0:
700                         dofsync();
701                         needdofsync = 0;
702                         if (tvp) {
703                                 tvp = NULL;
704                                 if (ppid != 1)
705                                         kill(ppid, SIGALRM);
706                         }
707                         continue;
708                 case -1:
709                         if (errno != EINTR)
710                                 logerror("select");
711                         continue;
712                 }
713                 STAILQ_FOREACH(sl, &shead, next) {
714                         if (FD_ISSET(sl->sl_socket, fdsr))
715                                 (*sl->sl_recv)(sl);
716                 }
717         }
718         free(fdsr);
719 }
720
721 static int
722 socklist_recv_signal(struct socklist *sl __unused)
723 {
724         ssize_t len;
725         int i, nsig, signo;
726
727         if (ioctl(sigpipe[0], FIONREAD, &i) != 0) {
728                 logerror("ioctl(FIONREAD)");
729                 err(1, "signal pipe read failed");
730         }
731         nsig = i / sizeof(signo);
732         dprintf("# of received signals = %d\n", nsig);
733         for (i = 0; i < nsig; i++) {
734                 len = read(sigpipe[0], &signo, sizeof(signo));
735                 if (len != sizeof(signo)) {
736                         logerror("signal pipe read failed");
737                         err(1, "signal pipe read failed");
738                 }
739                 dprintf("Received signal: %d from fd=%d\n", signo,
740                     sigpipe[0]);
741                 switch (signo) {
742                 case SIGHUP:
743                         WantInitialize = 1;
744                         break;
745                 case SIGCHLD:
746                         WantReapchild = 1;
747                         break;
748                 }
749         }
750         return (0);
751 }
752
753 static int
754 socklist_recv_sock(struct socklist *sl)
755 {
756         struct sockaddr_storage ss;
757         struct sockaddr *sa = (struct sockaddr *)&ss;
758         socklen_t sslen;
759         const char *hname;
760         char line[MAXLINE + 1];
761         int date, len;
762
763         sslen = sizeof(ss);
764         len = recvfrom(sl->sl_socket, line, sizeof(line) - 1, 0, sa, &sslen);
765         dprintf("received sa_len = %d\n", sslen);
766         if (len == 0)
767                 return (-1);
768         if (len < 0) {
769                 if (errno != EINTR)
770                         logerror("recvfrom");
771                 return (-1);
772         }
773         /* Received valid data. */
774         line[len] = '\0';
775         if (sl->sl_ss.ss_family == AF_LOCAL) {
776                 hname = LocalHostName;
777                 date = 0;
778         } else {
779                 hname = cvthname(sa);
780                 unmapped(sa);
781                 if (validate(sa, hname) == 0)
782                         hname = NULL;
783                 date = RemoteAddDate ? ADDDATE : 0;
784         }
785         if (hname != NULL)
786                 printline(hname, line, date);
787         else
788                 dprintf("Invalid msg from %s was ignored.", hname);
789
790         return (0);
791 }
792
793 static void
794 unmapped(struct sockaddr *sa)
795 {
796 #if defined(INET) && defined(INET6)
797         struct sockaddr_in6 *sin6;
798         struct sockaddr_in sin;
799
800         if (sa == NULL ||
801             sa->sa_family != AF_INET6 ||
802             sa->sa_len != sizeof(*sin6))
803                 return;
804         sin6 = satosin6(sa);
805         if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
806                 return;
807         sin = (struct sockaddr_in){
808                 .sin_family = AF_INET,
809                 .sin_len = sizeof(sin),
810                 .sin_port = sin6->sin6_port
811         };
812         memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[12],
813             sizeof(sin.sin_addr));
814         memcpy(sa, &sin, sizeof(sin));
815 #else
816         if (sa == NULL)
817                 return;
818 #endif
819 }
820
821 static void
822 usage(void)
823 {
824
825         fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n",
826                 "usage: syslogd [-468ACcdFknosTuv] [-a allowed_peer]",
827                 "               [-b bind_address] [-f config_file]",
828                 "               [-l [mode:]path] [-m mark_interval]",
829                 "               [-P pid_file] [-p log_socket]",
830                 "               [-S logpriv_socket]");
831         exit(1);
832 }
833
834 /*
835  * Take a raw input line, decode the message, and print the message
836  * on the appropriate log files.
837  */
838 static void
839 printline(const char *hname, char *msg, int flags)
840 {
841         char *p, *q;
842         long n;
843         int c, pri;
844         char line[MAXLINE + 1];
845
846         /* test for special codes */
847         p = msg;
848         pri = DEFUPRI;
849         if (*p == '<') {
850                 errno = 0;
851                 n = strtol(p + 1, &q, 10);
852                 if (*q == '>' && n >= 0 && n < INT_MAX && errno == 0) {
853                         p = q + 1;
854                         pri = n;
855                 }
856         }
857         if (pri &~ (LOG_FACMASK|LOG_PRIMASK))
858                 pri = DEFUPRI;
859
860         /*
861          * Don't allow users to log kernel messages.
862          * NOTE: since LOG_KERN == 0 this will also match
863          *       messages with no facility specified.
864          */
865         if ((pri & LOG_FACMASK) == LOG_KERN && !KeepKernFac)
866                 pri = LOG_MAKEPRI(LOG_USER, LOG_PRI(pri));
867
868         q = line;
869
870         while ((c = (unsigned char)*p++) != '\0' &&
871             q < &line[sizeof(line) - 4]) {
872                 if (mask_C1 && (c & 0x80) && c < 0xA0) {
873                         c &= 0x7F;
874                         *q++ = 'M';
875                         *q++ = '-';
876                 }
877                 if (isascii(c) && iscntrl(c)) {
878                         if (c == '\n') {
879                                 *q++ = ' ';
880                         } else if (c == '\t') {
881                                 *q++ = '\t';
882                         } else {
883                                 *q++ = '^';
884                                 *q++ = c ^ 0100;
885                         }
886                 } else {
887                         *q++ = c;
888                 }
889         }
890         *q = '\0';
891
892         logmsg(pri, line, hname, flags);
893 }
894
895 /*
896  * Read /dev/klog while data are available, split into lines.
897  */
898 static int
899 socklist_recv_file(struct socklist *sl)
900 {
901         char *p, *q, line[MAXLINE + 1];
902         int len, i;
903
904         len = 0;
905         for (;;) {
906                 i = read(sl->sl_socket, line + len, MAXLINE - 1 - len);
907                 if (i > 0) {
908                         line[i + len] = '\0';
909                 } else {
910                         if (i < 0 && errno != EINTR && errno != EAGAIN) {
911                                 logerror("klog");
912                                 close(sl->sl_socket);
913                                 sl->sl_socket = -1;
914                         }
915                         break;
916                 }
917
918                 for (p = line; (q = strchr(p, '\n')) != NULL; p = q + 1) {
919                         *q = '\0';
920                         printsys(p);
921                 }
922                 len = strlen(p);
923                 if (len >= MAXLINE - 1) {
924                         printsys(p);
925                         len = 0;
926                 }
927                 if (len > 0)
928                         memmove(line, p, len + 1);
929         }
930         if (len > 0)
931                 printsys(line);
932
933         return (len);
934 }
935
936 /*
937  * Take a raw input line from /dev/klog, format similar to syslog().
938  */
939 static void
940 printsys(char *msg)
941 {
942         char *p, *q;
943         long n;
944         int flags, isprintf, pri;
945
946         flags = ISKERNEL | SYNC_FILE | ADDDATE; /* fsync after write */
947         p = msg;
948         pri = DEFSPRI;
949         isprintf = 1;
950         if (*p == '<') {
951                 errno = 0;
952                 n = strtol(p + 1, &q, 10);
953                 if (*q == '>' && n >= 0 && n < INT_MAX && errno == 0) {
954                         p = q + 1;
955                         pri = n;
956                         isprintf = 0;
957                 }
958         }
959         /*
960          * Kernel printf's and LOG_CONSOLE messages have been displayed
961          * on the console already.
962          */
963         if (isprintf || (pri & LOG_FACMASK) == LOG_CONSOLE)
964                 flags |= IGN_CONS;
965         if (pri &~ (LOG_FACMASK|LOG_PRIMASK))
966                 pri = DEFSPRI;
967         logmsg(pri, p, LocalHostName, flags);
968 }
969
970 static time_t   now;
971
972 /*
973  * Match a program or host name against a specification.
974  * Return a non-0 value if the message must be ignored
975  * based on the specification.
976  */
977 static int
978 skip_message(const char *name, const char *spec, int checkcase)
979 {
980         const char *s;
981         char prev, next;
982         int exclude = 0;
983         /* Behaviour on explicit match */
984
985         if (spec == NULL)
986                 return 0;
987         switch (*spec) {
988         case '-':
989                 exclude = 1;
990                 /*FALLTHROUGH*/
991         case '+':
992                 spec++;
993                 break;
994         default:
995                 break;
996         }
997         if (checkcase)
998                 s = strstr (spec, name);
999         else
1000                 s = strcasestr (spec, name);
1001
1002         if (s != NULL) {
1003                 prev = (s == spec ? ',' : *(s - 1));
1004                 next = *(s + strlen (name));
1005
1006                 if (prev == ',' && (next == '\0' || next == ','))
1007                         /* Explicit match: skip iff the spec is an
1008                            exclusive one. */
1009                         return exclude;
1010         }
1011
1012         /* No explicit match for this name: skip the message iff
1013            the spec is an inclusive one. */
1014         return !exclude;
1015 }
1016
1017 /*
1018  * Log a message to the appropriate log files, users, etc. based on
1019  * the priority.
1020  */
1021 static void
1022 logmsg(int pri, const char *msg, const char *from, int flags)
1023 {
1024         struct filed *f;
1025         int i, fac, msglen, prilev;
1026         const char *timestamp;
1027         char prog[NAME_MAX+1];
1028         char buf[MAXLINE+1];
1029
1030         dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n",
1031             pri, flags, from, msg);
1032
1033         /*
1034          * Check to see if msg looks non-standard.
1035          */
1036         msglen = strlen(msg);
1037         if (msglen < 16 || msg[3] != ' ' || msg[6] != ' ' ||
1038             msg[9] != ':' || msg[12] != ':' || msg[15] != ' ')
1039                 flags |= ADDDATE;
1040
1041         (void)time(&now);
1042         if (flags & ADDDATE) {
1043                 timestamp = ctime(&now) + 4;
1044         } else {
1045                 timestamp = msg;
1046                 msg += 16;
1047                 msglen -= 16;
1048         }
1049
1050         /* skip leading blanks */
1051         while (isspace(*msg)) {
1052                 msg++;
1053                 msglen--;
1054         }
1055
1056         /* extract facility and priority level */
1057         if (flags & MARK)
1058                 fac = LOG_NFACILITIES;
1059         else
1060                 fac = LOG_FAC(pri);
1061
1062         /* Check maximum facility number. */
1063         if (fac > LOG_NFACILITIES)
1064                 return;
1065
1066         prilev = LOG_PRI(pri);
1067
1068         /* extract program name */
1069         for (i = 0; i < NAME_MAX; i++) {
1070                 if (!isprint(msg[i]) || msg[i] == ':' || msg[i] == '[' ||
1071                     msg[i] == '/' || isspace(msg[i]))
1072                         break;
1073                 prog[i] = msg[i];
1074         }
1075         prog[i] = 0;
1076
1077         /* add kernel prefix for kernel messages */
1078         if (flags & ISKERNEL) {
1079                 snprintf(buf, sizeof(buf), "%s: %s",
1080                     use_bootfile ? bootfile : "kernel", msg);
1081                 msg = buf;
1082                 msglen = strlen(buf);
1083         }
1084
1085         /* log the message to the particular outputs */
1086         if (!Initialized) {
1087                 f = &consfile;
1088                 /*
1089                  * Open in non-blocking mode to avoid hangs during open
1090                  * and close(waiting for the port to drain).
1091                  */
1092                 f->f_file = open(ctty, O_WRONLY | O_NONBLOCK, 0);
1093
1094                 if (f->f_file >= 0) {
1095                         (void)strlcpy(f->f_lasttime, timestamp,
1096                                 sizeof(f->f_lasttime));
1097                         fprintlog(f, flags, msg);
1098                         close(f->f_file);
1099                         f->f_file = -1;
1100                 }
1101                 return;
1102         }
1103         STAILQ_FOREACH(f, &fhead, next) {
1104                 /* skip messages that are incorrect priority */
1105                 if (!(((f->f_pcmp[fac] & PRI_EQ) && (f->f_pmask[fac] == prilev))
1106                      ||((f->f_pcmp[fac] & PRI_LT) && (f->f_pmask[fac] < prilev))
1107                      ||((f->f_pcmp[fac] & PRI_GT) && (f->f_pmask[fac] > prilev))
1108                      )
1109                     || f->f_pmask[fac] == INTERNAL_NOPRI)
1110                         continue;
1111
1112                 /* skip messages with the incorrect hostname */
1113                 if (skip_message(from, f->f_host, 0))
1114                         continue;
1115
1116                 /* skip messages with the incorrect program name */
1117                 if (skip_message(prog, f->f_program, 1))
1118                         continue;
1119
1120                 /* skip message to console if it has already been printed */
1121                 if (f->f_type == F_CONSOLE && (flags & IGN_CONS))
1122                         continue;
1123
1124                 /* don't output marks to recently written files */
1125                 if ((flags & MARK) && (now - f->f_time) < MarkInterval / 2)
1126                         continue;
1127
1128                 /*
1129                  * suppress duplicate lines to this file
1130                  */
1131                 if (no_compress - (f->f_type != F_PIPE) < 1 &&
1132                     (flags & MARK) == 0 && msglen == f->f_prevlen &&
1133                     !strcmp(msg, f->f_prevline) &&
1134                     !strcasecmp(from, f->f_prevhost)) {
1135                         (void)strlcpy(f->f_lasttime, timestamp,
1136                                 sizeof(f->f_lasttime));
1137                         f->f_prevcount++;
1138                         dprintf("msg repeated %d times, %ld sec of %d\n",
1139                             f->f_prevcount, (long)(now - f->f_time),
1140                             repeatinterval[f->f_repeatcount]);
1141                         /*
1142                          * If domark would have logged this by now,
1143                          * flush it now (so we don't hold isolated messages),
1144                          * but back off so we'll flush less often
1145                          * in the future.
1146                          */
1147                         if (now > REPEATTIME(f)) {
1148                                 fprintlog(f, flags, (char *)NULL);
1149                                 BACKOFF(f);
1150                         }
1151                 } else {
1152                         /* new line, save it */
1153                         if (f->f_prevcount)
1154                                 fprintlog(f, 0, (char *)NULL);
1155                         f->f_repeatcount = 0;
1156                         f->f_prevpri = pri;
1157                         (void)strlcpy(f->f_lasttime, timestamp,
1158                                 sizeof(f->f_lasttime));
1159                         (void)strlcpy(f->f_prevhost, from,
1160                             sizeof(f->f_prevhost));
1161                         if (msglen < MAXSVLINE) {
1162                                 f->f_prevlen = msglen;
1163                                 (void)strlcpy(f->f_prevline, msg, sizeof(f->f_prevline));
1164                                 fprintlog(f, flags, (char *)NULL);
1165                         } else {
1166                                 f->f_prevline[0] = 0;
1167                                 f->f_prevlen = 0;
1168                                 fprintlog(f, flags, msg);
1169                         }
1170                 }
1171         }
1172 }
1173
1174 static void
1175 dofsync(void)
1176 {
1177         struct filed *f;
1178
1179         STAILQ_FOREACH(f, &fhead, next) {
1180                 if ((f->f_type == F_FILE) &&
1181                     (f->f_flags & FFLAG_NEEDSYNC)) {
1182                         f->f_flags &= ~FFLAG_NEEDSYNC;
1183                         (void)fsync(f->f_file);
1184                 }
1185         }
1186 }
1187
1188 #define IOV_SIZE 7
1189 static void
1190 fprintlog(struct filed *f, int flags, const char *msg)
1191 {
1192         struct iovec iov[IOV_SIZE];
1193         struct addrinfo *r;
1194         int l, lsent = 0;
1195         char line[MAXLINE + 1], repbuf[80], greetings[200], *wmsg = NULL;
1196         char nul[] = "", space[] = " ", lf[] = "\n", crlf[] = "\r\n";
1197         const char *msgret;
1198
1199         if (f->f_type == F_WALL) {
1200                 /* The time displayed is not synchornized with the other log
1201                  * destinations (like messages).  Following fragment was using
1202                  * ctime(&now), which was updating the time every 30 sec.
1203                  * With f_lasttime, time is synchronized correctly.
1204                  */
1205                 iov[0] = (struct iovec){
1206                         .iov_base = greetings,
1207                         .iov_len = snprintf(greetings, sizeof(greetings),
1208                                     "\r\n\7Message from syslogd@%s "
1209                                     "at %.24s ...\r\n",
1210                                     f->f_prevhost, f->f_lasttime)
1211                 };
1212                 if (iov[0].iov_len >= sizeof(greetings))
1213                         iov[0].iov_len = sizeof(greetings) - 1;
1214                 iov[1] = (struct iovec){
1215                         .iov_base = nul,
1216                         .iov_len = 0
1217                 };
1218         } else {
1219                 iov[0] = (struct iovec){
1220                         .iov_base = f->f_lasttime,
1221                         .iov_len = strlen(f->f_lasttime)
1222                 };
1223                 iov[1] = (struct iovec){
1224                         .iov_base = space,
1225                         .iov_len = 1
1226                 };
1227         }
1228
1229         if (LogFacPri) {
1230                 static char fp_buf[30]; /* Hollow laugh */
1231                 int fac = f->f_prevpri & LOG_FACMASK;
1232                 int pri = LOG_PRI(f->f_prevpri);
1233                 const char *f_s = NULL;
1234                 char f_n[5];    /* Hollow laugh */
1235                 const char *p_s = NULL;
1236                 char p_n[5];    /* Hollow laugh */
1237
1238                 if (LogFacPri > 1) {
1239                   const CODE *c;
1240
1241                   for (c = facilitynames; c->c_name; c++) {
1242                     if (c->c_val == fac) {
1243                       f_s = c->c_name;
1244                       break;
1245                     }
1246                   }
1247                   for (c = prioritynames; c->c_name; c++) {
1248                     if (c->c_val == pri) {
1249                       p_s = c->c_name;
1250                       break;
1251                     }
1252                   }
1253                 }
1254                 if (!f_s) {
1255                   snprintf(f_n, sizeof f_n, "%d", LOG_FAC(fac));
1256                   f_s = f_n;
1257                 }
1258                 if (!p_s) {
1259                   snprintf(p_n, sizeof p_n, "%d", pri);
1260                   p_s = p_n;
1261                 }
1262                 snprintf(fp_buf, sizeof fp_buf, "<%s.%s> ", f_s, p_s);
1263                 iov[2] = (struct iovec){
1264                         .iov_base = fp_buf,
1265                         .iov_len = strlen(fp_buf)
1266                 };
1267         } else {
1268                 iov[2] = (struct iovec){
1269                         .iov_base = nul,
1270                         .iov_len = 0
1271                 };
1272         }
1273         iov[3] = (struct iovec){
1274                 .iov_base = f->f_prevhost,
1275                 .iov_len = strlen(f->f_prevhost)
1276         };
1277         iov[4] = (struct iovec){
1278                 .iov_base = space,
1279                 .iov_len = 1
1280         };
1281         if (msg) {
1282                 wmsg = strdup(msg); /* XXX iov_base needs a `const' sibling. */
1283                 if (wmsg == NULL) {
1284                         logerror("strdup");
1285                         exit(1);
1286                 }
1287                 iov[5] = (struct iovec){
1288                         .iov_base = wmsg,
1289                         .iov_len = strlen(msg)
1290                 };
1291         } else if (f->f_prevcount > 1) {
1292                 iov[5] = (struct iovec){
1293                         .iov_base = repbuf,
1294                         .iov_len = snprintf(repbuf, sizeof(repbuf),
1295                             "last message repeated %d times", f->f_prevcount)
1296                 };
1297         } else {
1298                 iov[5] = (struct iovec){
1299                         .iov_base = f->f_prevline,
1300                         .iov_len = f->f_prevlen
1301                 };
1302         }
1303         dprintf("Logging to %s", TypeNames[f->f_type]);
1304         f->f_time = now;
1305
1306         switch (f->f_type) {
1307         case F_UNUSED:
1308                 dprintf("\n");
1309                 break;
1310
1311         case F_FORW:
1312                 dprintf(" %s", f->fu_forw_hname);
1313                 switch (f->fu_forw_addr->ai_addr->sa_family) {
1314 #ifdef INET
1315                 case AF_INET:
1316                         dprintf(":%d\n",
1317                             ntohs(satosin(f->fu_forw_addr->ai_addr)->sin_port));
1318                         break;
1319 #endif
1320 #ifdef INET6
1321                 case AF_INET6:
1322                         dprintf(":%d\n",
1323                             ntohs(satosin6(f->fu_forw_addr->ai_addr)->sin6_port));
1324                         break;
1325 #endif
1326                 default:
1327                         dprintf("\n");
1328                 }
1329                 /* check for local vs remote messages */
1330                 if (strcasecmp(f->f_prevhost, LocalHostName))
1331                         l = snprintf(line, sizeof line - 1,
1332                             "<%d>%.15s Forwarded from %s: %s",
1333                             f->f_prevpri, (char *)iov[0].iov_base,
1334                             f->f_prevhost, (char *)iov[5].iov_base);
1335                 else
1336                         l = snprintf(line, sizeof line - 1, "<%d>%.15s %s",
1337                              f->f_prevpri, (char *)iov[0].iov_base,
1338                             (char *)iov[5].iov_base);
1339                 if (l < 0)
1340                         l = 0;
1341                 else if (l > MAXLINE)
1342                         l = MAXLINE;
1343
1344                 for (r = f->fu_forw_addr; r; r = r->ai_next) {
1345                         struct socklist *sl;
1346
1347                         STAILQ_FOREACH(sl, &shead, next) {
1348                                 if (sl->sl_ss.ss_family == AF_LOCAL ||
1349                                     sl->sl_ss.ss_family == AF_UNSPEC ||
1350                                     sl->sl_socket < 0)
1351                                         continue;
1352                                 lsent = sendto(sl->sl_socket, line, l, 0,
1353                                     r->ai_addr, r->ai_addrlen);
1354                                 if (lsent == l)
1355                                         break;
1356                         }
1357                         if (lsent == l && !send_to_all)
1358                                 break;
1359                 }
1360                 dprintf("lsent/l: %d/%d\n", lsent, l);
1361                 if (lsent != l) {
1362                         int e = errno;
1363                         logerror("sendto");
1364                         errno = e;
1365                         switch (errno) {
1366                         case ENOBUFS:
1367                         case ENETDOWN:
1368                         case ENETUNREACH:
1369                         case EHOSTUNREACH:
1370                         case EHOSTDOWN:
1371                         case EADDRNOTAVAIL:
1372                                 break;
1373                         /* case EBADF: */
1374                         /* case EACCES: */
1375                         /* case ENOTSOCK: */
1376                         /* case EFAULT: */
1377                         /* case EMSGSIZE: */
1378                         /* case EAGAIN: */
1379                         /* case ENOBUFS: */
1380                         /* case ECONNREFUSED: */
1381                         default:
1382                                 dprintf("removing entry: errno=%d\n", e);
1383                                 f->f_type = F_UNUSED;
1384                                 break;
1385                         }
1386                 }
1387                 break;
1388
1389         case F_FILE:
1390                 dprintf(" %s\n", f->fu_fname);
1391                 iov[6] = (struct iovec){
1392                         .iov_base = lf,
1393                         .iov_len = 1
1394                 };
1395                 if (writev(f->f_file, iov, nitems(iov)) < 0) {
1396                         /*
1397                          * If writev(2) fails for potentially transient errors
1398                          * like the filesystem being full, ignore it.
1399                          * Otherwise remove this logfile from the list.
1400                          */
1401                         if (errno != ENOSPC) {
1402                                 int e = errno;
1403                                 close_filed(f);
1404                                 errno = e;
1405                                 logerror(f->fu_fname);
1406                         }
1407                 } else if ((flags & SYNC_FILE) && (f->f_flags & FFLAG_SYNC)) {
1408                         f->f_flags |= FFLAG_NEEDSYNC;
1409                         needdofsync = 1;
1410                 }
1411                 break;
1412
1413         case F_PIPE:
1414                 dprintf(" %s\n", f->fu_pipe_pname);
1415                 iov[6] = (struct iovec){
1416                         .iov_base = lf,
1417                         .iov_len = 1
1418                 };
1419                 if (f->fu_pipe_pid == 0) {
1420                         if ((f->f_file = p_open(f->fu_pipe_pname,
1421                                                 &f->fu_pipe_pid)) < 0) {
1422                                 logerror(f->fu_pipe_pname);
1423                                 break;
1424                         }
1425                 }
1426                 if (writev(f->f_file, iov, nitems(iov)) < 0) {
1427                         int e = errno;
1428
1429                         deadq_enter(f->fu_pipe_pid, f->fu_pipe_pname);
1430                         close_filed(f);
1431                         errno = e;
1432                         logerror(f->fu_pipe_pname);
1433                 }
1434                 break;
1435
1436         case F_CONSOLE:
1437                 if (flags & IGN_CONS) {
1438                         dprintf(" (ignored)\n");
1439                         break;
1440                 }
1441                 /* FALLTHROUGH */
1442
1443         case F_TTY:
1444                 dprintf(" %s%s\n", _PATH_DEV, f->fu_fname);
1445                 iov[6] = (struct iovec){
1446                         .iov_base = crlf,
1447                         .iov_len = 2
1448                 };
1449                 errno = 0;      /* ttymsg() only sometimes returns an errno */
1450                 if ((msgret = ttymsg(iov, nitems(iov), f->fu_fname, 10))) {
1451                         f->f_type = F_UNUSED;
1452                         logerror(msgret);
1453                 }
1454                 break;
1455
1456         case F_USERS:
1457         case F_WALL:
1458                 dprintf("\n");
1459                 iov[6] = (struct iovec){
1460                         .iov_base = crlf,
1461                         .iov_len = 2
1462                 };
1463                 wallmsg(f, iov, nitems(iov));
1464                 break;
1465         }
1466         f->f_prevcount = 0;
1467         free(wmsg);
1468 }
1469
1470 /*
1471  *  WALLMSG -- Write a message to the world at large
1472  *
1473  *      Write the specified message to either the entire
1474  *      world, or a list of approved users.
1475  */
1476 static void
1477 wallmsg(struct filed *f, struct iovec *iov, const int iovlen)
1478 {
1479         static int reenter;                     /* avoid calling ourselves */
1480         struct utmpx *ut;
1481         int i;
1482         const char *p;
1483
1484         if (reenter++)
1485                 return;
1486         setutxent();
1487         /* NOSTRICT */
1488         while ((ut = getutxent()) != NULL) {
1489                 if (ut->ut_type != USER_PROCESS)
1490                         continue;
1491                 if (f->f_type == F_WALL) {
1492                         if ((p = ttymsg(iov, iovlen, ut->ut_line,
1493                             TTYMSGTIME)) != NULL) {
1494                                 errno = 0;      /* already in msg */
1495                                 logerror(p);
1496                         }
1497                         continue;
1498                 }
1499                 /* should we send the message to this user? */
1500                 for (i = 0; i < MAXUNAMES; i++) {
1501                         if (!f->fu_uname[i][0])
1502                                 break;
1503                         if (!strcmp(f->fu_uname[i], ut->ut_user)) {
1504                                 if ((p = ttymsg_check(iov, iovlen, ut->ut_line,
1505                                     TTYMSGTIME)) != NULL) {
1506                                         errno = 0;      /* already in msg */
1507                                         logerror(p);
1508                                 }
1509                                 break;
1510                         }
1511                 }
1512         }
1513         endutxent();
1514         reenter = 0;
1515 }
1516
1517 /*
1518  * Wrapper routine for ttymsg() that checks the terminal for messages enabled.
1519  */
1520 static const char *
1521 ttymsg_check(struct iovec *iov, int iovcnt, char *line, int tmout)
1522 {
1523         static char device[1024];
1524         static char errbuf[1024];
1525         struct stat sb;
1526
1527         (void) snprintf(device, sizeof(device), "%s%s", _PATH_DEV, line);
1528
1529         if (stat(device, &sb) < 0) {
1530                 (void) snprintf(errbuf, sizeof(errbuf),
1531                     "%s: %s", device, strerror(errno));
1532                 return (errbuf);
1533         }
1534         if ((sb.st_mode & S_IWGRP) == 0)
1535                 /* Messages disabled. */
1536                 return (NULL);
1537         return ttymsg(iov, iovcnt, line, tmout);
1538 }
1539
1540 static void
1541 reapchild(int signo __unused)
1542 {
1543         int status;
1544         pid_t pid;
1545         struct filed *f;
1546
1547         while ((pid = wait3(&status, WNOHANG, (struct rusage *)NULL)) > 0) {
1548                 /* First, look if it's a process from the dead queue. */
1549                 if (deadq_removebypid(pid))
1550                         continue;
1551
1552                 /* Now, look in list of active processes. */
1553                 STAILQ_FOREACH(f, &fhead, next) {
1554                         if (f->f_type == F_PIPE &&
1555                             f->fu_pipe_pid == pid) {
1556                                 close_filed(f);
1557                                 log_deadchild(pid, status, f->fu_pipe_pname);
1558                                 break;
1559                         }
1560                 }
1561         }
1562         WantReapchild = 0;
1563 }
1564
1565 /*
1566  * Return a printable representation of a host address.
1567  */
1568 static const char *
1569 cvthname(struct sockaddr *f)
1570 {
1571         int error, hl;
1572         static char hname[NI_MAXHOST], ip[NI_MAXHOST];
1573
1574         dprintf("cvthname(%d) len = %d\n", f->sa_family, f->sa_len);
1575         error = getnameinfo(f, f->sa_len, ip, sizeof(ip), NULL, 0,
1576                     NI_NUMERICHOST);
1577         if (error) {
1578                 dprintf("Malformed from address %s\n", gai_strerror(error));
1579                 return ("???");
1580         }
1581         dprintf("cvthname(%s)\n", ip);
1582
1583         if (!resolve)
1584                 return (ip);
1585
1586         error = getnameinfo(f, f->sa_len, hname, sizeof(hname),
1587                     NULL, 0, NI_NAMEREQD);
1588         if (error) {
1589                 dprintf("Host name for your address (%s) unknown\n", ip);
1590                 return (ip);
1591         }
1592         hl = strlen(hname);
1593         if (hl > 0 && hname[hl-1] == '.')
1594                 hname[--hl] = '\0';
1595         trimdomain(hname, hl);
1596         return (hname);
1597 }
1598
1599 static void
1600 dodie(int signo)
1601 {
1602
1603         WantDie = signo;
1604 }
1605
1606 static void
1607 domark(int signo __unused)
1608 {
1609
1610         MarkSet = 1;
1611 }
1612
1613 /*
1614  * Print syslogd errors some place.
1615  */
1616 static void
1617 logerror(const char *type)
1618 {
1619         char buf[512];
1620         static int recursed = 0;
1621
1622         /* If there's an error while trying to log an error, give up. */
1623         if (recursed)
1624                 return;
1625         recursed++;
1626         if (errno)
1627                 (void)snprintf(buf,
1628                     sizeof buf, "syslogd: %s: %s", type, strerror(errno));
1629         else
1630                 (void)snprintf(buf, sizeof buf, "syslogd: %s", type);
1631         errno = 0;
1632         dprintf("%s\n", buf);
1633         logmsg(LOG_SYSLOG|LOG_ERR, buf, LocalHostName, ADDDATE);
1634         recursed--;
1635 }
1636
1637 static void
1638 die(int signo)
1639 {
1640         struct filed *f;
1641         struct socklist *sl;
1642         char buf[100];
1643
1644         STAILQ_FOREACH(f, &fhead, next) {
1645                 /* flush any pending output */
1646                 if (f->f_prevcount)
1647                         fprintlog(f, 0, (char *)NULL);
1648                 if (f->f_type == F_PIPE && f->fu_pipe_pid > 0)
1649                         close_filed(f);
1650         }
1651         if (signo) {
1652                 dprintf("syslogd: exiting on signal %d\n", signo);
1653                 (void)snprintf(buf, sizeof(buf), "exiting on signal %d", signo);
1654                 errno = 0;
1655                 logerror(buf);
1656         }
1657         STAILQ_FOREACH(sl, &shead, next) {
1658                 if (sl->sl_ss.ss_family == AF_LOCAL)
1659                         unlink(sl->sl_peer->pe_name);
1660         }
1661         pidfile_remove(pfh);
1662
1663         exit(1);
1664 }
1665
1666 static int
1667 configfiles(const struct dirent *dp)
1668 {
1669         const char *p;
1670         size_t ext_len;
1671
1672         if (dp->d_name[0] == '.')
1673                 return (0);
1674
1675         ext_len = sizeof(include_ext) -1;
1676
1677         if (dp->d_namlen <= ext_len)
1678                 return (0);
1679
1680         p = &dp->d_name[dp->d_namlen - ext_len];
1681         if (strcmp(p, include_ext) != 0)
1682                 return (0);
1683
1684         return (1);
1685 }
1686
1687 static void
1688 readconfigfile(FILE *cf, int allow_includes)
1689 {
1690         FILE *cf2;
1691         struct filed *f;
1692         struct dirent **ent;
1693         char cline[LINE_MAX];
1694         char host[MAXHOSTNAMELEN];
1695         char prog[LINE_MAX];
1696         char file[MAXPATHLEN];
1697         char *p, *tmp;
1698         int i, nents;
1699         size_t include_len;
1700
1701         /*
1702          *  Foreach line in the conf table, open that file.
1703          */
1704         include_len = sizeof(include_str) -1;
1705         (void)strlcpy(host, "*", sizeof(host));
1706         (void)strlcpy(prog, "*", sizeof(prog));
1707         while (fgets(cline, sizeof(cline), cf) != NULL) {
1708                 /*
1709                  * check for end-of-section, comments, strip off trailing
1710                  * spaces and newline character. #!prog is treated specially:
1711                  * following lines apply only to that program.
1712                  */
1713                 for (p = cline; isspace(*p); ++p)
1714                         continue;
1715                 if (*p == 0)
1716                         continue;
1717                 if (allow_includes &&
1718                     strncmp(p, include_str, include_len) == 0 &&
1719                     isspace(p[include_len])) {
1720                         p += include_len;
1721                         while (isspace(*p))
1722                                 p++;
1723                         tmp = p;
1724                         while (*tmp != '\0' && !isspace(*tmp))
1725                                 tmp++;
1726                         *tmp = '\0';
1727                         dprintf("Trying to include files in '%s'\n", p);
1728                         nents = scandir(p, &ent, configfiles, alphasort);
1729                         if (nents == -1) {
1730                                 dprintf("Unable to open '%s': %s\n", p,
1731                                     strerror(errno));
1732                                 continue;
1733                         }
1734                         for (i = 0; i < nents; i++) {
1735                                 if (snprintf(file, sizeof(file), "%s/%s", p,
1736                                     ent[i]->d_name) >= (int)sizeof(file)) {
1737                                         dprintf("ignoring path too long: "
1738                                             "'%s/%s'\n", p, ent[i]->d_name);
1739                                         free(ent[i]);
1740                                         continue;
1741                                 }
1742                                 free(ent[i]);
1743                                 cf2 = fopen(file, "r");
1744                                 if (cf2 == NULL)
1745                                         continue;
1746                                 dprintf("reading %s\n", file);
1747                                 readconfigfile(cf2, 0);
1748                                 fclose(cf2);
1749                         }
1750                         free(ent);
1751                         continue;
1752                 }
1753                 if (*p == '#') {
1754                         p++;
1755                         if (*p != '!' && *p != '+' && *p != '-')
1756                                 continue;
1757                 }
1758                 if (*p == '+' || *p == '-') {
1759                         host[0] = *p++;
1760                         while (isspace(*p))
1761                                 p++;
1762                         if ((!*p) || (*p == '*')) {
1763                                 (void)strlcpy(host, "*", sizeof(host));
1764                                 continue;
1765                         }
1766                         if (*p == '@')
1767                                 p = LocalHostName;
1768                         for (i = 1; i < MAXHOSTNAMELEN - 1; i++) {
1769                                 if (!isalnum(*p) && *p != '.' && *p != '-'
1770                                     && *p != ',' && *p != ':' && *p != '%')
1771                                         break;
1772                                 host[i] = *p++;
1773                         }
1774                         host[i] = '\0';
1775                         continue;
1776                 }
1777                 if (*p == '!') {
1778                         p++;
1779                         while (isspace(*p)) p++;
1780                         if ((!*p) || (*p == '*')) {
1781                                 (void)strlcpy(prog, "*", sizeof(prog));
1782                                 continue;
1783                         }
1784                         for (i = 0; i < LINE_MAX - 1; i++) {
1785                                 if (!isprint(p[i]) || isspace(p[i]))
1786                                         break;
1787                                 prog[i] = p[i];
1788                         }
1789                         prog[i] = 0;
1790                         continue;
1791                 }
1792                 for (p = cline + 1; *p != '\0'; p++) {
1793                         if (*p != '#')
1794                                 continue;
1795                         if (*(p - 1) == '\\') {
1796                                 strcpy(p - 1, p);
1797                                 p--;
1798                                 continue;
1799                         }
1800                         *p = '\0';
1801                         break;
1802                 }
1803                 for (i = strlen(cline) - 1; i >= 0 && isspace(cline[i]); i--)
1804                         cline[i] = '\0';
1805                 f = cfline(cline, prog, host);
1806                 if (f != NULL)
1807                         addfile(f);
1808         }
1809 }
1810
1811 static void
1812 sighandler(int signo)
1813 {
1814
1815         /* Send an wake-up signal to the select() loop. */
1816         write(sigpipe[1], &signo, sizeof(signo));
1817 }
1818
1819 /*
1820  *  INIT -- Initialize syslogd from configuration table
1821  */
1822 static void
1823 init(int signo)
1824 {
1825         int i;
1826         FILE *cf;
1827         struct filed *f;
1828         char *p;
1829         char oldLocalHostName[MAXHOSTNAMELEN];
1830         char hostMsg[2*MAXHOSTNAMELEN+40];
1831         char bootfileMsg[LINE_MAX];
1832
1833         dprintf("init\n");
1834         WantInitialize = 0;
1835
1836         /*
1837          * Load hostname (may have changed).
1838          */
1839         if (signo != 0)
1840                 (void)strlcpy(oldLocalHostName, LocalHostName,
1841                     sizeof(oldLocalHostName));
1842         if (gethostname(LocalHostName, sizeof(LocalHostName)))
1843                 err(EX_OSERR, "gethostname() failed");
1844         if ((p = strchr(LocalHostName, '.')) != NULL) {
1845                 *p++ = '\0';
1846                 LocalDomain = p;
1847         } else {
1848                 LocalDomain = "";
1849         }
1850
1851         /*
1852          * Load / reload timezone data (in case it changed).
1853          *
1854          * Just calling tzset() again does not work, the timezone code
1855          * caches the result.  However, by setting the TZ variable, one
1856          * can defeat the caching and have the timezone code really
1857          * reload the timezone data.  Respect any initial setting of
1858          * TZ, in case the system is configured specially.
1859          */
1860         dprintf("loading timezone data via tzset()\n");
1861         if (getenv("TZ")) {
1862                 tzset();
1863         } else {
1864                 setenv("TZ", ":/etc/localtime", 1);
1865                 tzset();
1866                 unsetenv("TZ");
1867         }
1868
1869         /*
1870          *  Close all open log files.
1871          */
1872         Initialized = 0;
1873         STAILQ_FOREACH(f, &fhead, next) {
1874                 /* flush any pending output */
1875                 if (f->f_prevcount)
1876                         fprintlog(f, 0, (char *)NULL);
1877
1878                 switch (f->f_type) {
1879                 case F_FILE:
1880                 case F_FORW:
1881                 case F_CONSOLE:
1882                 case F_TTY:
1883                         close_filed(f);
1884                         break;
1885                 case F_PIPE:
1886                         deadq_enter(f->fu_pipe_pid, f->fu_pipe_pname);
1887                         close_filed(f);
1888                         break;
1889                 }
1890         }
1891         while(!STAILQ_EMPTY(&fhead)) {
1892                 f = STAILQ_FIRST(&fhead);
1893                 STAILQ_REMOVE_HEAD(&fhead, next);
1894                 free(f->f_program);
1895                 free(f->f_host);
1896                 free(f);
1897         }
1898
1899         /* open the configuration file */
1900         if ((cf = fopen(ConfFile, "r")) == NULL) {
1901                 dprintf("cannot open %s\n", ConfFile);
1902                 f = cfline("*.ERR\t/dev/console", "*", "*");
1903                 if (f != NULL)
1904                         addfile(f);
1905                 f = cfline("*.PANIC\t*", "*", "*");
1906                 if (f != NULL)
1907                         addfile(f);
1908                 Initialized = 1;
1909
1910                 return;
1911         }
1912
1913         readconfigfile(cf, 1);
1914
1915         /* close the configuration file */
1916         (void)fclose(cf);
1917
1918         Initialized = 1;
1919
1920         if (Debug) {
1921                 int port;
1922                 STAILQ_FOREACH(f, &fhead, next) {
1923                         for (i = 0; i <= LOG_NFACILITIES; i++)
1924                                 if (f->f_pmask[i] == INTERNAL_NOPRI)
1925                                         printf("X ");
1926                                 else
1927                                         printf("%d ", f->f_pmask[i]);
1928                         printf("%s: ", TypeNames[f->f_type]);
1929                         switch (f->f_type) {
1930                         case F_FILE:
1931                                 printf("%s", f->fu_fname);
1932                                 break;
1933
1934                         case F_CONSOLE:
1935                         case F_TTY:
1936                                 printf("%s%s", _PATH_DEV, f->fu_fname);
1937                                 break;
1938
1939                         case F_FORW:
1940                                 switch (f->fu_forw_addr->ai_addr->sa_family) {
1941 #ifdef INET
1942                                 case AF_INET:
1943                                         port = ntohs(satosin(f->fu_forw_addr->ai_addr)->sin_port);
1944                                         break;
1945 #endif
1946 #ifdef INET6
1947                                 case AF_INET6:
1948                                         port = ntohs(satosin6(f->fu_forw_addr->ai_addr)->sin6_port);
1949                                         break;
1950 #endif
1951                                 default:
1952                                         port = 0;
1953                                 }
1954                                 if (port != 514) {
1955                                         printf("%s:%d",
1956                                                 f->fu_forw_hname, port);
1957                                 } else {
1958                                         printf("%s", f->fu_forw_hname);
1959                                 }
1960                                 break;
1961
1962                         case F_PIPE:
1963                                 printf("%s", f->fu_pipe_pname);
1964                                 break;
1965
1966                         case F_USERS:
1967                                 for (i = 0; i < MAXUNAMES && *f->fu_uname[i]; i++)
1968                                         printf("%s, ", f->fu_uname[i]);
1969                                 break;
1970                         }
1971                         if (f->f_program)
1972                                 printf(" (%s)", f->f_program);
1973                         printf("\n");
1974                 }
1975         }
1976
1977         logmsg(LOG_SYSLOG|LOG_INFO, "syslogd: restart", LocalHostName, ADDDATE);
1978         dprintf("syslogd: restarted\n");
1979         /*
1980          * Log a change in hostname, but only on a restart.
1981          */
1982         if (signo != 0 && strcmp(oldLocalHostName, LocalHostName) != 0) {
1983                 (void)snprintf(hostMsg, sizeof(hostMsg),
1984                     "syslogd: hostname changed, \"%s\" to \"%s\"",
1985                     oldLocalHostName, LocalHostName);
1986                 logmsg(LOG_SYSLOG|LOG_INFO, hostMsg, LocalHostName, ADDDATE);
1987                 dprintf("%s\n", hostMsg);
1988         }
1989         /*
1990          * Log the kernel boot file if we aren't going to use it as
1991          * the prefix, and if this is *not* a restart.
1992          */
1993         if (signo == 0 && !use_bootfile) {
1994                 (void)snprintf(bootfileMsg, sizeof(bootfileMsg),
1995                     "syslogd: kernel boot file is %s", bootfile);
1996                 logmsg(LOG_KERN|LOG_INFO, bootfileMsg, LocalHostName, ADDDATE);
1997                 dprintf("%s\n", bootfileMsg);
1998         }
1999 }
2000
2001 /*
2002  * Crack a configuration file line
2003  */
2004 static struct filed *
2005 cfline(const char *line, const char *prog, const char *host)
2006 {
2007         struct filed *f;
2008         struct addrinfo hints, *res;
2009         int error, i, pri, syncfile;
2010         const char *p, *q;
2011         char *bp;
2012         char buf[MAXLINE], ebuf[100];
2013
2014         dprintf("cfline(\"%s\", f, \"%s\", \"%s\")\n", line, prog, host);
2015
2016         f = calloc(1, sizeof(*f));
2017         if (f == NULL) {
2018                 logerror("malloc");
2019                 exit(1);
2020         }
2021         errno = 0;      /* keep strerror() stuff out of logerror messages */
2022
2023         for (i = 0; i <= LOG_NFACILITIES; i++)
2024                 f->f_pmask[i] = INTERNAL_NOPRI;
2025
2026         /* save hostname if any */
2027         if (host && *host == '*')
2028                 host = NULL;
2029         if (host) {
2030                 int hl;
2031
2032                 f->f_host = strdup(host);
2033                 if (f->f_host == NULL) {
2034                         logerror("strdup");
2035                         exit(1);
2036                 }
2037                 hl = strlen(f->f_host);
2038                 if (hl > 0 && f->f_host[hl-1] == '.')
2039                         f->f_host[--hl] = '\0';
2040                 trimdomain(f->f_host, hl);
2041         }
2042
2043         /* save program name if any */
2044         if (prog && *prog == '*')
2045                 prog = NULL;
2046         if (prog) {
2047                 f->f_program = strdup(prog);
2048                 if (f->f_program == NULL) {
2049                         logerror("strdup");
2050                         exit(1);
2051                 }
2052         }
2053
2054         /* scan through the list of selectors */
2055         for (p = line; *p && *p != '\t' && *p != ' ';) {
2056                 int pri_done;
2057                 int pri_cmp;
2058                 int pri_invert;
2059
2060                 /* find the end of this facility name list */
2061                 for (q = p; *q && *q != '\t' && *q != ' ' && *q++ != '.'; )
2062                         continue;
2063
2064                 /* get the priority comparison */
2065                 pri_cmp = 0;
2066                 pri_done = 0;
2067                 pri_invert = 0;
2068                 if (*q == '!') {
2069                         pri_invert = 1;
2070                         q++;
2071                 }
2072                 while (!pri_done) {
2073                         switch (*q) {
2074                         case '<':
2075                                 pri_cmp |= PRI_LT;
2076                                 q++;
2077                                 break;
2078                         case '=':
2079                                 pri_cmp |= PRI_EQ;
2080                                 q++;
2081                                 break;
2082                         case '>':
2083                                 pri_cmp |= PRI_GT;
2084                                 q++;
2085                                 break;
2086                         default:
2087                                 pri_done++;
2088                                 break;
2089                         }
2090                 }
2091
2092                 /* collect priority name */
2093                 for (bp = buf; *q && !strchr("\t,; ", *q); )
2094                         *bp++ = *q++;
2095                 *bp = '\0';
2096
2097                 /* skip cruft */
2098                 while (strchr(",;", *q))
2099                         q++;
2100
2101                 /* decode priority name */
2102                 if (*buf == '*') {
2103                         pri = LOG_PRIMASK;
2104                         pri_cmp = PRI_LT | PRI_EQ | PRI_GT;
2105                 } else {
2106                         /* Ignore trailing spaces. */
2107                         for (i = strlen(buf) - 1; i >= 0 && buf[i] == ' '; i--)
2108                                 buf[i] = '\0';
2109
2110                         pri = decode(buf, prioritynames);
2111                         if (pri < 0) {
2112                                 errno = 0;
2113                                 (void)snprintf(ebuf, sizeof ebuf,
2114                                     "unknown priority name \"%s\"", buf);
2115                                 logerror(ebuf);
2116                                 return (NULL);
2117                         }
2118                 }
2119                 if (!pri_cmp)
2120                         pri_cmp = (UniquePriority)
2121                                   ? (PRI_EQ)
2122                                   : (PRI_EQ | PRI_GT)
2123                                   ;
2124                 if (pri_invert)
2125                         pri_cmp ^= PRI_LT | PRI_EQ | PRI_GT;
2126
2127                 /* scan facilities */
2128                 while (*p && !strchr("\t.; ", *p)) {
2129                         for (bp = buf; *p && !strchr("\t,;. ", *p); )
2130                                 *bp++ = *p++;
2131                         *bp = '\0';
2132
2133                         if (*buf == '*') {
2134                                 for (i = 0; i < LOG_NFACILITIES; i++) {
2135                                         f->f_pmask[i] = pri;
2136                                         f->f_pcmp[i] = pri_cmp;
2137                                 }
2138                         } else {
2139                                 i = decode(buf, facilitynames);
2140                                 if (i < 0) {
2141                                         errno = 0;
2142                                         (void)snprintf(ebuf, sizeof ebuf,
2143                                             "unknown facility name \"%s\"",
2144                                             buf);
2145                                         logerror(ebuf);
2146                                         return (NULL);
2147                                 }
2148                                 f->f_pmask[i >> 3] = pri;
2149                                 f->f_pcmp[i >> 3] = pri_cmp;
2150                         }
2151                         while (*p == ',' || *p == ' ')
2152                                 p++;
2153                 }
2154
2155                 p = q;
2156         }
2157
2158         /* skip to action part */
2159         while (*p == '\t' || *p == ' ')
2160                 p++;
2161
2162         if (*p == '-') {
2163                 syncfile = 0;
2164                 p++;
2165         } else
2166                 syncfile = 1;
2167
2168         switch (*p) {
2169         case '@':
2170                 {
2171                         char *tp;
2172                         char endkey = ':';
2173                         /*
2174                          * scan forward to see if there is a port defined.
2175                          * so we can't use strlcpy..
2176                          */
2177                         i = sizeof(f->fu_forw_hname);
2178                         tp = f->fu_forw_hname;
2179                         p++;
2180
2181                         /*
2182                          * an ipv6 address should start with a '[' in that case
2183                          * we should scan for a ']'
2184                          */
2185                         if (*p == '[') {
2186                                 p++;
2187                                 endkey = ']';
2188                         }
2189                         while (*p && (*p != endkey) && (i-- > 0)) {
2190                                 *tp++ = *p++;
2191                         }
2192                         if (endkey == ']' && *p == endkey)
2193                                 p++;
2194                         *tp = '\0';
2195                 }
2196                 /* See if we copied a domain and have a port */
2197                 if (*p == ':')
2198                         p++;
2199                 else
2200                         p = NULL;
2201
2202                 hints = (struct addrinfo){
2203                         .ai_family = family,
2204                         .ai_socktype = SOCK_DGRAM
2205                 };
2206                 error = getaddrinfo(f->fu_forw_hname,
2207                                 p ? p : "syslog", &hints, &res);
2208                 if (error) {
2209                         logerror(gai_strerror(error));
2210                         break;
2211                 }
2212                 f->fu_forw_addr = res;
2213                 f->f_type = F_FORW;
2214                 break;
2215
2216         case '/':
2217                 if ((f->f_file = open(p, logflags, 0600)) < 0) {
2218                         f->f_type = F_UNUSED;
2219                         logerror(p);
2220                         break;
2221                 }
2222                 if (syncfile)
2223                         f->f_flags |= FFLAG_SYNC;
2224                 if (isatty(f->f_file)) {
2225                         if (strcmp(p, ctty) == 0)
2226                                 f->f_type = F_CONSOLE;
2227                         else
2228                                 f->f_type = F_TTY;
2229                         (void)strlcpy(f->fu_fname, p + sizeof(_PATH_DEV) - 1,
2230                             sizeof(f->fu_fname));
2231                 } else {
2232                         (void)strlcpy(f->fu_fname, p, sizeof(f->fu_fname));
2233                         f->f_type = F_FILE;
2234                 }
2235                 break;
2236
2237         case '|':
2238                 f->fu_pipe_pid = 0;
2239                 (void)strlcpy(f->fu_pipe_pname, p + 1,
2240                     sizeof(f->fu_pipe_pname));
2241                 f->f_type = F_PIPE;
2242                 break;
2243
2244         case '*':
2245                 f->f_type = F_WALL;
2246                 break;
2247
2248         default:
2249                 for (i = 0; i < MAXUNAMES && *p; i++) {
2250                         for (q = p; *q && *q != ','; )
2251                                 q++;
2252                         (void)strncpy(f->fu_uname[i], p, MAXLOGNAME - 1);
2253                         if ((q - p) >= MAXLOGNAME)
2254                                 f->fu_uname[i][MAXLOGNAME - 1] = '\0';
2255                         else
2256                                 f->fu_uname[i][q - p] = '\0';
2257                         while (*q == ',' || *q == ' ')
2258                                 q++;
2259                         p = q;
2260                 }
2261                 f->f_type = F_USERS;
2262                 break;
2263         }
2264         return (f);
2265 }
2266
2267
2268 /*
2269  *  Decode a symbolic name to a numeric value
2270  */
2271 static int
2272 decode(const char *name, const CODE *codetab)
2273 {
2274         const CODE *c;
2275         char *p, buf[40];
2276
2277         if (isdigit(*name))
2278                 return (atoi(name));
2279
2280         for (p = buf; *name && p < &buf[sizeof(buf) - 1]; p++, name++) {
2281                 if (isupper(*name))
2282                         *p = tolower(*name);
2283                 else
2284                         *p = *name;
2285         }
2286         *p = '\0';
2287         for (c = codetab; c->c_name; c++)
2288                 if (!strcmp(buf, c->c_name))
2289                         return (c->c_val);
2290
2291         return (-1);
2292 }
2293
2294 static void
2295 markit(void)
2296 {
2297         struct filed *f;
2298         struct deadq_entry *dq, *dq0;
2299
2300         now = time((time_t *)NULL);
2301         MarkSeq += TIMERINTVL;
2302         if (MarkSeq >= MarkInterval) {
2303                 logmsg(LOG_INFO, "-- MARK --",
2304                     LocalHostName, ADDDATE|MARK);
2305                 MarkSeq = 0;
2306         }
2307
2308         STAILQ_FOREACH(f, &fhead, next) {
2309                 if (f->f_prevcount && now >= REPEATTIME(f)) {
2310                         dprintf("flush %s: repeated %d times, %d sec.\n",
2311                             TypeNames[f->f_type], f->f_prevcount,
2312                             repeatinterval[f->f_repeatcount]);
2313                         fprintlog(f, 0, (char *)NULL);
2314                         BACKOFF(f);
2315                 }
2316         }
2317
2318         /* Walk the dead queue, and see if we should signal somebody. */
2319         TAILQ_FOREACH_SAFE(dq, &deadq_head, dq_entries, dq0) {
2320                 switch (dq->dq_timeout) {
2321                 case 0:
2322                         /* Already signalled once, try harder now. */
2323                         if (kill(dq->dq_pid, SIGKILL) != 0)
2324                                 (void)deadq_remove(dq);
2325                         break;
2326
2327                 case 1:
2328                         /*
2329                          * Timed out on dead queue, send terminate
2330                          * signal.  Note that we leave the removal
2331                          * from the dead queue to reapchild(), which
2332                          * will also log the event (unless the process
2333                          * didn't even really exist, in case we simply
2334                          * drop it from the dead queue).
2335                          */
2336                         if (kill(dq->dq_pid, SIGTERM) != 0)
2337                                 (void)deadq_remove(dq);
2338                         else
2339                                 dq->dq_timeout--;
2340                         break;
2341                 default:
2342                         dq->dq_timeout--;
2343                 }
2344         }
2345         MarkSet = 0;
2346         (void)alarm(TIMERINTVL);
2347 }
2348
2349 /*
2350  * fork off and become a daemon, but wait for the child to come online
2351  * before returing to the parent, or we get disk thrashing at boot etc.
2352  * Set a timer so we don't hang forever if it wedges.
2353  */
2354 static int
2355 waitdaemon(int maxwait)
2356 {
2357         int fd;
2358         int status;
2359         pid_t pid, childpid;
2360
2361         switch (childpid = fork()) {
2362         case -1:
2363                 return (-1);
2364         case 0:
2365                 break;
2366         default:
2367                 signal(SIGALRM, timedout);
2368                 alarm(maxwait);
2369                 while ((pid = wait3(&status, 0, NULL)) != -1) {
2370                         if (WIFEXITED(status))
2371                                 errx(1, "child pid %d exited with return code %d",
2372                                         pid, WEXITSTATUS(status));
2373                         if (WIFSIGNALED(status))
2374                                 errx(1, "child pid %d exited on signal %d%s",
2375                                         pid, WTERMSIG(status),
2376                                         WCOREDUMP(status) ? " (core dumped)" :
2377                                         "");
2378                         if (pid == childpid)    /* it's gone... */
2379                                 break;
2380                 }
2381                 exit(0);
2382         }
2383
2384         if (setsid() == -1)
2385                 return (-1);
2386
2387         (void)chdir("/");
2388         if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
2389                 (void)dup2(fd, STDIN_FILENO);
2390                 (void)dup2(fd, STDOUT_FILENO);
2391                 (void)dup2(fd, STDERR_FILENO);
2392                 if (fd > STDERR_FILENO)
2393                         (void)close(fd);
2394         }
2395         return (getppid());
2396 }
2397
2398 /*
2399  * We get a SIGALRM from the child when it's running and finished doing it's
2400  * fsync()'s or O_SYNC writes for all the boot messages.
2401  *
2402  * We also get a signal from the kernel if the timer expires, so check to
2403  * see what happened.
2404  */
2405 static void
2406 timedout(int sig __unused)
2407 {
2408         int left;
2409         left = alarm(0);
2410         signal(SIGALRM, SIG_DFL);
2411         if (left == 0)
2412                 errx(1, "timed out waiting for child");
2413         else
2414                 _exit(0);
2415 }
2416
2417 /*
2418  * Add `s' to the list of allowable peer addresses to accept messages
2419  * from.
2420  *
2421  * `s' is a string in the form:
2422  *
2423  *    [*]domainname[:{servicename|portnumber|*}]
2424  *
2425  * or
2426  *
2427  *    netaddr/maskbits[:{servicename|portnumber|*}]
2428  *
2429  * Returns -1 on error, 0 if the argument was valid.
2430  */
2431 static int
2432 allowaddr(char *s)
2433 {
2434 #if defined(INET) || defined(INET6)
2435         char *cp1, *cp2;
2436         struct allowedpeer *ap;
2437         struct servent *se;
2438         int masklen = -1;
2439         struct addrinfo hints, *res;
2440 #ifdef INET
2441         in_addr_t *addrp, *maskp;
2442 #endif
2443 #ifdef INET6
2444         uint32_t *addr6p, *mask6p;
2445 #endif
2446         char ip[NI_MAXHOST];
2447
2448         ap = calloc(1, sizeof(*ap));
2449         if (ap == NULL)
2450                 err(1, "malloc failed");
2451
2452 #ifdef INET6
2453         if (*s != '[' || (cp1 = strchr(s + 1, ']')) == NULL)
2454 #endif
2455                 cp1 = s;
2456         if ((cp1 = strrchr(cp1, ':'))) {
2457                 /* service/port provided */
2458                 *cp1++ = '\0';
2459                 if (strlen(cp1) == 1 && *cp1 == '*')
2460                         /* any port allowed */
2461                         ap->port = 0;
2462                 else if ((se = getservbyname(cp1, "udp"))) {
2463                         ap->port = ntohs(se->s_port);
2464                 } else {
2465                         ap->port = strtol(cp1, &cp2, 0);
2466                         if (*cp2 != '\0')
2467                                 return (-1); /* port not numeric */
2468                 }
2469         } else {
2470                 if ((se = getservbyname("syslog", "udp")))
2471                         ap->port = ntohs(se->s_port);
2472                 else
2473                         /* sanity, should not happen */
2474                         ap->port = 514;
2475         }
2476
2477         if ((cp1 = strchr(s, '/')) != NULL &&
2478             strspn(cp1 + 1, "0123456789") == strlen(cp1 + 1)) {
2479                 *cp1 = '\0';
2480                 if ((masklen = atoi(cp1 + 1)) < 0)
2481                         return (-1);
2482         }
2483 #ifdef INET6
2484         if (*s == '[') {
2485                 cp2 = s + strlen(s) - 1;
2486                 if (*cp2 == ']') {
2487                         ++s;
2488                         *cp2 = '\0';
2489                 } else {
2490                         cp2 = NULL;
2491                 }
2492         } else {
2493                 cp2 = NULL;
2494         }
2495 #endif
2496         hints = (struct addrinfo){
2497                 .ai_family = PF_UNSPEC,
2498                 .ai_socktype = SOCK_DGRAM,
2499                 .ai_flags = AI_PASSIVE | AI_NUMERICHOST
2500         };
2501         if (getaddrinfo(s, NULL, &hints, &res) == 0) {
2502                 ap->isnumeric = 1;
2503                 memcpy(&ap->a_addr, res->ai_addr, res->ai_addrlen);
2504                 ap->a_mask = (struct sockaddr_storage){
2505                         .ss_family = res->ai_family,
2506                         .ss_len = res->ai_addrlen
2507                 };
2508                 switch (res->ai_family) {
2509 #ifdef INET
2510                 case AF_INET:
2511                         maskp = &sstosin(&ap->a_mask)->sin_addr.s_addr;
2512                         addrp = &sstosin(&ap->a_addr)->sin_addr.s_addr;
2513                         if (masklen < 0) {
2514                                 /* use default netmask */
2515                                 if (IN_CLASSA(ntohl(*addrp)))
2516                                         *maskp = htonl(IN_CLASSA_NET);
2517                                 else if (IN_CLASSB(ntohl(*addrp)))
2518                                         *maskp = htonl(IN_CLASSB_NET);
2519                                 else
2520                                         *maskp = htonl(IN_CLASSC_NET);
2521                         } else if (masklen == 0) {
2522                                 *maskp = 0;
2523                         } else if (masklen <= 32) {
2524                                 /* convert masklen to netmask */
2525                                 *maskp = htonl(~((1 << (32 - masklen)) - 1));
2526                         } else {
2527                                 freeaddrinfo(res);
2528                                 return (-1);
2529                         }
2530                         /* Lose any host bits in the network number. */
2531                         *addrp &= *maskp;
2532                         break;
2533 #endif
2534 #ifdef INET6
2535                 case AF_INET6:
2536                         if (masklen > 128) {
2537                                 freeaddrinfo(res);
2538                                 return (-1);
2539                         }
2540                         if (masklen < 0)
2541                                 masklen = 128;
2542                         mask6p = (uint32_t *)&sstosin6(&ap->a_mask)->sin6_addr.s6_addr32[0];
2543                         addr6p = (uint32_t *)&sstosin6(&ap->a_addr)->sin6_addr.s6_addr32[0];
2544                         /* convert masklen to netmask */
2545                         while (masklen > 0) {
2546                                 if (masklen < 32) {
2547                                         *mask6p =
2548                                             htonl(~(0xffffffff >> masklen));
2549                                         *addr6p &= *mask6p;
2550                                         break;
2551                                 } else {
2552                                         *mask6p++ = 0xffffffff;
2553                                         addr6p++;
2554                                         masklen -= 32;
2555                                 }
2556                         }
2557                         break;
2558 #endif
2559                 default:
2560                         freeaddrinfo(res);
2561                         return (-1);
2562                 }
2563                 freeaddrinfo(res);
2564         } else {
2565                 /* arg `s' is domain name */
2566                 ap->isnumeric = 0;
2567                 ap->a_name = s;
2568                 if (cp1)
2569                         *cp1 = '/';
2570 #ifdef INET6
2571                 if (cp2) {
2572                         *cp2 = ']';
2573                         --s;
2574                 }
2575 #endif
2576         }
2577         STAILQ_INSERT_TAIL(&aphead, ap, next);
2578
2579         if (Debug) {
2580                 printf("allowaddr: rule ");
2581                 if (ap->isnumeric) {
2582                         printf("numeric, ");
2583                         getnameinfo(sstosa(&ap->a_addr),
2584                                     (sstosa(&ap->a_addr))->sa_len,
2585                                     ip, sizeof ip, NULL, 0, NI_NUMERICHOST);
2586                         printf("addr = %s, ", ip);
2587                         getnameinfo(sstosa(&ap->a_mask),
2588                                     (sstosa(&ap->a_mask))->sa_len,
2589                                     ip, sizeof ip, NULL, 0, NI_NUMERICHOST);
2590                         printf("mask = %s; ", ip);
2591                 } else {
2592                         printf("domainname = %s; ", ap->a_name);
2593                 }
2594                 printf("port = %d\n", ap->port);
2595         }
2596 #endif
2597         return (0);
2598 }
2599
2600 /*
2601  * Validate that the remote peer has permission to log to us.
2602  */
2603 static int
2604 validate(struct sockaddr *sa, const char *hname)
2605 {
2606         int i;
2607         char name[NI_MAXHOST], ip[NI_MAXHOST], port[NI_MAXSERV];
2608         struct allowedpeer *ap;
2609 #ifdef INET
2610         struct sockaddr_in *sin4, *a4p = NULL, *m4p = NULL;
2611 #endif
2612 #ifdef INET6
2613         struct sockaddr_in6 *sin6, *a6p = NULL, *m6p = NULL;
2614 #endif
2615         struct addrinfo hints, *res;
2616         u_short sport;
2617         int num = 0;
2618
2619         STAILQ_FOREACH(ap, &aphead, next) {
2620                 num++;
2621         }
2622         dprintf("# of validation rule: %d\n", num);
2623         if (num == 0)
2624                 /* traditional behaviour, allow everything */
2625                 return (1);
2626
2627         (void)strlcpy(name, hname, sizeof(name));
2628         hints = (struct addrinfo){
2629                 .ai_family = PF_UNSPEC,
2630                 .ai_socktype = SOCK_DGRAM,
2631                 .ai_flags = AI_PASSIVE | AI_NUMERICHOST
2632         };
2633         if (getaddrinfo(name, NULL, &hints, &res) == 0)
2634                 freeaddrinfo(res);
2635         else if (strchr(name, '.') == NULL) {
2636                 strlcat(name, ".", sizeof name);
2637                 strlcat(name, LocalDomain, sizeof name);
2638         }
2639         if (getnameinfo(sa, sa->sa_len, ip, sizeof(ip), port, sizeof(port),
2640                         NI_NUMERICHOST | NI_NUMERICSERV) != 0)
2641                 return (0);     /* for safety, should not occur */
2642         dprintf("validate: dgram from IP %s, port %s, name %s;\n",
2643                 ip, port, name);
2644         sport = atoi(port);
2645
2646         /* now, walk down the list */
2647         i = 0;
2648         STAILQ_FOREACH(ap, &aphead, next) {
2649                 i++;
2650                 if (ap->port != 0 && ap->port != sport) {
2651                         dprintf("rejected in rule %d due to port mismatch.\n",
2652                             i);
2653                         continue;
2654                 }
2655
2656                 if (ap->isnumeric) {
2657                         if (ap->a_addr.ss_family != sa->sa_family) {
2658                                 dprintf("rejected in rule %d due to address family mismatch.\n", i);
2659                                 continue;
2660                         }
2661 #ifdef INET
2662                         else if (ap->a_addr.ss_family == AF_INET) {
2663                                 sin4 = satosin(sa);
2664                                 a4p = satosin(&ap->a_addr);
2665                                 m4p = satosin(&ap->a_mask);
2666                                 if ((sin4->sin_addr.s_addr & m4p->sin_addr.s_addr)
2667                                     != a4p->sin_addr.s_addr) {
2668                                         dprintf("rejected in rule %d due to IP mismatch.\n", i);
2669                                         continue;
2670                                 }
2671                         }
2672 #endif
2673 #ifdef INET6
2674                         else if (ap->a_addr.ss_family == AF_INET6) {
2675                                 sin6 = satosin6(sa);
2676                                 a6p = satosin6(&ap->a_addr);
2677                                 m6p = satosin6(&ap->a_mask);
2678                                 if (a6p->sin6_scope_id != 0 &&
2679                                     sin6->sin6_scope_id != a6p->sin6_scope_id) {
2680                                         dprintf("rejected in rule %d due to scope mismatch.\n", i);
2681                                         continue;
2682                                 }
2683                                 if (IN6_ARE_MASKED_ADDR_EQUAL(&sin6->sin6_addr,
2684                                     &a6p->sin6_addr, &m6p->sin6_addr) != 0) {
2685                                         dprintf("rejected in rule %d due to IP mismatch.\n", i);
2686                                         continue;
2687                                 }
2688                         }
2689 #endif
2690                         else
2691                                 continue;
2692                 } else {
2693                         if (fnmatch(ap->a_name, name, FNM_NOESCAPE) ==
2694                             FNM_NOMATCH) {
2695                                 dprintf("rejected in rule %d due to name "
2696                                     "mismatch.\n", i);
2697                                 continue;
2698                         }
2699                 }
2700                 dprintf("accepted in rule %d.\n", i);
2701                 return (1);     /* hooray! */
2702         }
2703         return (0);
2704 }
2705
2706 /*
2707  * Fairly similar to popen(3), but returns an open descriptor, as
2708  * opposed to a FILE *.
2709  */
2710 static int
2711 p_open(const char *prog, pid_t *rpid)
2712 {
2713         int pfd[2], nulldesc;
2714         pid_t pid;
2715         char *argv[4]; /* sh -c cmd NULL */
2716         char errmsg[200];
2717
2718         if (pipe(pfd) == -1)
2719                 return (-1);
2720         if ((nulldesc = open(_PATH_DEVNULL, O_RDWR)) == -1)
2721                 /* we are royally screwed anyway */
2722                 return (-1);
2723
2724         switch ((pid = fork())) {
2725         case -1:
2726                 close(nulldesc);
2727                 return (-1);
2728
2729         case 0:
2730                 (void)setsid(); /* Avoid catching SIGHUPs. */
2731                 argv[0] = strdup("sh");
2732                 argv[1] = strdup("-c");
2733                 argv[2] = strdup(prog);
2734                 argv[3] = NULL;
2735                 if (argv[0] == NULL || argv[1] == NULL || argv[2] == NULL) {
2736                         logerror("strdup");
2737                         exit(1);
2738                 }
2739
2740                 alarm(0);
2741
2742                 /* Restore signals marked as SIG_IGN. */
2743                 (void)signal(SIGINT, SIG_DFL);
2744                 (void)signal(SIGQUIT, SIG_DFL);
2745                 (void)signal(SIGPIPE, SIG_DFL);
2746
2747                 dup2(pfd[0], STDIN_FILENO);
2748                 dup2(nulldesc, STDOUT_FILENO);
2749                 dup2(nulldesc, STDERR_FILENO);
2750                 closefrom(STDERR_FILENO + 1);
2751
2752                 (void)execvp(_PATH_BSHELL, argv);
2753                 _exit(255);
2754         }
2755         close(nulldesc);
2756         close(pfd[0]);
2757         /*
2758          * Avoid blocking on a hung pipe.  With O_NONBLOCK, we are
2759          * supposed to get an EWOULDBLOCK on writev(2), which is
2760          * caught by the logic above anyway, which will in turn close
2761          * the pipe, and fork a new logging subprocess if necessary.
2762          * The stale subprocess will be killed some time later unless
2763          * it terminated itself due to closing its input pipe (so we
2764          * get rid of really dead puppies).
2765          */
2766         if (fcntl(pfd[1], F_SETFL, O_NONBLOCK) == -1) {
2767                 /* This is bad. */
2768                 (void)snprintf(errmsg, sizeof errmsg,
2769                                "Warning: cannot change pipe to PID %d to "
2770                                "non-blocking behaviour.",
2771                                (int)pid);
2772                 logerror(errmsg);
2773         }
2774         *rpid = pid;
2775         return (pfd[1]);
2776 }
2777
2778 static void
2779 deadq_enter(pid_t pid, const char *name)
2780 {
2781         struct deadq_entry *dq;
2782         int status;
2783
2784         if (pid == 0)
2785                 return;
2786         /*
2787          * Be paranoid, if we can't signal the process, don't enter it
2788          * into the dead queue (perhaps it's already dead).  If possible,
2789          * we try to fetch and log the child's status.
2790          */
2791         if (kill(pid, 0) != 0) {
2792                 if (waitpid(pid, &status, WNOHANG) > 0)
2793                         log_deadchild(pid, status, name);
2794                 return;
2795         }
2796
2797         dq = malloc(sizeof(*dq));
2798         if (dq == NULL) {
2799                 logerror("malloc");
2800                 exit(1);
2801         }
2802         *dq = (struct deadq_entry){
2803                 .dq_pid = pid,
2804                 .dq_timeout = DQ_TIMO_INIT
2805         };
2806         TAILQ_INSERT_TAIL(&deadq_head, dq, dq_entries);
2807 }
2808
2809 static int
2810 deadq_remove(struct deadq_entry *dq)
2811 {
2812         if (dq != NULL) {
2813                 TAILQ_REMOVE(&deadq_head, dq, dq_entries);
2814                 free(dq);
2815                 return (1);
2816         }
2817
2818         return (0);
2819 }
2820
2821 static int
2822 deadq_removebypid(pid_t pid)
2823 {
2824         struct deadq_entry *dq;
2825
2826         TAILQ_FOREACH(dq, &deadq_head, dq_entries) {
2827                 if (dq->dq_pid == pid)
2828                         break;
2829         }
2830         return (deadq_remove(dq));
2831 }
2832
2833 static void
2834 log_deadchild(pid_t pid, int status, const char *name)
2835 {
2836         int code;
2837         char buf[256];
2838         const char *reason;
2839
2840         errno = 0; /* Keep strerror() stuff out of logerror messages. */
2841         if (WIFSIGNALED(status)) {
2842                 reason = "due to signal";
2843                 code = WTERMSIG(status);
2844         } else {
2845                 reason = "with status";
2846                 code = WEXITSTATUS(status);
2847                 if (code == 0)
2848                         return;
2849         }
2850         (void)snprintf(buf, sizeof buf,
2851                        "Logging subprocess %d (%s) exited %s %d.",
2852                        pid, name, reason, code);
2853         logerror(buf);
2854 }
2855
2856 static int
2857 socksetup(struct peer *pe)
2858 {
2859         struct addrinfo hints, *res, *res0;
2860         int error;
2861         char *cp;
2862         /*
2863          * We have to handle this case for backwards compatibility:
2864          * If there are two (or more) colons but no '[' and ']',
2865          * assume this is an inet6 address without a service.
2866          */
2867         if (pe->pe_name != NULL) {
2868 #ifdef INET6
2869                 if (pe->pe_name[0] == '[' &&
2870                     (cp = strchr(pe->pe_name + 1, ']')) != NULL) {
2871                         pe->pe_name = &pe->pe_name[1];
2872                         *cp = '\0';
2873                         if (cp[1] == ':' && cp[2] != '\0')
2874                                 pe->pe_serv = cp + 2;
2875                 } else {
2876 #endif
2877                         cp = strchr(pe->pe_name, ':');
2878                         if (cp != NULL && strchr(cp + 1, ':') == NULL) {
2879                                 *cp = '\0';
2880                                 if (cp[1] != '\0')
2881                                         pe->pe_serv = cp + 1;
2882                                 if (cp == pe->pe_name)
2883                                         pe->pe_name = NULL;
2884                         }
2885 #ifdef INET6
2886                 }
2887 #endif
2888         }
2889         hints = (struct addrinfo){
2890                 .ai_family = AF_UNSPEC,
2891                 .ai_socktype = SOCK_DGRAM,
2892                 .ai_flags = AI_PASSIVE
2893         };
2894         dprintf("Try %s\n", pe->pe_name);
2895         if (pe->pe_serv == NULL)
2896                 pe->pe_serv = "syslog";
2897         error = getaddrinfo(pe->pe_name, pe->pe_serv, &hints, &res0);
2898         if (error) {
2899                 logerror(gai_strerror(error));
2900                 errno = 0;
2901                 die(0);
2902         }
2903         for (res = res0; res != NULL; res = res->ai_next) {
2904                 int s;
2905
2906                 if (res->ai_family != AF_LOCAL &&
2907                     SecureMode > 1) {
2908                         /* Only AF_LOCAL in secure mode. */
2909                         continue;
2910                 }
2911                 if (family != AF_UNSPEC && res->ai_family != family)
2912                         continue;
2913
2914                 s = socket(res->ai_family, res->ai_socktype,
2915                     res->ai_protocol);
2916                 if (s < 0) {
2917                         logerror("socket");
2918                         error++;
2919                         continue;
2920                 }
2921 #ifdef INET6
2922                 if (res->ai_family == AF_INET6) {
2923                         if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
2924                                &(int){1}, sizeof(int)) < 0) {
2925                                 logerror("setsockopt(IPV6_V6ONLY)");
2926                                 close(s);
2927                                 error++;
2928                                 continue;
2929                         }
2930                 }
2931 #endif
2932                 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
2933                     &(int){1}, sizeof(int)) < 0) {
2934                         logerror("setsockopt(SO_REUSEADDR)");
2935                         close(s);
2936                         error++;
2937                         continue;
2938                 }
2939
2940                 /*
2941                  * Bind INET and UNIX-domain sockets.
2942                  *
2943                  * A UNIX-domain socket is always bound to a pathname
2944                  * regardless of -N flag.
2945                  *
2946                  * For INET sockets, RFC 3164 recommends that client
2947                  * side message should come from the privileged syslogd port.
2948                  *
2949                  * If the system administrator chooses not to obey
2950                  * this, we can skip the bind() step so that the
2951                  * system will choose a port for us.
2952                  */
2953                 if (res->ai_family == AF_LOCAL)
2954                         unlink(pe->pe_name);
2955                 if (res->ai_family == AF_LOCAL ||
2956                     NoBind == 0 || pe->pe_name != NULL) {
2957                         if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
2958                                 logerror("bind");
2959                                 close(s);
2960                                 error++;
2961                                 continue;
2962                         }
2963                         if (res->ai_family == AF_LOCAL ||
2964                             SecureMode == 0)
2965                                 increase_rcvbuf(s);
2966                 }
2967                 if (res->ai_family == AF_LOCAL &&
2968                     chmod(pe->pe_name, pe->pe_mode) < 0) {
2969                         dprintf("chmod %s: %s\n", pe->pe_name,
2970                             strerror(errno));
2971                         close(s);
2972                         error++;
2973                         continue;
2974                 }
2975                 dprintf("new socket fd is %d\n", s);
2976                 listen(s, 5);
2977                 dprintf("shutdown\n");
2978                 if (SecureMode || res->ai_family == AF_LOCAL) {
2979                         /* Forbid communication in secure mode. */
2980                         if (shutdown(s, SHUT_RD) < 0 &&
2981                             errno != ENOTCONN) {
2982                                 logerror("shutdown");
2983                                 if (!Debug)
2984                                         die(0);
2985                         }
2986                         dprintf("listening on socket\n");
2987                 } else
2988                         dprintf("sending on socket\n");
2989                 addsock(res->ai_addr, res->ai_addrlen,
2990                     &(struct socklist){
2991                         .sl_socket = s,
2992                         .sl_peer = pe,
2993                         .sl_recv = socklist_recv_sock
2994                 });
2995         }
2996         freeaddrinfo(res0);
2997
2998         return(error);
2999 }
3000
3001 static void
3002 increase_rcvbuf(int fd)
3003 {
3004         socklen_t len;
3005
3006         if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len,
3007             &(socklen_t){sizeof(len)}) == 0) {
3008                 if (len < RCVBUF_MINSIZE) {
3009                         len = RCVBUF_MINSIZE;
3010                         setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));
3011                 }
3012         }
3013 }