]>
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 */
213 void cfline
__P((char *, struct filed
*));
214 char *cvthname
__P((struct sockaddr_in
*));
215 int decode
__P((const char *, CODE
*));
217 void domark
__P((int));
218 void fprintlog
__P((struct filed
*, int, char *));
219 void init
__P((int));
220 void logerror
__P((char *));
221 void logmsg
__P((int, char *, char *, int));
222 void printline
__P((char *, char *));
223 void printsys
__P((char *));
224 void reapchild
__P((int));
225 char *ttymsg
__P((struct iovec
*, int, char *, int));
226 void usage
__P((void));
227 void wallmsg
__P((struct filed
*, struct iovec
*));
234 int ch
, funix
, i
, inetm
, fklog
, klogm
, len
;
235 struct sockaddr_un sunx
, fromunix
;
236 struct sockaddr_in sin
, frominet
;
238 char *p
, line
[MSG_BSIZE
+ 1];
240 while ((ch
= getopt(argc
, argv
, "duf:m:p:")) != EOF
)
242 case 'd': /* debug */
245 case 'u': /* insecure */
248 case 'f': /* configuration file */
251 case 'm': /* mark interval */
252 MarkInterval
= atoi(optarg
) * 60;
261 if ((argc
-= optind
) != 0)
269 consfile
.f_type
= F_CONSOLE
;
270 (void)strcpy(consfile
.f_un
.f_fname
, ctty
);
271 (void)gethostname(LocalHostName
, sizeof(LocalHostName
));
272 if ((p
= strchr(LocalHostName
, '.')) != NULL
) {
277 (void)signal(SIGTERM
, die
);
278 (void)signal(SIGINT
, Debug
? die
: SIG_IGN
);
279 (void)signal(SIGQUIT
, Debug
? die
: SIG_IGN
);
280 (void)signal(SIGCHLD
, reapchild
);
281 (void)signal(SIGALRM
, domark
);
282 (void)alarm(TIMERINTVL
);
283 (void)unlink(LogName
);
286 #define SUN_LEN(unp) (strlen((unp)->sun_path) + 2)
288 memset(&sunx
, 0, sizeof(sunx
));
289 sunx
.sun_family
= AF_UNIX
;
290 (void)strncpy(sunx
.sun_path
, LogName
, sizeof(sunx
.sun_path
));
291 funix
= socket(AF_UNIX
, SOCK_DGRAM
, 0);
293 bind(funix
, (struct sockaddr
*)&sunx
, SUN_LEN(&sunx
)) < 0 ||
294 chmod(LogName
, 0666) < 0) {
295 (void) snprintf(line
, sizeof line
, "cannot create %s", LogName
);
297 dprintf("cannot create %s (%d)\n", LogName
, errno
);
300 finet
= socket(AF_INET
, SOCK_DGRAM
, 0);
305 sp
= getservbyname("syslog", "udp");
308 logerror("syslog/udp: unknown service");
311 memset(&sin
, 0, sizeof(sin
));
312 sin
.sin_family
= AF_INET
;
313 sin
.sin_port
= LogPort
= sp
->s_port
;
314 if (bind(finet
, (struct sockaddr
*)&sin
, sizeof(sin
)) < 0) {
319 inetm
= FDMASK(finet
);
323 if ((fklog
= open(_PATH_KLOG
, O_RDONLY
, 0)) >= 0)
324 klogm
= FDMASK(fklog
);
326 dprintf("can't open %s (%d)\n", _PATH_KLOG
, errno
);
330 /* tuck my process id away */
331 fp
= fopen(PidFile
, "w");
333 fprintf(fp
, "%d\n", getpid());
337 dprintf("off & running....\n");
340 (void)signal(SIGHUP
, init
);
343 int nfds
, readfds
= FDMASK(funix
) | inetm
| klogm
;
345 dprintf("readfds = %#x\n", readfds
);
346 nfds
= select(20, (fd_set
*)&readfds
, (fd_set
*)NULL
,
347 (fd_set
*)NULL
, (struct timeval
*)NULL
);
355 dprintf("got a message (%d, %#x)\n", nfds
, readfds
);
356 if (readfds
& klogm
) {
357 i
= read(fklog
, line
, sizeof(line
) - 1);
361 } else if (i
< 0 && errno
!= EINTR
) {
367 if (readfds
& FDMASK(funix
)) {
368 len
= sizeof(fromunix
);
369 i
= recvfrom(funix
, line
, MAXLINE
, 0,
370 (struct sockaddr
*)&fromunix
, &len
);
373 printline(LocalHostName
, line
);
374 } else if (i
< 0 && errno
!= EINTR
)
375 logerror("recvfrom unix");
377 if (readfds
& inetm
) {
378 len
= sizeof(frominet
);
379 i
= recvfrom(finet
, line
, MAXLINE
, 0,
380 (struct sockaddr
*)&frominet
, &len
);
384 printline(cvthname(&frominet
), line
);
385 } else if (i
< 0 && errno
!= EINTR
)
386 logerror("recvfrom inet");
396 (void)fprintf(stderr
,
397 "usage: syslogd [-f conffile] [-m markinterval] [-p logpath]\n");
402 * Take a raw input line, decode the message, and print the message
403 * on the appropriate log files.
406 printline(hname
, msg
)
411 char *p
, *q
, line
[MAXLINE
+ 1];
413 /* test for special codes */
418 while (isdigit(*++p
))
419 pri
= 10 * pri
+ (*p
- '0');
423 if (pri
&~ (LOG_FACMASK
|LOG_PRIMASK
))
426 /* don't allow users to log kernel messages */
427 if (LOG_FAC(pri
) == LOG_KERN
)
428 pri
= LOG_MAKEPRI(LOG_USER
, LOG_PRI(pri
));
432 while ((c
= *p
++) != '\0' &&
433 q
< &line
[sizeof(line
) - 2]) {
449 logmsg(pri
, line
, hname
, 0);
453 * Take a raw input line from /dev/klog, split and format similar to syslog().
460 char *lp
, *p
, *q
, line
[MAXLINE
+ 1];
462 (void)strcpy(line
, "mach_kernel: ");
463 lp
= line
+ strlen(line
);
464 for (p
= msg
; *p
!= '\0'; ) {
465 flags
= SYNC_FILE
| ADDDATE
; /* fsync file after write */
469 while (isdigit(*++p
))
470 pri
= 10 * pri
+ (*p
- '0');
474 /* kernel printf's come out on console */
477 if (pri
&~ (LOG_FACMASK
|LOG_PRIMASK
))
480 while (*p
!= '\0' && (c
= *p
++) != '\n' &&
484 logmsg(pri
, line
, LocalHostName
, flags
);
491 * Log a message to the appropriate log files, users, etc. based on
495 logmsg(pri
, msg
, from
, flags
)
501 int fac
, msglen
, omask
, prilev
;
504 dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n",
505 pri
, flags
, from
, msg
);
507 omask
= sigblock(sigmask(SIGHUP
)|sigmask(SIGALRM
));
510 * Check to see if msg looks non-standard.
512 msglen
= strlen(msg
);
513 if (msglen
< 16 || msg
[3] != ' ' || msg
[6] != ' ' ||
514 msg
[9] != ':' || msg
[12] != ':' || msg
[15] != ' ')
519 timestamp
= ctime(&now
) + 4;
526 /* extract facility and priority level */
528 fac
= LOG_NFACILITIES
;
531 prilev
= LOG_PRI(pri
);
533 /* log the message to the particular outputs */
536 f
->f_file
= open(ctty
, O_WRONLY
, 0);
538 if (f
->f_file
>= 0) {
539 fprintlog(f
, flags
, msg
);
540 (void)close(f
->f_file
);
542 (void)sigsetmask(omask
);
545 for (f
= Files
; f
; f
= f
->f_next
) {
546 /* skip messages that are incorrect priority */
547 if (f
->f_pmask
[fac
] < prilev
||
548 f
->f_pmask
[fac
] == INTERNAL_NOPRI
)
551 if (f
->f_type
== F_CONSOLE
&& (flags
& IGN_CONS
))
554 /* don't output marks to recently written files */
555 if ((flags
& MARK
) && (now
- f
->f_time
) < MarkInterval
/ 2)
559 * suppress duplicate lines to this file
561 if ((flags
& MARK
) == 0 && msglen
== f
->f_prevlen
&&
562 !strcmp(msg
, f
->f_prevline
) &&
563 !strcmp(from
, f
->f_prevhost
)) {
564 (void)strncpy(f
->f_lasttime
, timestamp
, 15);
566 dprintf("msg repeated %d times, %ld sec of %d\n",
567 f
->f_prevcount
, now
- f
->f_time
,
568 repeatinterval
[f
->f_repeatcount
]);
570 * If domark would have logged this by now,
571 * flush it now (so we don't hold isolated messages),
572 * but back off so we'll flush less often
575 if (now
> REPEATTIME(f
)) {
576 fprintlog(f
, flags
, (char *)NULL
);
580 /* new line, save it */
582 fprintlog(f
, 0, (char *)NULL
);
583 f
->f_repeatcount
= 0;
584 (void)strncpy(f
->f_lasttime
, timestamp
, 15);
585 (void)strncpy(f
->f_prevhost
, from
,
586 sizeof(f
->f_prevhost
));
587 if (msglen
< MAXSVLINE
) {
588 f
->f_prevlen
= msglen
;
590 (void)strcpy(f
->f_prevline
, msg
);
591 fprintlog(f
, flags
, (char *)NULL
);
593 f
->f_prevline
[0] = 0;
595 fprintlog(f
, flags
, msg
);
599 (void)sigsetmask(omask
);
603 fprintlog(f
, flags
, msg
)
611 char line
[MAXLINE
+ 1], repbuf
[80], greetings
[200];
614 if (f
->f_type
== F_WALL
) {
615 v
->iov_base
= greetings
;
616 v
->iov_len
= snprintf(greetings
, sizeof greetings
,
617 "\r\n\7Message from syslogd@%s at %.24s ...\r\n",
618 f
->f_prevhost
, ctime(&now
));
624 v
->iov_base
= f
->f_lasttime
;
631 v
->iov_base
= f
->f_prevhost
;
632 v
->iov_len
= strlen(v
->iov_base
);
640 v
->iov_len
= strlen(msg
);
641 } else if (f
->f_prevcount
> 1) {
642 v
->iov_base
= repbuf
;
643 v
->iov_len
= snprintf(repbuf
, sizeof repbuf
, "last message repeated %d times",
646 v
->iov_base
= f
->f_prevline
;
647 v
->iov_len
= f
->f_prevlen
;
651 dprintf("Logging to %s", TypeNames
[f
->f_type
]);
660 dprintf(" %s\n", f
->f_un
.f_forw
.f_hname
);
661 l
= snprintf(line
, sizeof line
, "<%d>%.15s %s", f
->f_prevpri
,
662 iov
[0].iov_base
, iov
[4].iov_base
);
665 if (sendto(finet
, line
, l
, 0,
666 (struct sockaddr
*)&f
->f_un
.f_forw
.f_addr
,
667 sizeof(f
->f_un
.f_forw
.f_addr
)) != l
) {
669 (void)close(f
->f_file
);
670 f
->f_type
= F_UNUSED
;
677 if (flags
& IGN_CONS
) {
678 dprintf(" (ignored)\n");
685 dprintf(" %s\n", f
->f_un
.f_fname
);
686 if (f
->f_type
!= F_FILE
) {
687 v
->iov_base
= "\r\n";
694 if (writev(f
->f_file
, iov
, 6) < 0) {
696 (void)close(f
->f_file
);
698 * Check for errors on TTY's due to loss of tty
700 if ((e
== EIO
|| e
== EBADF
) && f
->f_type
!= F_FILE
) {
701 f
->f_file
= open(f
->f_un
.f_fname
,
702 O_WRONLY
|O_APPEND
, 0);
704 f
->f_type
= F_UNUSED
;
705 logerror(f
->f_un
.f_fname
);
709 f
->f_type
= F_UNUSED
;
711 logerror(f
->f_un
.f_fname
);
713 } else if (flags
& SYNC_FILE
)
714 (void)fsync(f
->f_file
);
720 v
->iov_base
= "\r\n";
729 * WALLMSG -- Write a message to the world at large
731 * Write the specified message to either the entire
732 * world, or a list of approved users.
739 static int reenter
; /* avoid calling ourselves */
744 char line
[sizeof(ut
.ut_line
) + 1];
748 if ((uf
= fopen(_PATH_UTMP
, "r")) == NULL
) {
749 logerror(_PATH_UTMP
);
754 while (fread((char *)&ut
, sizeof(ut
), 1, uf
) == 1) {
755 if (ut
.ut_name
[0] == '\0')
757 strncpy(line
, ut
.ut_line
, sizeof(ut
.ut_line
));
758 line
[sizeof(ut
.ut_line
)] = '\0';
759 if (f
->f_type
== F_WALL
) {
760 if ((p
= ttymsg(iov
, 6, line
, 60*5)) != NULL
) {
761 errno
= 0; /* already in msg */
766 /* should we send the message to this user? */
767 for (i
= 0; i
< MAXUNAMES
; i
++) {
768 if (!f
->f_un
.f_uname
[i
][0])
770 if (!strncmp(f
->f_un
.f_uname
[i
], ut
.ut_name
,
772 if ((p
= ttymsg(iov
, 6, line
, 60*5)) != NULL
) {
773 errno
= 0; /* already in msg */
790 while (wait3((int *)&status
, WNOHANG
, (struct rusage
*)NULL
) > 0)
795 * Return a printable representation of a host address.
799 struct sockaddr_in
*f
;
804 dprintf("cvthname(%s)\n", inet_ntoa(f
->sin_addr
));
806 if (f
->sin_family
!= AF_INET
) {
807 dprintf("Malformed from address\n");
810 hp
= gethostbyaddr((char *)&f
->sin_addr
,
811 sizeof(struct in_addr
), f
->sin_family
);
813 dprintf("Host name for your address (%s) unknown\n",
814 inet_ntoa(f
->sin_addr
));
815 return (inet_ntoa(f
->sin_addr
));
817 if ((p
= strchr(hp
->h_name
, '.')) && strcmp(p
+ 1, LocalDomain
) == 0)
828 now
= time((time_t *)NULL
);
829 MarkSeq
+= TIMERINTVL
;
830 if (MarkSeq
>= MarkInterval
) {
831 logmsg(LOG_INFO
, "-- MARK --", LocalHostName
, ADDDATE
|MARK
);
835 for (f
= Files
; f
; f
= f
->f_next
) {
836 if (f
->f_prevcount
&& now
>= REPEATTIME(f
)) {
837 dprintf("flush %s: repeated %d times, %d sec.\n",
838 TypeNames
[f
->f_type
], f
->f_prevcount
,
839 repeatinterval
[f
->f_repeatcount
]);
840 fprintlog(f
, 0, (char *)NULL
);
844 (void)alarm(TIMERINTVL
);
848 * Print syslogd errors some place.
858 sizeof(buf
), "syslogd: %s: %s", type
, strerror(errno
));
860 (void)snprintf(buf
, sizeof(buf
), "syslogd: %s", type
);
862 dprintf("%s\n", buf
);
863 logmsg(LOG_SYSLOG
|LOG_ERR
, buf
, LocalHostName
, ADDDATE
);
873 for (f
= Files
; f
!= NULL
; f
= f
->f_next
) {
874 /* flush any pending output */
876 fprintlog(f
, 0, (char *)NULL
);
879 dprintf("syslogd: exiting on signal %d\n", signo
);
880 (void)snprintf(buf
, sizeof buf
, "exiting on signal %d", signo
);
884 (void)unlink(LogName
);
889 * INIT -- Initialize syslogd from configuration table
897 struct filed
*f
, *next
, **nextp
;
899 char cline
[LINE_MAX
];
904 * Close all open log files.
907 for (f
= Files
; f
!= NULL
; f
= next
) {
908 /* flush any pending output */
910 fprintlog(f
, 0, (char *)NULL
);
917 (void)close(f
->f_file
);
926 /* open the configuration file */
927 if ((cf
= fopen(ConfFile
, "r")) == NULL
) {
928 dprintf("cannot open %s\n", ConfFile
);
929 *nextp
= (struct filed
*)calloc(1, sizeof(*f
));
930 cfline("*.ERR\t/dev/console", *nextp
);
931 (*nextp
)->f_next
= (struct filed
*)calloc(1, sizeof(*f
));
932 cfline("*.PANIC\t*", (*nextp
)->f_next
);
938 * Foreach line in the conf table, open that file.
941 while (fgets(cline
, sizeof(cline
), cf
) != NULL
) {
943 * check for end-of-section, comments, strip off trailing
944 * spaces and newline character.
946 for (p
= cline
; isspace(*p
); ++p
)
948 if (*p
== NULL
|| *p
== '#')
950 for (p
= strchr(cline
, '\0'); isspace(*--p
);)
953 f
= (struct filed
*)calloc(1, sizeof(*f
));
959 /* close the configuration file */
965 for (f
= Files
; f
; f
= f
->f_next
) {
966 for (i
= 0; i
<= LOG_NFACILITIES
; i
++)
967 if (f
->f_pmask
[i
] == INTERNAL_NOPRI
)
970 printf("%d ", f
->f_pmask
[i
]);
971 printf("%s: ", TypeNames
[f
->f_type
]);
976 printf("%s", f
->f_un
.f_fname
);
980 printf("%s", f
->f_un
.f_forw
.f_hname
);
984 for (i
= 0; i
< MAXUNAMES
&& *f
->f_un
.f_uname
[i
]; i
++)
985 printf("%s, ", f
->f_un
.f_uname
[i
]);
992 logmsg(LOG_SYSLOG
|LOG_INFO
, "syslogd: restart", LocalHostName
, ADDDATE
);
993 dprintf("syslogd: restarted\n");
997 * Crack a configuration file line
1007 char buf
[MAXLINE
], ebuf
[100];
1009 dprintf("cfline(%s)\n", line
);
1011 errno
= 0; /* keep strerror() stuff out of logerror messages */
1013 /* clear out file entry */
1014 memset(f
, 0, sizeof(*f
));
1015 for (i
= 0; i
<= LOG_NFACILITIES
; i
++)
1016 f
->f_pmask
[i
] = INTERNAL_NOPRI
;
1018 /* scan through the list of selectors */
1019 for (p
= line
; *p
&& *p
!= '\t';) {
1021 /* find the end of this facility name list */
1022 for (q
= p
; *q
&& *q
!= '\t' && *q
++ != '.'; )
1025 /* collect priority name */
1026 for (bp
= buf
; *q
&& !strchr("\t,;", *q
); )
1031 while (strchr(", ;", *q
))
1034 /* decode priority name */
1036 pri
= LOG_PRIMASK
+ 1;
1038 pri
= decode(buf
, prioritynames
);
1040 (void)snprintf(ebuf
, sizeof ebuf
,
1041 "unknown priority name \"%s\"", buf
);
1047 /* scan facilities */
1048 while (*p
&& !strchr("\t.;", *p
)) {
1049 for (bp
= buf
; *p
&& !strchr("\t,;.", *p
); )
1053 for (i
= 0; i
< LOG_NFACILITIES
; i
++)
1054 f
->f_pmask
[i
] = pri
;
1056 i
= decode(buf
, facilitynames
);
1058 (void)snprintf(ebuf
, sizeof ebuf
,
1059 "unknown facility name \"%s\"",
1064 f
->f_pmask
[i
>> 3] = pri
;
1066 while (*p
== ',' || *p
== ' ')
1073 /* skip to action part */
1082 (void)strcpy(f
->f_un
.f_forw
.f_hname
, ++p
);
1083 hp
= gethostbyname(p
);
1087 logerror(hstrerror(h_errno
));
1090 memset(&f
->f_un
.f_forw
.f_addr
, 0,
1091 sizeof(f
->f_un
.f_forw
.f_addr
));
1092 f
->f_un
.f_forw
.f_addr
.sin_family
= AF_INET
;
1093 f
->f_un
.f_forw
.f_addr
.sin_port
= LogPort
;
1094 memmove(&f
->f_un
.f_forw
.f_addr
.sin_addr
, hp
->h_addr
, hp
->h_length
);
1099 (void)strcpy(f
->f_un
.f_fname
, p
);
1100 if ((f
->f_file
= open(p
, O_WRONLY
|O_APPEND
, 0)) < 0) {
1101 f
->f_file
= F_UNUSED
;
1105 if (isatty(f
->f_file
))
1109 if (strcmp(p
, ctty
) == 0)
1110 f
->f_type
= F_CONSOLE
;
1118 for (i
= 0; i
< MAXUNAMES
&& *p
; i
++) {
1119 for (q
= p
; *q
&& *q
!= ','; )
1121 (void)strncpy(f
->f_un
.f_uname
[i
], p
, UT_NAMESIZE
);
1122 if ((q
- p
) > UT_NAMESIZE
)
1123 f
->f_un
.f_uname
[i
][UT_NAMESIZE
] = '\0';
1125 f
->f_un
.f_uname
[i
][q
- p
] = '\0';
1126 while (*q
== ',' || *q
== ' ')
1130 f
->f_type
= F_USERS
;
1137 * Decode a symbolic name to a numeric value
1140 decode(name
, codetab
)
1148 return (atoi(name
));
1150 for (p
= buf
; *name
&& p
< &buf
[sizeof(buf
) - 1]; p
++, name
++) {
1152 *p
= tolower(*name
);
1157 for (c
= codetab
; c
->c_name
; c
++)
1158 if (!strcmp(buf
, c
->c_name
))