xref: /titanic_44/usr/src/lib/libast/common/comp/syslog.c (revision 67e3a03ed4a2813074d36330f062ed6e593a4937)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *           Copyright (c) 1985-2007 AT&T Knowledge Ventures            *
5 *                      and is licensed under the                       *
6 *                  Common Public License, Version 1.0                  *
7 *                      by AT&T Knowledge Ventures                      *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *            http://www.opensource.org/licenses/cpl1.0.txt             *
11 *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12 *                                                                      *
13 *              Information and Software Systems Research               *
14 *                            AT&T Research                             *
15 *                           Florham Park NJ                            *
16 *                                                                      *
17 *                 Glenn Fowler <gsf@research.att.com>                  *
18 *                  David Korn <dgk@research.att.com>                   *
19 *                   Phong Vo <kpv@research.att.com>                    *
20 *                                                                      *
21 ***********************************************************************/
22 #pragma prototyped
23 /*
24  * syslog implementation
25  */
26 
27 #include <ast.h>
28 
29 #if _lib_syslog
30 
31 NoN(syslog)
32 
33 #else
34 
35 #define LOG_TABLES
36 
37 #include "sysloglib.h"
38 
39 #include <error.h>
40 #include <tm.h>
41 
42 Syslog_state_t		log = { LOG_USER, -1, 0, ~0 };
43 
44 static const Namval_t	attempt[] =
45 {
46 	"/dev/log",			0,
47 	"lib/syslog/log",		0,
48 	"/dev/console",			LOG_CONS,
49 };
50 
51 const Namval_t		log_facility[] =
52 {
53 	"default",	0,
54 	"user",		LOG_USER,
55 	"kernel",	LOG_KERN,
56 	"mail",		LOG_MAIL,
57 	"daemon",	LOG_DAEMON,
58 	"security",	LOG_AUTH,
59 	"syslog",	LOG_SYSLOG,
60 	"lpr",		LOG_LPR,
61 	"news",		LOG_NEWS,
62 	"uucp",		LOG_UUCP,
63 	"cron",		LOG_CRON,
64 	"audit",	LOG_AUDIT,
65 	"logalert",	LOG_LFMT,
66 #ifdef LOG_SYSTEM2
67 	"system2",	LOG_SYSTEM2,
68 #endif
69 #ifdef LOG_SYSTEM1
70 	"system1",	LOG_SYSTEM1,
71 #endif
72 #ifdef LOG_SYSTEM0
73 	"system0",	LOG_SYSTEM0,
74 #endif
75 	0,		0
76 };
77 
78 const Namval_t		log_severity[] =
79 {
80 	"panic",	LOG_EMERG,
81 	"alert",	LOG_ALERT,
82 	"critical",	LOG_CRIT,
83 	"error",	LOG_ERR,
84 	"warning",	LOG_WARNING,
85 	"notice",	LOG_NOTICE,
86 	"info",		LOG_INFO,
87 	"debug",	LOG_DEBUG,
88 	0,		0
89 };
90 
91 #if _UWIN
92 
93 /*
94  * open /dev/(fdp|tcp|udp)/HOST/SERVICE for read
95  */
96 
97 #include <ctype.h>
98 #include <ls.h>
99 #include <sys/socket.h>
100 #include <sys/un.h>
101 #include <netdb.h>
102 #include <netinet/in.h>
103 
104 #if !defined(htons) && !_lib_htons
105 #	define htons(x)	(x)
106 #endif
107 #if !defined(htonl) && !_lib_htonl
108 #	define htonl(x)	(x)
109 #endif
110 
111 #ifndef INADDR_LOOPBACK
112 #define INADDR_LOOPBACK		0x7f000001L
113 #endif
114 
115 /*
116  * convert s to sockaddr_in
117  * -1 returned on error
118  */
119 
120 static int
121 str2inet(register char* s, char* prot, struct sockaddr_in* addr)
122 {
123 	register int	c;
124 	register int	v;
125 	register int	n = 0;
126 	unsigned long	a = 0;
127 	unsigned short	p = 0;
128 
129 	if (!memcmp(s, "local/", 6))
130 	{
131 		a = INADDR_LOOPBACK;
132 		n = 4;
133 		s += 6;
134 	}
135 	else if (!isdigit(*s))
136 	{
137 		struct hostent*	hp;
138 		char*		e = strchr(s, '/');
139 
140 		if (!(e = strchr(s, '/')))
141 			return -1;
142 		*e = 0;
143 		hp = gethostbyname(s);
144 		*e = '/';
145 		if (!hp || hp->h_addrtype != AF_INET || hp->h_length > sizeof(struct in_addr))
146 			return -1;
147 		a = (unsigned long)((struct in_addr*)hp->h_addr)->s_addr;
148 		n = 6;
149 		s = e + 1;
150 	}
151 	for (;;)
152 	{
153 		v = 0;
154 		while ((c = *s++) >= '0' && c <= '9')
155 			v = v * 10 + c - '0';
156 		if (++n <= 4)
157 			a = (a << 8) | (v & 0xff);
158 		else
159 		{
160 			if (n <= 5)
161 				a = htonl(a);
162 			if (c)
163 			{
164 				struct servent*	sp;
165 
166 				if (!(sp = getservbyname(s - 1, prot)))
167 					return -1;
168 				p = sp->s_port;
169 			}
170 			else
171 				p = htons(v);
172 			break;
173 		}
174 		if (c != '.' && c != '/')
175 			return -1;
176 	}
177 	memset((char*)addr, 0, sizeof(*addr));
178 	addr->sin_family = AF_INET;
179 	addr->sin_addr.s_addr = a;
180 	addr->sin_port = p;
181 	return 0;
182 }
183 
184 /*
185  * call this after open fails to see if path is a socket
186  */
187 
188 int
189 sockopen(const char* path)
190 {
191 	int			fd;
192 	struct sockaddr_in	addr;
193 	char			buf[PATH_MAX];
194 
195 	if (pathgetlink(path, buf, sizeof(buf)) <= 0)
196 	{
197 		if (strlen(path) >= sizeof(buf))
198 			return -1;
199 		strcpy(buf, path);
200 	}
201 #if LOCAL
202 	{
203 		int			ul;
204 		struct sockaddr_un	ua;
205 		struct stat		st;
206 
207 		if ((ul = strlen(buf)) < sizeof(ua.sun_path) && !stat(buf, &st) && S_ISSOCK(st.st_mode))
208 		{
209 			if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
210 				return -1;
211 			ua.sun_family = AF_UNIX;
212 			strcpy(ua.sun_path, buf);
213 			ul += sizeof(ua.sun_family) + 1;
214 			if (!connect(fd, (struct sockaddr*)&ua, ul))
215 				return fd;
216 			close(fd);
217 			return -1;
218 		}
219 	}
220 #endif
221 	if (!strmatch(buf, "/dev/(tcp|udp)/*/*"))
222 		return -1;
223 	buf[8] = 0;
224 	if (str2inet(buf + 9, buf + 5, &addr))
225 		return -1;
226 	if ((fd = socket(AF_INET, buf[5] == 't' ? SOCK_STREAM : SOCK_DGRAM, 0)) < 0)
227 		return -1;
228 	if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)))
229 	{
230 		close(fd);
231 		return -1;
232 	}
233 	return fd;
234 }
235 
236 #else
237 
238 int
239 sockopen(const char* path)
240 {
241 	return -1;
242 }
243 
244 #endif
245 
246 void
247 sendlog(const char* msg)
248 {
249 	register char*		s;
250 	register Namval_t*	p;
251 	register int		n;
252 
253 	n = msg ? strlen(msg) : 0;
254 	for (;;)
255 	{
256 		if (log.fd < 0)
257 		{
258 			char	buf[PATH_MAX];
259 
260 			if (log.attempt >= elementsof(attempt))
261 				break;
262 			p = (Namval_t*)&attempt[log.attempt++];
263 			if (p->value && !(p->value & log.flags))
264 				continue;
265 			if (*(s = p->name) != '/' && !(s = pathpath(buf, s, "", PATH_REGULAR|PATH_READ)))
266 				continue;
267 			if ((log.fd = open(s, O_WRONLY|O_APPEND|O_NOCTTY)) < 0 && (log.fd = sockopen(s)) < 0)
268 				continue;
269 			fcntl(log.fd, F_SETFD, FD_CLOEXEC);
270 		}
271 		if (!n || write(log.fd, msg, n) > 0)
272 			break;
273 		close(log.fd);
274 		log.fd = -1;
275 	}
276 	if (n && (log.flags & LOG_PERROR))
277 		write(2, msg, n);
278 }
279 
280 static int
281 extend(Sfio_t* sp, void* vp, Sffmt_t* dp)
282 {
283 	if (dp->fmt == 'm')
284 	{
285 		dp->flags |= SFFMT_VALUE;
286 		dp->fmt = 's';
287 		dp->size = -1;
288 		*((char**)vp) = fmterror(errno);
289 	}
290 	return 0;
291 }
292 
293 void
294 vsyslog(int priority, const char* format, va_list ap)
295 {
296 	register int	c;
297 	register char*	s;
298 	Sfio_t*		sp;
299 	Sffmt_t		fmt;
300 	char		buf[16];
301 
302 	if (!LOG_FACILITY(priority))
303 		priority |= log.facility;
304 	if (!(priority & log.mask))
305 		return;
306 	if (sp = sfstropen())
307 	{
308 		sfputr(sp, fmttime("%b %d %H:%M:%S", time(NiL)), -1);
309 		if (log.flags & LOG_LEVEL)
310 		{
311 			if ((c = LOG_SEVERITY(priority)) < elementsof(log_severity))
312 				s = (char*)log_severity[c].name;
313 			else
314 				sfsprintf(s = buf, sizeof(buf), "debug%d", c);
315 			sfprintf(sp, " %-8s ", s);
316 			if ((c = LOG_FACILITY(priority)) < elementsof(log_facility))
317 				s = (char*)log_facility[c].name;
318 			else
319 				sfsprintf(s = buf, sizeof(buf), "local%d", c);
320 			sfprintf(sp, " %-8s ", s);
321 		}
322 #if _lib_gethostname
323 		if (!*log.host && gethostname(log.host, sizeof(log.host)-1))
324 			strcpy(log.host, "localhost");
325 		sfprintf(sp, " %s", log.host);
326 #endif
327 		if (*log.ident)
328 			sfprintf(sp, " %s", log.ident);
329 		if (log.flags & LOG_PID)
330 		{
331 			if (!*log.ident)
332 				sfprintf(sp, " ");
333 			sfprintf(sp, "[%d]", getpid());
334 		}
335 		if (format)
336 		{
337 			sfprintf(sp, ": ");
338 			memset(&fmt, 0, sizeof(fmt));
339 			fmt.version = SFIO_VERSION;
340 			fmt.form = (char*)format;
341 			fmt.extf = extend;
342 			va_copy(fmt.args, ap);
343 			sfprintf(sp, "%!", &fmt);
344 		}
345 		if ((s = sfstrseek(sp, 0, SEEK_CUR)) && *(s - 1) != '\n')
346 			sfputc(sp, '\n');
347 		if (s = sfstruse(sp))
348 			sendlog(s);
349 		sfstrclose(sp);
350 	}
351 }
352 
353 void
354 syslog(int priority, const char* format, ...)
355 {
356 	va_list		ap;
357 
358 	va_start(ap, format);
359 	vsyslog(priority, format, ap);
360 	va_end(ap);
361 }
362 
363 #endif
364