xref: /titanic_51/usr/src/lib/libbc/libc/gen/common/syslog.c (revision 5d54f3d8999eac1762fe0a8c7177d20f1f201fae)
17c478bd9Sstevel@tonic-gate /*
2*5d54f3d8Smuffin  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3*5d54f3d8Smuffin  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /*
7*5d54f3d8Smuffin  * Copyright (c) 1983 Regents of the University of California.
8*5d54f3d8Smuffin  * All rights reserved.  The Berkeley software License Agreement
9*5d54f3d8Smuffin  * specifies the terms and conditions for redistribution.
107c478bd9Sstevel@tonic-gate  */
117c478bd9Sstevel@tonic-gate 
127c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
137c478bd9Sstevel@tonic-gate 
147c478bd9Sstevel@tonic-gate /*
157c478bd9Sstevel@tonic-gate  * SYSLOG -- print message on log file
167c478bd9Sstevel@tonic-gate  *
177c478bd9Sstevel@tonic-gate  * This routine looks a lot like printf, except that it
187c478bd9Sstevel@tonic-gate  * outputs to the log file instead of the standard output.
197c478bd9Sstevel@tonic-gate  * Also:
207c478bd9Sstevel@tonic-gate  *	adds a timestamp,
217c478bd9Sstevel@tonic-gate  *	prints the module name in front of the message,
227c478bd9Sstevel@tonic-gate  *	has some other formatting types (or will sometime),
237c478bd9Sstevel@tonic-gate  *	adds a newline on the end of the message.
247c478bd9Sstevel@tonic-gate  *
257c478bd9Sstevel@tonic-gate  * The output of this routine is intended to be read by /etc/syslogd.
267c478bd9Sstevel@tonic-gate  *
277c478bd9Sstevel@tonic-gate  * Author: Eric Allman
287c478bd9Sstevel@tonic-gate  * Modified to use UNIX domain IPC by Ralph Campbell
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #include <sys/types.h>
327c478bd9Sstevel@tonic-gate #include <sys/socket.h>
337c478bd9Sstevel@tonic-gate #include <sys/file.h>
347c478bd9Sstevel@tonic-gate #include <sys/signal.h>
357c478bd9Sstevel@tonic-gate #include <sys/syslog.h>
367c478bd9Sstevel@tonic-gate #include <sys/time.h>
37*5d54f3d8Smuffin #include <sys/unistd.h>
387c478bd9Sstevel@tonic-gate #include <netdb.h>
397c478bd9Sstevel@tonic-gate #include <strings.h>
40*5d54f3d8Smuffin #include <stdarg.h>
417c478bd9Sstevel@tonic-gate #include <vfork.h>
427c478bd9Sstevel@tonic-gate #include <stdio.h>
43*5d54f3d8Smuffin #include <errno.h>
44*5d54f3d8Smuffin #include <malloc.h>
45*5d54f3d8Smuffin 
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate #define	MAXLINE	1024			/* max message size */
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate #define	PRIMASK(p)	(1 << ((p) & LOG_PRIMASK))
507c478bd9Sstevel@tonic-gate #define	PRIFAC(p)	(((p) & LOG_FACMASK) >> 3)
517c478bd9Sstevel@tonic-gate #define	IMPORTANT 	LOG_ERR
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate static char	*logname = "/dev/log";
547c478bd9Sstevel@tonic-gate static char	*ctty = "/dev/console";
557c478bd9Sstevel@tonic-gate static char	*sysmsg = "/dev/sysmsg";
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate static struct _syslog {
587c478bd9Sstevel@tonic-gate 	int	_LogFile;
597c478bd9Sstevel@tonic-gate 	int	_LogStat;
607c478bd9Sstevel@tonic-gate 	char	*_LogTag;
617c478bd9Sstevel@tonic-gate 	int	_LogMask;
627c478bd9Sstevel@tonic-gate 	struct 	sockaddr _SyslogAddr;
637c478bd9Sstevel@tonic-gate 	char	*_SyslogHost;
647c478bd9Sstevel@tonic-gate 	int	_LogFacility;
657c478bd9Sstevel@tonic-gate } *_syslog;
667c478bd9Sstevel@tonic-gate #define	LogFile (_syslog->_LogFile)
677c478bd9Sstevel@tonic-gate #define	LogStat (_syslog->_LogStat)
687c478bd9Sstevel@tonic-gate #define	LogTag (_syslog->_LogTag)
697c478bd9Sstevel@tonic-gate #define	LogMask (_syslog->_LogMask)
707c478bd9Sstevel@tonic-gate #define	SyslogAddr (_syslog->_SyslogAddr)
717c478bd9Sstevel@tonic-gate #define	SyslogHost (_syslog->_SyslogHost)
727c478bd9Sstevel@tonic-gate #define	LogFacility (_syslog->_LogFacility)
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate extern char *strerror(int);
767c478bd9Sstevel@tonic-gate extern time_t time();
77*5d54f3d8Smuffin 
78*5d54f3d8Smuffin void	vsyslog(int, char *, va_list);
79*5d54f3d8Smuffin void	openlog(char *, int, int);
80*5d54f3d8Smuffin static int	snprintf(char *, size_t, char *, ...);
81*5d54f3d8Smuffin static int	vsnprintf(char *, size_t, char *, va_list ap);
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate static int
84*5d54f3d8Smuffin allocstatic(void)
857c478bd9Sstevel@tonic-gate {
867c478bd9Sstevel@tonic-gate 	_syslog = (struct _syslog *)calloc(1, sizeof (struct _syslog));
877c478bd9Sstevel@tonic-gate 	if (_syslog == 0)
887c478bd9Sstevel@tonic-gate 		return (0);	/* can't do it */
897c478bd9Sstevel@tonic-gate 	LogFile = -1;		/* fd for log */
907c478bd9Sstevel@tonic-gate 	LogStat	= 0;		/* status bits, set by openlog() */
917c478bd9Sstevel@tonic-gate 	LogTag = "syslog";	/* string to tag the entry with */
927c478bd9Sstevel@tonic-gate 	LogMask = 0xff;		/* mask of priorities to be logged */
937c478bd9Sstevel@tonic-gate 	LogFacility = LOG_USER;	/* default facility code */
947c478bd9Sstevel@tonic-gate 	return (1);
957c478bd9Sstevel@tonic-gate }
967c478bd9Sstevel@tonic-gate 
97*5d54f3d8Smuffin void
98*5d54f3d8Smuffin syslog(int pri, char *fmt, ...)
997c478bd9Sstevel@tonic-gate {
1007c478bd9Sstevel@tonic-gate 	va_list ap;
1017c478bd9Sstevel@tonic-gate 
102*5d54f3d8Smuffin 	va_start(ap, fmt);
1037c478bd9Sstevel@tonic-gate 	vsyslog(pri, fmt, ap);
1047c478bd9Sstevel@tonic-gate 	va_end(ap);
1057c478bd9Sstevel@tonic-gate }
1067c478bd9Sstevel@tonic-gate 
107*5d54f3d8Smuffin void
108*5d54f3d8Smuffin vsyslog(int pri, char *fmt, va_list ap)
1097c478bd9Sstevel@tonic-gate {
1107c478bd9Sstevel@tonic-gate 	char buf[MAXLINE + 1], outline[MAXLINE + 1];
111*5d54f3d8Smuffin 	char *b, *f, *o;
112*5d54f3d8Smuffin 	int c;
1137c478bd9Sstevel@tonic-gate 	long now;
1147c478bd9Sstevel@tonic-gate 	int pid, olderrno = errno;
1157c478bd9Sstevel@tonic-gate 	int retsiz, outsiz = MAXLINE + 1;
1167c478bd9Sstevel@tonic-gate 	int taglen;
1177c478bd9Sstevel@tonic-gate /*
1187c478bd9Sstevel@tonic-gate  * Maximum tag length is 256 (the pad in outline) minus the size of the
1197c478bd9Sstevel@tonic-gate  * other things that can go in the pad.
1207c478bd9Sstevel@tonic-gate  */
1217c478bd9Sstevel@tonic-gate #define	MAX_TAG	230
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	if (_syslog == 0 && !allocstatic())
1257c478bd9Sstevel@tonic-gate 		return;
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	/* see if we should just throw out this message */
1287c478bd9Sstevel@tonic-gate 	if (pri <= 0 || PRIFAC(pri) >= LOG_NFACILITIES ||
1297c478bd9Sstevel@tonic-gate 	    (PRIMASK(pri) & LogMask) == 0)
1307c478bd9Sstevel@tonic-gate 		return;
1317c478bd9Sstevel@tonic-gate 	if (LogFile < 0)
1327c478bd9Sstevel@tonic-gate 		openlog(LogTag, LogStat | LOG_NDELAY, 0);
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	/* set default facility if none specified */
1357c478bd9Sstevel@tonic-gate 	if ((pri & LOG_FACMASK) == 0)
1367c478bd9Sstevel@tonic-gate 		pri |= LogFacility;
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	/* build the message */
1397c478bd9Sstevel@tonic-gate 	o = outline;
1407c478bd9Sstevel@tonic-gate 	(void) time(&now);
1417c478bd9Sstevel@tonic-gate 	(void) sprintf(o, "<%d>%.15s ", pri, ctime(&now) + 4);
1427c478bd9Sstevel@tonic-gate 	o += strlen(o);
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	if (LogTag) {
1457c478bd9Sstevel@tonic-gate 		taglen = strlen(LogTag) < MAX_TAG ? strlen(LogTag) : MAX_TAG;
1467c478bd9Sstevel@tonic-gate 		strncpy(o, LogTag, taglen);
1477c478bd9Sstevel@tonic-gate 		o[taglen] = '\0';
1487c478bd9Sstevel@tonic-gate 		o += strlen(o);
1497c478bd9Sstevel@tonic-gate 	}
1507c478bd9Sstevel@tonic-gate 	if (LogStat & LOG_PID) {
1517c478bd9Sstevel@tonic-gate 		(void) sprintf(o, "[%d]", getpid());
1527c478bd9Sstevel@tonic-gate 		o += strlen(o);
1537c478bd9Sstevel@tonic-gate 	}
1547c478bd9Sstevel@tonic-gate 	if (LogTag) {
1557c478bd9Sstevel@tonic-gate 		(void) strcpy(o, ": ");
1567c478bd9Sstevel@tonic-gate 		o += 2;
1577c478bd9Sstevel@tonic-gate 	}
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	b = buf;
1607c478bd9Sstevel@tonic-gate 	f = fmt;
1617c478bd9Sstevel@tonic-gate 	while ((c = *f++) != '\0' && c != '\n' && b < &buf[MAXLINE]) {
1627c478bd9Sstevel@tonic-gate 		char *errstr;
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 		if (c != '%') {
1657c478bd9Sstevel@tonic-gate 			*b++ = c;
1667c478bd9Sstevel@tonic-gate 			continue;
1677c478bd9Sstevel@tonic-gate 		}
1687c478bd9Sstevel@tonic-gate 		if ((c = *f++) != 'm') {
1697c478bd9Sstevel@tonic-gate 			*b++ = '%';
1707c478bd9Sstevel@tonic-gate 			*b++ = c;
1717c478bd9Sstevel@tonic-gate 			continue;
1727c478bd9Sstevel@tonic-gate 		}
1737c478bd9Sstevel@tonic-gate 		if ((errstr = strerror(olderrno)) == NULL)
1747c478bd9Sstevel@tonic-gate 			(void) snprintf(b, &buf[MAXLINE] - b, "error %d",
1757c478bd9Sstevel@tonic-gate 			    olderrno);
1767c478bd9Sstevel@tonic-gate 		else {
1777c478bd9Sstevel@tonic-gate 			while (*errstr != '\0' && b < &buf[MAXLINE]) {
1787c478bd9Sstevel@tonic-gate 				if (*errstr == '%') {
1797c478bd9Sstevel@tonic-gate 					strcpy(b, "%%");
1807c478bd9Sstevel@tonic-gate 					b += 2;
1817c478bd9Sstevel@tonic-gate 				}
1827c478bd9Sstevel@tonic-gate 				else
1837c478bd9Sstevel@tonic-gate 					*b++ = *errstr;
1847c478bd9Sstevel@tonic-gate 				errstr++;
1857c478bd9Sstevel@tonic-gate 			}
1867c478bd9Sstevel@tonic-gate 			*b = '\0';
1877c478bd9Sstevel@tonic-gate 		}
1887c478bd9Sstevel@tonic-gate 		b += strlen(b);
1897c478bd9Sstevel@tonic-gate 	}
1907c478bd9Sstevel@tonic-gate 	if (b > buf && *(b-1) != '\n')	/* ensure at least one newline */
1917c478bd9Sstevel@tonic-gate 		*b++ = '\n';
1927c478bd9Sstevel@tonic-gate 	*b = '\0';
1937c478bd9Sstevel@tonic-gate 	(void) vsnprintf(o, &outline[sizeof (outline)] - o, buf, ap);
1947c478bd9Sstevel@tonic-gate 	c = strlen(outline) + 1;	/* add one for NULL byte */
1957c478bd9Sstevel@tonic-gate 	if (c > MAXLINE) {
1967c478bd9Sstevel@tonic-gate 		c = MAXLINE;
1977c478bd9Sstevel@tonic-gate 		outline[MAXLINE-1] = '\0';
1987c478bd9Sstevel@tonic-gate 	}
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	/* output the message to the local logger */
2017c478bd9Sstevel@tonic-gate 	if (sendto(LogFile, outline, c, 0, &SyslogAddr,
2027c478bd9Sstevel@tonic-gate 	    sizeof (SyslogAddr)) >= 0)
2037c478bd9Sstevel@tonic-gate 		return;
2047c478bd9Sstevel@tonic-gate 	if (!(LogStat & LOG_CONS))
2057c478bd9Sstevel@tonic-gate 		return;
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 	/* output the message to the console */
2087c478bd9Sstevel@tonic-gate 	pid = vfork();
2097c478bd9Sstevel@tonic-gate 	if (pid == -1)
2107c478bd9Sstevel@tonic-gate 		return;
2117c478bd9Sstevel@tonic-gate 	if (pid == 0) {
2127c478bd9Sstevel@tonic-gate 		int fd;
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 		(void) signal(SIGALRM, SIG_DFL);
2157c478bd9Sstevel@tonic-gate 		(void) sigsetmask(sigblock(0) & ~sigmask(SIGALRM));
2167c478bd9Sstevel@tonic-gate 		(void) alarm(5);
2177c478bd9Sstevel@tonic-gate 		if (((fd = open(sysmsg, O_WRONLY)) >= 0) ||
2187c478bd9Sstevel@tonic-gate 		    (fd = open(ctty, O_WRONLY)) >= 0) {
2197c478bd9Sstevel@tonic-gate 			(void) alarm(0);
2207c478bd9Sstevel@tonic-gate 			if (outsiz > 2) {	/* Just in case */
2217c478bd9Sstevel@tonic-gate 				(void) strcat(o, "\r\n");
2227c478bd9Sstevel@tonic-gate 				c += 2;
2237c478bd9Sstevel@tonic-gate 			}
2247c478bd9Sstevel@tonic-gate 			o = index(outline, '>') + 1;
2257c478bd9Sstevel@tonic-gate 			(void) write(fd, o, c - (o - outline));
2267c478bd9Sstevel@tonic-gate 			(void) close(fd);
2277c478bd9Sstevel@tonic-gate 		} else
2287c478bd9Sstevel@tonic-gate 			(void) alarm(0);
2297c478bd9Sstevel@tonic-gate 		_exit(0);
2307c478bd9Sstevel@tonic-gate 	}
2317c478bd9Sstevel@tonic-gate 	if (!(LogStat & LOG_NOWAIT))
2327c478bd9Sstevel@tonic-gate 		while ((c = wait((int *)0)) > 0 && c != pid)
2337c478bd9Sstevel@tonic-gate 			;
2347c478bd9Sstevel@tonic-gate }
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate /*
2377c478bd9Sstevel@tonic-gate  * OPENLOG -- open system log
2387c478bd9Sstevel@tonic-gate  */
239*5d54f3d8Smuffin void
240*5d54f3d8Smuffin openlog(char *ident, int logstat, int logfac)
2417c478bd9Sstevel@tonic-gate {
2427c478bd9Sstevel@tonic-gate 	if (_syslog == 0 && !allocstatic())
2437c478bd9Sstevel@tonic-gate 		return;
2447c478bd9Sstevel@tonic-gate 	if (ident != NULL)
2457c478bd9Sstevel@tonic-gate 		LogTag = ident;
2467c478bd9Sstevel@tonic-gate 	LogStat = logstat;
2477c478bd9Sstevel@tonic-gate 	if (logfac != 0)
2487c478bd9Sstevel@tonic-gate 		LogFacility = logfac & LOG_FACMASK;
2497c478bd9Sstevel@tonic-gate 	if (LogFile >= 0)
2507c478bd9Sstevel@tonic-gate 		return;
2517c478bd9Sstevel@tonic-gate 	SyslogAddr.sa_family = AF_UNIX;
2527c478bd9Sstevel@tonic-gate 	(void) strncpy(SyslogAddr.sa_data, logname,
2537c478bd9Sstevel@tonic-gate 	    sizeof (SyslogAddr.sa_data));
2547c478bd9Sstevel@tonic-gate 	if (LogStat & LOG_NDELAY) {
2557c478bd9Sstevel@tonic-gate 		LogFile = socket(AF_UNIX, SOCK_DGRAM, 0);
2567c478bd9Sstevel@tonic-gate 		(void) fcntl(LogFile, F_SETFD, 1);
2577c478bd9Sstevel@tonic-gate 	}
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate /*
2617c478bd9Sstevel@tonic-gate  * CLOSELOG -- close the system log
2627c478bd9Sstevel@tonic-gate  */
263*5d54f3d8Smuffin void
264*5d54f3d8Smuffin closelog(void)
2657c478bd9Sstevel@tonic-gate {
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 	if (_syslog == 0)
2687c478bd9Sstevel@tonic-gate 		return;
2697c478bd9Sstevel@tonic-gate 	(void) close(LogFile);
2707c478bd9Sstevel@tonic-gate 	LogFile = -1;
2717c478bd9Sstevel@tonic-gate }
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate /*
2747c478bd9Sstevel@tonic-gate  * SETLOGMASK -- set the log mask level
2757c478bd9Sstevel@tonic-gate  */
276*5d54f3d8Smuffin int
277*5d54f3d8Smuffin setlogmask(int pmask)
2787c478bd9Sstevel@tonic-gate {
2797c478bd9Sstevel@tonic-gate 	int omask;
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 	if (_syslog == 0 && !allocstatic())
2827c478bd9Sstevel@tonic-gate 		return (-1);
2837c478bd9Sstevel@tonic-gate 	omask = LogMask;
2847c478bd9Sstevel@tonic-gate 	if (pmask != 0)
2857c478bd9Sstevel@tonic-gate 		LogMask = pmask;
2867c478bd9Sstevel@tonic-gate 	return (omask);
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate /*
2907c478bd9Sstevel@tonic-gate  * snprintf/vsnprintf -- These routines are here
2917c478bd9Sstevel@tonic-gate  * temporarily to solve bugid 1220257. Perhaps
2927c478bd9Sstevel@tonic-gate  * they could become a public interface at some
2937c478bd9Sstevel@tonic-gate  * point but not for now.
2947c478bd9Sstevel@tonic-gate  */
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate extern int _doprnt();
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate static int
299*5d54f3d8Smuffin snprintf(char *string, size_t n, char *format, ...)
3007c478bd9Sstevel@tonic-gate {
301*5d54f3d8Smuffin 	int count;
3027c478bd9Sstevel@tonic-gate 	FILE siop;
3037c478bd9Sstevel@tonic-gate 	va_list ap;
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 	if (n == 0)
3067c478bd9Sstevel@tonic-gate 		return (0);
3077c478bd9Sstevel@tonic-gate 	siop._cnt = n - 1;
3087c478bd9Sstevel@tonic-gate 	siop._base = siop._ptr = (unsigned char *)string;
3097c478bd9Sstevel@tonic-gate 	siop._flag = _IOWRT+_IOSTRG;
310*5d54f3d8Smuffin 	va_start(ap, format);
3117c478bd9Sstevel@tonic-gate 	count = _doprnt(format, ap, &siop);
3127c478bd9Sstevel@tonic-gate 	va_end(ap);
3137c478bd9Sstevel@tonic-gate 	*siop._ptr = '\0';	/* plant terminating null character */
3147c478bd9Sstevel@tonic-gate 	return (count);
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate static int
318*5d54f3d8Smuffin vsnprintf(char *string, size_t n, char *format, va_list ap)
3197c478bd9Sstevel@tonic-gate {
320*5d54f3d8Smuffin 	int count;
3217c478bd9Sstevel@tonic-gate 	FILE siop;
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 	if (n == 0)
3247c478bd9Sstevel@tonic-gate 		return (0);
3257c478bd9Sstevel@tonic-gate 	siop._cnt = n - 1;
3267c478bd9Sstevel@tonic-gate 	siop._base = siop._ptr = (unsigned char *)string;
3277c478bd9Sstevel@tonic-gate 	siop._flag = _IOWRT+_IOSTRG;
3287c478bd9Sstevel@tonic-gate 	count = _doprnt(format, ap, &siop);
3297c478bd9Sstevel@tonic-gate 	*siop._ptr = '\0';	/* plant terminating null character */
3307c478bd9Sstevel@tonic-gate 	return (count);
3317c478bd9Sstevel@tonic-gate }
332