]>
git.saurik.com Git - apple/network_cmds.git/blob - syslogd.tproj/syslogd.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 * Copyright (c) 1983, 1988, 1993, 1994
26 * The Regents of the University of California. All rights reserved.
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by the University of
39 * California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 static char copyright
[] =
59 "@(#) Copyright (c) 1983, 1988, 1993, 1994\n\
60 The Regents of the University of California. All rights reserved.\n";
64 static char sccsid
[] = "@(#)syslogd.c 8.3 (Berkeley) 4/4/94";
68 * syslogd -- log system messages
70 * This program implements a system log. It takes a series of lines.
71 * Each line may have a priority, signified as "<n>" as
72 * the first characters of the line. If this is
73 * not present, a default priority is used.
75 * To kill syslogd, send a signal 15 (terminate). A signal 1 (hup) will
76 * cause it to reread its configuration file.
80 * MAXLINE -- the maximimum line length that can be handled.
81 * DEFUPRI -- the default priority for user messages
82 * DEFSPRI -- the default priority for kernel messages
85 * extensive changes by Ralph Campbell
86 * more extensive changes by Eric Allman (again)
89 #define MAXLINE 1024 /* maximum line length */
90 #define MAXSVLINE 120 /* maximum saved line length */
91 #define DEFUPRI (LOG_USER|LOG_NOTICE)
92 #define DEFSPRI (LOG_KERN|LOG_CRIT)
93 #define TIMERINTVL 30 /* interval for checking flush, mark */
95 #include <sys/param.h>
96 #include <sys/ioctl.h>
99 #include <sys/socket.h>
100 #include <sys/msgbuf.h>
103 #include <sys/time.h>
104 #include <sys/resource.h>
106 #include <netinet/in.h>
108 #include <arpa/inet.h>
120 #include "pathnames.h"
123 #include <sys/syslog.h>
125 char *LogName
= _PATH_LOG
;
126 char *ConfFile
= _PATH_LOGCONF
;
127 char *PidFile
= _PATH_LOGPID
;
128 char ctty
[] = _PATH_CONSOLE
;
130 #define FDMASK(fd) (1 << (fd))
132 #define dprintf if (Debug) printf
134 #define MAXUNAMES 20 /* maximum number of user names */
140 #define IGN_CONS 0x001 /* don't print on console */
141 #define SYNC_FILE 0x002 /* do fsync on file after printing */
142 #define ADDDATE 0x004 /* add a date to the message */
143 #define MARK 0x008 /* this message is a mark */
146 * This structure represents the files that will have log
151 struct filed
*f_next
; /* next in linked list */
152 short f_type
; /* entry type, see below */
153 short f_file
; /* file descriptor */
154 time_t f_time
; /* time this was last written */
155 u_char f_pmask
[LOG_NFACILITIES
+1]; /* priority mask */
157 char f_uname
[MAXUNAMES
][UT_NAMESIZE
+1];
159 char f_hname
[MAXHOSTNAMELEN
+1];
160 struct sockaddr_in f_addr
;
161 } f_forw
; /* forwarding address */
162 char f_fname
[MAXPATHLEN
];
164 char f_prevline
[MAXSVLINE
]; /* last message logged */
165 char f_lasttime
[16]; /* time of last occurrence */
166 char f_prevhost
[MAXHOSTNAMELEN
+1]; /* host from which recd. */
167 int f_prevpri
; /* pri of f_prevline */
168 int f_prevlen
; /* length of f_prevline */
169 int f_prevcount
; /* repetition cnt of prevline */
170 int f_repeatcount
; /* number of "repeated" msgs */
174 * Intervals at which we flush out "message repeated" messages,
175 * in seconds after previous message is logged. After each flush,
176 * we move to the next interval until we reach the largest.
178 int repeatinterval
[] = { 30, 120, 600 }; /* # of secs before flush */
179 #define MAXREPEAT ((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1)
180 #define REPEATTIME(f) ((f)->f_time + repeatinterval[(f)->f_repeatcount])
181 #define BACKOFF(f) { if (++(f)->f_repeatcount > MAXREPEAT) \
182 (f)->f_repeatcount = MAXREPEAT; \
185 /* values for f_type */
186 #define F_UNUSED 0 /* unused entry */
187 #define F_FILE 1 /* regular file */
188 #define F_TTY 2 /* terminal */
189 #define F_CONSOLE 3 /* console terminal */
190 #define F_FORW 4 /* remote machine */
191 #define F_USERS 5 /* list of users */
192 #define F_WALL 6 /* everyone logged on */
194 char *TypeNames
[7] = {
195 "UNUSED", "FILE", "TTY", "CONSOLE",
196 "FORW", "USERS", "WALL"
200 struct filed consfile
;
202 int Debug
= 0; /* debug flag */
203 int Insecure
= 0; /* insecure flag */
204 char LocalHostName
[MAXHOSTNAMELEN
+1]; /* our hostname */
205 char *LocalDomain
; /* our local domain name */
206 int InetInuse
= 0; /* non-zero if INET sockets are being used */
207 int finet
; /* Internet datagram socket */
208 int LogPort
; /* port number for INET connections */
209 int Initialized
= 0; /* set when we have initialized ourselves */
210 int MarkInterval
= 20 * 60; /* interval between marks in seconds */
211 int MarkSeq
= 0; /* mark sequence number */
212 int NoAddressToName
= 0; /* Do not convert address to name */
213 int RcvSockBufSize
= 42080; /* Our default receive socket buffer size */
215 void cfline
__P((char *, struct filed
*));
216 char *cvthname
__P((struct sockaddr_in
*));
217 int decode
__P((const char *, CODE
*));
219 void domark
__P((int));
220 void fprintlog
__P((struct filed
*, int, char *));
221 void init
__P((int));
222 void logerror
__P((char *));
223 void logmsg
__P((int, char *, char *, int));
224 void printline
__P((char *, char *));
225 void printsys
__P((char *));
226 void reapchild
__P((int));
227 char *ttymsg
__P((struct iovec
*, int, char *, int));
228 void usage
__P((void));
229 void wallmsg
__P((struct filed
*, struct iovec
*));
236 int ch
, funix
, i
, inetm
, fklog
, klogm
, len
;
237 struct sockaddr_un sunx
, fromunix
;
238 struct sockaddr_in sin
, frominet
;
240 char *p
, line
[MSG_BSIZE
+ 1];
242 while ((ch
= getopt(argc
, argv
, "duf:m:p:ns:")) != EOF
)
244 case 'd': /* debug */
247 case 'u': /* insecure */
250 case 'f': /* configuration file */
253 case 'm': /* mark interval */
254 MarkInterval
= atoi(optarg
) * 60;
263 if ((len
= atoi(optarg
)) > 0)
264 RcvSockBufSize
= len
;
270 if ((argc
-= optind
) != 0)
278 consfile
.f_type
= F_CONSOLE
;
279 (void)strcpy(consfile
.f_un
.f_fname
, ctty
);
280 (void)gethostname(LocalHostName
, sizeof(LocalHostName
));
281 if ((p
= strchr(LocalHostName
, '.')) != NULL
) {
286 (void)signal(SIGTERM
, die
);
287 (void)signal(SIGINT
, Debug
? die
: SIG_IGN
);
288 (void)signal(SIGQUIT
, Debug
? die
: SIG_IGN
);
289 (void)signal(SIGCHLD
, reapchild
);
290 (void)signal(SIGALRM
, domark
);
291 (void)alarm(TIMERINTVL
);
292 (void)unlink(LogName
);
295 #define SUN_LEN(unp) (strlen((unp)->sun_path) + 2)
297 memset(&sunx
, 0, sizeof(sunx
));
298 sunx
.sun_family
= AF_UNIX
;
299 (void)strncpy(sunx
.sun_path
, LogName
, sizeof(sunx
.sun_path
));
300 funix
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
302 bind(funix
, (struct sockaddr
*)&sunx
, SUN_LEN(&sunx
)) < 0 ||
303 chmod(LogName
, 0666) < 0) {
304 (void) snprintf(line
, sizeof line
, "cannot create %s", LogName
);
306 dprintf("cannot create %s (%d)\n", LogName
, errno
);
309 if (setsockopt(funix
, SOL_SOCKET
, SO_RCVBUF
, &RcvSockBufSize
, sizeof(int)) < 0)
310 logerror("setsockopt funix");
311 finet
= socket(AF_INET
, SOCK_DGRAM
, 0);
316 sp
= getservbyname("syslog", "udp");
319 logerror("syslog/udp: unknown service");
322 memset(&sin
, 0, sizeof(sin
));
323 sin
.sin_family
= AF_INET
;
324 sin
.sin_port
= LogPort
= sp
->s_port
;
325 if (bind(finet
, (struct sockaddr
*)&sin
, sizeof(sin
)) < 0) {
330 inetm
= FDMASK(finet
);
333 if (setsockopt(finet
, SOL_SOCKET
, SO_RCVBUF
, &RcvSockBufSize
, sizeof(int)) < 0)
334 logerror("setsockopt finet");
336 if ((fklog
= open(_PATH_KLOG
, O_RDONLY
, 0)) >= 0)
337 klogm
= FDMASK(fklog
);
339 dprintf("can't open %s (%d)\n", _PATH_KLOG
, errno
);
343 /* tuck my process id away */
344 fp
= fopen(PidFile
, "w");
346 fprintf(fp
, "%d\n", getpid());
350 dprintf("off & running....\n");
353 (void)signal(SIGHUP
, init
);
356 int nfds
, readfds
= FDMASK(funix
) | inetm
| klogm
;
358 dprintf("readfds = %#x\n", readfds
);
359 nfds
= select(20, (fd_set
*)&readfds
, (fd_set
*)NULL
,
360 (fd_set
*)NULL
, (struct timeval
*)NULL
);
368 dprintf("got a message (%d, %#x)\n", nfds
, readfds
);
369 if (readfds
& klogm
) {
370 i
= read(fklog
, line
, sizeof(line
) - 1);
374 } else if (i
< 0 && errno
!= EINTR
) {
380 if (readfds
& FDMASK(funix
)) {
381 len
= sizeof(fromunix
);
382 i
= recvfrom(funix
, line
, MAXLINE
, 0,
383 (struct sockaddr
*)&fromunix
, &len
);
386 printline(LocalHostName
, line
);
387 } else if (i
< 0 && errno
!= EINTR
)
388 logerror("recvfrom unix");
390 if (readfds
& inetm
) {
391 len
= sizeof(frominet
);
392 i
= recvfrom(finet
, line
, MAXLINE
, 0,
393 (struct sockaddr
*)&frominet
, &len
);
397 printline(cvthname(&frominet
), line
);
398 } else if (i
< 0 && errno
!= EINTR
)
399 logerror("recvfrom inet");
409 (void)fprintf(stderr
,
410 "usage: syslogd [-f conffile] [-m markinterval] [-p logpath] [-u] [-n] [-s size]\n");
415 * Take a raw input line, decode the message, and print the message
416 * on the appropriate log files.
419 printline(hname
, msg
)
424 char *p
, *q
, line
[MAXLINE
+ 1];
426 /* test for special codes */
431 while (isdigit(*++p
))
432 pri
= 10 * pri
+ (*p
- '0');
436 if (pri
&~ (LOG_FACMASK
|LOG_PRIMASK
))
439 /* don't allow users to log kernel messages */
440 if (LOG_FAC(pri
) == LOG_KERN
)
441 pri
= LOG_MAKEPRI(LOG_USER
, LOG_PRI(pri
));
445 while ((c
= *p
++) != '\0' &&
446 q
< &line
[sizeof(line
) - 2]) {
462 logmsg(pri
, line
, hname
, 0);
466 * Take a raw input line from /dev/klog, split and format similar to syslog().
473 char *lp
, *p
, *q
, line
[MAXLINE
+ 1];
475 (void)strcpy(line
, "mach_kernel: ");
476 lp
= line
+ strlen(line
);
477 for (p
= msg
; *p
!= '\0'; ) {
478 flags
= SYNC_FILE
| ADDDATE
; /* fsync file after write */
482 while (isdigit(*++p
))
483 pri
= 10 * pri
+ (*p
- '0');
487 /* kernel printf's come out on console */
490 if (pri
&~ (LOG_FACMASK
|LOG_PRIMASK
))
493 while (*p
!= '\0' && (c
= *p
++) != '\n' &&
497 logmsg(pri
, line
, LocalHostName
, flags
);
504 * Log a message to the appropriate log files, users, etc. based on
508 logmsg(pri
, msg
, from
, flags
)
514 int fac
, msglen
, omask
, prilev
;
517 dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n",
518 pri
, flags
, from
, msg
);
520 omask
= sigblock(sigmask(SIGHUP
)|sigmask(SIGALRM
));
523 * Check to see if msg looks non-standard.
525 msglen
= strlen(msg
);
526 if (msglen
< 16 || msg
[3] != ' ' || msg
[6] != ' ' ||
527 msg
[9] != ':' || msg
[12] != ':' || msg
[15] != ' ')
532 timestamp
= ctime(&now
) + 4;
539 /* extract facility and priority level */
541 fac
= LOG_NFACILITIES
;
544 prilev
= LOG_PRI(pri
);
546 /* log the message to the particular outputs */
549 f
->f_file
= open(ctty
, O_WRONLY
, 0);
551 if (f
->f_file
>= 0) {
552 fprintlog(f
, flags
, msg
);
553 (void)close(f
->f_file
);
555 (void)sigsetmask(omask
);
558 for (f
= Files
; f
; f
= f
->f_next
) {
559 /* skip messages that are incorrect priority */
560 if (f
->f_pmask
[fac
] < prilev
||
561 f
->f_pmask
[fac
] == INTERNAL_NOPRI
)
564 if (f
->f_type
== F_CONSOLE
&& (flags
& IGN_CONS
))
567 /* don't output marks to recently written files */
568 if ((flags
& MARK
) && (now
- f
->f_time
) < MarkInterval
/ 2)
572 * suppress duplicate lines to this file
574 if ((flags
& MARK
) == 0 && msglen
== f
->f_prevlen
&&
575 !strcmp(msg
, f
->f_prevline
) &&
576 !strcmp(from
, f
->f_prevhost
)) {
577 (void)strncpy(f
->f_lasttime
, timestamp
, 15);
579 dprintf("msg repeated %d times, %ld sec of %d\n",
580 f
->f_prevcount
, now
- f
->f_time
,
581 repeatinterval
[f
->f_repeatcount
]);
583 * If domark would have logged this by now,
584 * flush it now (so we don't hold isolated messages),
585 * but back off so we'll flush less often
588 if (now
> REPEATTIME(f
)) {
589 fprintlog(f
, flags
, (char *)NULL
);
593 /* new line, save it */
595 fprintlog(f
, 0, (char *)NULL
);
596 f
->f_repeatcount
= 0;
597 (void)strncpy(f
->f_lasttime
, timestamp
, 15);
598 (void)strncpy(f
->f_prevhost
, from
,
599 sizeof(f
->f_prevhost
));
600 if (msglen
< MAXSVLINE
) {
601 f
->f_prevlen
= msglen
;
603 (void)strcpy(f
->f_prevline
, msg
);
604 fprintlog(f
, flags
, (char *)NULL
);
606 f
->f_prevline
[0] = 0;
608 fprintlog(f
, flags
, msg
);
612 (void)sigsetmask(omask
);
616 fprintlog(f
, flags
, msg
)
624 char line
[MAXLINE
+ 1], repbuf
[80], greetings
[200];
627 if (f
->f_type
== F_WALL
) {
628 v
->iov_base
= greetings
;
629 v
->iov_len
= snprintf(greetings
, sizeof greetings
,
630 "\r\n\7Message from syslogd@%s at %.24s ...\r\n",
631 f
->f_prevhost
, ctime(&now
));
637 v
->iov_base
= f
->f_lasttime
;
644 v
->iov_base
= f
->f_prevhost
;
645 v
->iov_len
= strlen(v
->iov_base
);
653 v
->iov_len
= strlen(msg
);
654 } else if (f
->f_prevcount
> 1) {
655 v
->iov_base
= repbuf
;
656 v
->iov_len
= snprintf(repbuf
, sizeof repbuf
, "last message repeated %d times",
659 v
->iov_base
= f
->f_prevline
;
660 v
->iov_len
= f
->f_prevlen
;
664 dprintf("Logging to %s", TypeNames
[f
->f_type
]);
673 dprintf(" %s\n", f
->f_un
.f_forw
.f_hname
);
674 l
= snprintf(line
, sizeof line
, "<%d>%.15s %s", f
->f_prevpri
,
675 iov
[0].iov_base
, iov
[4].iov_base
);
678 if (sendto(finet
, line
, l
, 0,
679 (struct sockaddr
*)&f
->f_un
.f_forw
.f_addr
,
680 sizeof(f
->f_un
.f_forw
.f_addr
)) != l
) {
682 (void)close(f
->f_file
);
683 f
->f_type
= F_UNUSED
;
690 if (flags
& IGN_CONS
) {
691 dprintf(" (ignored)\n");
698 dprintf(" %s\n", f
->f_un
.f_fname
);
699 if (f
->f_type
!= F_FILE
) {
700 v
->iov_base
= "\r\n";
707 if (writev(f
->f_file
, iov
, 6) < 0) {
709 (void)close(f
->f_file
);
711 * Check for errors on TTY's due to loss of tty
713 if ((e
== EIO
|| e
== EBADF
) && f
->f_type
!= F_FILE
) {
714 f
->f_file
= open(f
->f_un
.f_fname
,
715 O_WRONLY
|O_APPEND
, 0);
717 f
->f_type
= F_UNUSED
;
718 logerror(f
->f_un
.f_fname
);
722 f
->f_type
= F_UNUSED
;
724 logerror(f
->f_un
.f_fname
);
726 } else if (flags
& SYNC_FILE
)
727 (void)fsync(f
->f_file
);
733 v
->iov_base
= "\r\n";
742 * WALLMSG -- Write a message to the world at large
744 * Write the specified message to either the entire
745 * world, or a list of approved users.
752 static int reenter
; /* avoid calling ourselves */
757 char line
[sizeof(ut
.ut_line
) + 1];
761 if ((uf
= fopen(_PATH_UTMP
, "r")) == NULL
) {
762 logerror(_PATH_UTMP
);
767 while (fread((char *)&ut
, sizeof(ut
), 1, uf
) == 1) {
768 if (ut
.ut_name
[0] == '\0')
770 strncpy(line
, ut
.ut_line
, sizeof(ut
.ut_line
));
771 line
[sizeof(ut
.ut_line
)] = '\0';
772 if (f
->f_type
== F_WALL
) {
773 if ((p
= ttymsg(iov
, 6, line
, 60*5)) != NULL
) {
774 errno
= 0; /* already in msg */
779 /* should we send the message to this user? */
780 for (i
= 0; i
< MAXUNAMES
; i
++) {
781 if (!f
->f_un
.f_uname
[i
][0])
783 if (!strncmp(f
->f_un
.f_uname
[i
], ut
.ut_name
,
785 if ((p
= ttymsg(iov
, 6, line
, 60*5)) != NULL
) {
786 errno
= 0; /* already in msg */
803 while (wait3((int *)&status
, WNOHANG
, (struct rusage
*)NULL
) > 0)
808 * Return a printable representation of a host address.
812 struct sockaddr_in
*f
;
817 dprintf("cvthname(%s)\n", inet_ntoa(f
->sin_addr
));
819 if (f
->sin_family
!= AF_INET
) {
820 dprintf("Malformed from address\n");
823 if (NoAddressToName
) {
826 hp
= gethostbyaddr((char *)&f
->sin_addr
,
827 sizeof(struct in_addr
), f
->sin_family
);
828 dprintf("Host name for your address (%s) unknown\n",
829 inet_ntoa(f
->sin_addr
));
832 return (inet_ntoa(f
->sin_addr
));
834 if ((p
= strchr(hp
->h_name
, '.')) && strcmp(p
+ 1, LocalDomain
) == 0)
845 now
= time((time_t *)NULL
);
846 MarkSeq
+= TIMERINTVL
;
847 if (MarkSeq
>= MarkInterval
) {
848 logmsg(LOG_INFO
, "-- MARK --", LocalHostName
, ADDDATE
|MARK
);
852 for (f
= Files
; f
; f
= f
->f_next
) {
853 if (f
->f_prevcount
&& now
>= REPEATTIME(f
)) {
854 dprintf("flush %s: repeated %d times, %d sec.\n",
855 TypeNames
[f
->f_type
], f
->f_prevcount
,
856 repeatinterval
[f
->f_repeatcount
]);
857 fprintlog(f
, 0, (char *)NULL
);
861 (void)alarm(TIMERINTVL
);
865 * Print syslogd errors some place.
875 sizeof(buf
), "syslogd: %s: %s", type
, strerror(errno
));
877 (void)snprintf(buf
, sizeof(buf
), "syslogd: %s", type
);
879 dprintf("%s\n", buf
);
880 logmsg(LOG_SYSLOG
|LOG_ERR
, buf
, LocalHostName
, ADDDATE
);
890 for (f
= Files
; f
!= NULL
; f
= f
->f_next
) {
891 /* flush any pending output */
893 fprintlog(f
, 0, (char *)NULL
);
896 dprintf("syslogd: exiting on signal %d\n", signo
);
897 (void)snprintf(buf
, sizeof buf
, "exiting on signal %d", signo
);
901 (void)unlink(LogName
);
906 * INIT -- Initialize syslogd from configuration table
914 struct filed
*f
, *next
, **nextp
;
916 char cline
[LINE_MAX
];
921 * Close all open log files.
924 for (f
= Files
; f
!= NULL
; f
= next
) {
925 /* flush any pending output */
927 fprintlog(f
, 0, (char *)NULL
);
934 (void)close(f
->f_file
);
943 /* open the configuration file */
944 if ((cf
= fopen(ConfFile
, "r")) == NULL
) {
945 dprintf("cannot open %s\n", ConfFile
);
946 *nextp
= (struct filed
*)calloc(1, sizeof(*f
));
947 cfline("*.ERR\t/dev/console", *nextp
);
948 (*nextp
)->f_next
= (struct filed
*)calloc(1, sizeof(*f
));
949 cfline("*.PANIC\t*", (*nextp
)->f_next
);
955 * Foreach line in the conf table, open that file.
958 while (fgets(cline
, sizeof(cline
), cf
) != NULL
) {
960 * check for end-of-section, comments, strip off trailing
961 * spaces and newline character.
963 for (p
= cline
; isspace(*p
); ++p
)
965 if (*p
== NULL
|| *p
== '#')
967 for (p
= strchr(cline
, '\0'); isspace(*--p
);)
970 f
= (struct filed
*)calloc(1, sizeof(*f
));
976 /* close the configuration file */
982 for (f
= Files
; f
; f
= f
->f_next
) {
983 for (i
= 0; i
<= LOG_NFACILITIES
; i
++)
984 if (f
->f_pmask
[i
] == INTERNAL_NOPRI
)
987 printf("%d ", f
->f_pmask
[i
]);
988 printf("%s: ", TypeNames
[f
->f_type
]);
993 printf("%s", f
->f_un
.f_fname
);
997 printf("%s", f
->f_un
.f_forw
.f_hname
);
1001 for (i
= 0; i
< MAXUNAMES
&& *f
->f_un
.f_uname
[i
]; i
++)
1002 printf("%s, ", f
->f_un
.f_uname
[i
]);
1009 logmsg(LOG_SYSLOG
|LOG_INFO
, "syslogd: restart", LocalHostName
, ADDDATE
);
1010 dprintf("syslogd: restarted\n");
1014 * Crack a configuration file line
1024 char buf
[MAXLINE
], ebuf
[100];
1026 dprintf("cfline(%s)\n", line
);
1028 errno
= 0; /* keep strerror() stuff out of logerror messages */
1030 /* clear out file entry */
1031 memset(f
, 0, sizeof(*f
));
1032 for (i
= 0; i
<= LOG_NFACILITIES
; i
++)
1033 f
->f_pmask
[i
] = INTERNAL_NOPRI
;
1035 /* scan through the list of selectors */
1036 for (p
= line
; *p
&& *p
!= '\t';) {
1038 /* find the end of this facility name list */
1039 for (q
= p
; *q
&& *q
!= '\t' && *q
++ != '.'; )
1042 /* collect priority name */
1043 for (bp
= buf
; *q
&& !strchr("\t,;", *q
); )
1048 while (strchr(", ;", *q
))
1051 /* decode priority name */
1053 pri
= LOG_PRIMASK
+ 1;
1055 pri
= decode(buf
, prioritynames
);
1057 (void)snprintf(ebuf
, sizeof ebuf
,
1058 "unknown priority name \"%s\"", buf
);
1064 /* scan facilities */
1065 while (*p
&& !strchr("\t.;", *p
)) {
1066 for (bp
= buf
; *p
&& !strchr("\t,;.", *p
); )
1070 for (i
= 0; i
< LOG_NFACILITIES
; i
++)
1071 f
->f_pmask
[i
] = pri
;
1073 i
= decode(buf
, facilitynames
);
1075 (void)snprintf(ebuf
, sizeof ebuf
,
1076 "unknown facility name \"%s\"",
1081 f
->f_pmask
[i
>> 3] = pri
;
1083 while (*p
== ',' || *p
== ' ')
1090 /* skip to action part */
1099 (void)strcpy(f
->f_un
.f_forw
.f_hname
, ++p
);
1100 hp
= gethostbyname(p
);
1104 logerror(hstrerror(h_errno
));
1107 memset(&f
->f_un
.f_forw
.f_addr
, 0,
1108 sizeof(f
->f_un
.f_forw
.f_addr
));
1109 f
->f_un
.f_forw
.f_addr
.sin_family
= AF_INET
;
1110 f
->f_un
.f_forw
.f_addr
.sin_port
= LogPort
;
1111 memmove(&f
->f_un
.f_forw
.f_addr
.sin_addr
, hp
->h_addr
, hp
->h_length
);
1116 (void)strcpy(f
->f_un
.f_fname
, p
);
1117 if ((f
->f_file
= open(p
, O_WRONLY
|O_APPEND
, 0)) < 0) {
1118 f
->f_file
= F_UNUSED
;
1122 if (isatty(f
->f_file
))
1126 if (strcmp(p
, ctty
) == 0)
1127 f
->f_type
= F_CONSOLE
;
1135 for (i
= 0; i
< MAXUNAMES
&& *p
; i
++) {
1136 for (q
= p
; *q
&& *q
!= ','; )
1138 (void)strncpy(f
->f_un
.f_uname
[i
], p
, UT_NAMESIZE
);
1139 if ((q
- p
) > UT_NAMESIZE
)
1140 f
->f_un
.f_uname
[i
][UT_NAMESIZE
] = '\0';
1142 f
->f_un
.f_uname
[i
][q
- p
] = '\0';
1143 while (*q
== ',' || *q
== ' ')
1147 f
->f_type
= F_USERS
;
1154 * Decode a symbolic name to a numeric value
1157 decode(name
, codetab
)
1165 return (atoi(name
));
1167 for (p
= buf
; *name
&& p
< &buf
[sizeof(buf
) - 1]; p
++, name
++) {
1169 *p
= tolower(*name
);
1174 for (c
= codetab
; c
->c_name
; c
++)
1175 if (!strcmp(buf
, c
->c_name
))