OpenSolaris_b135/lib/libbc/libc/gen/common/syslog.c

Compare this file to the similar file:
Show the results in this format:

/*
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*
 * Copyright (c) 1983 Regents of the University of California.
 * All rights reserved.  The Berkeley software License Agreement
 * specifies the terms and conditions for redistribution.
 */

#pragma ident	"%Z%%M%	%I%	%E% SMI"

/*
 * SYSLOG -- print message on log file
 *
 * This routine looks a lot like printf, except that it
 * outputs to the log file instead of the standard output.
 * Also:
 *	adds a timestamp,
 *	prints the module name in front of the message,
 *	has some other formatting types (or will sometime),
 *	adds a newline on the end of the message.
 *
 * The output of this routine is intended to be read by /etc/syslogd.
 *
 * Author: Eric Allman
 * Modified to use UNIX domain IPC by Ralph Campbell
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/signal.h>
#include <sys/syslog.h>
#include <sys/time.h>
#include <sys/unistd.h>
#include <netdb.h>
#include <strings.h>
#include <stdarg.h>
#include <vfork.h>
#include <stdio.h>
#include <errno.h>
#include <malloc.h>


#define	MAXLINE	1024			/* max message size */

#define	PRIMASK(p)	(1 << ((p) & LOG_PRIMASK))
#define	PRIFAC(p)	(((p) & LOG_FACMASK) >> 3)
#define	IMPORTANT 	LOG_ERR

static char	*logname = "/dev/log";
static char	*ctty = "/dev/console";
static char	*sysmsg = "/dev/sysmsg";

static struct _syslog {
	int	_LogFile;
	int	_LogStat;
	char	*_LogTag;
	int	_LogMask;
	struct 	sockaddr _SyslogAddr;
	char	*_SyslogHost;
	int	_LogFacility;
} *_syslog;
#define	LogFile (_syslog->_LogFile)
#define	LogStat (_syslog->_LogStat)
#define	LogTag (_syslog->_LogTag)
#define	LogMask (_syslog->_LogMask)
#define	SyslogAddr (_syslog->_SyslogAddr)
#define	SyslogHost (_syslog->_SyslogHost)
#define	LogFacility (_syslog->_LogFacility)


extern char *strerror(int);
extern time_t time();

void	vsyslog(int, char *, va_list);
void	openlog(char *, int, int);
static int	snprintf(char *, size_t, char *, ...);
static int	vsnprintf(char *, size_t, char *, va_list ap);

static int
allocstatic(void)
{
	_syslog = (struct _syslog *)calloc(1, sizeof (struct _syslog));
	if (_syslog == 0)
		return (0);	/* can't do it */
	LogFile = -1;		/* fd for log */
	LogStat	= 0;		/* status bits, set by openlog() */
	LogTag = "syslog";	/* string to tag the entry with */
	LogMask = 0xff;		/* mask of priorities to be logged */
	LogFacility = LOG_USER;	/* default facility code */
	return (1);
}

void
syslog(int pri, char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	vsyslog(pri, fmt, ap);
	va_end(ap);
}

void
vsyslog(int pri, char *fmt, va_list ap)
{
	char buf[MAXLINE + 1], outline[MAXLINE + 1];
	char *b, *f, *o;
	int c;
	long now;
	int pid, olderrno = errno;
	int retsiz, outsiz = MAXLINE + 1;
	int taglen;
/*
 * Maximum tag length is 256 (the pad in outline) minus the size of the
 * other things that can go in the pad.
 */
#define	MAX_TAG	230


	if (_syslog == 0 && !allocstatic())
		return;

	/* see if we should just throw out this message */
	if (pri <= 0 || PRIFAC(pri) >= LOG_NFACILITIES ||
	    (PRIMASK(pri) & LogMask) == 0)
		return;
	if (LogFile < 0)
		openlog(LogTag, LogStat | LOG_NDELAY, 0);

	/* set default facility if none specified */
	if ((pri & LOG_FACMASK) == 0)
		pri |= LogFacility;

	/* build the message */
	o = outline;
	(void) time(&now);
	(void) sprintf(o, "<%d>%.15s ", pri, ctime(&now) + 4);
	o += strlen(o);

	if (LogTag) {
		taglen = strlen(LogTag) < MAX_TAG ? strlen(LogTag) : MAX_TAG;
		strncpy(o, LogTag, taglen);
		o[taglen] = '\0';
		o += strlen(o);
	}
	if (LogStat & LOG_PID) {
		(void) sprintf(o, "[%d]", getpid());
		o += strlen(o);
	}
	if (LogTag) {
		(void) strcpy(o, ": ");
		o += 2;
	}

	b = buf;
	f = fmt;
	while ((c = *f++) != '\0' && c != '\n' && b < &buf[MAXLINE]) {
		char *errstr;

		if (c != '%') {
			*b++ = c;
			continue;
		}
		if ((c = *f++) != 'm') {
			*b++ = '%';
			*b++ = c;
			continue;
		}
		if ((errstr = strerror(olderrno)) == NULL)
			(void) snprintf(b, &buf[MAXLINE] - b, "error %d",
			    olderrno);
		else {
			while (*errstr != '\0' && b < &buf[MAXLINE]) {
				if (*errstr == '%') {
					strcpy(b, "%%");
					b += 2;
				}
				else
					*b++ = *errstr;
				errstr++;
			}
			*b = '\0';
		}
		b += strlen(b);
	}
	if (b > buf && *(b-1) != '\n')	/* ensure at least one newline */
		*b++ = '\n';
	*b = '\0';
	(void) vsnprintf(o, &outline[sizeof (outline)] - o, buf, ap);
	c = strlen(outline) + 1;	/* add one for NULL byte */
	if (c > MAXLINE) {
		c = MAXLINE;
		outline[MAXLINE-1] = '\0';
	}

	/* output the message to the local logger */
	if (sendto(LogFile, outline, c, 0, &SyslogAddr,
	    sizeof (SyslogAddr)) >= 0)
		return;
	if (!(LogStat & LOG_CONS))
		return;

	/* output the message to the console */
	pid = vfork();
	if (pid == -1)
		return;
	if (pid == 0) {
		int fd;

		(void) signal(SIGALRM, SIG_DFL);
		(void) sigsetmask(sigblock(0) & ~sigmask(SIGALRM));
		(void) alarm(5);
		if (((fd = open(sysmsg, O_WRONLY)) >= 0) ||
		    (fd = open(ctty, O_WRONLY)) >= 0) {
			(void) alarm(0);
			if (outsiz > 2) {	/* Just in case */
				(void) strcat(o, "\r\n");
				c += 2;
			}
			o = index(outline, '>') + 1;
			(void) write(fd, o, c - (o - outline));
			(void) close(fd);
		} else
			(void) alarm(0);
		_exit(0);
	}
	if (!(LogStat & LOG_NOWAIT))
		while ((c = wait((int *)0)) > 0 && c != pid)
			;
}

/*
 * OPENLOG -- open system log
 */
void
openlog(char *ident, int logstat, int logfac)
{
	if (_syslog == 0 && !allocstatic())
		return;
	if (ident != NULL)
		LogTag = ident;
	LogStat = logstat;
	if (logfac != 0)
		LogFacility = logfac & LOG_FACMASK;
	if (LogFile >= 0)
		return;
	SyslogAddr.sa_family = AF_UNIX;
	(void) strncpy(SyslogAddr.sa_data, logname,
	    sizeof (SyslogAddr.sa_data));
	if (LogStat & LOG_NDELAY) {
		LogFile = socket(AF_UNIX, SOCK_DGRAM, 0);
		(void) fcntl(LogFile, F_SETFD, 1);
	}
}

/*
 * CLOSELOG -- close the system log
 */
void
closelog(void)
{

	if (_syslog == 0)
		return;
	(void) close(LogFile);
	LogFile = -1;
}

/*
 * SETLOGMASK -- set the log mask level
 */
int
setlogmask(int pmask)
{
	int omask;

	if (_syslog == 0 && !allocstatic())
		return (-1);
	omask = LogMask;
	if (pmask != 0)
		LogMask = pmask;
	return (omask);
}

/*
 * snprintf/vsnprintf -- These routines are here
 * temporarily to solve bugid 1220257. Perhaps
 * they could become a public interface at some
 * point but not for now.
 */

extern int _doprnt();

static int
snprintf(char *string, size_t n, char *format, ...)
{
	int count;
	FILE siop;
	va_list ap;

	if (n == 0)
		return (0);
	siop._cnt = n - 1;
	siop._base = siop._ptr = (unsigned char *)string;
	siop._flag = _IOWRT+_IOSTRG;
	va_start(ap, format);
	count = _doprnt(format, ap, &siop);
	va_end(ap);
	*siop._ptr = '\0';	/* plant terminating null character */
	return (count);
}

static int
vsnprintf(char *string, size_t n, char *format, va_list ap)
{
	int count;
	FILE siop;

	if (n == 0)
		return (0);
	siop._cnt = n - 1;
	siop._base = siop._ptr = (unsigned char *)string;
	siop._flag = _IOWRT+_IOSTRG;
	count = _doprnt(format, ap, &siop);
	*siop._ptr = '\0';	/* plant terminating null character */
	return (count);
}