xref: /csrg-svn/lib/libc/gen/syslog.c (revision 12742)
1 #ifndef lint
2 static char SccsId[] =	"@(#)syslog.c	4.1 (Berkeley) 05/27/83";
3 #endif
4 
5 /*
6  * SYSLOG -- print message on log file
7  *
8  * This routine looks a lot like printf, except that it
9  * outputs to the log file instead of the standard output.
10  * Also, it prints the module name in front of lines,
11  * and has some other formatting types (or will sometime).
12  * Also, it adds a newline on the end of messages.
13  *
14  * The output of this routine is intended to be read by
15  * /etc/syslog, which will add timestamps.
16  */
17 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 
21 #include <syslog.h>
22 #include <netdb.h>
23 
24 #define	MAXLINE	1024		/* max message size */
25 #define BUFSLOP	20		/* space to allow for "extra stuff" */
26 #define NULL	0		/* manifest */
27 
28 int	LogFile = -1;		/* fd for log */
29 int	LogStat	= 0;		/* status bits, set by initlog */
30 char	*LogTag = NULL;		/* string to tag the entry with */
31 int	LogMask = LOG_DEBUG;	/* lowest priority to be logged */
32 
33 struct sockaddr_in SyslogAddr;
34 static char *SyslogHost = LOG_HOST;
35 
36 extern	int errno, sys_nerr;
37 extern	char *sys_errlist[];
38 
39 syslog(pri, fmt, p0, p1, p2, p3, p4)
40 	int pri;
41 	char *fmt;
42 {
43 	char buf[MAXLINE+BUFSLOP], outline[MAXLINE + 1];
44 	register char *b, *f;
45 
46 	if (LogFile < 0)
47 		openlog(0, 0);
48 	/* see if we should just throw out this message */
49 	if (pri > LogMask)
50 		return;
51 	for (b = buf, f = fmt; f && *f; b = buf) {
52 		register char c;
53 
54 		if (pri > 0 && (LogStat & LOG_COOLIT) == 0) {
55 			sprintf(b, "<%d>", pri);
56 			b += strlen(b);
57 		}
58 		if (LogStat & LOG_PID) {
59 			sprintf(b, "%d ", getpid());
60 			b += strlen(b);
61 		}
62 		if (LogTag) {
63 			sprintf(b, "%s: ", LogTag);
64 			b += strlen(b);
65 		}
66 		while ((c = *f++) != '\0' && c != '\n' && b < buf + MAXLINE) {
67 			if (c != '%') {
68 				*b++ = c;
69 				continue;
70 			}
71 			c = *f++;
72 			if (c != 'm') {
73 				*b++ = '%', *b++ = c, *b++ = '\0';
74 				continue;
75 			}
76 			if ((unsigned)errno > sys_nerr)
77 				sprintf(b, "error %d", errno);
78 			else
79 				strcat(b, sys_errlist[errno]);
80 			b += strlen(b);
81 		}
82 		if (c == '\0')
83 			f--;
84 		*b++ = '\n', *b = '\0';
85 		sprintf(outline, buf, p0, p1, p2, p3, p4);
86 		errno = 0;
87 		if (LogStat & LOG_DGRAM)
88 			(void) sendto(LogFile, outline, strlen(outline), 0,
89 				   &SyslogAddr, sizeof SyslogAddr);
90 		else
91 			(void) write(LogFile, outline, strlen(outline));
92 		if (errno)
93 			perror("syslog: sendto");
94 	}
95 }
96 
97 /*
98  * OPENLOG -- open system log
99  */
100 openlog(ident, logstat)
101 	char *ident;
102 	int logstat;
103 {
104 	struct servent *sp;
105 	struct hostent *hp;
106 
107 	LogTag = ident;
108 	LogStat = logstat;
109 	if (LogFile >= 0)
110 		return;
111 	sp = getservbyname("syslog", "udp");
112 	hp = gethostbyname(SyslogHost);
113 	if (sp == NULL || hp == NULL)
114 		goto bad;
115 	LogFile = socket(AF_INET, SOCK_DGRAM, 0);
116 	if (LogFile < 0) {
117 		perror("syslog: socket");
118 		goto bad;
119 	}
120 	bzero(&SyslogAddr, sizeof SyslogAddr);
121 	SyslogAddr.sin_family = hp->h_addrtype;
122 	bcopy(hp->h_addr, (char *)&SyslogAddr.sin_addr, hp->h_length);
123 	SyslogAddr.sin_port = sp->s_port;
124 	LogStat |= LOG_DGRAM;
125 	return;
126 bad:
127 	LogStat |= LOG_COOLIT;
128 	LogStat &= ~LOG_DGRAM;
129 	LogMask = LOG_CRIT;
130 	LogFile = open("/dev/console", 1);
131 	if (LogFile < 0) {
132 		perror("syslog: /dev/console");
133 		LogFile = 2;
134 	}
135 }
136 
137 /*
138  * CLOSELOG -- close the system log
139  */
140 closelog()
141 {
142 
143 	(void) close(LogFile);
144 	LogFile = -1;
145 }
146