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
allocstatic(void)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
syslog(int pri,char * fmt,...)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
vsyslog(int pri,char * fmt,va_list ap)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
openlog(char * ident,int logstat,int logfac)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
closelog(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
setlogmask(int pmask)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
snprintf(char * string,size_t n,char * format,...)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
vsnprintf(char * string,size_t n,char * format,va_list ap)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