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