diff options
Diffstat (limited to 'usr/src/lib/libbc/libc/gen/common/syslog.c')
-rw-r--r-- | usr/src/lib/libbc/libc/gen/common/syslog.c | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/usr/src/lib/libbc/libc/gen/common/syslog.c b/usr/src/lib/libbc/libc/gen/common/syslog.c new file mode 100644 index 0000000000..ffe71acfb6 --- /dev/null +++ b/usr/src/lib/libbc/libc/gen/common/syslog.c @@ -0,0 +1,341 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#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 <netdb.h> +#include <strings.h> +#include <varargs.h> +#include <vfork.h> +#include <stdio.h> + +#define MAXLINE 1024 /* max message size */ +#define NULL 0 /* manifest */ + +#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 int errno; + +extern char *calloc(); +extern char *strerror(int); +extern time_t time(); +extern unsigned int alarm(); + +static int +allocstatic() +{ + _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); +} + +/*VARARGS2*/ +syslog(pri, fmt, va_alist) + int pri; + char *fmt; + va_dcl +{ + va_list ap; + + va_start(ap); + vsyslog(pri, fmt, ap); + va_end(ap); +} + +vsyslog(pri, fmt, ap) + int pri; + char *fmt; + va_list ap; +{ + char buf[MAXLINE + 1], outline[MAXLINE + 1]; + register char *b, *f, *o; + register 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 + */ + +openlog(ident, logstat, logfac) + char *ident; + int logstat, 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 + */ + +closelog() +{ + + if (_syslog == 0) + return; + (void) close(LogFile); + LogFile = -1; +} + +/* + * SETLOGMASK -- set the log mask level + */ +setlogmask(pmask) + 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(); + +/*VARARGS3*/ +static int +snprintf(string, n, format, va_alist) +char *string, *format; +size_t n; +va_dcl +{ + register 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); + count = _doprnt(format, ap, &siop); + va_end(ap); + *siop._ptr = '\0'; /* plant terminating null character */ + return (count); +} + +/*VARARGS3*/ +static int +vsnprintf(string, n, format, ap) +char *string, *format; +size_t n; +va_list ap; +{ + register 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); +} |