xref: /onnv-gate/usr/src/lib/libbc/libc/gen/common/syslog.c (revision 722:636b850d4ee9)
1*722Smuffin /*
2*722Smuffin  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3*722Smuffin  * Use is subject to license terms.
4*722Smuffin  */
5*722Smuffin 
60Sstevel@tonic-gate /*
70Sstevel@tonic-gate  * Copyright (c) 1983 Regents of the University of California.
80Sstevel@tonic-gate  * All rights reserved.  The Berkeley software License Agreement
90Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
100Sstevel@tonic-gate  */
110Sstevel@tonic-gate 
120Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
130Sstevel@tonic-gate 
140Sstevel@tonic-gate /*
150Sstevel@tonic-gate  * SYSLOG -- print message on log file
160Sstevel@tonic-gate  *
170Sstevel@tonic-gate  * This routine looks a lot like printf, except that it
180Sstevel@tonic-gate  * outputs to the log file instead of the standard output.
190Sstevel@tonic-gate  * Also:
200Sstevel@tonic-gate  *	adds a timestamp,
210Sstevel@tonic-gate  *	prints the module name in front of the message,
220Sstevel@tonic-gate  *	has some other formatting types (or will sometime),
230Sstevel@tonic-gate  *	adds a newline on the end of the message.
240Sstevel@tonic-gate  *
250Sstevel@tonic-gate  * The output of this routine is intended to be read by /etc/syslogd.
260Sstevel@tonic-gate  *
270Sstevel@tonic-gate  * Author: Eric Allman
280Sstevel@tonic-gate  * Modified to use UNIX domain IPC by Ralph Campbell
290Sstevel@tonic-gate  */
300Sstevel@tonic-gate 
310Sstevel@tonic-gate #include <sys/types.h>
320Sstevel@tonic-gate #include <sys/socket.h>
330Sstevel@tonic-gate #include <sys/file.h>
340Sstevel@tonic-gate #include <sys/signal.h>
350Sstevel@tonic-gate #include <sys/syslog.h>
360Sstevel@tonic-gate #include <sys/time.h>
37*722Smuffin #include <sys/unistd.h>
380Sstevel@tonic-gate #include <netdb.h>
390Sstevel@tonic-gate #include <strings.h>
40*722Smuffin #include <stdarg.h>
410Sstevel@tonic-gate #include <vfork.h>
420Sstevel@tonic-gate #include <stdio.h>
43*722Smuffin #include <errno.h>
44*722Smuffin #include <malloc.h>
45*722Smuffin 
460Sstevel@tonic-gate 
470Sstevel@tonic-gate #define	MAXLINE	1024			/* max message size */
480Sstevel@tonic-gate 
490Sstevel@tonic-gate #define	PRIMASK(p)	(1 << ((p) & LOG_PRIMASK))
500Sstevel@tonic-gate #define	PRIFAC(p)	(((p) & LOG_FACMASK) >> 3)
510Sstevel@tonic-gate #define	IMPORTANT 	LOG_ERR
520Sstevel@tonic-gate 
530Sstevel@tonic-gate static char	*logname = "/dev/log";
540Sstevel@tonic-gate static char	*ctty = "/dev/console";
550Sstevel@tonic-gate static char	*sysmsg = "/dev/sysmsg";
560Sstevel@tonic-gate 
570Sstevel@tonic-gate static struct _syslog {
580Sstevel@tonic-gate 	int	_LogFile;
590Sstevel@tonic-gate 	int	_LogStat;
600Sstevel@tonic-gate 	char	*_LogTag;
610Sstevel@tonic-gate 	int	_LogMask;
620Sstevel@tonic-gate 	struct 	sockaddr _SyslogAddr;
630Sstevel@tonic-gate 	char	*_SyslogHost;
640Sstevel@tonic-gate 	int	_LogFacility;
650Sstevel@tonic-gate } *_syslog;
660Sstevel@tonic-gate #define	LogFile (_syslog->_LogFile)
670Sstevel@tonic-gate #define	LogStat (_syslog->_LogStat)
680Sstevel@tonic-gate #define	LogTag (_syslog->_LogTag)
690Sstevel@tonic-gate #define	LogMask (_syslog->_LogMask)
700Sstevel@tonic-gate #define	SyslogAddr (_syslog->_SyslogAddr)
710Sstevel@tonic-gate #define	SyslogHost (_syslog->_SyslogHost)
720Sstevel@tonic-gate #define	LogFacility (_syslog->_LogFacility)
730Sstevel@tonic-gate 
740Sstevel@tonic-gate 
750Sstevel@tonic-gate extern char *strerror(int);
760Sstevel@tonic-gate extern time_t time();
77*722Smuffin 
78*722Smuffin void	vsyslog(int, char *, va_list);
79*722Smuffin void	openlog(char *, int, int);
80*722Smuffin static int	snprintf(char *, size_t, char *, ...);
81*722Smuffin static int	vsnprintf(char *, size_t, char *, va_list ap);
820Sstevel@tonic-gate 
830Sstevel@tonic-gate static int
allocstatic(void)84*722Smuffin allocstatic(void)
850Sstevel@tonic-gate {
860Sstevel@tonic-gate 	_syslog = (struct _syslog *)calloc(1, sizeof (struct _syslog));
870Sstevel@tonic-gate 	if (_syslog == 0)
880Sstevel@tonic-gate 		return (0);	/* can't do it */
890Sstevel@tonic-gate 	LogFile = -1;		/* fd for log */
900Sstevel@tonic-gate 	LogStat	= 0;		/* status bits, set by openlog() */
910Sstevel@tonic-gate 	LogTag = "syslog";	/* string to tag the entry with */
920Sstevel@tonic-gate 	LogMask = 0xff;		/* mask of priorities to be logged */
930Sstevel@tonic-gate 	LogFacility = LOG_USER;	/* default facility code */
940Sstevel@tonic-gate 	return (1);
950Sstevel@tonic-gate }
960Sstevel@tonic-gate 
97*722Smuffin void
syslog(int pri,char * fmt,...)98*722Smuffin syslog(int pri, char *fmt, ...)
990Sstevel@tonic-gate {
1000Sstevel@tonic-gate 	va_list ap;
1010Sstevel@tonic-gate 
102*722Smuffin 	va_start(ap, fmt);
1030Sstevel@tonic-gate 	vsyslog(pri, fmt, ap);
1040Sstevel@tonic-gate 	va_end(ap);
1050Sstevel@tonic-gate }
1060Sstevel@tonic-gate 
107*722Smuffin void
vsyslog(int pri,char * fmt,va_list ap)108*722Smuffin vsyslog(int pri, char *fmt, va_list ap)
1090Sstevel@tonic-gate {
1100Sstevel@tonic-gate 	char buf[MAXLINE + 1], outline[MAXLINE + 1];
111*722Smuffin 	char *b, *f, *o;
112*722Smuffin 	int c;
1130Sstevel@tonic-gate 	long now;
1140Sstevel@tonic-gate 	int pid, olderrno = errno;
1150Sstevel@tonic-gate 	int retsiz, outsiz = MAXLINE + 1;
1160Sstevel@tonic-gate 	int taglen;
1170Sstevel@tonic-gate /*
1180Sstevel@tonic-gate  * Maximum tag length is 256 (the pad in outline) minus the size of the
1190Sstevel@tonic-gate  * other things that can go in the pad.
1200Sstevel@tonic-gate  */
1210Sstevel@tonic-gate #define	MAX_TAG	230
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate 	if (_syslog == 0 && !allocstatic())
1250Sstevel@tonic-gate 		return;
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate 	/* see if we should just throw out this message */
1280Sstevel@tonic-gate 	if (pri <= 0 || PRIFAC(pri) >= LOG_NFACILITIES ||
1290Sstevel@tonic-gate 	    (PRIMASK(pri) & LogMask) == 0)
1300Sstevel@tonic-gate 		return;
1310Sstevel@tonic-gate 	if (LogFile < 0)
1320Sstevel@tonic-gate 		openlog(LogTag, LogStat | LOG_NDELAY, 0);
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 	/* set default facility if none specified */
1350Sstevel@tonic-gate 	if ((pri & LOG_FACMASK) == 0)
1360Sstevel@tonic-gate 		pri |= LogFacility;
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate 	/* build the message */
1390Sstevel@tonic-gate 	o = outline;
1400Sstevel@tonic-gate 	(void) time(&now);
1410Sstevel@tonic-gate 	(void) sprintf(o, "<%d>%.15s ", pri, ctime(&now) + 4);
1420Sstevel@tonic-gate 	o += strlen(o);
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate 	if (LogTag) {
1450Sstevel@tonic-gate 		taglen = strlen(LogTag) < MAX_TAG ? strlen(LogTag) : MAX_TAG;
1460Sstevel@tonic-gate 		strncpy(o, LogTag, taglen);
1470Sstevel@tonic-gate 		o[taglen] = '\0';
1480Sstevel@tonic-gate 		o += strlen(o);
1490Sstevel@tonic-gate 	}
1500Sstevel@tonic-gate 	if (LogStat & LOG_PID) {
1510Sstevel@tonic-gate 		(void) sprintf(o, "[%d]", getpid());
1520Sstevel@tonic-gate 		o += strlen(o);
1530Sstevel@tonic-gate 	}
1540Sstevel@tonic-gate 	if (LogTag) {
1550Sstevel@tonic-gate 		(void) strcpy(o, ": ");
1560Sstevel@tonic-gate 		o += 2;
1570Sstevel@tonic-gate 	}
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 	b = buf;
1600Sstevel@tonic-gate 	f = fmt;
1610Sstevel@tonic-gate 	while ((c = *f++) != '\0' && c != '\n' && b < &buf[MAXLINE]) {
1620Sstevel@tonic-gate 		char *errstr;
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate 		if (c != '%') {
1650Sstevel@tonic-gate 			*b++ = c;
1660Sstevel@tonic-gate 			continue;
1670Sstevel@tonic-gate 		}
1680Sstevel@tonic-gate 		if ((c = *f++) != 'm') {
1690Sstevel@tonic-gate 			*b++ = '%';
1700Sstevel@tonic-gate 			*b++ = c;
1710Sstevel@tonic-gate 			continue;
1720Sstevel@tonic-gate 		}
1730Sstevel@tonic-gate 		if ((errstr = strerror(olderrno)) == NULL)
1740Sstevel@tonic-gate 			(void) snprintf(b, &buf[MAXLINE] - b, "error %d",
1750Sstevel@tonic-gate 			    olderrno);
1760Sstevel@tonic-gate 		else {
1770Sstevel@tonic-gate 			while (*errstr != '\0' && b < &buf[MAXLINE]) {
1780Sstevel@tonic-gate 				if (*errstr == '%') {
1790Sstevel@tonic-gate 					strcpy(b, "%%");
1800Sstevel@tonic-gate 					b += 2;
1810Sstevel@tonic-gate 				}
1820Sstevel@tonic-gate 				else
1830Sstevel@tonic-gate 					*b++ = *errstr;
1840Sstevel@tonic-gate 				errstr++;
1850Sstevel@tonic-gate 			}
1860Sstevel@tonic-gate 			*b = '\0';
1870Sstevel@tonic-gate 		}
1880Sstevel@tonic-gate 		b += strlen(b);
1890Sstevel@tonic-gate 	}
1900Sstevel@tonic-gate 	if (b > buf && *(b-1) != '\n')	/* ensure at least one newline */
1910Sstevel@tonic-gate 		*b++ = '\n';
1920Sstevel@tonic-gate 	*b = '\0';
1930Sstevel@tonic-gate 	(void) vsnprintf(o, &outline[sizeof (outline)] - o, buf, ap);
1940Sstevel@tonic-gate 	c = strlen(outline) + 1;	/* add one for NULL byte */
1950Sstevel@tonic-gate 	if (c > MAXLINE) {
1960Sstevel@tonic-gate 		c = MAXLINE;
1970Sstevel@tonic-gate 		outline[MAXLINE-1] = '\0';
1980Sstevel@tonic-gate 	}
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 	/* output the message to the local logger */
2010Sstevel@tonic-gate 	if (sendto(LogFile, outline, c, 0, &SyslogAddr,
2020Sstevel@tonic-gate 	    sizeof (SyslogAddr)) >= 0)
2030Sstevel@tonic-gate 		return;
2040Sstevel@tonic-gate 	if (!(LogStat & LOG_CONS))
2050Sstevel@tonic-gate 		return;
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 	/* output the message to the console */
2080Sstevel@tonic-gate 	pid = vfork();
2090Sstevel@tonic-gate 	if (pid == -1)
2100Sstevel@tonic-gate 		return;
2110Sstevel@tonic-gate 	if (pid == 0) {
2120Sstevel@tonic-gate 		int fd;
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate 		(void) signal(SIGALRM, SIG_DFL);
2150Sstevel@tonic-gate 		(void) sigsetmask(sigblock(0) & ~sigmask(SIGALRM));
2160Sstevel@tonic-gate 		(void) alarm(5);
2170Sstevel@tonic-gate 		if (((fd = open(sysmsg, O_WRONLY)) >= 0) ||
2180Sstevel@tonic-gate 		    (fd = open(ctty, O_WRONLY)) >= 0) {
2190Sstevel@tonic-gate 			(void) alarm(0);
2200Sstevel@tonic-gate 			if (outsiz > 2) {	/* Just in case */
2210Sstevel@tonic-gate 				(void) strcat(o, "\r\n");
2220Sstevel@tonic-gate 				c += 2;
2230Sstevel@tonic-gate 			}
2240Sstevel@tonic-gate 			o = index(outline, '>') + 1;
2250Sstevel@tonic-gate 			(void) write(fd, o, c - (o - outline));
2260Sstevel@tonic-gate 			(void) close(fd);
2270Sstevel@tonic-gate 		} else
2280Sstevel@tonic-gate 			(void) alarm(0);
2290Sstevel@tonic-gate 		_exit(0);
2300Sstevel@tonic-gate 	}
2310Sstevel@tonic-gate 	if (!(LogStat & LOG_NOWAIT))
2320Sstevel@tonic-gate 		while ((c = wait((int *)0)) > 0 && c != pid)
2330Sstevel@tonic-gate 			;
2340Sstevel@tonic-gate }
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate /*
2370Sstevel@tonic-gate  * OPENLOG -- open system log
2380Sstevel@tonic-gate  */
239*722Smuffin void
openlog(char * ident,int logstat,int logfac)240*722Smuffin openlog(char *ident, int logstat, int logfac)
2410Sstevel@tonic-gate {
2420Sstevel@tonic-gate 	if (_syslog == 0 && !allocstatic())
2430Sstevel@tonic-gate 		return;
2440Sstevel@tonic-gate 	if (ident != NULL)
2450Sstevel@tonic-gate 		LogTag = ident;
2460Sstevel@tonic-gate 	LogStat = logstat;
2470Sstevel@tonic-gate 	if (logfac != 0)
2480Sstevel@tonic-gate 		LogFacility = logfac & LOG_FACMASK;
2490Sstevel@tonic-gate 	if (LogFile >= 0)
2500Sstevel@tonic-gate 		return;
2510Sstevel@tonic-gate 	SyslogAddr.sa_family = AF_UNIX;
2520Sstevel@tonic-gate 	(void) strncpy(SyslogAddr.sa_data, logname,
2530Sstevel@tonic-gate 	    sizeof (SyslogAddr.sa_data));
2540Sstevel@tonic-gate 	if (LogStat & LOG_NDELAY) {
2550Sstevel@tonic-gate 		LogFile = socket(AF_UNIX, SOCK_DGRAM, 0);
2560Sstevel@tonic-gate 		(void) fcntl(LogFile, F_SETFD, 1);
2570Sstevel@tonic-gate 	}
2580Sstevel@tonic-gate }
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate /*
2610Sstevel@tonic-gate  * CLOSELOG -- close the system log
2620Sstevel@tonic-gate  */
263*722Smuffin void
closelog(void)264*722Smuffin closelog(void)
2650Sstevel@tonic-gate {
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate 	if (_syslog == 0)
2680Sstevel@tonic-gate 		return;
2690Sstevel@tonic-gate 	(void) close(LogFile);
2700Sstevel@tonic-gate 	LogFile = -1;
2710Sstevel@tonic-gate }
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate /*
2740Sstevel@tonic-gate  * SETLOGMASK -- set the log mask level
2750Sstevel@tonic-gate  */
276*722Smuffin int
setlogmask(int pmask)277*722Smuffin setlogmask(int pmask)
2780Sstevel@tonic-gate {
2790Sstevel@tonic-gate 	int omask;
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate 	if (_syslog == 0 && !allocstatic())
2820Sstevel@tonic-gate 		return (-1);
2830Sstevel@tonic-gate 	omask = LogMask;
2840Sstevel@tonic-gate 	if (pmask != 0)
2850Sstevel@tonic-gate 		LogMask = pmask;
2860Sstevel@tonic-gate 	return (omask);
2870Sstevel@tonic-gate }
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate /*
2900Sstevel@tonic-gate  * snprintf/vsnprintf -- These routines are here
2910Sstevel@tonic-gate  * temporarily to solve bugid 1220257. Perhaps
2920Sstevel@tonic-gate  * they could become a public interface at some
2930Sstevel@tonic-gate  * point but not for now.
2940Sstevel@tonic-gate  */
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate extern int _doprnt();
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate static int
snprintf(char * string,size_t n,char * format,...)299*722Smuffin snprintf(char *string, size_t n, char *format, ...)
3000Sstevel@tonic-gate {
301*722Smuffin 	int count;
3020Sstevel@tonic-gate 	FILE siop;
3030Sstevel@tonic-gate 	va_list ap;
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate 	if (n == 0)
3060Sstevel@tonic-gate 		return (0);
3070Sstevel@tonic-gate 	siop._cnt = n - 1;
3080Sstevel@tonic-gate 	siop._base = siop._ptr = (unsigned char *)string;
3090Sstevel@tonic-gate 	siop._flag = _IOWRT+_IOSTRG;
310*722Smuffin 	va_start(ap, format);
3110Sstevel@tonic-gate 	count = _doprnt(format, ap, &siop);
3120Sstevel@tonic-gate 	va_end(ap);
3130Sstevel@tonic-gate 	*siop._ptr = '\0';	/* plant terminating null character */
3140Sstevel@tonic-gate 	return (count);
3150Sstevel@tonic-gate }
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate static int
vsnprintf(char * string,size_t n,char * format,va_list ap)318*722Smuffin vsnprintf(char *string, size_t n, char *format, va_list ap)
3190Sstevel@tonic-gate {
320*722Smuffin 	int count;
3210Sstevel@tonic-gate 	FILE siop;
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 	if (n == 0)
3240Sstevel@tonic-gate 		return (0);
3250Sstevel@tonic-gate 	siop._cnt = n - 1;
3260Sstevel@tonic-gate 	siop._base = siop._ptr = (unsigned char *)string;
3270Sstevel@tonic-gate 	siop._flag = _IOWRT+_IOSTRG;
3280Sstevel@tonic-gate 	count = _doprnt(format, ap, &siop);
3290Sstevel@tonic-gate 	*siop._ptr = '\0';	/* plant terminating null character */
3300Sstevel@tonic-gate 	return (count);
3310Sstevel@tonic-gate }
332