xref: /titanic_50/usr/src/lib/libc/port/gen/syslog.c (revision 8f46313ce408b92df7a36773ef3aa5498641d00c)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5657b1f3dSraf  * Common Development and Distribution License (the "License").
6657b1f3dSraf  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21657b1f3dSraf 
227c478bd9Sstevel@tonic-gate /*
237257d1b4Sraf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1988 AT&T	*/
287c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
327c478bd9Sstevel@tonic-gate  * The Regents of the University of California
337c478bd9Sstevel@tonic-gate  * All Rights Reserved
347c478bd9Sstevel@tonic-gate  *
357c478bd9Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
367c478bd9Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
377c478bd9Sstevel@tonic-gate  * contributors.
387c478bd9Sstevel@tonic-gate  */
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate /*
427c478bd9Sstevel@tonic-gate  * SYSLOG -- print message on log file
437c478bd9Sstevel@tonic-gate  *
447c478bd9Sstevel@tonic-gate  * This routine looks a lot like printf, except that it
457c478bd9Sstevel@tonic-gate  * outputs to the log file instead of the standard output.
467c478bd9Sstevel@tonic-gate  * Also:
477c478bd9Sstevel@tonic-gate  *	adds a timestamp,
487c478bd9Sstevel@tonic-gate  *	prints the module name in front of the message,
497c478bd9Sstevel@tonic-gate  *	has some other formatting types (or will sometime),
507c478bd9Sstevel@tonic-gate  *	adds a newline on the end of the message.
517c478bd9Sstevel@tonic-gate  *
527c478bd9Sstevel@tonic-gate  * The output of this routine is intended to be read by /etc/syslogd.
537c478bd9Sstevel@tonic-gate  */
547c478bd9Sstevel@tonic-gate 
557257d1b4Sraf #pragma weak _syslog = syslog
567c478bd9Sstevel@tonic-gate 
577257d1b4Sraf #include "lint.h"
587c478bd9Sstevel@tonic-gate #include <sys/types.h>
597c478bd9Sstevel@tonic-gate #include <sys/types32.h>
607c478bd9Sstevel@tonic-gate #include <sys/mman.h>
617c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
627c478bd9Sstevel@tonic-gate #include <sys/strlog.h>
637c478bd9Sstevel@tonic-gate #include <sys/log.h>		/* for LOG_MAXPS */
647c478bd9Sstevel@tonic-gate #include <stdlib.h>
657c478bd9Sstevel@tonic-gate #include <procfs.h>
667c478bd9Sstevel@tonic-gate #include <syslog.h>
677c478bd9Sstevel@tonic-gate #include <signal.h>
687c478bd9Sstevel@tonic-gate #include <fcntl.h>
697c478bd9Sstevel@tonic-gate #include <string.h>
707c478bd9Sstevel@tonic-gate #include <stdarg.h>
717c478bd9Sstevel@tonic-gate #include <unistd.h>
727c478bd9Sstevel@tonic-gate #include <wait.h>
737c478bd9Sstevel@tonic-gate #include <stdio.h>
747c478bd9Sstevel@tonic-gate #include <string.h>
757c478bd9Sstevel@tonic-gate #include <errno.h>
767c478bd9Sstevel@tonic-gate #include <thread.h>
777c478bd9Sstevel@tonic-gate #include <synch.h>
787c478bd9Sstevel@tonic-gate #include <sys/door.h>
797c478bd9Sstevel@tonic-gate #include <sys/stat.h>
807c478bd9Sstevel@tonic-gate #include <stropts.h>
81657b1f3dSraf #include <sys/fork.h>
827c478bd9Sstevel@tonic-gate #include <sys/wait.h>
837c478bd9Sstevel@tonic-gate #include "libc.h"
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate #define	MAXLINE		1024		/* max message size (but see below) */
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate #define	PRIMASK(p)	(1 << ((p) & LOG_PRIMASK))
887c478bd9Sstevel@tonic-gate #define	PRIFAC(p)	(((p) & LOG_FACMASK) >> 3)
897c478bd9Sstevel@tonic-gate #define	IMPORTANT 	LOG_ERR
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate #ifndef FALSE
927c478bd9Sstevel@tonic-gate #define	FALSE 	0
937c478bd9Sstevel@tonic-gate #endif
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate #ifndef TRUE
967c478bd9Sstevel@tonic-gate #define	TRUE	1
977c478bd9Sstevel@tonic-gate #endif
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate #define	logname		"/dev/conslog"
1007c478bd9Sstevel@tonic-gate #define	ctty		"/dev/syscon"
1017c478bd9Sstevel@tonic-gate #define	sysmsg		"/dev/sysmsg"
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate #define	DOORFILE	"/var/run/syslog_door"
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate static struct __syslog {
1067c478bd9Sstevel@tonic-gate 	int	_LogFile;
1077c478bd9Sstevel@tonic-gate 	int	_LogStat;
1087c478bd9Sstevel@tonic-gate 	const char *_LogTag;
1097c478bd9Sstevel@tonic-gate 	int	_LogMask;
1107c478bd9Sstevel@tonic-gate 	char	*_SyslogHost;
1117c478bd9Sstevel@tonic-gate 	int	_LogFacility;
1127c478bd9Sstevel@tonic-gate 	int	_LogFileInvalid;
1137c478bd9Sstevel@tonic-gate 	int	_OpenLogCalled;
1147c478bd9Sstevel@tonic-gate 	dev_t   _LogDev;
1157c478bd9Sstevel@tonic-gate 	char	_ProcName[PRFNSZ + 1];
1167c478bd9Sstevel@tonic-gate } __syslog = {
1177c478bd9Sstevel@tonic-gate 	-1,		/* fd for log */
1187c478bd9Sstevel@tonic-gate 	0,		/* status bits, set by openlog() */
1197c478bd9Sstevel@tonic-gate 	"syslog",	/* string to tag the entry with */
1207c478bd9Sstevel@tonic-gate 	0xff,		/* mask of priorities to be logged */
1217c478bd9Sstevel@tonic-gate 	NULL,
1227c478bd9Sstevel@tonic-gate 	LOG_USER,	/* default facility code */
1237c478bd9Sstevel@tonic-gate 	FALSE,		/* check for validity of fd for log */
1247c478bd9Sstevel@tonic-gate 	0,		/* openlog has not yet been called */
1257c478bd9Sstevel@tonic-gate };
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate #define	LogFile (__syslog._LogFile)
1287c478bd9Sstevel@tonic-gate #define	LogStat (__syslog._LogStat)
1297c478bd9Sstevel@tonic-gate #define	LogTag (__syslog._LogTag)
1307c478bd9Sstevel@tonic-gate #define	LogMask (__syslog._LogMask)
1317c478bd9Sstevel@tonic-gate #define	SyslogHost (__syslog._SyslogHost)
1327c478bd9Sstevel@tonic-gate #define	LogFacility (__syslog._LogFacility)
1337c478bd9Sstevel@tonic-gate #define	LogFileInvalid (__syslog._LogFileInvalid)
1347c478bd9Sstevel@tonic-gate #define	OpenLogCalled (__syslog._OpenLogCalled)
1357c478bd9Sstevel@tonic-gate #define	LogDev (__syslog._LogDev)
1367c478bd9Sstevel@tonic-gate #define	ProcName (__syslog._ProcName)
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate static int syslogd_ok(void);
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate /*
1417c478bd9Sstevel@tonic-gate  * Regrettably, there are several instances inside libc where
1427c478bd9Sstevel@tonic-gate  * syslog() is called from the bottom of a deep call stack
1437c478bd9Sstevel@tonic-gate  * and a critical lock was acquired near the top of the stack.
1447c478bd9Sstevel@tonic-gate  *
1457c478bd9Sstevel@tonic-gate  * Because syslog() uses stdio (and it is called from within stdio)
1467c478bd9Sstevel@tonic-gate  * it runs the danger of deadlocking, perhaps with an interposed
1477c478bd9Sstevel@tonic-gate  * malloc() when fork() is occurring concurrently, perhaps with
1487c478bd9Sstevel@tonic-gate  * some other lock within libc.
1497c478bd9Sstevel@tonic-gate  *
1507c478bd9Sstevel@tonic-gate  * The only fix for this problem is to restructure libc not to do
1517c478bd9Sstevel@tonic-gate  * this thing and always to call syslog() with no locks held.
1527c478bd9Sstevel@tonic-gate  * This restructuring will require a substantial effort.
1537c478bd9Sstevel@tonic-gate  *
1547c478bd9Sstevel@tonic-gate  * Meanwhile, we just hope that on the rare occasion that syslog()
1557c478bd9Sstevel@tonic-gate  * is called from within libc (such occurrences should "never happen")
1567c478bd9Sstevel@tonic-gate  * that we don't get caught in a race condition deadlock.
1577c478bd9Sstevel@tonic-gate  */
1587c478bd9Sstevel@tonic-gate void
syslog(int pri,const char * fmt,...)1597c478bd9Sstevel@tonic-gate syslog(int pri, const char *fmt, ...)
1607c478bd9Sstevel@tonic-gate {
1617c478bd9Sstevel@tonic-gate 	va_list ap;
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
1647c478bd9Sstevel@tonic-gate 	vsyslog(pri, fmt, ap);
1657c478bd9Sstevel@tonic-gate 	va_end(ap);
1667c478bd9Sstevel@tonic-gate }
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate void
vsyslog(int pri,const char * fmt,va_list ap)1707c478bd9Sstevel@tonic-gate vsyslog(int pri, const char *fmt, va_list ap)
1717c478bd9Sstevel@tonic-gate {
1727c478bd9Sstevel@tonic-gate 	char *b, *f, *o;
1737c478bd9Sstevel@tonic-gate 	char c;
1747c478bd9Sstevel@tonic-gate 	int clen;
1757c478bd9Sstevel@tonic-gate 	char buf[MAXLINE + 2];
1767c478bd9Sstevel@tonic-gate 	char outline[MAXLINE + 256];  /* pad to allow date, system name... */
1777c478bd9Sstevel@tonic-gate 	time_t now;
1787c478bd9Sstevel@tonic-gate 	pid_t pid;
1797c478bd9Sstevel@tonic-gate 	struct log_ctl hdr;
1807c478bd9Sstevel@tonic-gate 	struct strbuf dat;
1817c478bd9Sstevel@tonic-gate 	struct strbuf ctl;
1827c478bd9Sstevel@tonic-gate 	char timestr[26];	/* hardwired value 26 due to Posix */
1837c478bd9Sstevel@tonic-gate 	size_t taglen;
1847c478bd9Sstevel@tonic-gate 	int olderrno = errno;
1857c478bd9Sstevel@tonic-gate 	struct stat statbuff;
1867c478bd9Sstevel@tonic-gate 	int procfd;
1877c478bd9Sstevel@tonic-gate 	char procfile[32];
1887c478bd9Sstevel@tonic-gate 	psinfo_t p;
1897c478bd9Sstevel@tonic-gate 	int showpid;
1907c478bd9Sstevel@tonic-gate 	uint32_t msgid;
1917c478bd9Sstevel@tonic-gate 	char *msgid_start, *msgid_end;
192657b1f3dSraf 	int nowait;
193*8f46313cSDavid Hanisch 	int ret;
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate /*
1967c478bd9Sstevel@tonic-gate  * Maximum tag length is 256 (the pad in outline) minus the size of the
1977c478bd9Sstevel@tonic-gate  * other things that can go in the pad.
1987c478bd9Sstevel@tonic-gate  */
1997c478bd9Sstevel@tonic-gate #define	MAX_TAG		230
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 	/* see if we should just throw out this message */
2027c478bd9Sstevel@tonic-gate 	if (pri < 0 || PRIFAC(pri) >= LOG_NFACILITIES ||
2037c478bd9Sstevel@tonic-gate 	    (PRIMASK(pri) & LogMask) == 0)
2047c478bd9Sstevel@tonic-gate 		return;
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	if (LogFileInvalid)
2077c478bd9Sstevel@tonic-gate 		return;
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 	/*
2107c478bd9Sstevel@tonic-gate 	 * if openlog() has not been called by the application,
2117c478bd9Sstevel@tonic-gate 	 * try to get the name of the application and set it
2127c478bd9Sstevel@tonic-gate 	 * as the ident string for messages. If unable to get
2137c478bd9Sstevel@tonic-gate 	 * it for any reason, fall back to using the default
2147c478bd9Sstevel@tonic-gate 	 * of syslog. If we succeed in getting the name, also
2157c478bd9Sstevel@tonic-gate 	 * turn on LOG_PID, to provide greater detail.
2167c478bd9Sstevel@tonic-gate 	 */
2177c478bd9Sstevel@tonic-gate 	showpid = 0;
2187c478bd9Sstevel@tonic-gate 	if (OpenLogCalled == 0) {
2198793b36bSNick Todd 		(void) sprintf(procfile, "/proc/%d/psinfo", (int)getpid());
2207c478bd9Sstevel@tonic-gate 		if ((procfd = open(procfile, O_RDONLY)) >= 0) {
2217c478bd9Sstevel@tonic-gate 			if (read(procfd, &p, sizeof (psinfo_t)) >= 0) {
2227c478bd9Sstevel@tonic-gate 				(void) strncpy(ProcName, p.pr_fname, PRFNSZ);
2237c478bd9Sstevel@tonic-gate 				LogTag = (const char *) &ProcName;
2247c478bd9Sstevel@tonic-gate 				showpid = LOG_PID;
2257c478bd9Sstevel@tonic-gate 			}
2267c478bd9Sstevel@tonic-gate 			(void) close(procfd);
2277c478bd9Sstevel@tonic-gate 		}
2287c478bd9Sstevel@tonic-gate 	}
2297c478bd9Sstevel@tonic-gate 	if (LogFile < 0)
2307c478bd9Sstevel@tonic-gate 		openlog(LogTag, LogStat|LOG_NDELAY|showpid, 0);
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	if ((fstat(LogFile, &statbuff) != 0) ||
2337c478bd9Sstevel@tonic-gate 	    (!S_ISCHR(statbuff.st_mode)) || (statbuff.st_rdev != LogDev)) {
2347c478bd9Sstevel@tonic-gate 		LogFileInvalid = TRUE;
2357c478bd9Sstevel@tonic-gate 		return;
2367c478bd9Sstevel@tonic-gate 	}
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	/* set default facility if none specified */
2397c478bd9Sstevel@tonic-gate 	if ((pri & LOG_FACMASK) == 0)
2407c478bd9Sstevel@tonic-gate 		pri |= LogFacility;
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 	/* build the header */
2437c478bd9Sstevel@tonic-gate 	hdr.pri = pri;
2447c478bd9Sstevel@tonic-gate 	hdr.flags = SL_CONSOLE;
2457c478bd9Sstevel@tonic-gate 	hdr.level = 0;
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate 	/* build the message */
2487c478bd9Sstevel@tonic-gate 	/*
2497c478bd9Sstevel@tonic-gate 	 * To avoid potential security problems, bounds checking is done
2507c478bd9Sstevel@tonic-gate 	 * on outline and buf.
2517c478bd9Sstevel@tonic-gate 	 * The following code presumes that the header information will
2527c478bd9Sstevel@tonic-gate 	 * fit in 250-odd bytes, as was accounted for in the buffer size
2537c478bd9Sstevel@tonic-gate 	 * allocation.  This is dependent on the assumption that the LogTag
2547c478bd9Sstevel@tonic-gate 	 * and the string returned by sprintf() for getpid() will return
2557c478bd9Sstevel@tonic-gate 	 * be less than 230-odd characters combined.
2567c478bd9Sstevel@tonic-gate 	 */
2577c478bd9Sstevel@tonic-gate 	o = outline;
2587c478bd9Sstevel@tonic-gate 	(void) time(&now);
2597c478bd9Sstevel@tonic-gate 	(void) sprintf(o, "%.15s ", ctime_r(&now, timestr, 26) + 4);
2607c478bd9Sstevel@tonic-gate 	o += strlen(o);
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 	if (LogTag) {
2637c478bd9Sstevel@tonic-gate 		taglen = strlen(LogTag) < MAX_TAG ? strlen(LogTag) : MAX_TAG;
2647c478bd9Sstevel@tonic-gate 		(void) strncpy(o, LogTag, taglen);
2657c478bd9Sstevel@tonic-gate 		o[taglen] = '\0';
2667c478bd9Sstevel@tonic-gate 		o += strlen(o);
2677c478bd9Sstevel@tonic-gate 	}
2687c478bd9Sstevel@tonic-gate 	if (LogStat & LOG_PID) {
2698793b36bSNick Todd 		(void) sprintf(o, "[%d]", (int)getpid());
2707c478bd9Sstevel@tonic-gate 		o += strlen(o);
2717c478bd9Sstevel@tonic-gate 	}
2727c478bd9Sstevel@tonic-gate 	if (LogTag) {
2737c478bd9Sstevel@tonic-gate 		(void) strcpy(o, ": ");
2747c478bd9Sstevel@tonic-gate 		o += 2;
2757c478bd9Sstevel@tonic-gate 	}
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	STRLOG_MAKE_MSGID(fmt, msgid);
2787c478bd9Sstevel@tonic-gate 	(void) sprintf(o, "[ID %u FACILITY_AND_PRIORITY] ", msgid);
2797c478bd9Sstevel@tonic-gate 	o += strlen(o);
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 	b = buf;
2827c478bd9Sstevel@tonic-gate 	f = (char *)fmt;
2837c478bd9Sstevel@tonic-gate 	while ((c = *f++) != '\0' && b < &buf[MAXLINE]) {
2847c478bd9Sstevel@tonic-gate 		char *errmsg;
2857c478bd9Sstevel@tonic-gate 		if (c != '%') {
2867c478bd9Sstevel@tonic-gate 			*b++ = c;
2877c478bd9Sstevel@tonic-gate 			continue;
2887c478bd9Sstevel@tonic-gate 		}
2897c478bd9Sstevel@tonic-gate 		if ((c = *f++) != 'm') {
2907c478bd9Sstevel@tonic-gate 			*b++ = '%';
2917c478bd9Sstevel@tonic-gate 			*b++ = c;
2927c478bd9Sstevel@tonic-gate 			continue;
2937c478bd9Sstevel@tonic-gate 		}
2947c478bd9Sstevel@tonic-gate 		if ((errmsg = strerror(olderrno)) == NULL)
2957c478bd9Sstevel@tonic-gate 			(void) snprintf(b, &buf[MAXLINE] - b, "error %d",
2967c478bd9Sstevel@tonic-gate 			    olderrno);
2977c478bd9Sstevel@tonic-gate 		else {
2987c478bd9Sstevel@tonic-gate 			while (*errmsg != '\0' && b < &buf[MAXLINE]) {
2997c478bd9Sstevel@tonic-gate 				if (*errmsg == '%') {
3007c478bd9Sstevel@tonic-gate 					(void) strcpy(b, "%%");
3017c478bd9Sstevel@tonic-gate 					b += 2;
3027c478bd9Sstevel@tonic-gate 				}
3037c478bd9Sstevel@tonic-gate 				else
3047c478bd9Sstevel@tonic-gate 					*b++ = *errmsg;
3057c478bd9Sstevel@tonic-gate 				errmsg++;
3067c478bd9Sstevel@tonic-gate 			}
3077c478bd9Sstevel@tonic-gate 			*b = '\0';
3087c478bd9Sstevel@tonic-gate 		}
3097c478bd9Sstevel@tonic-gate 		b += strlen(b);
3107c478bd9Sstevel@tonic-gate 	}
3117c478bd9Sstevel@tonic-gate 	if (b > buf && *(b-1) != '\n')	/* ensure at least one newline */
3127c478bd9Sstevel@tonic-gate 		*b++ = '\n';
3137c478bd9Sstevel@tonic-gate 	*b = '\0';
3147c478bd9Sstevel@tonic-gate 	/* LINTED variable format specifier */
3157c478bd9Sstevel@tonic-gate 	(void) vsnprintf(o, &outline[sizeof (outline)] - o, buf, ap);
3167c478bd9Sstevel@tonic-gate 	clen  = (int)strlen(outline) + 1;	/* add one for NULL byte */
3177c478bd9Sstevel@tonic-gate 	if (clen > MAXLINE) {
3187c478bd9Sstevel@tonic-gate 		clen = MAXLINE;
3197c478bd9Sstevel@tonic-gate 		outline[MAXLINE-1] = '\0';
3207c478bd9Sstevel@tonic-gate 	}
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 	/*
3237c478bd9Sstevel@tonic-gate 	 * 1136432 points out that the underlying log driver actually
3247c478bd9Sstevel@tonic-gate 	 * refuses to accept (ERANGE) messages longer than LOG_MAXPS
3257c478bd9Sstevel@tonic-gate 	 * bytes.  So it really doesn't make much sense to putmsg a
3267c478bd9Sstevel@tonic-gate 	 * longer message..
3277c478bd9Sstevel@tonic-gate 	 */
3287c478bd9Sstevel@tonic-gate 	if (clen > LOG_MAXPS) {
3297c478bd9Sstevel@tonic-gate 		clen = LOG_MAXPS;
3307c478bd9Sstevel@tonic-gate 		outline[LOG_MAXPS-1] = '\0';
3317c478bd9Sstevel@tonic-gate 	}
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 	/* set up the strbufs */
3347c478bd9Sstevel@tonic-gate 	ctl.maxlen = sizeof (struct log_ctl);
3357c478bd9Sstevel@tonic-gate 	ctl.len = sizeof (struct log_ctl);
3367c478bd9Sstevel@tonic-gate 	ctl.buf = (caddr_t)&hdr;
3377c478bd9Sstevel@tonic-gate 	dat.maxlen = sizeof (outline);
3387c478bd9Sstevel@tonic-gate 	dat.len = clen;
3397c478bd9Sstevel@tonic-gate 	dat.buf = outline;
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 	/* output the message to the local logger */
342*8f46313cSDavid Hanisch 	ret = putmsg(LogFile, &ctl, &dat, 0);
3437c478bd9Sstevel@tonic-gate 	if (!(LogStat & LOG_CONS))
3447c478bd9Sstevel@tonic-gate 		return;
345*8f46313cSDavid Hanisch 	if ((ret >= 0) && syslogd_ok())
346*8f46313cSDavid Hanisch 		return;
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	/*
3497c478bd9Sstevel@tonic-gate 	 * Output the message to the console directly.  To reduce visual
3507c478bd9Sstevel@tonic-gate 	 * clutter, we strip out the message ID.
3517c478bd9Sstevel@tonic-gate 	 */
3527c478bd9Sstevel@tonic-gate 	if ((msgid_start = strstr(outline, "[ID ")) != NULL &&
3537c478bd9Sstevel@tonic-gate 	    (msgid_end = strstr(msgid_start, "] ")) != NULL)
3547c478bd9Sstevel@tonic-gate 		(void) strcpy(msgid_start, msgid_end + 2);
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 	clen = strlen(outline) + 1;
3577c478bd9Sstevel@tonic-gate 
358657b1f3dSraf 	nowait = (LogStat & LOG_NOWAIT);
359657b1f3dSraf 	pid = forkx(nowait? 0 : (FORK_NOSIGCHLD | FORK_WAITPID));
360657b1f3dSraf 	if (pid == -1)
3617c478bd9Sstevel@tonic-gate 		return;
362657b1f3dSraf 
3637c478bd9Sstevel@tonic-gate 	if (pid == 0) {
364657b1f3dSraf 		sigset_t sigs;
3657c478bd9Sstevel@tonic-gate 		int fd;
3667c478bd9Sstevel@tonic-gate 
367657b1f3dSraf 		(void) sigset(SIGALRM, SIG_DFL);
368657b1f3dSraf 		(void) sigemptyset(&sigs);
369657b1f3dSraf 		(void) sigaddset(&sigs, SIGALRM);
370657b1f3dSraf 		(void) sigprocmask(SIG_UNBLOCK, &sigs, NULL);
3717c478bd9Sstevel@tonic-gate 		(void) alarm(5);
3727c478bd9Sstevel@tonic-gate 		if (((fd = open(sysmsg, O_WRONLY)) >= 0) ||
3737c478bd9Sstevel@tonic-gate 		    (fd = open(ctty, O_WRONLY)) >= 0) {
3747c478bd9Sstevel@tonic-gate 			(void) alarm(0);
3757c478bd9Sstevel@tonic-gate 			outline[clen - 1] = '\r';
3767c478bd9Sstevel@tonic-gate 			(void) write(fd, outline, clen);
3777c478bd9Sstevel@tonic-gate 			(void) close(fd);
3787c478bd9Sstevel@tonic-gate 		}
3797c478bd9Sstevel@tonic-gate 		_exit(0);
3807c478bd9Sstevel@tonic-gate 	}
381657b1f3dSraf 	if (!nowait)
382657b1f3dSraf 		while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
383657b1f3dSraf 			continue;
3847c478bd9Sstevel@tonic-gate }
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate /*
3877c478bd9Sstevel@tonic-gate  * Use a door call to syslogd to see if it's alive.
3887c478bd9Sstevel@tonic-gate  */
3897c478bd9Sstevel@tonic-gate static int
syslogd_ok(void)3907c478bd9Sstevel@tonic-gate syslogd_ok(void)
3917c478bd9Sstevel@tonic-gate {
3927c478bd9Sstevel@tonic-gate 	int d;
3937c478bd9Sstevel@tonic-gate 	int s;
3947c478bd9Sstevel@tonic-gate 	door_arg_t darg;
3957c478bd9Sstevel@tonic-gate 	door_info_t info;
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	if ((d = open(DOORFILE, O_RDONLY)) < 0)
3987c478bd9Sstevel@tonic-gate 		return (0);
3997c478bd9Sstevel@tonic-gate 	/*
4007c478bd9Sstevel@tonic-gate 	 * see if our pid matches the pid of the door server.
4017c478bd9Sstevel@tonic-gate 	 * If so, syslogd has called syslog(), probably as
4027c478bd9Sstevel@tonic-gate 	 * a result of some name service library error, and
4037c478bd9Sstevel@tonic-gate 	 * we don't want to let syslog continue and possibly
4047c478bd9Sstevel@tonic-gate 	 * fork here.
4057c478bd9Sstevel@tonic-gate 	 */
4067c478bd9Sstevel@tonic-gate 	info.di_target = 0;
4077c478bd9Sstevel@tonic-gate 	if (__door_info(d, &info) < 0 || info.di_target == getpid()) {
4087c478bd9Sstevel@tonic-gate 		(void) close(d);
4097c478bd9Sstevel@tonic-gate 		return (0);
4107c478bd9Sstevel@tonic-gate 	}
4117c478bd9Sstevel@tonic-gate 	darg.data_ptr = NULL;
4127c478bd9Sstevel@tonic-gate 	darg.data_size = 0;
4137c478bd9Sstevel@tonic-gate 	darg.desc_ptr = NULL;
4147c478bd9Sstevel@tonic-gate 	darg.desc_num = 0;
4157c478bd9Sstevel@tonic-gate 	darg.rbuf = NULL;
4167c478bd9Sstevel@tonic-gate 	darg.rsize = 0;
4177c478bd9Sstevel@tonic-gate 	s = __door_call(d, &darg);
4187c478bd9Sstevel@tonic-gate 	(void) close(d);
4197c478bd9Sstevel@tonic-gate 	if (s < 0)
4207c478bd9Sstevel@tonic-gate 		return (0);		/* failure - syslogd dead */
4217c478bd9Sstevel@tonic-gate 	else
4227c478bd9Sstevel@tonic-gate 		return (1);
4237c478bd9Sstevel@tonic-gate }
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate /*
4267c478bd9Sstevel@tonic-gate  * OPENLOG -- open system log
4277c478bd9Sstevel@tonic-gate  */
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate void
openlog(const char * ident,int logstat,int logfac)4307c478bd9Sstevel@tonic-gate openlog(const char *ident, int logstat, int logfac)
4317c478bd9Sstevel@tonic-gate {
4327c478bd9Sstevel@tonic-gate 	struct	stat	statbuff;
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 	OpenLogCalled = 1;
4357c478bd9Sstevel@tonic-gate 	if (ident != NULL)
4367c478bd9Sstevel@tonic-gate 		LogTag = ident;
4377c478bd9Sstevel@tonic-gate 	LogStat = logstat;
4387c478bd9Sstevel@tonic-gate 	if (logfac != 0)
4397c478bd9Sstevel@tonic-gate 		LogFacility = logfac & LOG_FACMASK;
4407c478bd9Sstevel@tonic-gate 
4417c478bd9Sstevel@tonic-gate 	/*
4427c478bd9Sstevel@tonic-gate 	 * if the fstat(2) fails or the st_rdev has changed
4437c478bd9Sstevel@tonic-gate 	 * then we must open the file
4447c478bd9Sstevel@tonic-gate 	 */
4457c478bd9Sstevel@tonic-gate 	if ((fstat(LogFile, &statbuff) == 0) &&
4467c478bd9Sstevel@tonic-gate 	    (S_ISCHR(statbuff.st_mode)) && (statbuff.st_rdev == LogDev))
4477c478bd9Sstevel@tonic-gate 		return;
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 	if (LogStat & LOG_NDELAY) {
4507c478bd9Sstevel@tonic-gate 		LogFile = open(logname, O_WRONLY);
4517c478bd9Sstevel@tonic-gate 		(void) fcntl(LogFile, F_SETFD, 1);
4527c478bd9Sstevel@tonic-gate 		(void) fstat(LogFile, &statbuff);
4537c478bd9Sstevel@tonic-gate 		LogDev = statbuff.st_rdev;
4547c478bd9Sstevel@tonic-gate 	}
4557c478bd9Sstevel@tonic-gate }
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate /*
4587c478bd9Sstevel@tonic-gate  * CLOSELOG -- close the system log
4597c478bd9Sstevel@tonic-gate  */
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate void
closelog(void)4627c478bd9Sstevel@tonic-gate closelog(void)
4637c478bd9Sstevel@tonic-gate {
4647c478bd9Sstevel@tonic-gate 	struct	stat	statbuff;
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 	OpenLogCalled = 0;
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 	/* if the LogFile is invalid it can not be closed */
4697c478bd9Sstevel@tonic-gate 	if (LogFileInvalid)
4707c478bd9Sstevel@tonic-gate 		return;
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate 	/*
4737c478bd9Sstevel@tonic-gate 	 * if the fstat(2) fails or the st_rdev has changed
4747c478bd9Sstevel@tonic-gate 	 * then we can not close the file
4757c478bd9Sstevel@tonic-gate 	 */
4767c478bd9Sstevel@tonic-gate 	if ((fstat(LogFile, &statbuff) == 0) && (statbuff.st_rdev == LogDev)) {
4777c478bd9Sstevel@tonic-gate 		(void) close(LogFile);
4787c478bd9Sstevel@tonic-gate 		LogFile = -1;
4797c478bd9Sstevel@tonic-gate 		LogStat = 0;
4807c478bd9Sstevel@tonic-gate 	}
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate /*
4847c478bd9Sstevel@tonic-gate  * SETLOGMASK -- set the log mask level
4857c478bd9Sstevel@tonic-gate  */
4867c478bd9Sstevel@tonic-gate int
setlogmask(int pmask)4877c478bd9Sstevel@tonic-gate setlogmask(int pmask)
4887c478bd9Sstevel@tonic-gate {
4897c478bd9Sstevel@tonic-gate 	int omask = 0;
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate 	omask = LogMask;
4927c478bd9Sstevel@tonic-gate 	if (pmask != 0)
4937c478bd9Sstevel@tonic-gate 		LogMask = pmask;
4947c478bd9Sstevel@tonic-gate 	return (omask);
4957c478bd9Sstevel@tonic-gate }
496