2 * Copyright (c) 1983, 1988 Regents of the University of California.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 #if !defined(lint) && !defined(NO_SCCS)
20 "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\
21 All rights reserved.\n";
24 #if !defined(lint) && !defined(NO_SCCS)
25 static char sccsid[] = "@(#)syslogd.c 5.27 (Berkeley) 10/10/88";
29 * syslogd -- log system messages
31 * This program implements a system log. It takes a series of lines.
32 * Each line may have a priority, signified as "<n>" as
33 * the first characters of the line. If this is
34 * not present, a default priority is used.
36 * To kill syslogd, send a signal 15 (terminate). A signal 1 (hup) will
37 * cause it to reread its configuration file.
41 * MAXLINE -- the maximum line length that can be handled.
42 * DEFUPRI -- the default priority for user messages
43 * DEFSPRI -- the default priority for kernel messages
46 * extensive changes by Ralph Campbell
47 * more extensive changes by Eric Allman (again)
49 * Steve Lord: Fix UNIX domain socket code, added linux kernel logging
51 * SYSLOG_INET - listen on a UDP socket
52 * SYSLOG_UNIXAF - listen on unix domain socket
53 * SYSLOG_KERNEL - listen to linux kernel
55 * Mon Feb 22 09:55:42 CST 1993: Dr. Wettstein
56 * Additional modifications to the source. Changed priority scheme
57 * to increase the level of configurability. In its stock configuration
58 * syslogd no longer logs all messages of a certain priority and above
59 * to a log file. The * wildcard is supported to specify all priorities.
60 * Note that this is a departure from the BSD standard.
62 * Syslogd will now listen to both the inetd and the unixd socket. The
63 * strategy is to allow all local programs to direct their output to
64 * syslogd through the unixd socket while the program listens to the
65 * inetd socket to get messages forwarded from other hosts.
67 * Fri Mar 12 16:55:33 CST 1993: Dr. Wettstein
68 * Thanks to Stephen Tweedie (dcs.ed.ac.uk!sct) for helpful bug-fixes
69 * and an enlightened commentary on the prioritization problem.
71 * Changed the priority scheme so that the default behavior mimics the
72 * standard BSD. In this scenario all messages of a specified priority
73 * and above are logged.
75 * Add the ability to specify a wildcard (=) as the first character
76 * of the priority name. Doing this specifies that ONLY messages with
77 * this level of priority are to be logged. For example:
79 * *.=debug /usr/adm/debug
81 * Would log only messages with a priority of debug to the /usr/adm/debug
84 * Providing an * as the priority specifies that all messages are to be
85 * logged. Note that this case is degenerate with specifying a priority
86 * level of debug. The wildcard * was retained because I believe that
87 * this is more intuitive.
89 * Thu Jun 24 11:34:13 CDT 1993: Dr. Wettstein
90 * Modified sources to incorporate changes in libc4.4. Messages from
91 * syslog are now null-terminated, syslogd code now parses messages
92 * based on this termination scheme. Linux as of libc4.4 supports the
93 * fsync system call. Modified code to fsync after all writes to
96 * Sat Dec 11 11:59:43 CST 1993: Dr. Wettstein
97 * Extensive changes to the source code to allow compilation with no
98 * complaints with -Wall.
100 * Reorganized the facility and priority name arrays so that they
101 * compatible with the syslog.h source found in /usr/include/syslog.h.
102 * NOTE that this should really be changed. The reason I do not
103 * allow the use of the values defined in syslog.h is on account of
104 * the extensions made to allow the wildcard character in the
105 * priority field. To fix this properly one should malloc an array,
106 * copy the contents of the array defined by syslog.h and then
107 * make whatever modifications that are desired. Next round.
109 * Thu Jan 6 12:07:36 CST 1994: Dr. Wettstein
110 * Added support for proper decomposition and re-assembly of
111 * fragment messages on UNIX domain sockets. Lack of this capability
112 * was causing 'partial' messages to be output. Since facility and
113 * priority information is encoded as a leader on the messages this
114 * was causing lines to be placed in erroneous files.
116 * Also added a patch from Shane Alderton (shane@ion.apana.org.au) to
117 * correct a problem with syslogd dumping core when an attempt was made
118 * to write log messages to a logged-on user. Thank you.
120 * Many thanks to Juha Virtanen (jiivee@hut.fi) for a series of
121 * interchanges which lead to the fixing of problems with messages set
122 * to priorities of none and emerg. Also thanks to Juha for a patch
123 * to exclude users with a class of LOGIN from receiving messages.
125 * Shane Alderton provided an additional patch to fix zombies which
126 * were conceived when messages were written to multiple users.
128 * Mon Feb 6 09:57:10 CST 1995: Dr. Wettstein
129 * Patch to properly reset the single priority message flag. Thanks
130 * to Christopher Gori for spotting this bug and forwarding a patch.
132 * Wed Feb 22 15:38:31 CST 1995: Dr. Wettstein
133 * Added version information to startup messages.
135 * Added defines so that paths to important files are taken from
136 * the definitions in paths.h. Hopefully this will insure that
137 * everything follows the FSSTND standards. Thanks to Chris Metcalf
138 * for a set of patches to provide this functionality. Also thanks
139 * Elias Levy for prompting me to get these into the sources.
141 * Wed Jul 26 18:57:23 MET DST 1995: Martin Schulze
142 * Linux' gethostname only returns the hostname and not the fqdn as
143 * expected in the code. But if you call hostname with an fqdn then
144 * gethostname will return an fqdn, so we have to mention that. This
147 * The 'LocalDomain' and the hostname of a remote machine is
148 * converted to lower case, because the original caused some
149 * inconsistency, because the (at least my) nameserver did respond an
150 * fqdn containing of upper- _and_ lowercase letters while
151 * 'LocalDomain' consisted only of lowercase letters and that didn't
154 * Sat Aug 5 18:59:15 MET DST 1995: Martin Schulze
155 * Now no messages that were received from any remote host are sent
156 * out to another. At my domain this missing feature caused ugly
157 * syslog-loops, sometimes.
159 * Remember that no message is sent out. I can't figure out any
160 * scenario where it might be useful to change this behavior and to
161 * send out messages to other hosts than the one from which we
162 * received the message, but I might be shortsighted. :-/
164 * Thu Aug 10 19:01:08 MET DST 1995: Martin Schulze
165 * Added my pidfile.[ch] to it to perform a better handling with
166 * pidfiles. Now both, syslogd and klogd, can only be started
167 * once. They check the pidfile.
169 * Sun Aug 13 19:01:41 MET DST 1995: Martin Schulze
170 * Add an addition to syslog.conf's interpretation. If a priority
171 * begins with an exclamation mark ('!') the normal interpretation
172 * of the priority is inverted: ".!*" is the same as ".none", ".!=info"
173 * don't logs the info priority, ".!crit" won't log any message with
174 * the priority crit or higher. For example:
176 * mail.*;mail.!=info /usr/adm/mail
178 * Would log all messages of the facility mail except those with
179 * the priority info to /usr/adm/mail. This makes the syslogd
180 * much more flexible.
182 * Defined TABLE_ALLPRI=255 and changed some occurrences.
184 * Sat Aug 19 21:40:13 MET DST 1995: Martin Schulze
185 * Making the table of facilities and priorities while in debug
186 * mode more readable.
188 * If debugging is turned on, printing the whole table of
189 * facilities and priorities every hexadecimal or 'X' entry is
190 * now 2 characters wide.
192 * The number of the entry is prepended to each line of
193 * facilities and priorities, and F_UNUSED lines are not shown
196 * Corrected some #ifdef SYSV's.
198 * Mon Aug 21 22:10:35 MET DST 1995: Martin Schulze
199 * Corrected a strange behavior during parsing of configuration
200 * file. The original BSD syslogd doesn't understand spaces as
201 * separators between specifier and action. This syslogd now
202 * understands them. The old behavior caused some confusion over
203 * the Linux community.
205 * Thu Oct 19 00:02:07 MET 1995: Martin Schulze
206 * The default behavior has changed for security reasons. The
207 * syslogd will not receive any remote message unless you turn
208 * reception on with the "-r" option.
210 * Not defining SYSLOG_INET will result in not doing any network
211 * activity, i.e. not sending or receiving messages. I changed
212 * this because the old idea is implemented with the "-r" option
213 * and the old thing didn't work anyway.
215 * Thu Oct 26 13:14:06 MET 1995: Martin Schulze
216 * Added another logfile type F_FORW_UNKN. The problem I ran into
217 * was a name server that runs on my machine and a forwarder of
218 * kern.crit to another host. The hosts address can only be
219 * fetched using the nameserver. But named is started after
220 * syslogd, so syslogd complained.
222 * This logfile type will retry to get the address of the
223 * hostname ten times and then complain. This should be enough to
224 * get the named up and running during boot sequence.
226 * Fri Oct 27 14:08:15 1995: Dr. Wettstein
227 * Changed static array of logfiles to a dynamic array. This
228 * can grow during process.
230 * Fri Nov 10 23:08:18 1995: Martin Schulze
231 * Inserted a new tabular sys_h_errlist that contains plain text
232 * for error codes that are returned from the net subsystem and
233 * stored in h_errno. I have also changed some wrong lookups to
236 * Wed Nov 22 22:32:55 1995: Martin Schulze
237 * Added the fabulous strip-domain feature that allows us to
238 * strip off (several) domain names from the fqdn and only log
239 * the simple hostname. This is useful if you're in a LAN that
240 * has a central log server and also different domains.
242 * I have also also added the -l switch do define hosts as
243 * local. These will get logged with their simple hostname, too.
245 * Thu Nov 23 19:02:56 MET DST 1995: Martin Schulze
246 * Added the possibility to omit fsyncing of logfiles after every
247 * write. This will give some performance back if you have
248 * programs that log in a very verbose manner (like innd or
249 * smartlist). Thanks to Stephen R. van den Berg <srb@cuci.nl>
252 * Thu Jan 18 11:14:36 CST 1996: Dr. Wettstein
253 * Added patche from beta-testers to stop compile error. Also
254 * added removal of pid file as part of termination cleanup.
256 * Wed Feb 14 12:42:09 CST 1996: Dr. Wettstein
257 * Allowed forwarding of messages received from remote hosts to
258 * be controlled by a command-line switch. Specifying -h allows
259 * forwarding. The default behavior is to disable forwarding of
260 * messages which were received from a remote host.
262 * Parent process of syslogd does not exit until child process has
263 * finished initialization process. This allows rc.* startup to
264 * pause until syslogd facility is up and operating.
266 * Re-arranged the select code to move UNIX domain socket accepts
267 * to be processed later. This was a contributed change which
268 * has been proposed to correct the delays sometimes encountered
269 * when syslogd starts up.
271 * Minor code cleanups.
273 * Thu May 2 15:15:33 CDT 1996: Dr. Wettstein
274 * Fixed bug in init function which resulted in file descripters
275 * being orphaned when syslogd process was re-initialized with SIGHUP
276 * signal. Thanks to Edvard Tuinder
277 * (Edvard.Tuinder@praseodymium.cistron.nl) for putting me on the
278 * trail of this bug. I am amazed that we didn't catch this one
281 * Tue May 14 00:03:35 MET DST 1996: Martin Schulze
282 * Corrected a mistake that causes the syslogd to stop logging at
283 * some virtual consoles under Linux. This was caused by checking
284 * the wrong error code. Thanks to Michael Nonweiler
285 * <mrn20@hermes.cam.ac.uk> for sending me a patch.
287 * Mon May 20 13:29:32 MET DST 1996: Miquel van Smoorenburg <miquels@cistron.nl>
288 * Added continuation line supported and fixed a bug in
291 * Tue May 28 00:58:45 MET DST 1996: Martin Schulze
292 * Corrected behaviour of blocking pipes - i.e. the whole system
293 * hung. Michael Nonweiler <mrn20@hermes.cam.ac.uk> has sent us
294 * a patch to correct this. A new logfile type F_PIPE has been
297 * Mon Feb 3 10:12:15 MET DST 1997: Martin Schulze
298 * Corrected behaviour of logfiles if the file can't be opened.
299 * There was a bug that causes syslogd to try to log into non
300 * existing files which ate cpu power.
302 * Sun Feb 9 03:22:12 MET DST 1997: Martin Schulze
303 * Modified syslogd.c to not kill itself which confuses bash 2.0.
305 * Mon Feb 10 00:09:11 MET DST 1997: Martin Schulze
306 * Improved debug code to decode the numeric facility/priority
307 * pair into textual information.
309 * Tue Jun 10 12:35:10 MET DST 1997: Martin Schulze
310 * Corrected freeing of logfiles. Thanks to Jos Vos <jos@xos.nl>
311 * for reporting the bug and sending an idea to fix the problem.
313 * Tue Jun 10 12:51:41 MET DST 1997: Martin Schulze
314 * Removed sleep(10) from parent process. This has caused a slow
315 * startup in former times - and I don't see any reason for this.
317 * Sun Jun 15 16:23:29 MET DST 1997: Michael Alan Dorman
318 * Some more glibc patches made by <mdorman@debian.org>.
320 * Thu Jan 1 16:04:52 CET 1998: Martin Schulze <joey@infodrom.north.de
321 * Applied patch from Herbert Thielen <Herbert.Thielen@lpr.e-technik.tu-muenchen.de>.
322 * This included some balance parentheses for emacs and a bug in
323 * the exclamation mark handling.
325 * Fixed small bug which caused syslogd to write messages to the
326 * wrong logfile under some very rare conditions. Thanks to
327 * Herbert Xu <herbert@gondor.apana.org.au> for fiddling this out.
329 * Thu Jan 8 22:46:35 CET 1998: Martin Schulze <joey@infodrom.north.de>
330 * Reworked one line of the above patch as it prevented syslogd
331 * from binding the socket with the result that no messages were
332 * forwarded to other hosts.
334 * Sat Jan 10 01:33:06 CET 1998: Martin Schulze <joey@infodrom.north.de>
335 * Fixed small bugs in F_FORW_UNKN meachanism. Thanks to Torsten
336 * Neumann <torsten@londo.rhein-main.de> for pointing me to it.
338 * Mon Jan 12 19:50:58 CET 1998: Martin Schulze <joey@infodrom.north.de>
339 * Modified debug output concerning remote receiption.
341 * Mon Feb 23 23:32:35 CET 1998: Topi Miettinen <Topi.Miettinen@ml.tele.fi>
342 * Re-worked handling of Unix and UDP sockets to support closing /
343 * opening of them in order to have it open only if it is needed
344 * either for forwarding to a remote host or by receiption from
347 * Wed Feb 25 10:54:09 CET 1998: Martin Schulze <joey@infodrom.north.de>
348 * Fixed little comparison mistake that prevented the MARK
349 * feature to work properly.
351 * Wed Feb 25 13:21:44 CET 1998: Martin Schulze <joey@infodrom.north.de>
352 * Corrected Topi's patch as it prevented forwarding during
353 * startup due to an unknown LogPort.
355 * Sat Oct 10 20:01:48 CEST 1998: Martin Schulze <joey@infodrom.north.de>
356 * Added support for TESTING define which will turn syslogd into
357 * stdio-mode used for debugging.
359 * Sun Oct 11 20:16:59 CEST 1998: Martin Schulze <joey@infodrom.north.de>
360 * Reworked the initialization/fork code. Now the parent
361 * process activates a signal handler which the daughter process
362 * will raise if it is initialized. Only after that one the
363 * parent process may exit. Otherwise klogd might try to flush
364 * its log cache while syslogd can't receive the messages yet.
366 * Mon Oct 12 13:30:35 CEST 1998: Martin Schulze <joey@infodrom.north.de>
367 * Redirected some error output with regard to argument parsing to
370 * Mon Oct 12 14:02:51 CEST 1998: Martin Schulze <joey@infodrom.north.de>
371 * Applied patch provided vom Topi Miettinen with regard to the
372 * people from OpenBSD. This provides the additional '-a'
373 * argument used for specifying additional UNIX domain sockets to
374 * listen to. This is been used with chroot()'ed named's for
375 * example. See for http://www.psionic.com/papers/dns.html
377 * Mon Oct 12 18:29:44 CEST 1998: Martin Schulze <joey@infodrom.north.de>
378 * Added `ftp' facility which was introduced in glibc version 2.
379 * It's #ifdef'ed so won't harm with older libraries.
381 * Mon Oct 12 19:59:21 MET DST 1998: Martin Schulze <joey@infodrom.north.de>
382 * Code cleanups with regard to bsd -> posix transition and
383 * stronger security (buffer length checking). Thanks to Topi
384 * Miettinen <tom@medialab.sonera.net>
385 * . index() --> strchr()
386 * . sprintf() --> snprintf()
387 * . bcopy() --> memcpy()
388 * . bzero() --> memset()
389 * . UNAMESZ --> UT_NAMESIZE
390 * . sys_errlist --> strerror()
392 * Mon Oct 12 20:22:59 CEST 1998: Martin Schulze <joey@infodrom.north.de>
393 * Added support for setutent()/getutent()/endutend() instead of
394 * binary reading the UTMP file. This is the the most portable
395 * way. This allows /var/run/utmp format to change, even to a
396 * real database or utmp daemon. Also if utmp file locking is
397 * implemented in libc, syslog will use it immediately. Thanks
398 * to Topi Miettinen <tom@medialab.sonera.net>.
400 * Mon Oct 12 20:49:18 MET DST 1998: Martin Schulze <joey@infodrom.north.de>
401 * Avoid logging of SIGCHLD when syslogd is in the process of
402 * exiting and closing its files. Again thanks to Topi.
404 * Mon Oct 12 22:18:34 CEST 1998: Martin Schulze <joey@infodrom.north.de>
405 * Modified printline() to support 8bit characters - such as
406 * russion letters. Thanks to Vladas Lapinskas <lapinskas@mail.iae.lt>.
408 * Sat Nov 14 02:29:37 CET 1998: Martin Schulze <joey@infodrom.north.de>
409 * ``-m 0'' now turns of MARK logging entirely.
411 * Tue Jan 19 01:04:18 MET 1999: Martin Schulze <joey@infodrom.north.de>
412 * Finally fixed an error with `-a' processing, thanks to Topi
413 * Miettinen <tom@medialab.sonera.net>.
415 * Sun May 23 10:08:53 CEST 1999: Martin Schulze <joey@infodrom.north.de>
416 * Removed superflous call to utmpname(). The path to the utmp
417 * file is defined in the used libc and should not be hardcoded
418 * into the syslogd binary referring the system it was compiled on.
420 * Sun Sep 17 21:26:16 CEST 2000: Martin Schulze <joey@infodrom.ffis.de>
421 * Don't close open sockets upon reload. Thanks to Bill
424 * Mon Sep 18 09:10:47 CEST 2000: Martin Schulze <joey@infodrom.ffis.de>
425 * Fixed bug in printchopped() that caused syslogd to emit
426 * kern.emerg messages when splitting long lines. Thanks to
427 * Daniel Jacobowitz <dan@debian.org> for the fix.
429 * Mon Sep 18 15:33:26 CEST 2000: Martin Schulze <joey@infodrom.ffis.de>
430 * Removed unixm/unix domain sockets and switch to Datagram Unix
431 * Sockets. This should remove one possibility to play DoS with
432 * syslogd. Thanks to Olaf Kirch <okir@caldera.de> for the patch.
434 * Sun Mar 11 20:23:44 CET 2001: Martin Schulze <joey@infodrom.ffis.de>
435 * Don't return a closed fd if `-a' is called with a wrong path.
436 * Thanks to Bill Nottingham <notting@redhat.com> for providing
438 * Thu Apr 13 05:08:10 CEST 2001: Jon Burgess <Jon_Burgess@eur.3com.com>
439 * Moved the installation of the signal handler up a little bit
440 * so it guaranteed to be available when the child is forked,
441 * hence, fixing a race condition. This used to create problems
442 * with UML and fast machines.
444 * Sat Apr 17 18:03:05 CEST 2004: Steve Grubb <linux_4ever@yahoo.com>
445 * Correct memory allocation for for commandline arguments in
448 * Thu Apr 29 12:38:39 CEST 2004: Solar Designer <solar@openwall.com>
449 * Applied Openwall paranoia patches to improve crunch_list().
451 * Tue May 4 16:47:30 CEST 2004: Solar Designer <solar@openwall.com>
452 * Ensure that "len" is not placed in a register, and that the
453 * endtty() signal handler is not installed too early which could
454 * cause a segmentation fault or worse.
456 * Tue May 4 16:52:01 CEST 2004: Solar Designer <solar@openwall.com>
457 * Adjust the size of a variable to prevent a buffer overflow
458 * should _PATH_DEV ever contain something different than "/dev/".
460 * Tue Nov 2 20:28:23 CET 2004: Colin Phipps <cph@cph.demon.co.uk>
461 * Don't block on the network socket, in case a packet gets lost
462 * between select and recv.
464 * Sun Nov 7 12:28:47 CET 2004: Martin Schulze <joey@infodrom.org>
465 * Discard any timestamp information found in received syslog
466 * messages. This will affect local messages sent from a
467 * different timezone.
469 * Sun Nov 7 13:47:00 CET 2004: Martin Schulze <joey@infodrom.org>
470 * Remove trailing newline when forwarding messages.
472 * Thu May 25 09:47:38 CEST 2006: Martin Schulze <joey@infodrom.org>
473 * Reset the 'restart' flag immediately after entering the
474 * restart code, so that subsequent SIGHUPs are able to set it
475 * again and cause a new restart. This fixes a race condition
476 * when somebody sends tons of HUP signals.
478 * Thu May 24 15:24:49 CEST 2007: Martin Schulze <joey@infodrom.org>
479 * Ignore errors caused by filled up disks so that the log
480 * continues to be written as soon as space becomes available
483 * Sat May 26 10:05:05 CEST 2007: Martin Schulze <joey@infodrom.org>
484 * Only try to gather the local domain name when messages are to
485 * be received from the network, it's not needed otherwise.
487 * Sat May 26 12:22:44 CEST 2007: Martin Schulze <joey@infodrom.org>
488 * Properly accompany the MARK message with the facility.
490 * Mon May 28 19:44:39 CEST 2007: Martin Schulze <joey@infodrom.org>
491 * Notify the waiting parent process if the client dies to it
492 * doesn't wait the entire five minutes.
494 * Wed Jul 4 21:02:22 CEST 2007: Martin Schulze <joey@infodrom.org>
495 * Open a pipe with O_NOCTTY to avoid them becoming the controlling
496 * tty and normal files with O_NONBLOCK to avoid blocking.
498 * Fri Oct 26 17:21:15 CEST 2007: Thomas Jarosch <thomas.jarosch@intra2net.com>
499 * Move hostname setting code from main() into init().
501 * Wed May 7 21:00:39 CEST 2007: Martin Schulze <joey@infodrom.org>
502 * Make sure that the service name is only queried, when it is needed,
503 * i.e. when we are sending to or receiving from the network.
505 * Fri Sep 10 08:29:04 CEST 2010: Martin Schulze <joey@infodrom.org>
506 * Replace strcpy with memmove to fix continuation line problems
507 * on 64bit architectures, patch by David Couture.
511 #define MAXLINE 1024 /* maximum line length */
512 #define MAXSVLINE 240 /* maximum saved line length */
513 #define DEFUPRI (LOG_USER|LOG_NOTICE)
514 #define DEFSPRI (LOG_KERN|LOG_CRIT)
515 #define TIMERINTVL 30 /* interval for checking flush, mark */
517 #define CONT_LINE 1 /* Allow continuation lines */
523 #include <sys/types.h>
533 #include <sys/syslog.h>
534 #include <sys/param.h>
535 #include <sys/errno.h>
536 #include <sys/ioctl.h>
537 #include <sys/stat.h>
538 #include <sys/wait.h>
539 #include <sys/socket.h>
540 #include <sys/file.h>
544 #include <sys/msgbuf.h>
548 #include <sys/time.h>
549 #include <sys/resource.h>
552 #include <netinet/in.h>
555 #include <arpa/nameser.h>
556 #include <arpa/inet.h>
563 #if defined(__linux__)
569 #define UTMP_FILE UTMP_FILENAME
572 #define UTMP_FILE _PATH_UTMP
574 #define UTMP_FILE "/etc/utmp"
579 #ifndef _PATH_LOGCONF
580 #define _PATH_LOGCONF "/etc/syslog.conf"
583 #if defined(SYSLOGD_PIDNAME)
586 #define _PATH_LOGPID _PATH_VARRUN SYSLOGD_PIDNAME
588 #define _PATH_LOGPID "/etc/" SYSLOGD_PIDNAME
593 #define _PATH_LOGPID _PATH_VARRUN "syslogd.pid"
595 #define _PATH_LOGPID "/etc/syslogd.pid"
601 #define _PATH_DEV "/dev/"
604 #ifndef _PATH_CONSOLE
605 #define _PATH_CONSOLE "/dev/console"
609 #define _PATH_TTY "/dev/tty"
613 #define _PATH_LOG "/dev/log"
616 char *ConfFile = _PATH_LOGCONF;
617 char *PidFile = _PATH_LOGPID;
618 char ctty[] = _PATH_CONSOLE;
622 static int debugging_on = 0;
623 static int nlogs = -1;
624 static int restart = 0;
629 char *funixn[MAXFUNIX] = { _PATH_LOG };
630 int funix[MAXFUNIX] = { -1, };
633 # define UNAMESZ UT_NAMESIZE /* length of a login name */
635 # define UNAMESZ 8 /* length of a login name */
637 #define MAXUNAMES 20 /* maximum number of user names */
638 #define MAXFNAME 200 /* max file pathname length */
640 #define INTERNAL_NOPRI 0x10 /* the "no priority" priority */
641 #define TABLE_NOPRI 0 /* Value to indicate no priority in f_pmask */
642 #define TABLE_ALLPRI 0xFF /* Value to indicate all priorities in f_pmask */
643 #define LOG_MARK LOG_MAKEPRI(LOG_NFACILITIES, 0) /* mark "facility" */
645 #define MAX_PRI 191 /* Maximum Priority per RFC 3164 */
651 #define IGN_CONS 0x001 /* don't print on console */
652 #define SYNC_FILE 0x002 /* do fsync on file after printing */
653 #define ADDDATE 0x004 /* add a date to the message */
654 #define MARK 0x008 /* this message is a mark */
657 * This table contains plain text for h_errno errors used by the
660 const char *sys_h_errlist[] = {
661 "No problem", /* NETDB_SUCCESS */
662 "Authoritative answer: host not found", /* HOST_NOT_FOUND */
663 "Non-authoritative answer: host not found, or serverfail", /* TRY_AGAIN */
664 "Non recoverable errors", /* NO_RECOVERY */
665 "Valid name, no data record of requested type", /* NO_DATA */
666 "no address, look for MX record" /* NO_ADDRESS */
670 * This structure represents the files that will have log
676 struct filed *f_next; /* next in linked list */
678 short f_type; /* entry type, see below */
679 short f_file; /* file descriptor */
680 time_t f_time; /* time this was last written */
681 char *f_host; /* host from which to recd. */
682 u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */
684 char f_uname[MAXUNAMES][UNAMESZ+1];
686 char f_hname[MAXHOSTNAMELEN+1];
687 struct addrinfo *f_addr;
688 } f_forw; /* forwarding address */
689 char f_fname[MAXFNAME];
691 char f_prevline[MAXSVLINE]; /* last message logged */
692 char f_lasttime[16]; /* time of last occurrence */
693 char f_prevhost[MAXHOSTNAMELEN+1]; /* host from which recd. */
694 int f_prevpri; /* pri of f_prevline */
695 int f_prevlen; /* length of f_prevline */
696 int f_prevcount; /* repetition cnt of prevline */
697 int f_repeatcount; /* number of "repeated" msgs */
698 int f_flags; /* store some additional flags */
702 * Intervals at which we flush out "message repeated" messages,
703 * in seconds after previous message is logged. After each flush,
704 * we move to the next interval until we reach the largest.
706 int repeatinterval[] = { 30, 60 }; /* # of secs before flush */
707 #define MAXREPEAT ((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1)
708 #define REPEATTIME(f) ((f)->f_time + repeatinterval[(f)->f_repeatcount])
709 #define BACKOFF(f) { if (++(f)->f_repeatcount > MAXREPEAT) \
710 (f)->f_repeatcount = MAXREPEAT; \
713 #define INET_SUSPEND_TIME 180 /* equal to 3 minutes */
714 #define INET_RETRY_MAX 10 /* maximum of retries for getaddrinfo() */
717 #define LIST_DELIMITER ':' /* delimiter between two hosts */
719 /* values for f_type */
720 #define F_UNUSED 0 /* unused entry */
721 #define F_FILE 1 /* regular file */
722 #define F_TTY 2 /* terminal */
723 #define F_CONSOLE 3 /* console terminal */
724 #define F_FORW 4 /* remote machine */
725 #define F_USERS 5 /* list of users */
726 #define F_WALL 6 /* everyone logged on */
727 #define F_FORW_SUSP 7 /* suspended host forwarding */
728 #define F_FORW_UNKN 8 /* unknown host forwarding */
729 #define F_PIPE 9 /* named pipe */
730 char *TypeNames[] = {
731 "UNUSED", "FILE", "TTY", "CONSOLE",
732 "FORW", "USERS", "WALL", "FORW(SUSPENDED)",
733 "FORW(UNKNOWN)", "PIPE"
736 struct filed *Files = (struct filed *) 0;
737 struct filed consfile;
744 struct code PriNames[] = {
745 {"alert", LOG_ALERT},
747 {"debug", LOG_DEBUG},
748 {"emerg", LOG_EMERG},
750 {"error", LOG_ERR}, /* DEPRECATED */
752 {"none", INTERNAL_NOPRI}, /* INTERNAL */
753 {"notice", LOG_NOTICE},
754 {"panic", LOG_EMERG}, /* DEPRECATED */
755 {"warn", LOG_WARNING}, /* DEPRECATED */
756 {"warning", LOG_WARNING},
761 struct code FacNames[] = {
763 {"authpriv", LOG_AUTHPRIV},
765 {"daemon", LOG_DAEMON},
769 {"mark", LOG_MARK}, /* INTERNAL */
771 {"security", LOG_AUTH}, /* DEPRECATED */
772 {"syslog", LOG_SYSLOG},
778 {"local0", LOG_LOCAL0},
779 {"local1", LOG_LOCAL1},
780 {"local2", LOG_LOCAL2},
781 {"local3", LOG_LOCAL3},
782 {"local4", LOG_LOCAL4},
783 {"local5", LOG_LOCAL5},
784 {"local6", LOG_LOCAL6},
785 {"local7", LOG_LOCAL7},
789 int Debug; /* debug flag */
790 char LocalHostName[MAXHOSTNAMELEN+1]; /* our hostname */
791 char *LocalDomain; /* our local domain name */
792 char *emptystring = "";
793 int InetInuse = 0; /* non-zero if INET sockets are being used */
794 int *finet = NULL; /* Internet datagram sockets */
795 int Initialized = 0; /* set when we have initialized ourselves */
796 int MarkInterval = 20 * 60; /* interval between marks in seconds */
798 int family = PF_UNSPEC; /* protocol family (IPv4, IPv6 or both) */
800 int family = PF_INET; /* protocol family (IPv4 only) */
802 int send_to_all = 0; /* send message to all IPv4/IPv6 addresses */
803 int MarkSeq = 0; /* mark sequence number */
804 int LastAlarm = 0; /* last value passed to alarm() (seconds) */
805 int DupesPending = 0; /* Number of unflushed duplicate messages */
806 int NoFork = 0; /* don't fork - don't run in daemon mode */
807 int AcceptRemote = 0; /* receive messages that come via UDP */
808 char **StripDomains = NULL; /* these domains may be stripped before writing logs */
809 char **LocalHosts = NULL; /* these hosts are logged with their hostname */
810 int NoHops = 1; /* Can we bounce syslog messages through an
811 intermediate host. */
815 /* Function prototypes. */
816 int main(int argc, char **argv);
817 char **crunch_list(char *list);
820 void printchopped(const char *hname, char *msg, int len, int fd);
821 void printline(const char *hname, char *msg);
822 void printsys(char *msg);
823 void logmsg(int pri, char *msg, const char *from, int flags);
824 void fprintlog(register struct filed *f, char *from, int flags, char *msg);
826 void wallmsg(register struct filed *f, struct iovec *iov);
828 const char *cvtaddr(struct sockaddr_storage *f, int len);
829 const char *cvthname(struct sockaddr_storage *f, int len);
832 void logerror(const char *type);
835 void doexit(int sig);
838 void cfline(char *line, register struct filed *f);
839 int decode(char *name, struct code *codetab);
840 #if defined(__GLIBC__)
841 #define dprintf mydprintf
842 #endif /* __GLIBC__ */
843 static void dprintf(char *, ...);
844 static void allocate_log(void);
845 void sighup_handler();
848 static int create_unix_socket(const char *path);
851 static int *create_inet_sockets();
862 #if !defined(__GLIBC__)
864 #else /* __GLIBC__ */
869 #endif /* __GLIBC__ */
871 * It took me quite some time to figure out how this is
872 * supposed to work so I guess I should better write it down.
873 * unixm is a list of file descriptors from which one can
874 * read(). This is in contrary to readfds which is a list of
875 * file descriptors where activity is monitored by select()
876 * and from which one cannot read(). -Joey
878 * Changed: unixm is gone, since we now use datagram unix sockets.
879 * Hence we recv() from unix sockets directly (rather than
880 * first accept()ing connections on them), so there's no need
881 * for separate book-keeping. --okir
888 struct sockaddr_storage frominet;
890 pid_t ppid = getpid();
894 char line[MAXLINE +1];
902 for (i = 1; i < MAXFUNIX; i++) {
907 while ((ch = getopt(argc, argv, "46Aa:dhf:l:m:np:rs:v")) != EOF)
921 if (nfunix < MAXFUNIX)
922 funixn[nfunix++] = optarg;
924 fprintf(stderr, "Out of descriptors, ignoring %s\n", optarg);
926 case 'd': /* debug */
929 case 'f': /* configuration file */
937 fprintf (stderr, "Only one -l argument allowed," \
938 "the first one is taken.\n");
941 LocalHosts = crunch_list(optarg);
943 case 'm': /* mark interval */
944 MarkInterval = atoi(optarg) * 60;
946 case 'n': /* don't fork */
949 case 'p': /* path to regular log socket */
952 case 'r': /* accept remote messages */
957 fprintf (stderr, "Only one -s argument allowed," \
958 "the first one is taken.\n");
961 StripDomains = crunch_list(optarg);
964 printf("syslogd %s.%s\n", VERSION, PATCHLEVEL);
970 if ((argc -= optind))
974 if ( !(Debug || NoFork) )
976 dprintf("Checking pidfile.\n");
977 if (!check_pid(PidFile))
979 signal (SIGTERM, doexit);
986 * Not reached unless something major went wrong. 5
987 * minutes should be a fair amount of time to wait.
988 * Please note that this procedure is important since
989 * the father must not exit before syslogd isn't
990 * initialized or the klogd won't be able to flush its
995 signal (SIGTERM, SIG_DFL);
996 num_fds = getdtablesize();
997 for (i= 0; i < num_fds; i++)
1003 fputs("syslogd: Already running.\n", stderr);
1016 /* tuck my process id away */
1019 dprintf("Writing pidfile.\n");
1020 if (!check_pid(PidFile))
1022 if (!write_pid(PidFile))
1024 dprintf("Can't write pid.\n");
1025 if (getpid() != ppid)
1026 kill (ppid, SIGTERM);
1032 dprintf("Pidfile (and pid) already exist.\n");
1033 if (getpid() != ppid)
1034 kill (ppid, SIGTERM);
1037 } /* if ( !Debug ) */
1040 consfile.f_type = F_CONSOLE;
1041 (void) strcpy(consfile.f_un.f_fname, ctty);
1043 /* Initialization is done by init() */
1044 (void) strcpy(LocalHostName, emptystring);
1045 LocalDomain = emptystring;
1047 (void) signal(SIGTERM, die);
1048 (void) signal(SIGINT, Debug ? die : SIG_IGN);
1049 (void) signal(SIGQUIT, Debug ? die : SIG_IGN);
1050 (void) signal(SIGCHLD, reapchild);
1051 (void) signal(SIGALRM, domark);
1052 (void) signal(SIGUSR1, Debug ? debug_switch : SIG_IGN);
1053 (void) signal(SIGXFSZ, SIG_IGN);
1055 LastAlarm = MarkInterval;
1058 /* Create a partial message table for all file descriptors. */
1059 num_fds = getdtablesize();
1060 dprintf("Allocated parts table for %d file descriptors.\n", num_fds);
1061 if ( (parts = (char **) malloc(num_fds * sizeof(char *))) == \
1064 logerror("Cannot allocate memory for message parts table.");
1066 if (getpid() != ppid)
1067 kill (ppid, SIGTERM);
1071 for(i= 0; i < num_fds; ++i)
1072 parts[i] = (char *) 0;
1074 dprintf("Starting.\n");
1079 dprintf("Debugging disabled, SIGUSR1 to turn on debugging.\n");
1083 * Send a signal to the parent to it can terminate.
1085 if (getpid() != ppid)
1086 kill (ppid, SIGTERM);
1089 /* Main loop begins here. */
1095 #ifdef SYSLOG_UNIXAF
1098 * Add the Unix Domain Sockets to the list of read
1101 /* Copy master connections */
1102 for (i = 0; i < nfunix; i++) {
1103 if (funix[i] != -1) {
1104 FD_SET(funix[i], &readfds);
1105 if (funix[i]>maxfds) maxfds=funix[i];
1113 * Add the Internet Domain Socket to the list of read
1116 if ( InetInuse && AcceptRemote ) {
1117 for (i = 0; i < *finet; i++) {
1118 if (finet[i+1] != -1)
1119 FD_SET(finet[i+1], &readfds);
1120 if (finet[i+1]>maxfds) maxfds=finet[i+1];
1122 dprintf("Listening on syslog UDP port.\n");
1127 FD_SET(fileno(stdin), &readfds);
1128 if (fileno(stdin) > maxfds) maxfds = fileno(stdin);
1130 dprintf("Listening on stdin. Press Ctrl-C to interrupt.\n");
1135 dprintf("Calling select, active file descriptors (max %d): ", maxfds);
1136 for (nfds= 0; nfds <= maxfds; ++nfds)
1137 if ( FD_ISSET(nfds, &readfds) )
1138 dprintf("%d ", nfds);
1141 nfds = select(maxfds+1, (fd_set *) &readfds, (fd_set *) NULL,
1142 (fd_set *) NULL, (struct timeval *) NULL);
1146 dprintf("\nReceived SIGHUP, reloading syslogd.\n");
1151 dprintf("No select activity.\n");
1157 dprintf("Select interrupted.\n");
1163 dprintf("\nSuccessful select, descriptor count = %d, " \
1164 "Activity on: ", nfds);
1165 for (nfds= 0; nfds <= maxfds; ++nfds)
1166 if ( FD_ISSET(nfds, &readfds) )
1167 dprintf("%d ", nfds);
1172 #ifdef SYSLOG_UNIXAF
1173 for (i = 0; i < nfunix; i++) {
1174 if ((fd = funix[i]) != -1 && FD_ISSET(fd, &readfds)) {
1175 memset(line, 0, sizeof(line));
1176 msglen = recv(fd, line, MAXLINE - 2, 0);
1177 dprintf("Message from UNIX socket: #%d\n", fd);
1179 printchopped(LocalHostName, line, msglen + 2, fd);
1180 else if (msglen < 0 && errno != EINTR) {
1181 dprintf("UNIX socket error: %d = %s.\n", \
1182 errno, strerror(errno));
1183 logerror("recvfrom UNIX");
1190 if (InetInuse && AcceptRemote && finet) {
1191 for (i = 0; i < *finet; i++) {
1192 if (finet[i+1] != -1 && FD_ISSET(finet[i+1], &readfds)) {
1193 len = sizeof(frominet);
1194 memset(line, 0, sizeof(line));
1195 msglen = recvfrom(finet[i+1], line, MAXLINE - 2, 0, \
1196 (struct sockaddr *) &frominet, &len);
1198 const char *addr = cvtaddr(&frominet, len);
1199 dprintf("Message from inetd socket: #%d, host: %s\n",
1203 /* Note that if cvthname() returns NULL then
1204 we shouldn't attempt to log the line -- jch */
1205 const char *from = cvthname(&frominet, len);
1207 printchopped(from, line,
1208 msglen + 2, finet[i+1]);
1209 } else if (msglen < 0 && errno != EINTR && errno != EAGAIN) {
1210 dprintf("INET socket error: %d = %s.\n", \
1211 errno, strerror(errno));
1212 logerror("recvfrom inet");
1213 /* should be harmless now that we set
1214 * BSDCOMPAT on the socket */
1222 if ( FD_ISSET(fileno(stdin), &readfds) ) {
1223 dprintf("Message from stdin.\n");
1224 memset(line, '\0', sizeof(line));
1226 parts[fileno(stdin)] = (char *) 0;
1227 i = read(fileno(stdin), line, MAXLINE);
1229 printchopped(LocalHostName, line, i+1, fileno(stdin));
1231 if (errno != EINTR) {
1235 FD_CLR(fileno(stdin), &readfds);
1244 fprintf(stderr, "usage: syslogd [-46Adrvh] [-l hostlist] [-m markinterval] [-n] [-p path]\n" \
1245 " [-s domainlist] [-f conffile]\n");
1249 #ifdef SYSLOG_UNIXAF
1250 static int create_unix_socket(const char *path)
1252 struct sockaddr_un sunx;
1254 char line[MAXLINE +1];
1256 if (path[0] == '\0')
1259 (void) unlink(path);
1261 memset(&sunx, 0, sizeof(sunx));
1262 sunx.sun_family = AF_UNIX;
1263 (void) strncpy(sunx.sun_path, path, sizeof(sunx.sun_path));
1264 fd = socket(AF_UNIX, SOCK_DGRAM, 0);
1265 if (fd < 0 || bind(fd, (struct sockaddr *) &sunx,
1266 sizeof(sunx.sun_family)+strlen(sunx.sun_path)) < 0 ||
1267 chmod(path, 0666) < 0) {
1268 (void) snprintf(line, sizeof(line), "cannot create %s", path);
1270 dprintf("cannot create %s (%d).\n", path, errno);
1282 static int *create_inet_sockets()
1284 struct addrinfo hints, *res, *r;
1285 int error, maxs, *s, *socks;
1286 int on = 1, sockflags;
1288 memset(&hints, 0, sizeof(hints));
1289 hints.ai_flags = AI_PASSIVE;
1290 hints.ai_family = family;
1291 hints.ai_socktype = SOCK_DGRAM;
1292 error = getaddrinfo(NULL, "syslog", &hints, &res);
1294 logerror("network logging disabled (syslog/udp service unknown).");
1295 logerror("see syslogd(8) for details of whether and how to enable it.");
1296 logerror(gai_strerror(error));
1300 /* Count max number of sockets we may open */
1301 for (maxs = 0, r = res; r; r = r->ai_next, maxs++);
1302 socks = malloc((maxs+1) * sizeof(int));
1304 logerror("couldn't allocate memory for sockets");
1308 *socks = 0; /* num of sockets counter at start of array */
1310 for (r = res; r; r = r->ai_next) {
1311 *s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
1316 if (r->ai_family == AF_INET6) {
1317 if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY,
1318 (char *) &on, sizeof(on)) < 0) {
1319 logerror("setsockopt (IPV6_ONLY), suspending IPv6");
1324 if (setsockopt(*s, SOL_SOCKET, SO_REUSEADDR,
1325 (char *) &on, sizeof(on)) < 0 ) {
1326 logerror("setsockopt(REUSEADDR), suspending inet");
1330 /* We must not block on the network socket, in case a packet
1331 * gets lost between select and recv, otherise the process
1332 * will stall until the timeout, and other processes trying to
1333 * log will also stall.
1335 if ((sockflags = fcntl(*s, F_GETFL)) != -1) {
1336 sockflags |= O_NONBLOCK;
1338 * SETFL could fail too, so get it caught by the subsequent
1341 sockflags = fcntl(*s, F_SETFL, sockflags);
1343 if (sockflags == -1) {
1344 logerror("fcntl(O_NONBLOCK), suspending inet");
1348 if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) {
1349 logerror("bind, suspending inet");
1359 logerror("no valid sockets, suspending inet");
1373 char **result = NULL;
1377 /* strip off trailing delimiters */
1378 while (*p && p[strlen(p)-1] == LIST_DELIMITER)
1379 p[strlen(p)-1] = '\0';
1380 /* cut off leading delimiters */
1381 while (p[0] == LIST_DELIMITER)
1384 /* count delimiters to calculate the number of elements */
1385 for (n = i = 0; p[i]; i++)
1386 if (p[i] == LIST_DELIMITER) n++;
1388 if ((result = (char **)malloc(sizeof(char *) * (n + 2))) == NULL) {
1389 printf ("Sorry, can't get enough memory, exiting.\n");
1394 * We now can assume that the first and last
1395 * characters are different from any delimiters,
1396 * so we don't have to care about this.
1399 while ((q = strchr(p, LIST_DELIMITER)) && m < n) {
1400 result[m] = (char *) malloc((q - p + 1) * sizeof(char));
1401 if (result[m] == NULL) {
1402 printf ("Sorry, can't get enough memory, exiting.\n");
1405 memcpy(result[m], p, q - p);
1406 result[m][q - p] = '\0';
1410 if ((result[m] = strdup(p)) == NULL) {
1411 printf ("Sorry, can't get enough memory, exiting.\n");
1419 dprintf ("#%d: %s\n", m, result[m++]);
1439 i = open(_PATH_TTY, O_RDWR);
1441 (void) ioctl(i, (int) TIOCNOTTY, (char *)0);
1450 * Parse the line to make sure that the msg is not a composite of more
1454 void printchopped(hname, msg, len, fd)
1462 auto char *start = msg,
1465 tmpline[MAXLINE + 1];
1467 dprintf("Message length: %d, File descriptor: %d.\n", len, fd);
1469 if ( parts[fd] != (char *) 0 )
1471 dprintf("Including part from messages.\n");
1472 strcpy(tmpline, parts[fd]);
1474 parts[fd] = (char *) 0;
1475 if ( (strlen(msg) + strlen(tmpline)) > MAXLINE )
1477 logerror("Cannot glue message parts together");
1478 printline(hname, tmpline);
1483 dprintf("Previous: %s\n", tmpline);
1484 dprintf("Next: %s\n", msg);
1485 strcat(tmpline, msg); /* length checked above */
1486 printline(hname, tmpline);
1487 if ( (strlen(msg) + 1) == len )
1490 start = strchr(msg, '\0') + 1;
1494 if ( msg[len-1] != '\0' )
1497 for(p= msg+len-1; *p != '\0' && p > msg; )
1500 ptlngth = strlen(p);
1501 if ( (parts[fd] = malloc(ptlngth + 1)) == (char *) 0 )
1502 logerror("Cannot allocate memory for message part.");
1505 strcpy(parts[fd], p);
1506 dprintf("Saving partial msg: %s\n", parts[fd]);
1507 memset(p, '\0', ptlngth);
1512 end = strchr(start + 1, '\0');
1513 printline(hname, start);
1515 } while ( *start != '\0' );
1523 * Take a raw input line, decode the message, and print the message
1524 * on the appropriate log files.
1527 void printline(hname, msg)
1531 register char *p, *q;
1532 register unsigned char c;
1533 char line[MAXLINE + 1];
1534 unsigned int pri; // Valid Priority values are 0-191
1535 int prilen=0; // Track Priority value string len
1538 /* test for special codes */
1545 while (--msglen > 0 && isdigit((unsigned char)*++p) &&
1547 pri = 10 * pri + (*p - '0');
1550 if (*p == '>' && prilen)
1558 if ((pri &~ (LOG_FACMASK|LOG_PRIMASK)) || (pri > MAX_PRI)) {
1563 memset (line, 0, sizeof(line));
1565 while ((c = *p++) && q < &line[sizeof(line) - 4]) {
1566 if (c == '\n' || c == 127)
1576 logmsg(pri, line, hname, SYNC_FILE);
1583 * Take a raw input line from /dev/klog, split and format similar to syslog().
1589 register char *p, *q;
1591 char line[MAXLINE + 1];
1595 (void) snprintf(line, sizeof(line), "vmunix: ");
1596 lp = line + strlen(line);
1597 for (p = msg; *p != '\0'; ) {
1602 while (isdigit(*++p))
1603 pri = 10 * pri + (*p - '0');
1607 /* kernel printf's come out on console */
1610 if (pri &~ (LOG_FACMASK|LOG_PRIMASK))
1613 while (*p != '\0' && (c = *p++) != '\n' &&
1617 logmsg(pri, line, LocalHostName, flags);
1623 * Decode a priority into textual information like auth.emerg.
1628 static char res[20];
1629 CODE *c_pri, *c_fac;
1631 for (c_fac = facilitynames; c_fac->c_name && !(c_fac->c_val == LOG_FAC(pri)<<3); c_fac++);
1632 for (c_pri = prioritynames; c_pri->c_name && !(c_pri->c_val == LOG_PRI(pri)); c_pri++);
1634 snprintf (res, sizeof(res), "%s.%s<%d>", c_fac->c_name, c_pri->c_name, pri);
1642 * Log a message to the appropriate log files, users, etc. based on
1646 void logmsg(pri, msg, from, flags)
1652 register struct filed *f;
1653 int fac, prilev, lognum;
1656 #ifdef __gnu_linux__
1664 dprintf("logmsg: %s, flags %x, from %s, msg %s\n", textpri(pri), flags, from, msg);
1666 #ifdef __gnu_linux__
1668 sigaddset(&mask, SIGHUP);
1669 sigaddset(&mask, SIGALRM);
1670 sigprocmask(SIG_BLOCK, &mask, NULL);
1673 omask = sigblock(sigmask(SIGHUP)|sigmask(SIGALRM));
1678 * Check to see if msg looks non-standard.
1680 * A message looks like
1681 * Nov 17 11:42:33 CRON[
1685 * Remote messages are not accompanied by a timestamp.
1686 * Local messages are accompanied by a timestamp (program's timezone)
1688 msglen = strlen(msg);
1689 if (!(msglen < 16 || msg[3] != ' ' || msg[6] != ' ' ||
1690 msg[9] != ':' || msg[12] != ':' || msg[15] != ' ')) {
1696 timestamp = ctime(&now) + 4;
1698 /* extract facility and priority level */
1700 prilev = LOG_PRI(pri);
1702 /* log the message to the particular outputs */
1705 f->f_file = open(ctty, O_WRONLY|O_NOCTTY);
1707 if (f->f_file >= 0) {
1709 fprintlog(f, (char *)from, flags, msg);
1710 (void) close(f->f_file);
1713 #ifdef __gnu_linux__
1714 sigprocmask(SIG_UNBLOCK, &mask, NULL);
1717 (void) sigsetmask(omask);
1723 for (lognum = 0; lognum <= nlogs; lognum++) {
1726 for (f = Files; f; f = f->f_next) {
1729 /* skip messages that are incorrect priority */
1730 if ( (f->f_pmask[fac] == TABLE_NOPRI) || \
1731 ((f->f_pmask[fac] & (1<<prilev)) == 0) )
1734 if (f->f_type == F_CONSOLE && (flags & IGN_CONS))
1737 /* don't output marks to recently written files */
1738 if ((flags & MARK) && (now - f->f_time) < MarkInterval / 2)
1742 * suppress duplicate lines to this file
1744 if ((flags & MARK) == 0 && msglen == f->f_prevlen &&
1745 !strcmp(msg, f->f_prevline) &&
1746 !strcmp(from, f->f_prevhost)) {
1747 (void) strncpy(f->f_lasttime, timestamp, 15);
1749 dprintf("msg repeated %d times, %ld sec of %d.\n",
1750 f->f_prevcount, now - f->f_time,
1751 repeatinterval[f->f_repeatcount]);
1753 if (f->f_prevcount == 1 && DupesPending++ == 0) {
1755 dprintf("setting alarm to flush duplicate messages\n");
1758 MarkSeq += LastAlarm - seconds;
1759 LastAlarm = seconds;
1760 if (LastAlarm > TIMERINTVL)
1761 LastAlarm = TIMERINTVL;
1766 * If domark would have logged this by now,
1767 * flush it now (so we don't hold isolated messages),
1768 * but back off so we'll flush less often
1771 if (now > REPEATTIME(f)) {
1772 fprintlog(f, (char *)from, flags, (char *)NULL);
1776 /* new line, save it */
1777 if (f->f_prevcount) {
1778 fprintlog(f, (char *)from, 0, (char *)NULL);
1780 if (--DupesPending == 0) {
1781 dprintf("unsetting duplicate message flush alarm\n");
1783 MarkSeq += LastAlarm - alarm(0);
1784 LastAlarm = MarkInterval - MarkSeq;
1789 f->f_repeatcount = 0;
1790 (void) strncpy(f->f_lasttime, timestamp, 15);
1791 (void) strncpy(f->f_prevhost, from,
1792 sizeof(f->f_prevhost));
1793 if (msglen < MAXSVLINE) {
1794 f->f_prevlen = msglen;
1795 (void) strcpy(f->f_prevline, msg);
1796 fprintlog(f, (char *)from, flags, (char *)NULL);
1798 f->f_prevline[0] = 0;
1800 fprintlog(f, (char *)from, flags, msg);
1804 #ifdef __gnu_linux__
1805 sigprocmask(SIG_UNBLOCK, &mask, NULL);
1808 (void) sigsetmask(omask);
1813 } /* balance parentheses for emacs */
1816 void fprintlog(f, from, flags, msg)
1817 register struct filed *f;
1822 struct iovec iov[6];
1823 register struct iovec *v = iov;
1827 char line[MAXLINE + 1];
1829 struct addrinfo hints, *ai;
1833 dprintf("Called fprintlog, ");
1835 v->iov_base = f->f_lasttime;
1841 v->iov_base = f->f_prevhost;
1842 v->iov_len = strlen(v->iov_base);
1849 v->iov_len = strlen(msg);
1850 } else if (f->f_prevcount > 1) {
1851 (void) snprintf(repbuf, sizeof(repbuf), "last message repeated %d times",
1853 v->iov_base = repbuf;
1854 v->iov_len = strlen(repbuf);
1856 v->iov_base = f->f_prevline;
1857 v->iov_len = f->f_prevlen;
1861 dprintf("logging to %s", TypeNames[f->f_type]);
1863 switch (f->f_type) {
1871 fwd_suspend = time((time_t *) 0) - f->f_time;
1872 if ( fwd_suspend >= INET_SUSPEND_TIME ) {
1873 dprintf("\nForwarding suspension over, " \
1879 dprintf(" %s\n", f->f_un.f_forw.f_hname);
1880 dprintf("Forwarding suspension not over, time " \
1881 "left: %d.\n", INET_SUSPEND_TIME - \
1887 * The trick is to wait some time, then retry to get the
1888 * address. If that fails retry x times and then give up.
1890 * You'll run into this problem mostly if the name server you
1891 * need for resolving the address is on the same machine, but
1892 * is started after syslogd.
1895 dprintf(" %s\n", f->f_un.f_forw.f_hname);
1896 fwd_suspend = time((time_t *) 0) - f->f_time;
1897 if ( fwd_suspend >= INET_SUSPEND_TIME ) {
1898 dprintf("Forwarding suspension to unknown over, retrying\n");
1899 memset(&hints, 0, sizeof(hints));
1900 hints.ai_family = family;
1901 hints.ai_socktype = SOCK_DGRAM;
1902 if ((err = getaddrinfo(f->f_un.f_forw.f_hname, "syslog", &hints, &ai))) {
1903 dprintf("Failure: %s\n", gai_strerror(err));
1904 dprintf("Retries: %d\n", f->f_prevcount);
1905 if ( --f->f_prevcount < 0 ) {
1906 dprintf("Giving up.\n");
1907 f->f_type = F_UNUSED;
1910 dprintf("Left retries: %d\n", f->f_prevcount);
1913 dprintf("%s found, resuming.\n", f->f_un.f_forw.f_hname);
1914 f->f_un.f_forw.f_addr = ai;
1921 dprintf("Forwarding suspension not over, time " \
1922 "left: %d\n", INET_SUSPEND_TIME - fwd_suspend);
1927 * Don't send any message to a remote host if it
1928 * already comes from one. (we don't care 'bout who
1929 * sent the message, we don't send it anyway) -Joey
1932 dprintf(" %s\n", f->f_un.f_forw.f_hname);
1933 if ( strcmp(from, LocalHostName) && NoHops )
1934 dprintf("Not sending message to remote.\n");
1938 (void) snprintf(line, sizeof(line), "<%d>%s", f->f_prevpri, \
1939 (char *) iov[4].iov_base);
1944 for (ai = f->f_un.f_forw.f_addr; ai; ai = ai->ai_next) {
1945 for (i = 0; i < *finet; i++) {
1947 lsent = sendto(finet[i+1], line, l, 0,
1948 ai->ai_addr, ai->ai_addrlen);
1955 if (err == -1 && !send_to_all)
1959 dprintf("INET sendto error: %d = %s.\n",
1960 err, strerror(err));
1961 f->f_type = F_FORW_SUSP;
1974 if (flags & IGN_CONS) {
1976 dprintf(" (ignored).\n");
1985 dprintf(" %s\n", f->f_un.f_fname);
1986 if (f->f_type == F_TTY || f->f_type == F_CONSOLE) {
1987 v->iov_base = "\r\n";
1994 /* f->f_file == -1 is an indicator that we couldn't
1995 open the file at startup. */
1996 if (f->f_file == -1)
1999 if (writev(f->f_file, iov, 6) < 0) {
2002 /* If a named pipe is full, just ignore it for now */
2003 if (f->f_type == F_PIPE && e == EAGAIN)
2006 /* If the filesystem is filled up, just ignore
2007 it for now and continue writing when
2009 if (f->f_type == F_FILE && e == ENOSPC)
2012 (void) close(f->f_file);
2014 * Check for EBADF on TTY's due to vhangup() XXX
2015 * Linux uses EIO instead (mrn 12 May 96)
2017 if ((f->f_type == F_TTY || f->f_type == F_CONSOLE)
2023 f->f_file = open(f->f_un.f_fname, O_WRONLY|O_APPEND|O_NOCTTY);
2024 if (f->f_file < 0) {
2025 f->f_type = F_UNUSED;
2026 logerror(f->f_un.f_fname);
2032 f->f_type = F_UNUSED;
2034 logerror(f->f_un.f_fname);
2036 } else if (f->f_type == F_FILE && (f->f_flags & SYNC_FILE))
2037 (void) fsync(f->f_file);
2044 v->iov_base = "\r\n";
2049 if (f->f_type != F_FORW_UNKN)
2054 }} /* balance parentheses for emacs */
2065 * WALLMSG -- Write a message to the world at large
2067 * Write the specified message to either the entire
2068 * world, or a list of approved users.
2071 void wallmsg(f, iov)
2072 register struct filed *f;
2075 char p[sizeof (_PATH_DEV) + UNAMESZ];
2078 static int reenter = 0;
2081 char greetings[200];
2088 /* open the user login file */
2093 * Might as well fork instead of using nonblocking I/O
2094 * and doing notty().
2097 (void) signal(SIGTERM, SIG_DFL);
2100 (void) signal(SIGTTOU, SIG_IGN);
2101 (void) sigsetmask(0);
2103 (void) snprintf(greetings, sizeof(greetings),
2104 "\r\n\7Message from syslogd@%s at %.24s ...\r\n",
2105 (char *) iov[2].iov_base, ctime(&now));
2106 len = strlen(greetings);
2108 /* scan the user login file */
2109 while ((uptr = getutent())) {
2110 memcpy(&ut, uptr, sizeof(ut));
2111 /* is this slot used? */
2112 if (ut.ut_name[0] == '\0')
2114 if (ut.ut_type != USER_PROCESS)
2116 if (!(strcmp (ut.ut_name,"LOGIN"))) /* paranoia */
2119 /* should we send the message to this user? */
2120 if (f->f_type == F_USERS) {
2121 for (i = 0; i < MAXUNAMES; i++) {
2122 if (!f->f_un.f_uname[i][0]) {
2126 if (strncmp(f->f_un.f_uname[i],
2127 ut.ut_name, UNAMESZ) == 0)
2134 /* compute the device name */
2135 strcpy(p, _PATH_DEV);
2136 strncat(p, ut.ut_line, UNAMESZ);
2138 if (f->f_type == F_WALL) {
2139 iov[0].iov_base = greetings;
2140 iov[0].iov_len = len;
2143 if (setjmp(ttybuf) == 0) {
2144 (void) signal(SIGALRM, endtty);
2146 /* open the terminal */
2147 ttyf = open(p, O_WRONLY|O_NOCTTY);
2151 if (fstat(ttyf, &statb) == 0 &&
2152 (statb.st_mode & S_IWRITE))
2153 (void) writev(ttyf, iov, 6);
2162 /* close the user login file */
2169 int saved_errno = errno;
2170 #if defined(SYSV) && !defined(linux)
2171 (void) signal(SIGCHLD, reapchild); /* reset signal handler -ASP */
2176 while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0)
2180 (void) signal(SIGCHLD, reapchild); /* reset signal handler -ASP */
2182 errno = saved_errno;
2185 const char *cvtaddr (struct sockaddr_storage *f, int len)
2187 static char ip[NI_MAXHOST];
2189 if (getnameinfo((struct sockaddr *) f, len,
2190 ip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST))
2196 * Return a printable representation of a host address.
2198 * Here we could check if the host is permitted to send us syslog
2199 * messages. We just have to check the hostname we're about to return
2200 * and compared it (case-insensitively) to a blacklist or whitelist.
2201 * Callers of cvthname() need to know that if NULL is returned then
2202 * the host is to be ignored.
2204 const char *cvthname(struct sockaddr_storage *f, int len)
2206 static char hname[NI_MAXHOST];
2211 if ((error = getnameinfo((struct sockaddr *) f, len,
2212 hname, NI_MAXHOST, NULL, 0, NI_NAMEREQD))) {
2213 dprintf("Host name for your address (%s) unknown: %s\n", gai_strerror(error));
2214 if ((error = getnameinfo((struct sockaddr *) f, len,
2215 hname, NI_MAXHOST, NULL, 0, NI_NUMERICHOST))) {
2216 dprintf("Malformed from address: %s\n", gai_strerror(error));
2222 * Convert to lower case, just like LocalDomain above
2224 for (p = hname; *p ; p++)
2229 * Notice that the string still contains the fqdn, but your
2230 * hostname and domain are separated by a '\0'.
2232 if ((p = strchr(hname, '.'))) {
2233 if (strcmp(p + 1, LocalDomain) == 0) {
2239 while (StripDomains[count]) {
2240 if (strcmp(p + 1, StripDomains[count]) == 0) {
2249 while (LocalHosts[count]) {
2250 if (!strcmp(hname, LocalHosts[count])) {
2265 register struct filed *f;
2270 if (MarkInterval > 0) {
2272 MarkSeq += LastAlarm;
2273 if (MarkSeq >= MarkInterval) {
2274 logmsg(LOG_MARK|LOG_INFO, "-- MARK --", LocalHostName, ADDDATE|MARK);
2275 MarkSeq -= MarkInterval;
2280 for (lognum = 0; lognum <= nlogs; lognum++) {
2283 for (f = Files; f; f = f->f_next) {
2285 if (f->f_prevcount && now >= REPEATTIME(f)) {
2286 dprintf("flush %s: repeated %d times, %d sec.\n",
2287 TypeNames[f->f_type], f->f_prevcount,
2288 repeatinterval[f->f_repeatcount]);
2289 fprintlog(f, LocalHostName, 0, (char *)NULL);
2294 (void) signal(SIGALRM, domark);
2296 LastAlarm = MarkInterval - MarkSeq;
2297 if (DupesPending && LastAlarm > TIMERINTVL)
2298 LastAlarm = TIMERINTVL;
2300 (void) alarm(LastAlarm);
2306 dprintf("Switching debugging_on to %s\n", (debugging_on == 0) ? "true" : "false");
2307 debugging_on = (debugging_on == 0) ? 1 : 0;
2308 signal(SIGUSR1, debug_switch);
2313 * Print syslogd errors some place.
2315 void logerror(const char *type)
2319 dprintf("Called logerr, msg: %s\n", type);
2322 (void) snprintf(buf, sizeof(buf), "syslogd: %s", type);
2324 (void) snprintf(buf, sizeof(buf), "syslogd: %s: %s", type, strerror(errno));
2326 logmsg(LOG_SYSLOG|LOG_ERR, buf, LocalHostName, ADDDATE);
2335 register struct filed *f;
2339 int was_initialized = Initialized;
2341 Initialized = 0; /* Don't log SIGCHLDs in case we
2342 receive one during exiting */
2344 for (lognum = 0; lognum <= nlogs; lognum++) {
2346 /* flush any pending output */
2348 fprintlog(f, LocalHostName, 0, (char *)NULL);
2351 Initialized = was_initialized;
2353 dprintf("syslogd: exiting on signal %d\n", sig);
2354 (void) snprintf(buf, sizeof(buf), "exiting on signal %d", sig);
2356 logmsg(LOG_SYSLOG|LOG_INFO, buf, LocalHostName, ADDDATE);
2359 /* Close the UNIX sockets. */
2360 for (i = 0; i < nfunix; i++)
2363 /* Close the inet sockets. */
2364 if (InetInuse && finet) {
2365 for (i = 0; i < *finet; i++)
2370 /* Clean-up files. */
2371 for (i = 0; i < nfunix; i++)
2372 if (funixn[i] && funix[i] != -1)
2373 (void)unlink(funixn[i]);
2375 (void) remove_pid(PidFile);
2381 * Signal handler to terminate the parent process.
2392 * INIT -- Initialize syslogd from configuration table
2397 register int i, lognum;
2399 register struct filed *f;
2402 register struct filed **nextp = (struct filed **) 0;
2406 register unsigned int Forwarding = 0;
2413 struct hostent *hent;
2416 * Close all open log files and free log descriptor array.
2418 dprintf("Called init.\n");
2422 dprintf("Initializing log structures.\n");
2424 for (lognum = 0; lognum <= nlogs; lognum++ ) {
2427 /* flush any pending output */
2429 fprintlog(f, LocalHostName, 0, (char *)NULL);
2431 switch (f->f_type) {
2436 (void) close(f->f_file);
2440 freeaddrinfo(f->f_un.f_forw.f_addr);
2446 * This is needed especially when HUPing syslogd as the
2447 * structure would grow infinitively. -Joey
2450 free((void *) Files);
2451 Files = (struct filed *) 0;
2462 (void) gethostname(LocalHostName, sizeof(LocalHostName));
2463 LocalDomain = emptystring;
2464 if ( (p = strchr(LocalHostName, '.')) ) {
2468 else if ( AcceptRemote )
2471 * It's not clearly defined whether gethostname()
2472 * should return the simple hostname or the fqdn. A
2473 * good piece of software should be aware of both and
2474 * we want to distribute good software. Joey
2476 * Good software also always checks its return values...
2477 * If syslogd starts up before DNS is up & /etc/hosts
2478 * doesn't have LocalHostName listed, gethostbyname will
2481 hent = gethostbyname(LocalHostName);
2483 snprintf(LocalHostName, sizeof(LocalHostName), "%s", hent->h_name);
2485 if ( (p = strchr(LocalHostName, '.')) )
2493 * Convert to lower case to recognize the correct domain laterly
2495 for (p = (char *)LocalDomain; *p ; p++)
2499 /* open the configuration file */
2500 if ((cf = fopen(ConfFile, "r")) == NULL) {
2501 dprintf("cannot open %s.\n", ConfFile);
2504 f = &Files[lognum++];
2506 cfline("*.err\t" _PATH_CONSOLE, f);
2508 snprintf(cbuf,sizeof(cbuf), "*.*\t%s", ttyname(0));
2512 *nextp = (struct filed *)calloc(1, sizeof(*f));
2513 cfline("*.ERR\t" _PATH_CONSOLE, *nextp);
2514 (*nextp)->f_next = (struct filed *)calloc(1, sizeof(*f)) /* ASP */
2515 cfline("*.PANIC\t*", (*nextp)->f_next);
2522 * Foreach line in the conf table, open that file.
2526 while (fgets(cline, sizeof(cbuf) - (cline - cbuf), cf) != NULL) {
2528 while (fgets(cline, sizeof(cline), cf) != NULL) {
2531 * check for end-of-section, comments, strip off trailing
2532 * spaces and newline character.
2534 for (p = cline; isspace(*p); ++p);
2535 if (*p == '\0' || *p == '#')
2538 memmove(cline, p, strlen(p)+1);
2540 for (p = strchr(cline, '\0'); isspace(*--p););
2543 if ((p - cbuf) > BUFSIZ - 30) {
2544 /* Oops the buffer is full - what now? */
2556 f = (struct filed *)calloc(1, sizeof(*f));
2561 f = &Files[lognum++];
2567 if (f->f_type == F_FORW || f->f_type == F_FORW_SUSP || f->f_type == F_FORW_UNKN) {
2572 /* close the configuration file */
2575 #ifdef SYSLOG_UNIXAF
2576 for (i = 0; i < nfunix; i++) {
2578 /* Don't close the socket, preserve it instead
2582 if ((funix[i] = create_unix_socket(funixn[i])) != -1)
2583 dprintf("Opened UNIX socket `%s'.\n", funixn[i]);
2588 if (Forwarding || AcceptRemote) {
2590 finet = create_inet_sockets();
2593 dprintf("Opened syslog UDP port.\n");
2599 for (i = 0; i < *finet; i++)
2600 if (finet[i+1] != -1)
2613 for (lognum = 0; lognum <= nlogs; lognum++) {
2615 if (f->f_type != F_UNUSED) {
2616 printf ("%2d: ", lognum);
2618 for (f = Files; f; f = f->f_next) {
2619 if (f->f_type != F_UNUSED) {
2621 for (i = 0; i <= LOG_NFACILITIES; i++)
2622 if (f->f_pmask[i] == TABLE_NOPRI)
2625 printf("%2X ", f->f_pmask[i]);
2626 printf("%s: ", TypeNames[f->f_type]);
2627 switch (f->f_type) {
2632 printf("%s", f->f_un.f_fname);
2633 if (f->f_file == -1)
2634 printf(" (unused)");
2640 printf("%s", f->f_un.f_forw.f_hname);
2644 for (i = 0; i < MAXUNAMES && *f->f_un.f_uname[i]; i++)
2645 printf("%s, ", f->f_un.f_uname[i]);
2655 logmsg(LOG_SYSLOG|LOG_INFO, "syslogd " VERSION "." PATCHLEVEL "#" DEBRELEASE \
2656 ": restart (remote reception)." , LocalHostName, \
2659 logmsg(LOG_SYSLOG|LOG_INFO, "syslogd " VERSION "." PATCHLEVEL \
2660 ": restart (remote reception)." , LocalHostName, \
2665 logmsg(LOG_SYSLOG|LOG_INFO, "syslogd " VERSION "." PATCHLEVEL "#" DEBRELEASE \
2666 ": restart." , LocalHostName, ADDDATE);
2668 logmsg(LOG_SYSLOG|LOG_INFO, "syslogd " VERSION "." PATCHLEVEL \
2669 ": restart." , LocalHostName, ADDDATE);
2671 (void) signal(SIGHUP, sighup_handler);
2672 dprintf("syslogd: restarted.\n");
2675 }}} /* balance parentheses for emacs */
2679 * Crack a configuration file line
2682 void cfline(line, f)
2684 register struct filed *f;
2695 struct addrinfo hints, *ai;
2700 dprintf("cfline(%s)\n", line);
2702 errno = 0; /* keep strerror() stuff out of logerror messages */
2704 /* clear out file entry */
2706 memset((char *) f, 0, sizeof(*f));
2708 for (i = 0; i <= LOG_NFACILITIES; i++) {
2709 f->f_pmask[i] = TABLE_NOPRI;
2713 /* scan through the list of selectors */
2714 for (p = line; *p && *p != '\t' && *p != ' ';) {
2716 /* find the end of this facility name list */
2717 for (q = p; *q && *q != '\t' && *q++ != '.'; )
2720 /* collect priority name */
2721 for (bp = buf; *q && !strchr("\t ,;", *q); )
2726 while (strchr(",;", *q))
2729 /* decode priority name */
2730 if ( *buf == '!' ) {
2732 for (bp=buf; *(bp+1); bp++)
2742 pri = decode(&buf[1], PriNames);
2746 pri = decode(buf, PriNames);
2750 (void) snprintf(xbuf, sizeof(xbuf), "unknown priority name \"%s\"", buf);
2755 /* scan facilities */
2756 while (*p && !strchr("\t .;", *p)) {
2757 for (bp = buf; *p && !strchr("\t ,;.", *p); )
2761 for (i = 0; i <= LOG_NFACILITIES; i++) {
2762 if ( pri == INTERNAL_NOPRI ) {
2764 f->f_pmask[i] = TABLE_ALLPRI;
2766 f->f_pmask[i] = TABLE_NOPRI;
2768 else if ( singlpri ) {
2770 f->f_pmask[i] &= ~(1<<pri);
2772 f->f_pmask[i] |= (1<<pri);
2776 if ( pri == TABLE_ALLPRI ) {
2778 f->f_pmask[i] = TABLE_NOPRI;
2780 f->f_pmask[i] = TABLE_ALLPRI;
2785 for (i2= 0; i2 <= pri; ++i2)
2786 f->f_pmask[i] &= ~(1<<i2);
2788 for (i2= 0; i2 <= pri; ++i2)
2789 f->f_pmask[i] |= (1<<i2);
2794 i = decode(buf, FacNames);
2797 (void) snprintf(xbuf, sizeof(xbuf), "unknown facility name \"%s\"", buf);
2802 if ( pri == INTERNAL_NOPRI ) {
2804 f->f_pmask[i >> 3] = TABLE_ALLPRI;
2806 f->f_pmask[i >> 3] = TABLE_NOPRI;
2807 } else if ( singlpri ) {
2809 f->f_pmask[i >> 3] &= ~(1<<pri);
2811 f->f_pmask[i >> 3] |= (1<<pri);
2813 if ( pri == TABLE_ALLPRI ) {
2815 f->f_pmask[i >> 3] = TABLE_NOPRI;
2817 f->f_pmask[i >> 3] = TABLE_ALLPRI;
2820 for (i2= 0; i2 <= pri; ++i2)
2821 f->f_pmask[i >> 3] &= ~(1<<i2);
2823 for (i2= 0; i2 <= pri; ++i2)
2824 f->f_pmask[i >> 3] |= (1<<i2);
2828 while (*p == ',' || *p == ' ')
2835 /* skip to action part */
2836 while (*p == '\t' || *p == ' ')
2846 dprintf("leading char in action: %c\n", *p);
2851 (void) strcpy(f->f_un.f_forw.f_hname, ++p);
2852 dprintf("forwarding host: %s\n", p); /*ASP*/
2853 memset(&hints, 0, sizeof(hints));
2854 hints.ai_family = family;
2855 hints.ai_socktype = SOCK_DGRAM;
2856 if (getaddrinfo(p, "syslog", &hints, &ai)) {
2858 * The host might be unknown due to an
2859 * inaccessible nameserver (perhaps on the
2860 * same host). We try to get the ip number
2861 * later, like FORW_SUSP.
2863 f->f_type = F_FORW_UNKN;
2864 f->f_prevcount = INET_RETRY_MAX;
2865 f->f_time = time ( (time_t *)0 );
2866 f->f_un.f_forw.f_addr = NULL;
2869 f->f_un.f_forw.f_addr = ai;
2876 (void) strcpy(f->f_un.f_fname, p);
2877 dprintf ("filename: %s\n", p); /*ASP*/
2879 f->f_flags |= SYNC_FILE;
2881 f->f_file = open(++p, O_RDWR|O_NONBLOCK|O_NOCTTY);
2884 f->f_file = open(p, O_WRONLY|O_APPEND|O_CREAT|O_NONBLOCK|O_NOCTTY,
2889 if ( f->f_file < 0 ){
2891 dprintf("Error opening log file: %s\n", p);
2895 if (isatty(f->f_file)) {
2899 if (strcmp(p, ctty) == 0)
2900 f->f_type = F_CONSOLE;
2904 dprintf ("write-all\n");
2909 dprintf ("users: %s\n", p); /* ASP */
2910 for (i = 0; i < MAXUNAMES && *p; i++) {
2911 for (q = p; *q && *q != ','; )
2913 (void) strncpy(f->f_un.f_uname[i], p, UNAMESZ);
2914 if ((q - p) > UNAMESZ)
2915 f->f_un.f_uname[i][UNAMESZ] = '\0';
2917 f->f_un.f_uname[i][q - p] = '\0';
2918 while (*q == ',' || *q == ' ')
2922 f->f_type = F_USERS;
2930 * Decode a symbolic name to a numeric value
2933 int decode(name, codetab)
2935 struct code *codetab;
2937 register struct code *c;
2941 dprintf ("symbolic name: %s", name);
2945 return (atoi(name));
2947 (void) strncpy(buf, name, 79);
2948 for (p = buf; *p; p++)
2951 for (c = codetab; c->c_name; c++)
2952 if (!strcmp(buf, c->c_name))
2954 dprintf (" ==> %d\n", c->c_val);
2960 static void dprintf(char *fmt, ...)
2965 if ( !(Debug && debugging_on) )
2969 vfprintf(stdout, fmt, ap);
2978 * The following function is responsible for allocating/reallocating the
2979 * array which holds the structures which define the logging outputs.
2981 static void allocate_log()
2984 dprintf("Called allocate_log, nlogs = %d.\n", nlogs);
2987 * Decide whether the array needs to be initialized or needs to
2992 Files = (struct filed *) malloc(sizeof(struct filed));
2993 if ( Files == (void *) 0 )
2995 dprintf("Cannot initialize log structure.");
2996 logerror("Cannot initialize log structure.");
3002 /* Re-allocate the array. */
3003 Files = (struct filed *) realloc(Files, (nlogs+2) * \
3004 sizeof(struct filed));
3005 if ( Files == (struct filed *) 0 )
3007 dprintf("Cannot grow log structure.");
3008 logerror("Cannot grow log structure.");
3014 * Initialize the array element, bump the number of elements in the
3015 * the array and return.
3018 memset(&Files[nlogs], '\0', sizeof(struct filed));
3024 * The following function is resposible for handling a SIGHUP signal. Since
3025 * we are now doing mallocs/free as part of init we had better not being
3026 * doing this during a signal handler. Instead this function simply sets
3027 * a flag variable which will tell the main loop to go through a restart.
3029 void sighup_handler()
3033 signal(SIGHUP, sighup_handler);