xref: /titanic_44/usr/src/cmd/syslogd/syslogd.c (revision 0ea5e3a571e3da934507bdd32924d11659c70704)
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
5004388ebScasper  * Common Development and Distribution License (the "License").
6004388ebScasper  * 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  */
217c478bd9Sstevel@tonic-gate /*
22004388ebScasper  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  *	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T
287c478bd9Sstevel@tonic-gate  *	All Rights Reserved
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
337c478bd9Sstevel@tonic-gate  * The Regents of the University of California
347c478bd9Sstevel@tonic-gate  * All Rights Reserved
357c478bd9Sstevel@tonic-gate  *
367c478bd9Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
377c478bd9Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
387c478bd9Sstevel@tonic-gate  * contributors.
397c478bd9Sstevel@tonic-gate  */
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate /*
447c478bd9Sstevel@tonic-gate  *  syslogd -- log system messages
457c478bd9Sstevel@tonic-gate  *
467c478bd9Sstevel@tonic-gate  * This program implements a system log. It takes a series of lines.
477c478bd9Sstevel@tonic-gate  * Each line may have a priority, signified as "<n>" as
487c478bd9Sstevel@tonic-gate  * the first characters of the line.  If this is
497c478bd9Sstevel@tonic-gate  * not present, a default priority is used.
507c478bd9Sstevel@tonic-gate  *
517c478bd9Sstevel@tonic-gate  * To kill syslogd, send a signal 15 (terminate).  A signal 1 (hup) will
527c478bd9Sstevel@tonic-gate  * cause it to reconfigure.
537c478bd9Sstevel@tonic-gate  *
547c478bd9Sstevel@tonic-gate  * Defined Constants:
557c478bd9Sstevel@tonic-gate  *
567c478bd9Sstevel@tonic-gate  * MAXLINE -- the maximimum line length that can be handled.
577c478bd9Sstevel@tonic-gate  * DEFUPRI -- the default priority for user messages.
587c478bd9Sstevel@tonic-gate  * DEFSPRI -- the default priority for kernel messages.
597c478bd9Sstevel@tonic-gate  *
607c478bd9Sstevel@tonic-gate  */
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate #include <unistd.h>
637c478bd9Sstevel@tonic-gate #include <note.h>
647c478bd9Sstevel@tonic-gate #include <errno.h>
657c478bd9Sstevel@tonic-gate #include <sys/types.h>
667c478bd9Sstevel@tonic-gate #include <stdio.h>
67004388ebScasper #include <stdio_ext.h>
687c478bd9Sstevel@tonic-gate #include <stdlib.h>
697c478bd9Sstevel@tonic-gate #include <ctype.h>
707c478bd9Sstevel@tonic-gate #include <signal.h>
717c478bd9Sstevel@tonic-gate #include <string.h>
727c478bd9Sstevel@tonic-gate #include <strings.h>
73*0ea5e3a5Sjjj #include <libscf.h>
747c478bd9Sstevel@tonic-gate #include <netconfig.h>
757c478bd9Sstevel@tonic-gate #include <netdir.h>
767c478bd9Sstevel@tonic-gate #include <pwd.h>
777c478bd9Sstevel@tonic-gate #include <sys/socket.h>
787c478bd9Sstevel@tonic-gate #include <tiuser.h>
797c478bd9Sstevel@tonic-gate #include <utmpx.h>
807c478bd9Sstevel@tonic-gate #include <limits.h>
817c478bd9Sstevel@tonic-gate #include <pthread.h>
827c478bd9Sstevel@tonic-gate #include <fcntl.h>
837c478bd9Sstevel@tonic-gate #include <stropts.h>
847c478bd9Sstevel@tonic-gate #include <assert.h>
857c478bd9Sstevel@tonic-gate #include <sys/statvfs.h>
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate #include <sys/param.h>
887c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
897c478bd9Sstevel@tonic-gate #include <sys/syslog.h>
907c478bd9Sstevel@tonic-gate #include <sys/strlog.h>
917c478bd9Sstevel@tonic-gate #include <sys/stat.h>
927c478bd9Sstevel@tonic-gate #include <sys/time.h>
937c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
947c478bd9Sstevel@tonic-gate #include <sys/poll.h>
957c478bd9Sstevel@tonic-gate #include <sys/wait.h>
967c478bd9Sstevel@tonic-gate #include <sys/resource.h>
977c478bd9Sstevel@tonic-gate #include <sys/mman.h>
987c478bd9Sstevel@tonic-gate #include <sys/note.h>
997c478bd9Sstevel@tonic-gate #include <door.h>
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate #include <wchar.h>
1027c478bd9Sstevel@tonic-gate #include <locale.h>
1037c478bd9Sstevel@tonic-gate #include <stdarg.h>
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate #include "dataq.h"
1067c478bd9Sstevel@tonic-gate #include "conf.h"
1077c478bd9Sstevel@tonic-gate #include "syslogd.h"
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate #define	DOORFILE		"/var/run/syslog_door"
1107c478bd9Sstevel@tonic-gate #define	RELATIVE_DOORFILE	"../var/run/syslog_door"
1117c478bd9Sstevel@tonic-gate #define	OLD_DOORFILE		"/etc/.syslog_door"
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate #define	PIDFILE			"/var/run/syslog.pid"
1147c478bd9Sstevel@tonic-gate #define	RELATIVE_PIDFILE	"../var/run/syslog.pid"
1157c478bd9Sstevel@tonic-gate #define	OLD_PIDFILE		"/etc/syslog.pid"
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate static char		*Version = "%I%";
1187c478bd9Sstevel@tonic-gate static char		*LogName = "/dev/log";
1197c478bd9Sstevel@tonic-gate static char		*ConfFile = "/etc/syslog.conf";
1207c478bd9Sstevel@tonic-gate static char		ctty[] = "/dev/console";
1217c478bd9Sstevel@tonic-gate static char		sysmsg[] = "/dev/sysmsg";
1227c478bd9Sstevel@tonic-gate static int		DoorFd = -1;
1237c478bd9Sstevel@tonic-gate static int		DoorCreated = 0;
1247c478bd9Sstevel@tonic-gate static int		PidfileCreated = 0;
1257c478bd9Sstevel@tonic-gate static char		*DoorFileName = DOORFILE;
1267c478bd9Sstevel@tonic-gate static char		*PidFileName = PIDFILE;
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate /*
1297c478bd9Sstevel@tonic-gate  * configuration file directives
1307c478bd9Sstevel@tonic-gate  */
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate static struct code	PriNames[] = {
1337c478bd9Sstevel@tonic-gate 	"panic",	LOG_EMERG,
1347c478bd9Sstevel@tonic-gate 	"emerg",	LOG_EMERG,
1357c478bd9Sstevel@tonic-gate 	"alert",	LOG_ALERT,
1367c478bd9Sstevel@tonic-gate 	"crit",		LOG_CRIT,
1377c478bd9Sstevel@tonic-gate 	"err",		LOG_ERR,
1387c478bd9Sstevel@tonic-gate 	"error",	LOG_ERR,
1397c478bd9Sstevel@tonic-gate 	"warn",		LOG_WARNING,
1407c478bd9Sstevel@tonic-gate 	"warning",	LOG_WARNING,
1417c478bd9Sstevel@tonic-gate 	"notice",	LOG_NOTICE,
1427c478bd9Sstevel@tonic-gate 	"info",		LOG_INFO,
1437c478bd9Sstevel@tonic-gate 	"debug",	LOG_DEBUG,
1447c478bd9Sstevel@tonic-gate 	"none",		NOPRI,
1457c478bd9Sstevel@tonic-gate 	NULL,		-1
1467c478bd9Sstevel@tonic-gate };
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate static struct code	FacNames[] = {
1497c478bd9Sstevel@tonic-gate 	"kern",		LOG_KERN,
1507c478bd9Sstevel@tonic-gate 	"user",		LOG_USER,
1517c478bd9Sstevel@tonic-gate 	"mail",		LOG_MAIL,
1527c478bd9Sstevel@tonic-gate 	"daemon",	LOG_DAEMON,
1537c478bd9Sstevel@tonic-gate 	"auth",		LOG_AUTH,
1547c478bd9Sstevel@tonic-gate 	"security",	LOG_AUTH,
1557c478bd9Sstevel@tonic-gate 	"mark",		LOG_MARK,
1567c478bd9Sstevel@tonic-gate 	"syslog",	LOG_SYSLOG,
1577c478bd9Sstevel@tonic-gate 	"lpr",		LOG_LPR,
1587c478bd9Sstevel@tonic-gate 	"news",		LOG_NEWS,
1597c478bd9Sstevel@tonic-gate 	"uucp",		LOG_UUCP,
1607c478bd9Sstevel@tonic-gate 	"audit",	LOG_AUDIT,
1617c478bd9Sstevel@tonic-gate 	"cron",		LOG_CRON,
1627c478bd9Sstevel@tonic-gate 	"local0",	LOG_LOCAL0,
1637c478bd9Sstevel@tonic-gate 	"local1",	LOG_LOCAL1,
1647c478bd9Sstevel@tonic-gate 	"local2",	LOG_LOCAL2,
1657c478bd9Sstevel@tonic-gate 	"local3",	LOG_LOCAL3,
1667c478bd9Sstevel@tonic-gate 	"local4",	LOG_LOCAL4,
1677c478bd9Sstevel@tonic-gate 	"local5",	LOG_LOCAL5,
1687c478bd9Sstevel@tonic-gate 	"local6",	LOG_LOCAL6,
1697c478bd9Sstevel@tonic-gate 	"local7",	LOG_LOCAL7,
1707c478bd9Sstevel@tonic-gate 	NULL,		-1
1717c478bd9Sstevel@tonic-gate };
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate static char		*TypeNames[7] = {
1747c478bd9Sstevel@tonic-gate 	"UNUSED",	"FILE",		"TTY",		"CONSOLE",
1757c478bd9Sstevel@tonic-gate 	"FORW",		"USERS",	"WALL"
1767c478bd9Sstevel@tonic-gate };
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate /*
1797c478bd9Sstevel@tonic-gate  * we allocate our own thread stacks so we can create them
1807c478bd9Sstevel@tonic-gate  * without the MAP_NORESERVE option. We need to be sure
1817c478bd9Sstevel@tonic-gate  * we have stack space even if the machine runs out of swap
1827c478bd9Sstevel@tonic-gate  */
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate #define	DEFAULT_STACKSIZE (100 * 1024)  /* 100 k stack */
1857c478bd9Sstevel@tonic-gate #define	DEFAULT_REDZONESIZE (8 * 1024)	/* 8k redzone */
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate static pthread_mutex_t wmp = PTHREAD_MUTEX_INITIALIZER;	/* wallmsg lock */
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate static pthread_mutex_t cft = PTHREAD_MUTEX_INITIALIZER;
1907c478bd9Sstevel@tonic-gate static int conf_threads = 0;
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate static pthread_mutex_t hup_lock = PTHREAD_MUTEX_INITIALIZER;
1937c478bd9Sstevel@tonic-gate static pthread_cond_t hup_done = PTHREAD_COND_INITIALIZER;
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate static pthread_mutex_t logerror_lock = PTHREAD_MUTEX_INITIALIZER;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate #define	HUP_ACCEPTABLE		0x0000	/* can start SIGHUP process */
1987c478bd9Sstevel@tonic-gate #define	HUP_INPROGRESS		0x0001	/* SIGHUP process in progress */
1997c478bd9Sstevel@tonic-gate #define	HUP_COMPLETED		0x0002	/* SIGHUP process completed */
2007c478bd9Sstevel@tonic-gate #define	HUP_SUSP_LOGMSG_REQD	0x1000	/* request to suspend */
2017c478bd9Sstevel@tonic-gate #define	HUP_LOGMSG_SUSPENDED	0x2000	/* logmsg is suspended */
2027c478bd9Sstevel@tonic-gate static int hup_state = HUP_ACCEPTABLE;
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate static size_t stacksize;		/* thread stack size */
2057c478bd9Sstevel@tonic-gate static size_t redzonesize;		/* thread stack redzone size */
2067c478bd9Sstevel@tonic-gate static char *stack_ptr;			/* ptr to allocated stacks */
2077c478bd9Sstevel@tonic-gate static char *cstack_ptr;		/* ptr to conf_thr stacks */
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate static time_t start_time;
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate static pthread_t sys_thread;		/* queues messages from us */
2127c478bd9Sstevel@tonic-gate static pthread_t net_thread;		/* queues messages from the net */
2137c478bd9Sstevel@tonic-gate static pthread_t log_thread;		/* message processing thread */
2147c478bd9Sstevel@tonic-gate static pthread_t hnl_thread;		/* hostname lookup thread */
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate static dataq_t inputq;			/* the input queue */
2177c478bd9Sstevel@tonic-gate static dataq_t tmpq;			/* temporary queue for err msg */
2187c478bd9Sstevel@tonic-gate static dataq_t hnlq;			/* hostname lookup queue */
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate static struct filed fallback[2];
2217c478bd9Sstevel@tonic-gate static struct filed *Files;
2227c478bd9Sstevel@tonic-gate static int nlogs;
2237c478bd9Sstevel@tonic-gate static int Debug;			/* debug flag */
2247c478bd9Sstevel@tonic-gate static host_list_t LocalHostName;	/* our hostname */
2257c478bd9Sstevel@tonic-gate static host_list_t NullHostName;	/* in case of lookup failure */
2267c478bd9Sstevel@tonic-gate static int debuglev = 1;		/* debug print level */
2277c478bd9Sstevel@tonic-gate static int interrorlog;			/* internal error logging */
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate static int MarkInterval = 20;		/* interval between marks (mins) */
2307c478bd9Sstevel@tonic-gate static int Marking = 0;			/* non-zero if marking some file */
2317c478bd9Sstevel@tonic-gate static int Ninputs = 0;			/* number of network inputs */
2327c478bd9Sstevel@tonic-gate static int curalarm = 0;		/* current timeout value (secs) */
2337c478bd9Sstevel@tonic-gate static int sys_msg_count = 0;		/* total msgs rcvd from local log */
2347c478bd9Sstevel@tonic-gate static int sys_init_msg_count = 0;	/* initially received */
2357c478bd9Sstevel@tonic-gate static int net_msg_count = 0;		/* total msgs rcvd from net */
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate static struct pollfd Pfd;		/* Pollfd for local the log device */
2387c478bd9Sstevel@tonic-gate static struct pollfd *Nfd;		/* Array of pollfds for udp ports */
2397c478bd9Sstevel@tonic-gate static struct netconfig *Ncf;
2407c478bd9Sstevel@tonic-gate static struct netbuf **Myaddrs;
2417c478bd9Sstevel@tonic-gate static struct t_unitdata **Udp;
2427c478bd9Sstevel@tonic-gate static struct t_uderr **Errp;
2437c478bd9Sstevel@tonic-gate static int turnoff = 0;
2447c478bd9Sstevel@tonic-gate static int shutting_down;
2457c478bd9Sstevel@tonic-gate 
246293d1fc4Spd155743 static struct hostname_cache **hnc_cache;
2477c478bd9Sstevel@tonic-gate static pthread_mutex_t hnc_mutex = PTHREAD_MUTEX_INITIALIZER;
2487c478bd9Sstevel@tonic-gate static size_t hnc_size = DEF_HNC_SIZE;
2497c478bd9Sstevel@tonic-gate static unsigned int hnc_ttl = DEF_HNC_TTL;
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate #define	DPRINT0(d, m)		if ((Debug) && debuglev >= (d)) \
2527c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, m)
2537c478bd9Sstevel@tonic-gate #define	DPRINT1(d, m, a)	if ((Debug) && debuglev >= (d)) \
2547c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, m, a)
2557c478bd9Sstevel@tonic-gate #define	DPRINT2(d, m, a, b)	if ((Debug) && debuglev >= (d)) \
2567c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, m, a, b)
2577c478bd9Sstevel@tonic-gate #define	DPRINT3(d, m, a, b, c)	if ((Debug) && debuglev >= (d)) \
2587c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, m, a, b, c)
2597c478bd9Sstevel@tonic-gate #define	DPRINT4(d, m, a, b, c, e)	if ((Debug) && debuglev >= (d)) \
2607c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, m, a, b, c, e)
2617c478bd9Sstevel@tonic-gate #define	MALLOC_FAIL(x)	\
2627c478bd9Sstevel@tonic-gate 		logerror("malloc failed: " x)
2637c478bd9Sstevel@tonic-gate #define	MALLOC_FAIL_EXIT	\
2647c478bd9Sstevel@tonic-gate 		logerror("malloc failed - fatal"); \
2657c478bd9Sstevel@tonic-gate 		exit(1)
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate #define	MAILCMD "mailx -s \"syslogd shut down\" root"
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate /*
2717c478bd9Sstevel@tonic-gate  * Number of seconds to wait before giving up on threads that won't
2727c478bd9Sstevel@tonic-gate  * shutdown: (that's right, 10 minutes!)
2737c478bd9Sstevel@tonic-gate  */
2747c478bd9Sstevel@tonic-gate #define	LOOP_MAX	(10 * 60)
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate /*
2777c478bd9Sstevel@tonic-gate  * Interval(sec) to check the status of output queue while processing
2787c478bd9Sstevel@tonic-gate  * HUP signal.
2797c478bd9Sstevel@tonic-gate  */
2807c478bd9Sstevel@tonic-gate #define	LOOP_INTERVAL	(15)
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate int
2837c478bd9Sstevel@tonic-gate main(int argc, char **argv)
2847c478bd9Sstevel@tonic-gate {
2857c478bd9Sstevel@tonic-gate 	int i;
2867c478bd9Sstevel@tonic-gate 	char *pstr;
2877c478bd9Sstevel@tonic-gate 	int sig, fd;
2887c478bd9Sstevel@tonic-gate 	int tflag = 0, Tflag = 0;
2897c478bd9Sstevel@tonic-gate 	sigset_t sigs, allsigs;
2907c478bd9Sstevel@tonic-gate 	struct rlimit rlim;
2917c478bd9Sstevel@tonic-gate 	char *debugstr;
2927c478bd9Sstevel@tonic-gate 	int mcount = 0;
2937c478bd9Sstevel@tonic-gate 	struct sigaction act;
2947c478bd9Sstevel@tonic-gate 	pthread_t mythreadno = 0;
2957c478bd9Sstevel@tonic-gate 	char cbuf [30];
2967c478bd9Sstevel@tonic-gate 	struct stat sb;
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate #ifdef DEBUG
2997c478bd9Sstevel@tonic-gate #define	DEBUGDIR "/var/tmp"
3007c478bd9Sstevel@tonic-gate 	if (chdir(DEBUGDIR))
3017c478bd9Sstevel@tonic-gate 		DPRINT2(1, "main(%u): Unable to cd to %s\n", mythreadno,
3027c478bd9Sstevel@tonic-gate 			DEBUGDIR);
3037c478bd9Sstevel@tonic-gate #endif /* DEBUG */
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 	if ((debugstr = getenv("SYSLOGD_DEBUG")) != NULL)
3087c478bd9Sstevel@tonic-gate 		if ((debuglev = atoi(debugstr)) == 0)
3097c478bd9Sstevel@tonic-gate 			debuglev = 1;
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate #if ! defined(TEXT_DOMAIN)	/* should be defined by cc -D */
3127c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
3137c478bd9Sstevel@tonic-gate #endif
3147c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate 	(void) time(&start_time);
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 	if (lstat("/var/run", &sb) != 0 || !(S_ISDIR(sb.st_mode))) {
3197c478bd9Sstevel@tonic-gate 		DoorFileName = OLD_DOORFILE;
3207c478bd9Sstevel@tonic-gate 		PidFileName  = OLD_PIDFILE;
3217c478bd9Sstevel@tonic-gate 	}
3227c478bd9Sstevel@tonic-gate 
323*0ea5e3a5Sjjj 	properties();
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate 	while ((i = getopt(argc, argv, "df:p:m:tT")) != EOF) {
3267c478bd9Sstevel@tonic-gate 		switch (i) {
3277c478bd9Sstevel@tonic-gate 		case 'f':		/* configuration file */
3287c478bd9Sstevel@tonic-gate 			ConfFile = optarg;
3297c478bd9Sstevel@tonic-gate 			break;
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 		case 'd':		/* debug */
3327c478bd9Sstevel@tonic-gate 			Debug++;
3337c478bd9Sstevel@tonic-gate 			break;
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 		case 'p':		/* path */
3367c478bd9Sstevel@tonic-gate 			LogName = optarg;
3377c478bd9Sstevel@tonic-gate 			break;
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 		case 'm':		/* mark interval */
3407c478bd9Sstevel@tonic-gate 			for (pstr = optarg; *pstr; pstr++) {
3417c478bd9Sstevel@tonic-gate 				if (! (isdigit(*pstr))) {
3427c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
3437c478bd9Sstevel@tonic-gate 						"Illegal interval\n");
3447c478bd9Sstevel@tonic-gate 					usage();
3457c478bd9Sstevel@tonic-gate 				}
3467c478bd9Sstevel@tonic-gate 			}
3477c478bd9Sstevel@tonic-gate 			MarkInterval = atoi(optarg);
3487c478bd9Sstevel@tonic-gate 			if (MarkInterval < 1 || MarkInterval > INT_MAX) {
3497c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
3507c478bd9Sstevel@tonic-gate 					"Interval must be between 1 and %d\n",
3517c478bd9Sstevel@tonic-gate 					INT_MAX);
3527c478bd9Sstevel@tonic-gate 				usage();
3537c478bd9Sstevel@tonic-gate 			}
3547c478bd9Sstevel@tonic-gate 			break;
3557c478bd9Sstevel@tonic-gate 		case 't':		/* turn off remote reception */
3567c478bd9Sstevel@tonic-gate 			tflag++;
3577c478bd9Sstevel@tonic-gate 			turnoff++;
3587c478bd9Sstevel@tonic-gate 			break;
3597c478bd9Sstevel@tonic-gate 		case 'T':		/* turn on remote reception */
3607c478bd9Sstevel@tonic-gate 			Tflag++;
3617c478bd9Sstevel@tonic-gate 			turnoff = 0;
3627c478bd9Sstevel@tonic-gate 			break;
3637c478bd9Sstevel@tonic-gate 		default:
3647c478bd9Sstevel@tonic-gate 			usage();
3657c478bd9Sstevel@tonic-gate 		}
3667c478bd9Sstevel@tonic-gate 	}
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	if (optind < argc)
3697c478bd9Sstevel@tonic-gate 		usage();
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	if (tflag && Tflag) {
3727c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "specify only one of -t and -T\n");
3737c478bd9Sstevel@tonic-gate 		usage();
3747c478bd9Sstevel@tonic-gate 	}
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 	/*
3777c478bd9Sstevel@tonic-gate 	 * close all fd's except 0-2
3787c478bd9Sstevel@tonic-gate 	 */
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 	closefrom(3);
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 	if (!Debug) {
3837c478bd9Sstevel@tonic-gate 		if (fork())
3847c478bd9Sstevel@tonic-gate 			return (0);
3857c478bd9Sstevel@tonic-gate 		(void) close(0);
3867c478bd9Sstevel@tonic-gate 		(void) open("/", 0);
3877c478bd9Sstevel@tonic-gate 		(void) dup2(0, 1);
3887c478bd9Sstevel@tonic-gate 		(void) dup2(0, 2);
3897c478bd9Sstevel@tonic-gate 		untty();
3907c478bd9Sstevel@tonic-gate 	}
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	if (Debug) {
3937c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
3947c478bd9Sstevel@tonic-gate 	}
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	/*
3977c478bd9Sstevel@tonic-gate 	 * DO NOT call logerror() until tmpq is initialized.
3987c478bd9Sstevel@tonic-gate 	 */
3997c478bd9Sstevel@tonic-gate 	disable_errorlog();
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	/*
4027c478bd9Sstevel@tonic-gate 	 * ensure that file descriptor limit is "high enough"
4037c478bd9Sstevel@tonic-gate 	 */
4047c478bd9Sstevel@tonic-gate 	(void) getrlimit(RLIMIT_NOFILE, &rlim);
4057c478bd9Sstevel@tonic-gate 	if (rlim.rlim_cur < rlim.rlim_max)
4067c478bd9Sstevel@tonic-gate 		rlim.rlim_cur = rlim.rlim_max;
4077c478bd9Sstevel@tonic-gate 	if (setrlimit(RLIMIT_NOFILE, &rlim) < 0)
4087c478bd9Sstevel@tonic-gate 		logerror("Unable to increase file descriptor limit.");
409004388ebScasper 	(void) enable_extended_FILE_stdio(-1, -1);
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 	/* block all signals from all threads initially */
4127c478bd9Sstevel@tonic-gate 	(void) sigfillset(&allsigs);
4137c478bd9Sstevel@tonic-gate 	(void) pthread_sigmask(SIG_BLOCK, &allsigs, NULL);
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	DPRINT2(1, "main(%u): Started at time %s", mythreadno,
4167c478bd9Sstevel@tonic-gate 		ctime_r(&start_time, cbuf));
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	init();			/* read configuration, start threads */
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 	DPRINT1(1, "main(%u): off & running....\n", mythreadno);
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate 	/* now set up to catch signals we care about */
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&sigs);
4257c478bd9Sstevel@tonic-gate 	(void) sigaddset(&sigs, SIGHUP);	/* reconfigure */
4267c478bd9Sstevel@tonic-gate 	(void) sigaddset(&sigs, SIGALRM);	/* mark & flush timer */
4277c478bd9Sstevel@tonic-gate 	(void) sigaddset(&sigs, SIGTERM);	/* exit */
4287c478bd9Sstevel@tonic-gate 	(void) sigaddset(&sigs, SIGINT);	/* exit if debugging */
4297c478bd9Sstevel@tonic-gate 	(void) sigaddset(&sigs, SIGQUIT);	/* exit if debugging */
4307c478bd9Sstevel@tonic-gate 	(void) sigaddset(&sigs, SIGPIPE);	/* catch & discard */
4317c478bd9Sstevel@tonic-gate 	(void) sigaddset(&sigs, SIGUSR1);	/* dump debug stats */
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 	/*
4347c478bd9Sstevel@tonic-gate 	 * We must set up to catch these signals, even though sigwait
4357c478bd9Sstevel@tonic-gate 	 * will get them before the isr does.  Setting SA_SIGINFO ensures
4367c478bd9Sstevel@tonic-gate 	 * that signals will be enqueued.
4377c478bd9Sstevel@tonic-gate 	 */
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
4407c478bd9Sstevel@tonic-gate 	act.sa_sigaction = signull;
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGHUP, &act, NULL);
4437c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGALRM, &act, NULL);
4447c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGTERM, &act, NULL);
4457c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGINT, &act, NULL);
4467c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGQUIT, &act, NULL);
4477c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGPIPE, &act, NULL);
4487c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGUSR1, &act, NULL);
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate 	/* we now turn into the signal handling thread */
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	DPRINT1(2, "main(%u): now handling signals\n", mythreadno);
4537c478bd9Sstevel@tonic-gate 	for (;;) {
4547c478bd9Sstevel@tonic-gate 		(void) sigwait(&sigs, &sig);
4557c478bd9Sstevel@tonic-gate 		DPRINT2(2, "main(%u): received signal %d\n", mythreadno, sig);
4567c478bd9Sstevel@tonic-gate 		switch (sig) {
4577c478bd9Sstevel@tonic-gate 		case SIGALRM:
4587c478bd9Sstevel@tonic-gate 			DPRINT1(1, "main(%u): Got SIGALRM\n",
4597c478bd9Sstevel@tonic-gate 				mythreadno);
4607c478bd9Sstevel@tonic-gate 			flushmsg(NOCOPY);
4617c478bd9Sstevel@tonic-gate 			if (Marking && (++mcount % MARKCOUNT == 0)) {
4627c478bd9Sstevel@tonic-gate 				if (logmymsg(LOG_INFO, "-- MARK --",
4637c478bd9Sstevel@tonic-gate 					ADDDATE|MARK|NOCOPY, 0) == -1) {
4647c478bd9Sstevel@tonic-gate 					MALLOC_FAIL(
4657c478bd9Sstevel@tonic-gate 						"dropping MARK message");
4667c478bd9Sstevel@tonic-gate 				}
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 				mcount = 0;
4697c478bd9Sstevel@tonic-gate 			}
4707c478bd9Sstevel@tonic-gate 			curalarm = MarkInterval * 60 / MARKCOUNT;
4717c478bd9Sstevel@tonic-gate 			(void) alarm((unsigned)curalarm);
4727c478bd9Sstevel@tonic-gate 			DPRINT2(2, "main(%u): Next alarm in %d "
4737c478bd9Sstevel@tonic-gate 				"seconds\n", mythreadno, curalarm);
4747c478bd9Sstevel@tonic-gate 			break;
4757c478bd9Sstevel@tonic-gate 		case SIGHUP:
4767c478bd9Sstevel@tonic-gate 			DPRINT1(1, "main(%u): got SIGHUP - "
4777c478bd9Sstevel@tonic-gate 				"reconfiguring\n", mythreadno);
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 			reconfigure();
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 			DPRINT1(1, "main(%u): done processing SIGHUP\n",
4827c478bd9Sstevel@tonic-gate 				mythreadno);
4837c478bd9Sstevel@tonic-gate 			break;
4847c478bd9Sstevel@tonic-gate 		case SIGQUIT:
4857c478bd9Sstevel@tonic-gate 		case SIGINT:
4867c478bd9Sstevel@tonic-gate 			if (!Debug) {
4877c478bd9Sstevel@tonic-gate 				/* allow these signals if debugging */
4887c478bd9Sstevel@tonic-gate 				break;
4897c478bd9Sstevel@tonic-gate 			}
4907c478bd9Sstevel@tonic-gate 			/* FALLTHROUGH */
4917c478bd9Sstevel@tonic-gate 		case SIGTERM:
4927c478bd9Sstevel@tonic-gate 			DPRINT2(1, "main(%u): going down on signal %d\n",
4937c478bd9Sstevel@tonic-gate 				mythreadno, sig);
4947c478bd9Sstevel@tonic-gate 			(void) alarm(0);
4957c478bd9Sstevel@tonic-gate 			flushmsg(0);
4967c478bd9Sstevel@tonic-gate 			errno = 0;
4977c478bd9Sstevel@tonic-gate 			t_errno = 0;
4987c478bd9Sstevel@tonic-gate 			logerror("going down on signal %d", sig);
4997c478bd9Sstevel@tonic-gate 			disable_errorlog();	/* force msg to console */
5007c478bd9Sstevel@tonic-gate 			(void) shutdown_msg();	/* stop threads */
5017c478bd9Sstevel@tonic-gate 			shutdown_input();
5027c478bd9Sstevel@tonic-gate 			close_door();
5037c478bd9Sstevel@tonic-gate 			delete_doorfiles();
5047c478bd9Sstevel@tonic-gate 			return (0);
5057c478bd9Sstevel@tonic-gate 			break;
5067c478bd9Sstevel@tonic-gate 		case SIGUSR1:			/* secret debug dump mode */
5077c478bd9Sstevel@tonic-gate 			/* if in debug mode, use stdout */
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate 			if (Debug) {
5107c478bd9Sstevel@tonic-gate 				dumpstats(STDOUT_FILENO);
5117c478bd9Sstevel@tonic-gate 				break;
5127c478bd9Sstevel@tonic-gate 			}
5137c478bd9Sstevel@tonic-gate 			/* otherwise dump to a debug file */
5147c478bd9Sstevel@tonic-gate 			if ((fd = open(DEBUGFILE,
5157c478bd9Sstevel@tonic-gate 				(O_WRONLY|O_CREAT|O_TRUNC|O_EXCL),
5167c478bd9Sstevel@tonic-gate 					0644)) < 0)
5177c478bd9Sstevel@tonic-gate 				break;
5187c478bd9Sstevel@tonic-gate 			dumpstats(fd);
5197c478bd9Sstevel@tonic-gate 			(void) close(fd);
5207c478bd9Sstevel@tonic-gate 			break;
5217c478bd9Sstevel@tonic-gate 		default:
5227c478bd9Sstevel@tonic-gate 			DPRINT2(2, "main(%u): unexpected signal %d\n",
5237c478bd9Sstevel@tonic-gate 				mythreadno, sig);
5247c478bd9Sstevel@tonic-gate 			break;
5257c478bd9Sstevel@tonic-gate 		}
5267c478bd9Sstevel@tonic-gate 	}
5277c478bd9Sstevel@tonic-gate }
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate /*
5307c478bd9Sstevel@tonic-gate  * Attempts to open the local log device
5317c478bd9Sstevel@tonic-gate  * and return a file descriptor.
5327c478bd9Sstevel@tonic-gate  */
5337c478bd9Sstevel@tonic-gate static int
5347c478bd9Sstevel@tonic-gate openklog(char *name, int mode)
5357c478bd9Sstevel@tonic-gate {
5367c478bd9Sstevel@tonic-gate 	int fd;
5377c478bd9Sstevel@tonic-gate 	struct strioctl str;
5387c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 	if (Debug) {
5417c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
5427c478bd9Sstevel@tonic-gate 	}
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate 	if ((fd = open(name, mode)) < 0) {
5457c478bd9Sstevel@tonic-gate 		logerror("cannot open %s", name);
5467c478bd9Sstevel@tonic-gate 		DPRINT3(1, "openklog(%u): cannot create %s (%d)\n",
5477c478bd9Sstevel@tonic-gate 			mythreadno, name, errno);
5487c478bd9Sstevel@tonic-gate 		return (-1);
5497c478bd9Sstevel@tonic-gate 	}
5507c478bd9Sstevel@tonic-gate 	str.ic_cmd = I_CONSLOG;
5517c478bd9Sstevel@tonic-gate 	str.ic_timout = 0;
5527c478bd9Sstevel@tonic-gate 	str.ic_len = 0;
5537c478bd9Sstevel@tonic-gate 	str.ic_dp = NULL;
5547c478bd9Sstevel@tonic-gate 	if (ioctl(fd, I_STR, &str) < 0) {
5557c478bd9Sstevel@tonic-gate 		logerror("cannot register to log console messages");
5567c478bd9Sstevel@tonic-gate 		DPRINT2(1, "openklog(%u): cannot register to log "
5577c478bd9Sstevel@tonic-gate 			"console messages (%d)\n", mythreadno, errno);
5587c478bd9Sstevel@tonic-gate 		return (-1);
5597c478bd9Sstevel@tonic-gate 	}
5607c478bd9Sstevel@tonic-gate 	return (fd);
5617c478bd9Sstevel@tonic-gate }
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate /*
5657c478bd9Sstevel@tonic-gate  * Open the log device, and pull up all pending messages.
5667c478bd9Sstevel@tonic-gate  */
5677c478bd9Sstevel@tonic-gate static void
5687c478bd9Sstevel@tonic-gate prepare_sys_poll()
5697c478bd9Sstevel@tonic-gate {
5707c478bd9Sstevel@tonic-gate 	int nfds, funix;
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 	if ((funix = openklog(LogName, O_RDONLY)) < 0) {
5737c478bd9Sstevel@tonic-gate 		logerror("can't open kernel log device - fatal");
5747c478bd9Sstevel@tonic-gate 		exit(1);
5757c478bd9Sstevel@tonic-gate 	}
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate 	Pfd.fd = funix;
5787c478bd9Sstevel@tonic-gate 	Pfd.events = POLLIN;
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate 	for (;;) {
5817c478bd9Sstevel@tonic-gate 		nfds = poll(&Pfd, 1, 0);
5827c478bd9Sstevel@tonic-gate 		if (nfds <= 0) {
5837c478bd9Sstevel@tonic-gate 			if (sys_init_msg_count > 0)
5847c478bd9Sstevel@tonic-gate 				flushmsg(SYNC_FILE);
5857c478bd9Sstevel@tonic-gate 			break;
5867c478bd9Sstevel@tonic-gate 		}
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 		if (Pfd.revents & POLLIN) {
5897c478bd9Sstevel@tonic-gate 			getkmsg(0);
5907c478bd9Sstevel@tonic-gate 		} else if (Pfd.revents & (POLLNVAL|POLLHUP|POLLERR)) {
5917c478bd9Sstevel@tonic-gate 			logerror("kernel log driver poll error");
5927c478bd9Sstevel@tonic-gate 			break;
5937c478bd9Sstevel@tonic-gate 		}
5947c478bd9Sstevel@tonic-gate 	}
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate }
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate /*
5997c478bd9Sstevel@tonic-gate  * this thread listens to the local stream log driver for log messages
6007c478bd9Sstevel@tonic-gate  * generated by this host, formats them, and queues them to the logger
6017c478bd9Sstevel@tonic-gate  * thread.
6027c478bd9Sstevel@tonic-gate  */
6037c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6047c478bd9Sstevel@tonic-gate static void *
6057c478bd9Sstevel@tonic-gate sys_poll(void *ap)
6067c478bd9Sstevel@tonic-gate {
6077c478bd9Sstevel@tonic-gate 	int nfds;
6087c478bd9Sstevel@tonic-gate 	static int klogerrs = 0;
6097c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate 	if (Debug) {
6127c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
6137c478bd9Sstevel@tonic-gate 	}
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 	DPRINT1(1, "sys_poll(%u): sys_thread started\n", mythreadno);
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 	/*
6187c478bd9Sstevel@tonic-gate 	 * Try to process as many messages as we can without blocking on poll.
6197c478bd9Sstevel@tonic-gate 	 * We count such "initial" messages with sys_init_msg_count and
6207c478bd9Sstevel@tonic-gate 	 * enqueue them without the SYNC_FILE flag.  When no more data is
6217c478bd9Sstevel@tonic-gate 	 * waiting on the local log device, we set timeout to INFTIM,
6227c478bd9Sstevel@tonic-gate 	 * clear sys_init_msg_count, and generate a flush message to sync
6237c478bd9Sstevel@tonic-gate 	 * the previously counted initial messages out to disk.
6247c478bd9Sstevel@tonic-gate 	 */
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 	sys_init_msg_count = 0;
6277c478bd9Sstevel@tonic-gate 
6287c478bd9Sstevel@tonic-gate 	for (;;) {
6297c478bd9Sstevel@tonic-gate 		errno = 0;
6307c478bd9Sstevel@tonic-gate 		t_errno = 0;
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate 		nfds = poll(&Pfd, 1, INFTIM);
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate 		if (nfds == 0)
6357c478bd9Sstevel@tonic-gate 			continue;
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate 		if (nfds < 0) {
6387c478bd9Sstevel@tonic-gate 			if (errno != EINTR)
6397c478bd9Sstevel@tonic-gate 				logerror("poll");
6407c478bd9Sstevel@tonic-gate 			continue;
6417c478bd9Sstevel@tonic-gate 		}
6427c478bd9Sstevel@tonic-gate 		if (Pfd.revents & POLLIN) {
6437c478bd9Sstevel@tonic-gate 			getkmsg(INFTIM);
6447c478bd9Sstevel@tonic-gate 		} else {
6457c478bd9Sstevel@tonic-gate 			if (shutting_down) {
6467c478bd9Sstevel@tonic-gate 				pthread_exit(0);
6477c478bd9Sstevel@tonic-gate 			}
6487c478bd9Sstevel@tonic-gate 			if (Pfd.revents & (POLLNVAL|POLLHUP|POLLERR)) {
6497c478bd9Sstevel@tonic-gate 				logerror("kernel log driver poll error");
6507c478bd9Sstevel@tonic-gate 				(void) close(Pfd.fd);
6517c478bd9Sstevel@tonic-gate 				Pfd.fd = -1;
6527c478bd9Sstevel@tonic-gate 			}
6537c478bd9Sstevel@tonic-gate 		}
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate 		while (Pfd.fd == -1 && klogerrs++ < 10) {
6567c478bd9Sstevel@tonic-gate 			Pfd.fd = openklog(LogName, O_RDONLY);
6577c478bd9Sstevel@tonic-gate 		}
6587c478bd9Sstevel@tonic-gate 		if (klogerrs >= 10) {
6597c478bd9Sstevel@tonic-gate 			logerror("can't reopen kernel log device - fatal");
6607c478bd9Sstevel@tonic-gate 			exit(1);
6617c478bd9Sstevel@tonic-gate 		}
6627c478bd9Sstevel@tonic-gate 	}
6637c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
6647c478bd9Sstevel@tonic-gate 	return (NULL);
6657c478bd9Sstevel@tonic-gate }
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate /*
6687c478bd9Sstevel@tonic-gate  * Pull up one message from log driver.
6697c478bd9Sstevel@tonic-gate  */
6707c478bd9Sstevel@tonic-gate static void
6717c478bd9Sstevel@tonic-gate getkmsg(int timeout)
6727c478bd9Sstevel@tonic-gate {
6737c478bd9Sstevel@tonic-gate 	int flags = 0, i;
6747c478bd9Sstevel@tonic-gate 	char *lastline;
6757c478bd9Sstevel@tonic-gate 	struct strbuf ctl, dat;
6767c478bd9Sstevel@tonic-gate 	struct log_ctl hdr;
6777c478bd9Sstevel@tonic-gate 	char buf[MAXLINE+1];
6787c478bd9Sstevel@tonic-gate 	size_t buflen;
6797c478bd9Sstevel@tonic-gate 	size_t len;
6807c478bd9Sstevel@tonic-gate 	char tmpbuf[MAXLINE+1];
6817c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate 	if (Debug) {
6847c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
6857c478bd9Sstevel@tonic-gate 	}
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate 	dat.maxlen = MAXLINE;
6887c478bd9Sstevel@tonic-gate 	dat.buf = buf;
6897c478bd9Sstevel@tonic-gate 	ctl.maxlen = sizeof (struct log_ctl);
6907c478bd9Sstevel@tonic-gate 	ctl.buf = (caddr_t)&hdr;
6917c478bd9Sstevel@tonic-gate 
6927c478bd9Sstevel@tonic-gate 	while ((i = getmsg(Pfd.fd, &ctl, &dat, &flags)) == MOREDATA) {
6937c478bd9Sstevel@tonic-gate 		lastline = &dat.buf[dat.len];
6947c478bd9Sstevel@tonic-gate 		*lastline = '\0';
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate 		DPRINT2(5, "sys_poll:(%u): getmsg: dat.len = %d\n",
6977c478bd9Sstevel@tonic-gate 			mythreadno, dat.len);
6987c478bd9Sstevel@tonic-gate 		buflen = strlen(buf);
6997c478bd9Sstevel@tonic-gate 		len = findnl_bkwd(buf, buflen);
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate 		(void) memcpy(tmpbuf, buf, len);
7027c478bd9Sstevel@tonic-gate 		tmpbuf[len] = '\0';
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 		/*
7057c478bd9Sstevel@tonic-gate 		 * Format sys will enqueue the log message.
7067c478bd9Sstevel@tonic-gate 		 * Set the sync flag if timeout != 0, which
7077c478bd9Sstevel@tonic-gate 		 * means that we're done handling all the
7087c478bd9Sstevel@tonic-gate 		 * initial messages ready during startup.
7097c478bd9Sstevel@tonic-gate 		 */
7107c478bd9Sstevel@tonic-gate 		if (timeout == 0) {
7117c478bd9Sstevel@tonic-gate 			formatsys(&hdr, tmpbuf, 0);
7127c478bd9Sstevel@tonic-gate 			sys_init_msg_count++;
7137c478bd9Sstevel@tonic-gate 		} else {
7147c478bd9Sstevel@tonic-gate 			formatsys(&hdr, tmpbuf, 1);
7157c478bd9Sstevel@tonic-gate 		}
7167c478bd9Sstevel@tonic-gate 		sys_msg_count++;
7177c478bd9Sstevel@tonic-gate 
7187c478bd9Sstevel@tonic-gate 		if (len != buflen) {
7197c478bd9Sstevel@tonic-gate 			/* If anything remains in buf */
7207c478bd9Sstevel@tonic-gate 			size_t remlen;
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate 			if (buf[len] == '\n') {
7237c478bd9Sstevel@tonic-gate 				/* skip newline */
7247c478bd9Sstevel@tonic-gate 				len++;
7257c478bd9Sstevel@tonic-gate 			}
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate 			/*
7287c478bd9Sstevel@tonic-gate 			 *  Move the remaining bytes to
7297c478bd9Sstevel@tonic-gate 			 * the beginnning of buf.
7307c478bd9Sstevel@tonic-gate 			 */
7317c478bd9Sstevel@tonic-gate 
7327c478bd9Sstevel@tonic-gate 			remlen = buflen - len;
7337c478bd9Sstevel@tonic-gate 			(void) memcpy(buf, &buf[len], remlen);
7347c478bd9Sstevel@tonic-gate 			dat.maxlen = MAXLINE - remlen;
7357c478bd9Sstevel@tonic-gate 			dat.buf = &buf[remlen];
7367c478bd9Sstevel@tonic-gate 		} else {
7377c478bd9Sstevel@tonic-gate 			dat.maxlen = MAXLINE;
7387c478bd9Sstevel@tonic-gate 			dat.buf = buf;
7397c478bd9Sstevel@tonic-gate 		}
7407c478bd9Sstevel@tonic-gate 	}
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate 	if (i == 0 && dat.len > 0) {
7437c478bd9Sstevel@tonic-gate 		dat.buf[dat.len] = '\0';
7447c478bd9Sstevel@tonic-gate 		/*
7457c478bd9Sstevel@tonic-gate 		 * Format sys will enqueue the log message.
7467c478bd9Sstevel@tonic-gate 		 * Set the sync flag if timeout != 0, which
7477c478bd9Sstevel@tonic-gate 		 * means that we're done handling all the
7487c478bd9Sstevel@tonic-gate 		 * initial messages ready during startup.
7497c478bd9Sstevel@tonic-gate 		 */
7507c478bd9Sstevel@tonic-gate 		DPRINT2(5, "getkmsg(%u): getmsg: dat.maxlen = %d\n",
7517c478bd9Sstevel@tonic-gate 			mythreadno, dat.maxlen);
7527c478bd9Sstevel@tonic-gate 		DPRINT2(5, "getkmsg(%u): getmsg: dat.len = %d\n",
7537c478bd9Sstevel@tonic-gate 			mythreadno, dat.len);
7547c478bd9Sstevel@tonic-gate 		DPRINT2(5, "getkmsg(%u): getmsg: strlen(dat.buf) = %d\n",
7557c478bd9Sstevel@tonic-gate 			mythreadno, strlen(dat.buf));
7567c478bd9Sstevel@tonic-gate 		DPRINT2(5, "getkmsg(%u): getmsg: dat.buf = \"%s\"\n",
7577c478bd9Sstevel@tonic-gate 			mythreadno, dat.buf);
7587c478bd9Sstevel@tonic-gate 		DPRINT2(5, "getkmsg(%u): buf len = %d\n",
7597c478bd9Sstevel@tonic-gate 			mythreadno, strlen(buf));
7607c478bd9Sstevel@tonic-gate 		if (timeout == 0) {
7617c478bd9Sstevel@tonic-gate 			formatsys(&hdr, buf, 0);
7627c478bd9Sstevel@tonic-gate 			sys_init_msg_count++;
7637c478bd9Sstevel@tonic-gate 		} else {
7647c478bd9Sstevel@tonic-gate 			formatsys(&hdr, buf, 1);
7657c478bd9Sstevel@tonic-gate 		}
7667c478bd9Sstevel@tonic-gate 		sys_msg_count++;
7677c478bd9Sstevel@tonic-gate 	} else if (i < 0 && errno != EINTR) {
7687c478bd9Sstevel@tonic-gate 		if (!shutting_down) {
7697c478bd9Sstevel@tonic-gate 			logerror("kernel log driver read error");
7707c478bd9Sstevel@tonic-gate 		}
7717c478bd9Sstevel@tonic-gate 		(void) close(Pfd.fd);
7727c478bd9Sstevel@tonic-gate 		Pfd.fd = -1;
7737c478bd9Sstevel@tonic-gate 	}
7747c478bd9Sstevel@tonic-gate }
7757c478bd9Sstevel@tonic-gate 
7767c478bd9Sstevel@tonic-gate /*
7777c478bd9Sstevel@tonic-gate  * this thread polls all the network interfaces for syslog messages
7787c478bd9Sstevel@tonic-gate  * forwarded to us, tags them with the hostname they are received
7797c478bd9Sstevel@tonic-gate  * from, and queues them to the logger thread.
7807c478bd9Sstevel@tonic-gate  */
7817c478bd9Sstevel@tonic-gate /*ARGSUSED*/
7827c478bd9Sstevel@tonic-gate static void *
7837c478bd9Sstevel@tonic-gate net_poll(void *ap)
7847c478bd9Sstevel@tonic-gate {
7857c478bd9Sstevel@tonic-gate 	int nfds, i;
7867c478bd9Sstevel@tonic-gate 	int flags = 0;
7877c478bd9Sstevel@tonic-gate 	struct t_unitdata *udp;
7887c478bd9Sstevel@tonic-gate 	struct t_uderr *errp;
7897c478bd9Sstevel@tonic-gate 	char buf[MAXLINE+1];
7907c478bd9Sstevel@tonic-gate 	char *uap;
7917c478bd9Sstevel@tonic-gate 	log_message_t *mp;
7927c478bd9Sstevel@tonic-gate 	host_info_t *hinfo;
7937c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
7947c478bd9Sstevel@tonic-gate 
7957c478bd9Sstevel@tonic-gate 	if (Debug) {
7967c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
7977c478bd9Sstevel@tonic-gate 	}
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate 	DPRINT1(1, "net_poll(%u): net_thread started\n", mythreadno);
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp))
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate 	for (;;) {
8047c478bd9Sstevel@tonic-gate 		errno = 0;
8057c478bd9Sstevel@tonic-gate 		t_errno = 0;
8067c478bd9Sstevel@tonic-gate 		nfds = poll(Nfd, Ninputs, -1);
8077c478bd9Sstevel@tonic-gate 		if (nfds == 0)
8087c478bd9Sstevel@tonic-gate 			continue;
8097c478bd9Sstevel@tonic-gate 
8107c478bd9Sstevel@tonic-gate 		if (nfds < 0) {
8117c478bd9Sstevel@tonic-gate 			if (errno != EINTR)
8127c478bd9Sstevel@tonic-gate 				logerror("poll");
8137c478bd9Sstevel@tonic-gate 			continue;
8147c478bd9Sstevel@tonic-gate 		}
8157c478bd9Sstevel@tonic-gate 		for (i = 0; nfds > 0 && i < Ninputs; i++) {
8167c478bd9Sstevel@tonic-gate 			if ((Nfd[i].revents & POLLIN) == 0) {
8177c478bd9Sstevel@tonic-gate 				if (shutting_down) {
8187c478bd9Sstevel@tonic-gate 					pthread_exit(0);
8197c478bd9Sstevel@tonic-gate 				}
8207c478bd9Sstevel@tonic-gate 				if (Nfd[i].revents &
8217c478bd9Sstevel@tonic-gate 					(POLLNVAL|POLLHUP|POLLERR)) {
8227c478bd9Sstevel@tonic-gate 					logerror("POLLNVAL|POLLHUP|POLLERR");
8237c478bd9Sstevel@tonic-gate 					(void) t_close(Nfd[i].fd);
8247c478bd9Sstevel@tonic-gate 					Nfd[i].fd = -1;
8257c478bd9Sstevel@tonic-gate 					nfds--;
8267c478bd9Sstevel@tonic-gate 				}
8277c478bd9Sstevel@tonic-gate 				continue;
8287c478bd9Sstevel@tonic-gate 			}
8297c478bd9Sstevel@tonic-gate 
8307c478bd9Sstevel@tonic-gate 			udp = Udp[i];
8317c478bd9Sstevel@tonic-gate 			udp->udata.buf = buf;
8327c478bd9Sstevel@tonic-gate 			udp->udata.maxlen = MAXLINE;
8337c478bd9Sstevel@tonic-gate 			udp->udata.len = 0;
8347c478bd9Sstevel@tonic-gate 			flags = 0;
8357c478bd9Sstevel@tonic-gate 			if (t_rcvudata(Nfd[i].fd, udp, &flags) < 0) {
8367c478bd9Sstevel@tonic-gate 				errp = Errp[i];
8377c478bd9Sstevel@tonic-gate 				if (t_errno == TLOOK) {
8387c478bd9Sstevel@tonic-gate 					if (t_rcvuderr(Nfd[i].fd, errp) < 0) {
8397c478bd9Sstevel@tonic-gate 						if (!shutting_down) {
8407c478bd9Sstevel@tonic-gate 							logerror("t_rcvuderr");
8417c478bd9Sstevel@tonic-gate 						}
842*0ea5e3a5Sjjj 						(void) t_close(Nfd[i].fd);
8437c478bd9Sstevel@tonic-gate 						Nfd[i].fd = -1;
8447c478bd9Sstevel@tonic-gate 					}
8457c478bd9Sstevel@tonic-gate 				} else {
8467c478bd9Sstevel@tonic-gate 					if (!shutting_down) {
8477c478bd9Sstevel@tonic-gate 						logerror("t_rcvudata");
8487c478bd9Sstevel@tonic-gate 					}
849*0ea5e3a5Sjjj 					(void) t_close(Nfd[i].fd);
8507c478bd9Sstevel@tonic-gate 					Nfd[i].fd = -1;
8517c478bd9Sstevel@tonic-gate 				}
8527c478bd9Sstevel@tonic-gate 				nfds--;
8537c478bd9Sstevel@tonic-gate 				if (shutting_down) {
8547c478bd9Sstevel@tonic-gate 					pthread_exit(0);
8557c478bd9Sstevel@tonic-gate 				}
8567c478bd9Sstevel@tonic-gate 				continue;
8577c478bd9Sstevel@tonic-gate 			}
8587c478bd9Sstevel@tonic-gate 			nfds--;
8597c478bd9Sstevel@tonic-gate 
8607c478bd9Sstevel@tonic-gate 			if (udp->udata.len == 0) {
8617c478bd9Sstevel@tonic-gate 				if (Debug) {
8627c478bd9Sstevel@tonic-gate 					uap = NULL;
8637c478bd9Sstevel@tonic-gate 					if (udp->addr.len > 0) {
8647c478bd9Sstevel@tonic-gate 						uap = taddr2uaddr(&Ncf[i],
8657c478bd9Sstevel@tonic-gate 							&udp->addr);
8667c478bd9Sstevel@tonic-gate 					}
8677c478bd9Sstevel@tonic-gate 					DPRINT2(1, "net_poll(%u):"
8687c478bd9Sstevel@tonic-gate 						" received empty packet"
8697c478bd9Sstevel@tonic-gate 						" from %s\n", mythreadno,
8707c478bd9Sstevel@tonic-gate 						uap ? uap : "<unknown>");
8717c478bd9Sstevel@tonic-gate 					if (uap)
8727c478bd9Sstevel@tonic-gate 						free(uap);
8737c478bd9Sstevel@tonic-gate 				}
8747c478bd9Sstevel@tonic-gate 				continue;	/* No data */
8757c478bd9Sstevel@tonic-gate 			}
8767c478bd9Sstevel@tonic-gate 			if (udp->addr.len == 0) {
8777c478bd9Sstevel@tonic-gate 				/*
8787c478bd9Sstevel@tonic-gate 				 * The previous message was larger than
8797c478bd9Sstevel@tonic-gate 				 * MAXLINE, and T_MORE should have been set.
8807c478bd9Sstevel@tonic-gate 				 * Further data needs to be discarded as
8817c478bd9Sstevel@tonic-gate 				 * we've already received MAXLINE.
8827c478bd9Sstevel@tonic-gate 				 */
8837c478bd9Sstevel@tonic-gate 				DPRINT1(1, "net_poll(%u): discarding packet "
8847c478bd9Sstevel@tonic-gate 					"exceeds max line size\n", mythreadno);
8857c478bd9Sstevel@tonic-gate 				continue;
8867c478bd9Sstevel@tonic-gate 			}
8877c478bd9Sstevel@tonic-gate 
8887c478bd9Sstevel@tonic-gate 			net_msg_count++;
8897c478bd9Sstevel@tonic-gate 
8907c478bd9Sstevel@tonic-gate 			if ((mp = new_msg()) == NULL) {
8917c478bd9Sstevel@tonic-gate 				MALLOC_FAIL("dropping message from "
8927c478bd9Sstevel@tonic-gate 					"remote");
8937c478bd9Sstevel@tonic-gate 				continue;
8947c478bd9Sstevel@tonic-gate 			}
8957c478bd9Sstevel@tonic-gate 
8967c478bd9Sstevel@tonic-gate 			buf[udp->udata.len] = '\0';
8977c478bd9Sstevel@tonic-gate 			formatnet(&udp->udata, mp);
8987c478bd9Sstevel@tonic-gate 
8997c478bd9Sstevel@tonic-gate 			if (Debug) {
9007c478bd9Sstevel@tonic-gate 				uap = taddr2uaddr(&Ncf[i], &udp->addr);
9017c478bd9Sstevel@tonic-gate 				DPRINT2(1, "net_poll(%u): received message"
9027c478bd9Sstevel@tonic-gate 					" from %s\n", mythreadno,
9037c478bd9Sstevel@tonic-gate 					uap ? uap : "<unknown>");
9047c478bd9Sstevel@tonic-gate 				free(uap);
9057c478bd9Sstevel@tonic-gate 			}
9067c478bd9Sstevel@tonic-gate 			if ((hinfo = malloc(sizeof (*hinfo))) == NULL ||
9077c478bd9Sstevel@tonic-gate 				(hinfo->addr.buf =
9087c478bd9Sstevel@tonic-gate 					malloc(udp->addr.len)) == NULL) {
9097c478bd9Sstevel@tonic-gate 				MALLOC_FAIL("dropping message from "
9107c478bd9Sstevel@tonic-gate 					"remote");
9117c478bd9Sstevel@tonic-gate 				if (hinfo) {
9127c478bd9Sstevel@tonic-gate 					free(hinfo);
9137c478bd9Sstevel@tonic-gate 				}
9147c478bd9Sstevel@tonic-gate 				free_msg(mp);
9157c478bd9Sstevel@tonic-gate 				continue;
9167c478bd9Sstevel@tonic-gate 			}
9177c478bd9Sstevel@tonic-gate 
9187c478bd9Sstevel@tonic-gate 			hinfo->ncp = &Ncf[i];
9197c478bd9Sstevel@tonic-gate 			hinfo->addr.len = udp->addr.len;
9207c478bd9Sstevel@tonic-gate 			(void) memcpy(hinfo->addr.buf, udp->addr.buf,
9217c478bd9Sstevel@tonic-gate 					udp->addr.len);
9227c478bd9Sstevel@tonic-gate 			mp->ptr = hinfo;
9237c478bd9Sstevel@tonic-gate 			if (dataq_enqueue(&hnlq, (void *)mp) == -1) {
9247c478bd9Sstevel@tonic-gate 				MALLOC_FAIL("dropping message from "
9257c478bd9Sstevel@tonic-gate 					"remote");
9267c478bd9Sstevel@tonic-gate 				free_msg(mp);
9277c478bd9Sstevel@tonic-gate 				free(hinfo->addr.buf);
9287c478bd9Sstevel@tonic-gate 				free(hinfo);
9297c478bd9Sstevel@tonic-gate 				continue;
9307c478bd9Sstevel@tonic-gate 			}
9317c478bd9Sstevel@tonic-gate 			DPRINT3(5, "net_poll(%u): enqueued msg %p "
932*0ea5e3a5Sjjj 				"on queue %p\n", mythreadno, (void *)mp,
933*0ea5e3a5Sjjj 				(void *)&hnlq);
9347c478bd9Sstevel@tonic-gate 		}
9357c478bd9Sstevel@tonic-gate 	}
9367c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
9377c478bd9Sstevel@tonic-gate 	return (NULL);
9387c478bd9Sstevel@tonic-gate }
9397c478bd9Sstevel@tonic-gate 
9407c478bd9Sstevel@tonic-gate static void
9417c478bd9Sstevel@tonic-gate usage(void)
9427c478bd9Sstevel@tonic-gate {
9437c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
9447c478bd9Sstevel@tonic-gate 	    "usage: syslogd [-d] [-t|-T] [-mmarkinterval] [-ppath]"
9457c478bd9Sstevel@tonic-gate 	    " [-fconffile]\n");
9467c478bd9Sstevel@tonic-gate 	exit(1);
9477c478bd9Sstevel@tonic-gate }
9487c478bd9Sstevel@tonic-gate 
9497c478bd9Sstevel@tonic-gate static void
9507c478bd9Sstevel@tonic-gate untty(void)
9517c478bd9Sstevel@tonic-gate {
9527c478bd9Sstevel@tonic-gate 	if (!Debug)
9537c478bd9Sstevel@tonic-gate 		(void) setsid();
9547c478bd9Sstevel@tonic-gate }
9557c478bd9Sstevel@tonic-gate 
9567c478bd9Sstevel@tonic-gate /*
9577c478bd9Sstevel@tonic-gate  * generate a log message internally. The original version of syslogd
9587c478bd9Sstevel@tonic-gate  * simply called logmsg directly, but because everything is now based
9597c478bd9Sstevel@tonic-gate  * on message passing, we need an internal way to generate and queue
9607c478bd9Sstevel@tonic-gate  * log messages from within syslogd itself.
9617c478bd9Sstevel@tonic-gate  */
9627c478bd9Sstevel@tonic-gate static int
9637c478bd9Sstevel@tonic-gate logmymsg(int pri, char *msg, int flags, int pending)
9647c478bd9Sstevel@tonic-gate {
9657c478bd9Sstevel@tonic-gate 	log_message_t *mp;
9667c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
9677c478bd9Sstevel@tonic-gate 	dataq_t *qptr;
9687c478bd9Sstevel@tonic-gate 
9697c478bd9Sstevel@tonic-gate 	if (Debug) {
9707c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
9717c478bd9Sstevel@tonic-gate 	}
9727c478bd9Sstevel@tonic-gate 
9737c478bd9Sstevel@tonic-gate 	if ((mp = new_msg()) == NULL) {
9747c478bd9Sstevel@tonic-gate 		return (-1);
9757c478bd9Sstevel@tonic-gate 	}
9767c478bd9Sstevel@tonic-gate 
9777c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp))
9787c478bd9Sstevel@tonic-gate 	mp->pri = pri;
9797c478bd9Sstevel@tonic-gate 	mp->hlp = &LocalHostName;
9807c478bd9Sstevel@tonic-gate 	(void) strlcpy(mp->msg, msg, MAXLINE+1);
9817c478bd9Sstevel@tonic-gate 	mp->flags = flags;
9827c478bd9Sstevel@tonic-gate 	(void) time(&mp->ts);
9837c478bd9Sstevel@tonic-gate 
9847c478bd9Sstevel@tonic-gate 	qptr = pending ? &tmpq : &inputq;
9857c478bd9Sstevel@tonic-gate 	if (dataq_enqueue(qptr, (void *)mp) == -1) {
9867c478bd9Sstevel@tonic-gate 		free_msg(mp);
9877c478bd9Sstevel@tonic-gate 		return (-1);
9887c478bd9Sstevel@tonic-gate 	}
9897c478bd9Sstevel@tonic-gate 
9907c478bd9Sstevel@tonic-gate 	DPRINT3(5, "logmymsg(%u): enqueued msg %p on queue %p\n",
991*0ea5e3a5Sjjj 		mythreadno, (void *)mp, (void *)qptr);
9927c478bd9Sstevel@tonic-gate 	DPRINT2(5, "logmymsg(%u): Message content: %s\n", mythreadno, msg);
9937c478bd9Sstevel@tonic-gate 	return (0);
9947c478bd9Sstevel@tonic-gate }
9957c478bd9Sstevel@tonic-gate 
9967c478bd9Sstevel@tonic-gate /*
9977c478bd9Sstevel@tonic-gate  * Generate an internal shutdown message
9987c478bd9Sstevel@tonic-gate  */
9997c478bd9Sstevel@tonic-gate static int
10007c478bd9Sstevel@tonic-gate shutdown_msg(void)
10017c478bd9Sstevel@tonic-gate {
10027c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
10037c478bd9Sstevel@tonic-gate 	log_message_t *mp;
10047c478bd9Sstevel@tonic-gate 
10057c478bd9Sstevel@tonic-gate 	if (Debug) {
10067c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
10077c478bd9Sstevel@tonic-gate 	}
10087c478bd9Sstevel@tonic-gate 
10097c478bd9Sstevel@tonic-gate 	if ((mp = new_msg()) == NULL) {
10107c478bd9Sstevel@tonic-gate 		return (-1);
10117c478bd9Sstevel@tonic-gate 	}
10127c478bd9Sstevel@tonic-gate 
10137c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp));
10147c478bd9Sstevel@tonic-gate 	mp->flags = SHUTDOWN;
10157c478bd9Sstevel@tonic-gate 	mp->hlp = &LocalHostName;
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate 	if (dataq_enqueue(&inputq, (void *)mp) == -1) {
10187c478bd9Sstevel@tonic-gate 		free_msg(mp);
10197c478bd9Sstevel@tonic-gate 		return (-1);
10207c478bd9Sstevel@tonic-gate 	}
10217c478bd9Sstevel@tonic-gate 
10227c478bd9Sstevel@tonic-gate 	DPRINT3(5, "shutdown_msg(%u): enqueued msg %p on queue %p\n",
1023*0ea5e3a5Sjjj 		mythreadno, (void *)mp, (void *)&inputq);
10247c478bd9Sstevel@tonic-gate 	return (0);
10257c478bd9Sstevel@tonic-gate }
10267c478bd9Sstevel@tonic-gate 
10277c478bd9Sstevel@tonic-gate /*
10287c478bd9Sstevel@tonic-gate  * Generate an internal flush message
10297c478bd9Sstevel@tonic-gate  */
10307c478bd9Sstevel@tonic-gate static void
10317c478bd9Sstevel@tonic-gate flushmsg(int flags)
10327c478bd9Sstevel@tonic-gate {
10337c478bd9Sstevel@tonic-gate 	log_message_t *mp;
10347c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
10357c478bd9Sstevel@tonic-gate 
10367c478bd9Sstevel@tonic-gate 	if (Debug) {
10377c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
10387c478bd9Sstevel@tonic-gate 	}
10397c478bd9Sstevel@tonic-gate 
10407c478bd9Sstevel@tonic-gate 	if ((mp = new_msg()) == NULL) {
10417c478bd9Sstevel@tonic-gate 		MALLOC_FAIL("dropping flush msg");
10427c478bd9Sstevel@tonic-gate 		return;
10437c478bd9Sstevel@tonic-gate 	}
10447c478bd9Sstevel@tonic-gate 
10457c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp));
10467c478bd9Sstevel@tonic-gate 	mp->flags = FLUSHMSG | flags;
10477c478bd9Sstevel@tonic-gate 	mp->hlp = &LocalHostName;
10487c478bd9Sstevel@tonic-gate 
10497c478bd9Sstevel@tonic-gate 	if (dataq_enqueue(&inputq, (void *)mp) == -1) {
10507c478bd9Sstevel@tonic-gate 		free_msg(mp);
10517c478bd9Sstevel@tonic-gate 		MALLOC_FAIL("dropping flush msg");
10527c478bd9Sstevel@tonic-gate 		return;
10537c478bd9Sstevel@tonic-gate 	}
10547c478bd9Sstevel@tonic-gate 
10557c478bd9Sstevel@tonic-gate 	DPRINT4(5, "flush_msg(%u): enqueued msg %p on queue %p, flags "
1056*0ea5e3a5Sjjj 		"0x%x\n", mythreadno, (void *)mp, (void *)&inputq, flags);
10577c478bd9Sstevel@tonic-gate }
10587c478bd9Sstevel@tonic-gate 
10597c478bd9Sstevel@tonic-gate /*
10607c478bd9Sstevel@tonic-gate  * Do some processing on messages received from the net
10617c478bd9Sstevel@tonic-gate  */
10627c478bd9Sstevel@tonic-gate static void
10637c478bd9Sstevel@tonic-gate formatnet(struct netbuf *nbp, log_message_t *mp)
10647c478bd9Sstevel@tonic-gate {
10657c478bd9Sstevel@tonic-gate 	char *p;
10667c478bd9Sstevel@tonic-gate 	int pri;
10677c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
10687c478bd9Sstevel@tonic-gate 
10697c478bd9Sstevel@tonic-gate 	if (Debug) {
10707c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
10717c478bd9Sstevel@tonic-gate 	}
10727c478bd9Sstevel@tonic-gate 
1073*0ea5e3a5Sjjj 	DPRINT2(5, "formatnet(%u): called for msg %p\n", mythreadno,
1074*0ea5e3a5Sjjj 		(void *)mp);
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate 	mp->flags = NETWORK;
10777c478bd9Sstevel@tonic-gate 	(void) time(&mp->ts);
10787c478bd9Sstevel@tonic-gate 
10797c478bd9Sstevel@tonic-gate 	/* test for special codes */
10807c478bd9Sstevel@tonic-gate 	pri = DEFUPRI;
10817c478bd9Sstevel@tonic-gate 	p = nbp->buf;
10827c478bd9Sstevel@tonic-gate 	DPRINT2(9, "formatnet(%u): Message content:\n>%s<\n", mythreadno,
10837c478bd9Sstevel@tonic-gate 		p);
10847c478bd9Sstevel@tonic-gate 	if (*p == '<' && isdigit(*(p+1))) {
10857c478bd9Sstevel@tonic-gate 		pri = 0;
10867c478bd9Sstevel@tonic-gate 		while (isdigit(*++p))
10877c478bd9Sstevel@tonic-gate 			pri = 10 * pri + (*p - '0');
10887c478bd9Sstevel@tonic-gate 		if (*p == '>')
10897c478bd9Sstevel@tonic-gate 			++p;
10907c478bd9Sstevel@tonic-gate 		if (pri <= 0 || pri >= (LOG_NFACILITIES << 3))
10917c478bd9Sstevel@tonic-gate 			pri = DEFUPRI;
10927c478bd9Sstevel@tonic-gate 	}
10937c478bd9Sstevel@tonic-gate 
10947c478bd9Sstevel@tonic-gate 	mp->pri = pri;
10957c478bd9Sstevel@tonic-gate 	(void) strlcpy(mp->msg, p, MAXLINE+1);
10967c478bd9Sstevel@tonic-gate }
10977c478bd9Sstevel@tonic-gate 
10987c478bd9Sstevel@tonic-gate /*
10997c478bd9Sstevel@tonic-gate  * Do some processing on messages generated by this host
11007c478bd9Sstevel@tonic-gate  * and then enqueue the log message.
11017c478bd9Sstevel@tonic-gate  */
11027c478bd9Sstevel@tonic-gate static void
11037c478bd9Sstevel@tonic-gate formatsys(struct log_ctl *lp, char *msg, int sync)
11047c478bd9Sstevel@tonic-gate {
11057c478bd9Sstevel@tonic-gate 	char *p, *q;
11067c478bd9Sstevel@tonic-gate 	char line[MAXLINE + 1];
11077c478bd9Sstevel@tonic-gate 	size_t msglen;
11087c478bd9Sstevel@tonic-gate 	log_message_t	*mp;
11097c478bd9Sstevel@tonic-gate 	char cbuf[30];
11107c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
11117c478bd9Sstevel@tonic-gate 
11127c478bd9Sstevel@tonic-gate 	if (Debug) {
11137c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
11147c478bd9Sstevel@tonic-gate 	}
11157c478bd9Sstevel@tonic-gate 
11167c478bd9Sstevel@tonic-gate 	DPRINT3(3, "formatsys(%u): log_ctl.mid = %d, log_ctl.sid = %d\n",
11177c478bd9Sstevel@tonic-gate 		mythreadno, lp->mid, lp->sid);
11187c478bd9Sstevel@tonic-gate 	DPRINT2(9, "formatsys(%u): Message Content:\n>%s<\n", mythreadno,
11197c478bd9Sstevel@tonic-gate 		msg);
11207c478bd9Sstevel@tonic-gate 
11217c478bd9Sstevel@tonic-gate 	/* msglen includes the null termination */
11227c478bd9Sstevel@tonic-gate 	msglen = strlen(msg) + 1;
11237c478bd9Sstevel@tonic-gate 
11247c478bd9Sstevel@tonic-gate 	for (p = msg; *p != '\0'; ) {
11257c478bd9Sstevel@tonic-gate 		size_t linelen;
11267c478bd9Sstevel@tonic-gate 		size_t len;
11277c478bd9Sstevel@tonic-gate 
11287c478bd9Sstevel@tonic-gate 		/*
11297c478bd9Sstevel@tonic-gate 		 * Allocate a log_message_t structure.
11307c478bd9Sstevel@tonic-gate 		 * We should do it here since a single message (msg)
11317c478bd9Sstevel@tonic-gate 		 * could be composed of many lines.
11327c478bd9Sstevel@tonic-gate 		 */
11337c478bd9Sstevel@tonic-gate 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp));
11347c478bd9Sstevel@tonic-gate 
11357c478bd9Sstevel@tonic-gate 		if ((mp = new_msg()) == NULL) {
11367c478bd9Sstevel@tonic-gate 			MALLOC_FAIL("dropping message");
11377c478bd9Sstevel@tonic-gate 			/*
11387c478bd9Sstevel@tonic-gate 			 * Should bail out from the loop.
11397c478bd9Sstevel@tonic-gate 			 */
11407c478bd9Sstevel@tonic-gate 			break;
11417c478bd9Sstevel@tonic-gate 		}
11427c478bd9Sstevel@tonic-gate 
11437c478bd9Sstevel@tonic-gate 		mp->flags &= ~NETWORK;
11447c478bd9Sstevel@tonic-gate 		mp->hlp = &LocalHostName;
11457c478bd9Sstevel@tonic-gate 		mp->ts = lp->ttime;
11467c478bd9Sstevel@tonic-gate 		if (lp->flags & SL_LOGONLY)
11477c478bd9Sstevel@tonic-gate 			mp->flags |= IGN_CONS;
11487c478bd9Sstevel@tonic-gate 		if (lp->flags & SL_CONSONLY)
11497c478bd9Sstevel@tonic-gate 			mp->flags |= IGN_FILE;
11507c478bd9Sstevel@tonic-gate 
11517c478bd9Sstevel@tonic-gate 		/* extract facility */
11527c478bd9Sstevel@tonic-gate 		if ((lp->pri & LOG_FACMASK) == LOG_KERN) {
11537c478bd9Sstevel@tonic-gate 			(void) sprintf(line, "%.15s ",
11547c478bd9Sstevel@tonic-gate 				ctime_r(&mp->ts, cbuf) + 4);
11557c478bd9Sstevel@tonic-gate 		} else {
11567c478bd9Sstevel@tonic-gate 			(void) sprintf(line, "");
11577c478bd9Sstevel@tonic-gate 		}
11587c478bd9Sstevel@tonic-gate 
11597c478bd9Sstevel@tonic-gate 		linelen = strlen(line);
11607c478bd9Sstevel@tonic-gate 		q = line + linelen;
11617c478bd9Sstevel@tonic-gate 
11627c478bd9Sstevel@tonic-gate 		DPRINT2(5, "formatsys(%u): msglen = %d\n", mythreadno, msglen);
11637c478bd9Sstevel@tonic-gate 		len = copynl_frwd(q, MAXLINE + 1 - linelen, p, msglen);
11647c478bd9Sstevel@tonic-gate 		DPRINT2(5, "formatsys(%u): len (copynl_frwd) = %d\n",
11657c478bd9Sstevel@tonic-gate 			mythreadno, len);
11667c478bd9Sstevel@tonic-gate 
11677c478bd9Sstevel@tonic-gate 		p += len;
11687c478bd9Sstevel@tonic-gate 		msglen -= len;
11697c478bd9Sstevel@tonic-gate 
11707c478bd9Sstevel@tonic-gate 		if (*p == '\n') {
11717c478bd9Sstevel@tonic-gate 			/* skip newline */
11727c478bd9Sstevel@tonic-gate 			p++;
11737c478bd9Sstevel@tonic-gate 		}
11747c478bd9Sstevel@tonic-gate 
11757c478bd9Sstevel@tonic-gate 		if (sync && ((lp->pri & LOG_FACMASK) == LOG_KERN))
11767c478bd9Sstevel@tonic-gate 			mp->flags |= SYNC_FILE;	/* fsync file after write */
11777c478bd9Sstevel@tonic-gate 
11787c478bd9Sstevel@tonic-gate 		if (len != 0) {
11797c478bd9Sstevel@tonic-gate 			(void) strlcpy(mp->msg, line, MAXLINE+1);
11807c478bd9Sstevel@tonic-gate 			mp->pri = lp->pri;
11817c478bd9Sstevel@tonic-gate 
11827c478bd9Sstevel@tonic-gate 			if (dataq_enqueue(&inputq, (void *)mp) == -1) {
11837c478bd9Sstevel@tonic-gate 				free_msg(mp);
11847c478bd9Sstevel@tonic-gate 				MALLOC_FAIL("dropping message");
11857c478bd9Sstevel@tonic-gate 				break;
11867c478bd9Sstevel@tonic-gate 			}
11877c478bd9Sstevel@tonic-gate 
11887c478bd9Sstevel@tonic-gate 			DPRINT3(5, "formatsys(%u): sys_thread enqueued msg "
1189*0ea5e3a5Sjjj 				"%p on queue %p\n", mythreadno, (void *)mp,
1190*0ea5e3a5Sjjj 				(void *)&inputq);
11917c478bd9Sstevel@tonic-gate 		} else
11927c478bd9Sstevel@tonic-gate 			free_msg(mp);
11937c478bd9Sstevel@tonic-gate 	}
11947c478bd9Sstevel@tonic-gate }
11957c478bd9Sstevel@tonic-gate 
11967c478bd9Sstevel@tonic-gate /*
11977c478bd9Sstevel@tonic-gate  * Log a message to the appropriate log files, users, etc. based on
11987c478bd9Sstevel@tonic-gate  * the priority.
11997c478bd9Sstevel@tonic-gate  */
12007c478bd9Sstevel@tonic-gate /*ARGSUSED*/
12017c478bd9Sstevel@tonic-gate static void *
12027c478bd9Sstevel@tonic-gate logmsg(void *ap)
12037c478bd9Sstevel@tonic-gate {
12047c478bd9Sstevel@tonic-gate 	struct filed *f;
12057c478bd9Sstevel@tonic-gate 	int fac, prilev, flags, refcnt;
12067c478bd9Sstevel@tonic-gate 	int fake_shutdown, skip_shutdown;
12077c478bd9Sstevel@tonic-gate 	log_message_t *mp, *save_mp;
12087c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
12097c478bd9Sstevel@tonic-gate 
12107c478bd9Sstevel@tonic-gate 	if (Debug) {
12117c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
12127c478bd9Sstevel@tonic-gate 	}
12137c478bd9Sstevel@tonic-gate 
12147c478bd9Sstevel@tonic-gate 	DPRINT1(1, "logmsg(%u): msg dispatcher started\n", mythreadno);
12157c478bd9Sstevel@tonic-gate 
12167c478bd9Sstevel@tonic-gate 	fake_shutdown = skip_shutdown = 0;
12177c478bd9Sstevel@tonic-gate 	save_mp = NULL;
12187c478bd9Sstevel@tonic-gate 	for (;;) {
12197c478bd9Sstevel@tonic-gate 		if (save_mp) {
12207c478bd9Sstevel@tonic-gate 			/*
12217c478bd9Sstevel@tonic-gate 			 * If we have set aside a message in order to fake a
12227c478bd9Sstevel@tonic-gate 			 * SHUTDOWN, use that message before picking from the
12237c478bd9Sstevel@tonic-gate 			 * queue again.
12247c478bd9Sstevel@tonic-gate 			 */
12257c478bd9Sstevel@tonic-gate 			mp = save_mp;
12267c478bd9Sstevel@tonic-gate 			save_mp = NULL;
12277c478bd9Sstevel@tonic-gate 		} else {
12287c478bd9Sstevel@tonic-gate 			(void) dataq_dequeue(&inputq, (void **)&mp, 0);
12297c478bd9Sstevel@tonic-gate 		}
12307c478bd9Sstevel@tonic-gate 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp))
12317c478bd9Sstevel@tonic-gate 		DPRINT3(5, "logmsg(%u): msg dispatcher dequeued %p from "
1232*0ea5e3a5Sjjj 			"queue %p\n", mythreadno, (void *)mp,
1233*0ea5e3a5Sjjj 			(void *)&inputq);
12347c478bd9Sstevel@tonic-gate 
12357c478bd9Sstevel@tonic-gate 		/*
12367c478bd9Sstevel@tonic-gate 		 * In most cases, if the message traffic is low, logmsg() wakes
12377c478bd9Sstevel@tonic-gate 		 * up when it receives the SHUTDOWN msg, and will sleep until
12387c478bd9Sstevel@tonic-gate 		 * HUP process is complete.  However, if the inputq is too
12397c478bd9Sstevel@tonic-gate 		 * long, logmsg() may not receive SHUTDOWN before reconfigure()
12407c478bd9Sstevel@tonic-gate 		 * releases the logger fds, filed and logit threads.  That, in
12417c478bd9Sstevel@tonic-gate 		 * turn, will cause logmsg to refer to invalid fileds.
12427c478bd9Sstevel@tonic-gate 		 *
12437c478bd9Sstevel@tonic-gate 		 * logmsg() needs to respond to the SHUTDOWN message within
12447c478bd9Sstevel@tonic-gate 		 * LOOP_INTERVAL seconds when reconfigure() enqueues it. It
12457c478bd9Sstevel@tonic-gate 		 * does so in most cases.  When it does not respond in time,
12467c478bd9Sstevel@tonic-gate 		 * logmsg() needs to be in suspended state immediately, since
12477c478bd9Sstevel@tonic-gate 		 * filed may have been invalidated. reconfigure() will set the
12487c478bd9Sstevel@tonic-gate 		 * HUP_SUSP_LOGMSG_REQD bit in hup_state and wait another
12497c478bd9Sstevel@tonic-gate 		 * LOOP_INTERVAL seconds before proceeding.
12507c478bd9Sstevel@tonic-gate 		 *
12517c478bd9Sstevel@tonic-gate 		 * When HUP_SUSP_LOGMSG_REQD is set, we will create a fake
12527c478bd9Sstevel@tonic-gate 		 * SHUTDOWN message, and dispatch it to the various logit
12537c478bd9Sstevel@tonic-gate 		 * threads, and logmsg() itself will suspend.  In order to
12547c478bd9Sstevel@tonic-gate 		 * ignore the real SHUTDOWN which will arrive later, we keep a
12557c478bd9Sstevel@tonic-gate 		 * counter (skip_shutdown) and decrement it when the SHUTDOWN
12567c478bd9Sstevel@tonic-gate 		 * message arrives.
12577c478bd9Sstevel@tonic-gate 		 */
12587c478bd9Sstevel@tonic-gate 		if ((hup_state & HUP_SUSP_LOGMSG_REQD) &&
12597c478bd9Sstevel@tonic-gate 			(mp->flags & SHUTDOWN) == 0) {
12607c478bd9Sstevel@tonic-gate 			DPRINT1(3, "logmsg(%u): suspend request\n",
12617c478bd9Sstevel@tonic-gate 				mythreadno);
12627c478bd9Sstevel@tonic-gate 
12637c478bd9Sstevel@tonic-gate 			save_mp = mp;
12647c478bd9Sstevel@tonic-gate 
12657c478bd9Sstevel@tonic-gate 			/* create a fake SHUTDOWN msg */
12667c478bd9Sstevel@tonic-gate 			if ((mp = new_msg()) == NULL) {
12677c478bd9Sstevel@tonic-gate 				MALLOC_FAIL("dropping message");
12687c478bd9Sstevel@tonic-gate 				if (mp->flags & SHUTDOWN) {
12697c478bd9Sstevel@tonic-gate 					(void) logerror_to_console(1,
12707c478bd9Sstevel@tonic-gate 						"unable to shutdown "
12717c478bd9Sstevel@tonic-gate 						"logger thread");
12727c478bd9Sstevel@tonic-gate 				}
12737c478bd9Sstevel@tonic-gate 				continue;
12747c478bd9Sstevel@tonic-gate 			}
12757c478bd9Sstevel@tonic-gate 			mp->flags = SHUTDOWN;
12767c478bd9Sstevel@tonic-gate 			mp->hlp = &LocalHostName;
12777c478bd9Sstevel@tonic-gate 			fake_shutdown = 1;
12787c478bd9Sstevel@tonic-gate 			skip_shutdown++;
12797c478bd9Sstevel@tonic-gate 			DPRINT2(3, "logmsg(%u): pending SHUTDOWN %d\n",
12807c478bd9Sstevel@tonic-gate 				mythreadno, skip_shutdown);
12817c478bd9Sstevel@tonic-gate 		}
12827c478bd9Sstevel@tonic-gate 
12837c478bd9Sstevel@tonic-gate 		/*
12847c478bd9Sstevel@tonic-gate 		 * is it a shutdown or flush message ?
12857c478bd9Sstevel@tonic-gate 		 */
12867c478bd9Sstevel@tonic-gate 		if ((mp->flags & SHUTDOWN) || (mp->flags & FLUSHMSG)) {
1287*0ea5e3a5Sjjj 			(void) pthread_mutex_lock(&mp->msg_mutex);
12887c478bd9Sstevel@tonic-gate 
12897c478bd9Sstevel@tonic-gate 			if ((mp->flags & SHUTDOWN) &&
12907c478bd9Sstevel@tonic-gate 				!fake_shutdown && skip_shutdown > 0) {
12917c478bd9Sstevel@tonic-gate 				skip_shutdown--;
1292*0ea5e3a5Sjjj 				(void) pthread_mutex_unlock(&mp->msg_mutex);
12937c478bd9Sstevel@tonic-gate 				free_msg(mp);
12947c478bd9Sstevel@tonic-gate 				DPRINT2(3, "logmsg(%u): released late "
12957c478bd9Sstevel@tonic-gate 					"arrived SHUTDOWN. pending %d\n",
12967c478bd9Sstevel@tonic-gate 					mythreadno, skip_shutdown);
12977c478bd9Sstevel@tonic-gate 				continue;
12987c478bd9Sstevel@tonic-gate 			}
12997c478bd9Sstevel@tonic-gate 
13007c478bd9Sstevel@tonic-gate 			for (f = Files; f < &Files[nlogs]; f++) {
1301*0ea5e3a5Sjjj 				(void) pthread_mutex_lock(&f->filed_mutex);
13027c478bd9Sstevel@tonic-gate 
13037c478bd9Sstevel@tonic-gate 				if (f->f_type == F_UNUSED) {
1304*0ea5e3a5Sjjj 					(void) pthread_mutex_unlock(
1305*0ea5e3a5Sjjj 					    &f->filed_mutex);
13067c478bd9Sstevel@tonic-gate 					continue;
13077c478bd9Sstevel@tonic-gate 				}
13087c478bd9Sstevel@tonic-gate 
13097c478bd9Sstevel@tonic-gate 				f->f_queue_count++;
13107c478bd9Sstevel@tonic-gate 				mp->refcnt++;
13117c478bd9Sstevel@tonic-gate 
13127c478bd9Sstevel@tonic-gate 				if (dataq_enqueue(&f->f_queue,
13137c478bd9Sstevel@tonic-gate 					(void *)mp) == -1) {
13147c478bd9Sstevel@tonic-gate 					f->f_queue_count--;
13157c478bd9Sstevel@tonic-gate 					mp->refcnt--;
1316*0ea5e3a5Sjjj 					(void) pthread_mutex_unlock(
1317*0ea5e3a5Sjjj 					    &f->filed_mutex);
13187c478bd9Sstevel@tonic-gate 					MALLOC_FAIL("dropping message");
13197c478bd9Sstevel@tonic-gate 
13207c478bd9Sstevel@tonic-gate 					if (mp->flags & SHUTDOWN) {
13217c478bd9Sstevel@tonic-gate 						(void) logerror_to_console(1,
13227c478bd9Sstevel@tonic-gate 							"unable to shutdown "
13237c478bd9Sstevel@tonic-gate 							"logger thread");
13247c478bd9Sstevel@tonic-gate 					}
13257c478bd9Sstevel@tonic-gate 
13267c478bd9Sstevel@tonic-gate 					continue;
13277c478bd9Sstevel@tonic-gate 				}
13287c478bd9Sstevel@tonic-gate 				DPRINT3(5, "logmsg(%u): enqueued msg %p "
1329*0ea5e3a5Sjjj 					"on queue %p\n", mythreadno,
1330*0ea5e3a5Sjjj 					(void *)mp, (void *)&f->f_queue);
1331*0ea5e3a5Sjjj 				(void) pthread_mutex_unlock(&f->filed_mutex);
13327c478bd9Sstevel@tonic-gate 			}
13337c478bd9Sstevel@tonic-gate 
13347c478bd9Sstevel@tonic-gate 			/*
13357c478bd9Sstevel@tonic-gate 			 * flags value needs to be saved because mp may
13367c478bd9Sstevel@tonic-gate 			 * have been freed before SHUTDOWN test below.
13377c478bd9Sstevel@tonic-gate 			 */
13387c478bd9Sstevel@tonic-gate 			flags = mp->flags;
13397c478bd9Sstevel@tonic-gate 			refcnt = mp->refcnt;
13407c478bd9Sstevel@tonic-gate 
1341*0ea5e3a5Sjjj 			(void) pthread_mutex_unlock(&mp->msg_mutex);
13427c478bd9Sstevel@tonic-gate 			if (refcnt == 0)
13437c478bd9Sstevel@tonic-gate 				free_msg(mp);
13447c478bd9Sstevel@tonic-gate 
13457c478bd9Sstevel@tonic-gate 			if (flags & SHUTDOWN) {
1346*0ea5e3a5Sjjj 				(void) pthread_mutex_lock(&hup_lock);
13477c478bd9Sstevel@tonic-gate 				while (hup_state != HUP_COMPLETED) {
13487c478bd9Sstevel@tonic-gate 					hup_state |= HUP_LOGMSG_SUSPENDED;
13497c478bd9Sstevel@tonic-gate 					(void) pthread_cond_wait(&hup_done,
13507c478bd9Sstevel@tonic-gate 						&hup_lock);
13517c478bd9Sstevel@tonic-gate 					hup_state &= ~HUP_LOGMSG_SUSPENDED;
13527c478bd9Sstevel@tonic-gate 				}
13537c478bd9Sstevel@tonic-gate 				hup_state = HUP_ACCEPTABLE;
1354*0ea5e3a5Sjjj 				(void) pthread_mutex_unlock(&hup_lock);
13557c478bd9Sstevel@tonic-gate 				fake_shutdown = 0;
13567c478bd9Sstevel@tonic-gate 			}
13577c478bd9Sstevel@tonic-gate 			continue;
13587c478bd9Sstevel@tonic-gate 		}
13597c478bd9Sstevel@tonic-gate 
13607c478bd9Sstevel@tonic-gate 		/*
13617c478bd9Sstevel@tonic-gate 		 * Check to see if msg looks non-standard.
13627c478bd9Sstevel@tonic-gate 		 */
13637c478bd9Sstevel@tonic-gate 		if ((int)strlen(mp->msg) < 16 || mp->msg[3] != ' ' ||
13647c478bd9Sstevel@tonic-gate 			mp->msg[6] != ' ' || mp->msg[9] != ':' ||
13657c478bd9Sstevel@tonic-gate 			mp->msg[12] != ':' || mp->msg[15] != ' ')
13667c478bd9Sstevel@tonic-gate 			mp->flags |= ADDDATE;
13677c478bd9Sstevel@tonic-gate 
13687c478bd9Sstevel@tonic-gate 		/* extract facility and priority level */
13697c478bd9Sstevel@tonic-gate 		fac = (mp->pri & LOG_FACMASK) >> 3;
13707c478bd9Sstevel@tonic-gate 		if (mp->flags & MARK)
13717c478bd9Sstevel@tonic-gate 			fac = LOG_NFACILITIES;
13727c478bd9Sstevel@tonic-gate 		prilev = mp->pri & LOG_PRIMASK;
13737c478bd9Sstevel@tonic-gate 
13747c478bd9Sstevel@tonic-gate 		DPRINT3(3, "logmsg(%u): fac = %d, pri = %d\n",
13757c478bd9Sstevel@tonic-gate 			mythreadno, fac, prilev);
13767c478bd9Sstevel@tonic-gate 
13777c478bd9Sstevel@tonic-gate 		/*
13787c478bd9Sstevel@tonic-gate 		 * Because different devices log at different speeds,
13797c478bd9Sstevel@tonic-gate 		 * it's important to hold the mutex for the current
13807c478bd9Sstevel@tonic-gate 		 * message until it's been enqueued to all log files,
13817c478bd9Sstevel@tonic-gate 		 * so the reference count is accurate before any
13827c478bd9Sstevel@tonic-gate 		 * of the log threads can decrement it.
13837c478bd9Sstevel@tonic-gate 		 */
13847c478bd9Sstevel@tonic-gate 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mp))
13857c478bd9Sstevel@tonic-gate 		_NOTE(COMPETING_THREADS_NOW)
1386*0ea5e3a5Sjjj 		(void) pthread_mutex_lock(&mp->msg_mutex);
13877c478bd9Sstevel@tonic-gate 
13887c478bd9Sstevel@tonic-gate 		for (f = Files; f < &Files[nlogs]; f++) {
13897c478bd9Sstevel@tonic-gate 			/* skip messages that are incorrect priority */
13907c478bd9Sstevel@tonic-gate 			if (f->f_pmask[fac] < (unsigned)prilev ||
13917c478bd9Sstevel@tonic-gate 				f->f_pmask[fac] == NOPRI)
13927c478bd9Sstevel@tonic-gate 				continue;
13937c478bd9Sstevel@tonic-gate 			if (f->f_queue_count > Q_HIGHWATER_MARK) {
13947c478bd9Sstevel@tonic-gate 				DPRINT4(5, "logmsg(%u): Dropping message "
13957c478bd9Sstevel@tonic-gate 					"%p on file %p, count = %d\n",
1396*0ea5e3a5Sjjj 					mythreadno, (void *)mp, (void *)f,
13977c478bd9Sstevel@tonic-gate 					f->f_queue_count);
13987c478bd9Sstevel@tonic-gate 				continue;
13997c478bd9Sstevel@tonic-gate 			}
14007c478bd9Sstevel@tonic-gate 
14017c478bd9Sstevel@tonic-gate 			/*
14027c478bd9Sstevel@tonic-gate 			 * Need to grab filed_mutex before testing the f_type.
14037c478bd9Sstevel@tonic-gate 			 * Otherwise logit() may set F_UNUSED after the test
14047c478bd9Sstevel@tonic-gate 			 * below, and start pulling out the pending messages.
14057c478bd9Sstevel@tonic-gate 			 */
14067c478bd9Sstevel@tonic-gate 
1407*0ea5e3a5Sjjj 			(void) pthread_mutex_lock(&f->filed_mutex);
14087c478bd9Sstevel@tonic-gate 
14097c478bd9Sstevel@tonic-gate 			if (f->f_type == F_UNUSED ||
14107c478bd9Sstevel@tonic-gate 			    (f->f_type == F_FILE && (mp->flags & IGN_FILE)) ||
14117c478bd9Sstevel@tonic-gate 			    (f->f_type == F_CONSOLE &&
14127c478bd9Sstevel@tonic-gate 				(mp->flags & IGN_CONS))) {
1413*0ea5e3a5Sjjj 				(void) pthread_mutex_unlock(&f->filed_mutex);
14147c478bd9Sstevel@tonic-gate 				continue;
14157c478bd9Sstevel@tonic-gate 			}
14167c478bd9Sstevel@tonic-gate 
14177c478bd9Sstevel@tonic-gate 			f->f_queue_count++;
14187c478bd9Sstevel@tonic-gate 			mp->refcnt++;
14197c478bd9Sstevel@tonic-gate 
14207c478bd9Sstevel@tonic-gate 			if (dataq_enqueue(&f->f_queue, (void *)mp) == -1) {
14217c478bd9Sstevel@tonic-gate 				f->f_queue_count--;
14227c478bd9Sstevel@tonic-gate 				mp->refcnt--;
1423*0ea5e3a5Sjjj 				(void) pthread_mutex_unlock(&f->filed_mutex);
14247c478bd9Sstevel@tonic-gate 				MALLOC_FAIL("dropping message");
14257c478bd9Sstevel@tonic-gate 				continue;
14267c478bd9Sstevel@tonic-gate 			}
14277c478bd9Sstevel@tonic-gate 
14287c478bd9Sstevel@tonic-gate 			DPRINT3(5, "logmsg(%u): enqueued msg %p on queue "
1429*0ea5e3a5Sjjj 				"%p\n", mythreadno, (void *)mp,
1430*0ea5e3a5Sjjj 				(void *)&f->f_queue);
1431*0ea5e3a5Sjjj 			(void) pthread_mutex_unlock(&f->filed_mutex);
14327c478bd9Sstevel@tonic-gate 		}
14337c478bd9Sstevel@tonic-gate 		refcnt = mp->refcnt;
1434*0ea5e3a5Sjjj 		(void) pthread_mutex_unlock(&mp->msg_mutex);
14357c478bd9Sstevel@tonic-gate 		if (refcnt == 0)
14367c478bd9Sstevel@tonic-gate 			free_msg(mp);
14377c478bd9Sstevel@tonic-gate 	}
14387c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
14397c478bd9Sstevel@tonic-gate 	return (NULL);
14407c478bd9Sstevel@tonic-gate }
14417c478bd9Sstevel@tonic-gate 
14427c478bd9Sstevel@tonic-gate /*
14437c478bd9Sstevel@tonic-gate  * function to actually write the log message to the selected file.
14447c478bd9Sstevel@tonic-gate  * each file has a logger thread that runs this routine. The function
14457c478bd9Sstevel@tonic-gate  * is called with a pointer to its file structure.
14467c478bd9Sstevel@tonic-gate  */
14477c478bd9Sstevel@tonic-gate static void *
14487c478bd9Sstevel@tonic-gate logit(void *ap)
14497c478bd9Sstevel@tonic-gate {
14507c478bd9Sstevel@tonic-gate 	struct filed *f = ap;
14517c478bd9Sstevel@tonic-gate 	log_message_t *mp;
14527c478bd9Sstevel@tonic-gate 	int forwardingloop = 0;
1453*0ea5e3a5Sjjj 	const char *errmsg = "logit(%u): %s to %s forwarding loop detected\n";
14547c478bd9Sstevel@tonic-gate 	int i, currofst, prevofst, refcnt;
14557c478bd9Sstevel@tonic-gate 	host_list_t *hlp;
14567c478bd9Sstevel@tonic-gate 
14577c478bd9Sstevel@tonic-gate 	assert(f != NULL);
14587c478bd9Sstevel@tonic-gate 
14597c478bd9Sstevel@tonic-gate 	DPRINT4(5, "logit(%u): logger started for \"%s\" (queue %p, filed "
1460*0ea5e3a5Sjjj 		"%p)\n", f->f_thread, f->f_un.f_fname, (void *)&f->f_queue,
1461*0ea5e3a5Sjjj 		(void *)f);
14627c478bd9Sstevel@tonic-gate 	_NOTE(COMPETING_THREADS_NOW);
14637c478bd9Sstevel@tonic-gate 
14647c478bd9Sstevel@tonic-gate 	while (f->f_type != F_UNUSED) {
14657c478bd9Sstevel@tonic-gate 		(void) dataq_dequeue(&f->f_queue, (void **)&mp, 0);
14667c478bd9Sstevel@tonic-gate 		DPRINT3(5, "logit(%u): logger dequeued msg %p from queue "
1467*0ea5e3a5Sjjj 			"%p\n", f->f_thread, (void *)mp, (void *)&f->f_queue);
1468*0ea5e3a5Sjjj 		(void) pthread_mutex_lock(&f->filed_mutex);
14697c478bd9Sstevel@tonic-gate 		assert(f->f_queue_count > 0);
14707c478bd9Sstevel@tonic-gate 		f->f_queue_count--;
1471*0ea5e3a5Sjjj 		(void) pthread_mutex_unlock(&f->filed_mutex);
14727c478bd9Sstevel@tonic-gate 		assert(mp->refcnt > 0);
14737c478bd9Sstevel@tonic-gate 
14747c478bd9Sstevel@tonic-gate 		/*
14757c478bd9Sstevel@tonic-gate 		 * is it a shutdown message ?
14767c478bd9Sstevel@tonic-gate 		 */
14777c478bd9Sstevel@tonic-gate 		if (mp->flags & SHUTDOWN) {
1478*0ea5e3a5Sjjj 			(void) pthread_mutex_lock(&mp->msg_mutex);
14797c478bd9Sstevel@tonic-gate 			refcnt = --mp->refcnt;
1480*0ea5e3a5Sjjj 			(void) pthread_mutex_unlock(&mp->msg_mutex);
14817c478bd9Sstevel@tonic-gate 			if (refcnt == 0)
14827c478bd9Sstevel@tonic-gate 				free_msg(mp);
14837c478bd9Sstevel@tonic-gate 			break;
14847c478bd9Sstevel@tonic-gate 		}
14857c478bd9Sstevel@tonic-gate 
14867c478bd9Sstevel@tonic-gate 		/*
14877c478bd9Sstevel@tonic-gate 		 * Is it a logsync message?
14887c478bd9Sstevel@tonic-gate 		 */
14897c478bd9Sstevel@tonic-gate 		if ((mp->flags & (FLUSHMSG | LOGSYNC)) ==
14907c478bd9Sstevel@tonic-gate 		    (FLUSHMSG | LOGSYNC)) {
14917c478bd9Sstevel@tonic-gate 			if (f->f_type != F_FILE)
14927c478bd9Sstevel@tonic-gate 				goto out;	/* nothing to do */
14937c478bd9Sstevel@tonic-gate 			(void) close(f->f_file);
14947c478bd9Sstevel@tonic-gate 			f->f_file = open64(f->f_un.f_fname,
14957c478bd9Sstevel@tonic-gate 					O_WRONLY|O_APPEND|O_NOCTTY);
14967c478bd9Sstevel@tonic-gate 			if (f->f_file < 0) {
14977c478bd9Sstevel@tonic-gate 				f->f_type = F_UNUSED;
14987c478bd9Sstevel@tonic-gate 				logerror(f->f_un.f_fname);
14997c478bd9Sstevel@tonic-gate 				f->f_stat.errs++;
15007c478bd9Sstevel@tonic-gate 			}
15017c478bd9Sstevel@tonic-gate 			goto out;
15027c478bd9Sstevel@tonic-gate 		}
15037c478bd9Sstevel@tonic-gate 
15047c478bd9Sstevel@tonic-gate 		/*
15057c478bd9Sstevel@tonic-gate 		 * If the message flags include both flush and sync,
15067c478bd9Sstevel@tonic-gate 		 * then just sync the file out to disk if appropriate.
15077c478bd9Sstevel@tonic-gate 		 */
15087c478bd9Sstevel@tonic-gate 		if ((mp->flags & (FLUSHMSG | SYNC_FILE)) ==
15097c478bd9Sstevel@tonic-gate 		    (FLUSHMSG | SYNC_FILE)) {
15107c478bd9Sstevel@tonic-gate 			if (f->f_type == F_FILE) {
15117c478bd9Sstevel@tonic-gate 				DPRINT2(5, "logit(%u): got FLUSH|SYNC "
15127c478bd9Sstevel@tonic-gate 					"for filed %p\n", f->f_thread,
1513*0ea5e3a5Sjjj 					(void *)f);
15147c478bd9Sstevel@tonic-gate 				(void) fsync(f->f_file);
15157c478bd9Sstevel@tonic-gate 			}
15167c478bd9Sstevel@tonic-gate 			goto out;
15177c478bd9Sstevel@tonic-gate 		}
15187c478bd9Sstevel@tonic-gate 
15197c478bd9Sstevel@tonic-gate 		/*
15207c478bd9Sstevel@tonic-gate 		 * Otherwise if it's a standard flush message, write
15217c478bd9Sstevel@tonic-gate 		 * out any saved messages to the file.
15227c478bd9Sstevel@tonic-gate 		 */
15237c478bd9Sstevel@tonic-gate 		if ((mp->flags & FLUSHMSG) && (f->f_prevcount > 0)) {
15247c478bd9Sstevel@tonic-gate 			set_flush_msg(f);
15257c478bd9Sstevel@tonic-gate 			writemsg(SAVED, f);
15267c478bd9Sstevel@tonic-gate 			goto out;
15277c478bd9Sstevel@tonic-gate 		}
15287c478bd9Sstevel@tonic-gate 
15297c478bd9Sstevel@tonic-gate 		(void) strlcpy(f->f_current.msg, mp->msg, MAXLINE+1);
15307c478bd9Sstevel@tonic-gate 		(void) strlcpy(f->f_current.host, mp->hlp->hl_hosts[0],
15317c478bd9Sstevel@tonic-gate 				SYS_NMLN);
15327c478bd9Sstevel@tonic-gate 		f->f_current.pri = mp->pri;
15337c478bd9Sstevel@tonic-gate 		f->f_current.flags = mp->flags;
15347c478bd9Sstevel@tonic-gate 		f->f_current.time = mp->ts;
15357c478bd9Sstevel@tonic-gate 		f->f_msgflag &= ~CURRENT_VALID;
15367c478bd9Sstevel@tonic-gate 		hlp = mp->hlp;
15377c478bd9Sstevel@tonic-gate 
15387c478bd9Sstevel@tonic-gate 		prevofst = (f->f_prevmsg.flags & ADDDATE) ? 0 : 16;
15397c478bd9Sstevel@tonic-gate 		currofst = (f->f_current.flags & ADDDATE) ? 0 : 16;
15407c478bd9Sstevel@tonic-gate 
15417c478bd9Sstevel@tonic-gate 		if (f->f_type == F_FORW) {
15427c478bd9Sstevel@tonic-gate 			/*
15437c478bd9Sstevel@tonic-gate 			 * Should not forward MARK messages, as they are
15447c478bd9Sstevel@tonic-gate 			 * not defined outside of the current system.
15457c478bd9Sstevel@tonic-gate 			 */
15467c478bd9Sstevel@tonic-gate 
15477c478bd9Sstevel@tonic-gate 			if (mp->flags & MARK) {
15487c478bd9Sstevel@tonic-gate 				DPRINT1(1, "logit(%u): cannot forward "
15497c478bd9Sstevel@tonic-gate 					"Mark\n", f->f_thread);
15507c478bd9Sstevel@tonic-gate 				goto out;
15517c478bd9Sstevel@tonic-gate 			}
15527c478bd9Sstevel@tonic-gate 
15537c478bd9Sstevel@tonic-gate 			/*
15547c478bd9Sstevel@tonic-gate 			 * can not forward message if we do
15557c478bd9Sstevel@tonic-gate 			 * not have a host to forward to
15567c478bd9Sstevel@tonic-gate 			 */
15577c478bd9Sstevel@tonic-gate 			if (hlp == (host_list_t *)NULL)
15587c478bd9Sstevel@tonic-gate 				goto out;
15597c478bd9Sstevel@tonic-gate 			/*
15607c478bd9Sstevel@tonic-gate 			 * a forwarding loop is created on machines
15617c478bd9Sstevel@tonic-gate 			 * with multiple interfaces because the
15627c478bd9Sstevel@tonic-gate 			 * network address of the sender is different
15637c478bd9Sstevel@tonic-gate 			 * to the receiver even though it is the
15647c478bd9Sstevel@tonic-gate 			 * same machine. Instead, if the
15657c478bd9Sstevel@tonic-gate 			 * hostname the source and target are
15667c478bd9Sstevel@tonic-gate 			 * the same the message if thrown away
15677c478bd9Sstevel@tonic-gate 			 */
15687c478bd9Sstevel@tonic-gate 			forwardingloop = 0;
15697c478bd9Sstevel@tonic-gate 			for (i = 0; i < hlp->hl_cnt; i++) {
15707c478bd9Sstevel@tonic-gate 				if (strcmp(hlp->hl_hosts[i],
15717c478bd9Sstevel@tonic-gate 					f->f_un.f_forw.f_hname) == 0) {
15727c478bd9Sstevel@tonic-gate 					DPRINT3(1, errmsg, f->f_thread,
15737c478bd9Sstevel@tonic-gate 						f->f_un.f_forw.f_hname,
15747c478bd9Sstevel@tonic-gate 						hlp->hl_hosts[i]);
15757c478bd9Sstevel@tonic-gate 					forwardingloop = 1;
15767c478bd9Sstevel@tonic-gate 					break;
15777c478bd9Sstevel@tonic-gate 				}
15787c478bd9Sstevel@tonic-gate 			}
15797c478bd9Sstevel@tonic-gate 
15807c478bd9Sstevel@tonic-gate 			if (forwardingloop == 1) {
15817c478bd9Sstevel@tonic-gate 				f->f_stat.cantfwd++;
15827c478bd9Sstevel@tonic-gate 				goto out;
15837c478bd9Sstevel@tonic-gate 			}
15847c478bd9Sstevel@tonic-gate 		}
15857c478bd9Sstevel@tonic-gate 
15867c478bd9Sstevel@tonic-gate 		f->f_msgflag |= CURRENT_VALID;
15877c478bd9Sstevel@tonic-gate 
15887c478bd9Sstevel@tonic-gate 		/* check for dup message */
15897c478bd9Sstevel@tonic-gate 		if (f->f_type != F_FORW &&
15907c478bd9Sstevel@tonic-gate 			(f->f_msgflag & OLD_VALID) &&
15917c478bd9Sstevel@tonic-gate 			prevofst == currofst &&
15927c478bd9Sstevel@tonic-gate 			(strcmp(f->f_prevmsg.msg + prevofst,
15937c478bd9Sstevel@tonic-gate 				f->f_current.msg + currofst) == 0) &&
15947c478bd9Sstevel@tonic-gate 			(strcmp(f->f_prevmsg.host,
15957c478bd9Sstevel@tonic-gate 				f->f_current.host) == 0)) {
15967c478bd9Sstevel@tonic-gate 			/* a dup */
15977c478bd9Sstevel@tonic-gate 			DPRINT2(2, "logit(%u): msg is dup - %p\n",
1598*0ea5e3a5Sjjj 				f->f_thread, (void *)mp);
15997c478bd9Sstevel@tonic-gate 			if (currofst == 16) {
16007c478bd9Sstevel@tonic-gate 				(void) strncpy(f->f_prevmsg.msg,
16017c478bd9Sstevel@tonic-gate 				f->f_current.msg, 15); /* update time */
16027c478bd9Sstevel@tonic-gate 			}
16037c478bd9Sstevel@tonic-gate 			f->f_prevcount++;
16047c478bd9Sstevel@tonic-gate 			f->f_stat.dups++;
16057c478bd9Sstevel@tonic-gate 			f->f_stat.total++;
16067c478bd9Sstevel@tonic-gate 			f->f_msgflag &= ~CURRENT_VALID;
16077c478bd9Sstevel@tonic-gate 		} else {
16087c478bd9Sstevel@tonic-gate 			/* new: mark or prior dups exist */
16097c478bd9Sstevel@tonic-gate 			if (f->f_current.flags & MARK || f->f_prevcount > 0) {
16107c478bd9Sstevel@tonic-gate 				if (f->f_prevcount > 0 && f->f_type != F_FORW) {
16117c478bd9Sstevel@tonic-gate 					set_flush_msg(f);
16127c478bd9Sstevel@tonic-gate 					if (f->f_msgflag & OLD_VALID) {
16137c478bd9Sstevel@tonic-gate 						writemsg(SAVED, f);
16147c478bd9Sstevel@tonic-gate 					}
16157c478bd9Sstevel@tonic-gate 				}
16167c478bd9Sstevel@tonic-gate 				if (f->f_msgflag & CURRENT_VALID)
16177c478bd9Sstevel@tonic-gate 					writemsg(CURRENT, f);
16187c478bd9Sstevel@tonic-gate 				if (!(mp->flags & NOCOPY))
16197c478bd9Sstevel@tonic-gate 					copy_msg(f);
16207c478bd9Sstevel@tonic-gate 				if (f->f_current.flags & MARK) {
16217c478bd9Sstevel@tonic-gate 					DPRINT2(2, "logit(%u): msg is "
1622*0ea5e3a5Sjjj 						"mark - %p)\n", f->f_thread,
1623*0ea5e3a5Sjjj 						(void *)mp);
16247c478bd9Sstevel@tonic-gate 					f->f_msgflag &= ~OLD_VALID;
16257c478bd9Sstevel@tonic-gate 				} else {
16267c478bd9Sstevel@tonic-gate 					DPRINT2(2, "logit(%u): saving "
1627*0ea5e3a5Sjjj 						"message - %p\n", f->f_thread,
1628*0ea5e3a5Sjjj 						(void *)mp);
16297c478bd9Sstevel@tonic-gate 				}
16307c478bd9Sstevel@tonic-gate 				f->f_stat.total++;
16317c478bd9Sstevel@tonic-gate 			} else { /* new message */
16327c478bd9Sstevel@tonic-gate 				DPRINT2(2, "logit(%u): msg is new "
1633*0ea5e3a5Sjjj 					"- %p\n", f->f_thread, (void *)mp);
16347c478bd9Sstevel@tonic-gate 				writemsg(CURRENT, f);
16357c478bd9Sstevel@tonic-gate 				if (!(mp->flags & NOCOPY))
16367c478bd9Sstevel@tonic-gate 					copy_msg(f);
16377c478bd9Sstevel@tonic-gate 				f->f_stat.total++;
16387c478bd9Sstevel@tonic-gate 			}
16397c478bd9Sstevel@tonic-gate 		}
16407c478bd9Sstevel@tonic-gate 		/*
16417c478bd9Sstevel@tonic-gate 		 * if message refcnt goes to zero after we decrement
16427c478bd9Sstevel@tonic-gate 		 * it here, we are the last consumer of the message,
16437c478bd9Sstevel@tonic-gate 		 * and we should free it.  We need to hold the lock
16447c478bd9Sstevel@tonic-gate 		 * between decrementing the count and checking for
16457c478bd9Sstevel@tonic-gate 		 * zero so another thread doesn't beat us to it.
16467c478bd9Sstevel@tonic-gate 		 */
16477c478bd9Sstevel@tonic-gate out:
1648*0ea5e3a5Sjjj 		(void) pthread_mutex_lock(&mp->msg_mutex);
16497c478bd9Sstevel@tonic-gate 		refcnt = --mp->refcnt;
1650*0ea5e3a5Sjjj 		(void) pthread_mutex_unlock(&mp->msg_mutex);
16517c478bd9Sstevel@tonic-gate 		if (refcnt == 0)
16527c478bd9Sstevel@tonic-gate 			free_msg(mp);
16537c478bd9Sstevel@tonic-gate 	}
16547c478bd9Sstevel@tonic-gate 	/* register our exit */
16557c478bd9Sstevel@tonic-gate 
16567c478bd9Sstevel@tonic-gate 	/*
16577c478bd9Sstevel@tonic-gate 	 * Pull out all pending messages, if they exist.
16587c478bd9Sstevel@tonic-gate 	 */
16597c478bd9Sstevel@tonic-gate 
1660*0ea5e3a5Sjjj 	(void) pthread_mutex_lock(&f->filed_mutex);
16617c478bd9Sstevel@tonic-gate 
16627c478bd9Sstevel@tonic-gate 	while (f->f_queue_count > 0) {
16637c478bd9Sstevel@tonic-gate 		(void) dataq_dequeue(&f->f_queue, (void **)&mp, 0);
16647c478bd9Sstevel@tonic-gate 		DPRINT3(5, "logit(%u): logger dequeued msg %p from queue "
16657c478bd9Sstevel@tonic-gate 			"%p\n",
1666*0ea5e3a5Sjjj 			f->f_thread, (void *)mp, (void *)&f->f_queue);
1667*0ea5e3a5Sjjj 		(void) pthread_mutex_lock(&mp->msg_mutex);
16687c478bd9Sstevel@tonic-gate 		refcnt = --mp->refcnt;
1669*0ea5e3a5Sjjj 		(void) pthread_mutex_unlock(&mp->msg_mutex);
16707c478bd9Sstevel@tonic-gate 		if (refcnt == 0)
16717c478bd9Sstevel@tonic-gate 			free_msg(mp);
16727c478bd9Sstevel@tonic-gate 		f->f_queue_count--;
16737c478bd9Sstevel@tonic-gate 	}
16747c478bd9Sstevel@tonic-gate 
1675*0ea5e3a5Sjjj 	(void) pthread_mutex_unlock(&f->filed_mutex);
16767c478bd9Sstevel@tonic-gate 
16777c478bd9Sstevel@tonic-gate 	if (f->f_type != F_USERS && f->f_type != F_WALL &&
16787c478bd9Sstevel@tonic-gate 		f->f_type != F_UNUSED) {
16797c478bd9Sstevel@tonic-gate 		if (f->f_type == F_FORW)
16807c478bd9Sstevel@tonic-gate 			(void) t_close(f->f_file);
16817c478bd9Sstevel@tonic-gate 		else
16827c478bd9Sstevel@tonic-gate 			(void) close(f->f_file);
16837c478bd9Sstevel@tonic-gate 	}
16847c478bd9Sstevel@tonic-gate 
16857c478bd9Sstevel@tonic-gate 	/*
16867c478bd9Sstevel@tonic-gate 	 * Since f_type may have been changed before this point, we need
16877c478bd9Sstevel@tonic-gate 	 * to test orig_type.
16887c478bd9Sstevel@tonic-gate 	 */
16897c478bd9Sstevel@tonic-gate 	if (f->f_orig_type == F_FORW) {
16907c478bd9Sstevel@tonic-gate 		free(f->f_un.f_forw.f_addr.buf);
16917c478bd9Sstevel@tonic-gate 	}
16927c478bd9Sstevel@tonic-gate 
16937c478bd9Sstevel@tonic-gate 	f->f_type = F_UNUSED;
1694*0ea5e3a5Sjjj 	(void) pthread_mutex_lock(&cft);
16957c478bd9Sstevel@tonic-gate 	--conf_threads;
1696*0ea5e3a5Sjjj 	(void) pthread_mutex_unlock(&cft);
16977c478bd9Sstevel@tonic-gate 	DPRINT1(5, "logit(%u): logging thread exited\n", f->f_thread);
16987c478bd9Sstevel@tonic-gate 	return (NULL);
16997c478bd9Sstevel@tonic-gate }
17007c478bd9Sstevel@tonic-gate 
17017c478bd9Sstevel@tonic-gate /*
17027c478bd9Sstevel@tonic-gate  * change the previous message to a flush message, stating how
17037c478bd9Sstevel@tonic-gate  * many repeats occurred since the last flush
17047c478bd9Sstevel@tonic-gate  */
17057c478bd9Sstevel@tonic-gate static void
17067c478bd9Sstevel@tonic-gate set_flush_msg(struct filed *f)
17077c478bd9Sstevel@tonic-gate {
17087c478bd9Sstevel@tonic-gate 	char tbuf[10];
17097c478bd9Sstevel@tonic-gate 	int prevofst = (f->f_prevmsg.flags & ADDDATE) ? 0 : 16;
17107c478bd9Sstevel@tonic-gate 
17117c478bd9Sstevel@tonic-gate 	if (f->f_prevcount == 1)
17127c478bd9Sstevel@tonic-gate 		(void) strncpy(tbuf, "time", sizeof (tbuf));
17137c478bd9Sstevel@tonic-gate 	else
17147c478bd9Sstevel@tonic-gate 		(void) strncpy(tbuf, "times", sizeof (tbuf));
17157c478bd9Sstevel@tonic-gate 
1716*0ea5e3a5Sjjj 	(void) snprintf(f->f_prevmsg.msg+prevofst,
1717*0ea5e3a5Sjjj 	    sizeof (f->f_prevmsg.msg) - prevofst,
17187c478bd9Sstevel@tonic-gate 	    "last message repeated %d %s", f->f_prevcount, tbuf);
17197c478bd9Sstevel@tonic-gate 	f->f_prevcount = 0;
17207c478bd9Sstevel@tonic-gate 	f->f_msgflag |= OLD_VALID;
17217c478bd9Sstevel@tonic-gate }
17227c478bd9Sstevel@tonic-gate 
17237c478bd9Sstevel@tonic-gate 
17247c478bd9Sstevel@tonic-gate /*
17257c478bd9Sstevel@tonic-gate  * the actual writing of the message is broken into a separate function
17267c478bd9Sstevel@tonic-gate  * because each file has a current and saved message associated with
17277c478bd9Sstevel@tonic-gate  * it (for duplicate message detection). It is necessary to be able
17287c478bd9Sstevel@tonic-gate  * to write either the saved message or the current message.
17297c478bd9Sstevel@tonic-gate  */
17307c478bd9Sstevel@tonic-gate static void
17317c478bd9Sstevel@tonic-gate writemsg(int selection, struct filed *f)
17327c478bd9Sstevel@tonic-gate {
17337c478bd9Sstevel@tonic-gate 	char *cp, *p;
17347c478bd9Sstevel@tonic-gate 	int pri;
17357c478bd9Sstevel@tonic-gate 	int flags;
17367c478bd9Sstevel@tonic-gate 	int l;
17377c478bd9Sstevel@tonic-gate 	time_t ts;
17387c478bd9Sstevel@tonic-gate 	struct t_unitdata ud;
17397c478bd9Sstevel@tonic-gate 	char *eomp, *eomp2, *from, *text, *msg;
17407c478bd9Sstevel@tonic-gate 	char line[MAXLINE*2];
17417c478bd9Sstevel@tonic-gate 	char head[MAXLINE+1];
17427c478bd9Sstevel@tonic-gate 	char tmpbuf[MAXLINE+1];
17437c478bd9Sstevel@tonic-gate 	char cbuf[30];
17447c478bd9Sstevel@tonic-gate 	char *filtered;
17457c478bd9Sstevel@tonic-gate 	char *msgid_start, *msgid_end;
17467c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
17477c478bd9Sstevel@tonic-gate 	size_t	hlen, filter_len;
17487c478bd9Sstevel@tonic-gate 
17497c478bd9Sstevel@tonic-gate 	if (Debug) {
17507c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
17517c478bd9Sstevel@tonic-gate 	}
17527c478bd9Sstevel@tonic-gate 
17537c478bd9Sstevel@tonic-gate 	switch (selection) {
17547c478bd9Sstevel@tonic-gate 	default:
17557c478bd9Sstevel@tonic-gate 	case CURRENT:		/* print current message */
17567c478bd9Sstevel@tonic-gate 		msg = f->f_current.msg;
17577c478bd9Sstevel@tonic-gate 		from = f->f_current.host;
17587c478bd9Sstevel@tonic-gate 		pri = f->f_current.pri;
17597c478bd9Sstevel@tonic-gate 		flags = f->f_current.flags;
17607c478bd9Sstevel@tonic-gate 		ts = f->f_current.time;
17617c478bd9Sstevel@tonic-gate 		f->f_msgflag &= ~CURRENT_VALID;
17627c478bd9Sstevel@tonic-gate 		break;
17637c478bd9Sstevel@tonic-gate 	case SAVED:		/* print saved message */
17647c478bd9Sstevel@tonic-gate 		msg = f->f_prevmsg.msg;
17657c478bd9Sstevel@tonic-gate 		from = f->f_prevmsg.host;
17667c478bd9Sstevel@tonic-gate 		pri = f->f_prevmsg.pri;
17677c478bd9Sstevel@tonic-gate 		flags = f->f_prevmsg.flags;
17687c478bd9Sstevel@tonic-gate 		ts = f->f_prevmsg.time;
17697c478bd9Sstevel@tonic-gate 		f->f_msgflag &= ~OLD_VALID;
17707c478bd9Sstevel@tonic-gate 		break;
17717c478bd9Sstevel@tonic-gate 	}
17727c478bd9Sstevel@tonic-gate 
17737c478bd9Sstevel@tonic-gate 	if (msg[0] == '\0')
17747c478bd9Sstevel@tonic-gate 		return;
17757c478bd9Sstevel@tonic-gate 
17767c478bd9Sstevel@tonic-gate 	cp = line;
17777c478bd9Sstevel@tonic-gate 
17787c478bd9Sstevel@tonic-gate 	if (flags & ADDDATE)
17797c478bd9Sstevel@tonic-gate 		(void) strncpy(cp, ctime_r(&ts, cbuf) + 4, 15);
17807c478bd9Sstevel@tonic-gate 	else
17817c478bd9Sstevel@tonic-gate 		(void) strncpy(cp, msg, 15);
17827c478bd9Sstevel@tonic-gate 
17837c478bd9Sstevel@tonic-gate 	line[15] = '\0';
17847c478bd9Sstevel@tonic-gate 	(void) strcat(cp, " ");
17857c478bd9Sstevel@tonic-gate 	(void) strcat(cp, from);
17867c478bd9Sstevel@tonic-gate 	(void) strcat(cp, " ");
17877c478bd9Sstevel@tonic-gate 	text = cp + strlen(cp);
17887c478bd9Sstevel@tonic-gate 
17897c478bd9Sstevel@tonic-gate 	if (flags & ADDDATE)
17907c478bd9Sstevel@tonic-gate 		(void) strcat(cp, msg);
17917c478bd9Sstevel@tonic-gate 	else
17927c478bd9Sstevel@tonic-gate 		(void) strcat(cp, msg+16);
17937c478bd9Sstevel@tonic-gate 	DPRINT2(5, "writemsg(%u): text = \"%s\"\n", mythreadno, text);
17947c478bd9Sstevel@tonic-gate 
17957c478bd9Sstevel@tonic-gate 	errno = 0;
17967c478bd9Sstevel@tonic-gate 	t_errno = 0;
17977c478bd9Sstevel@tonic-gate 	switch (f->f_type) {
17987c478bd9Sstevel@tonic-gate 	case F_UNUSED:
17997c478bd9Sstevel@tonic-gate 		DPRINT1(1, "writemsg(%u): UNUSED\n", mythreadno);
18007c478bd9Sstevel@tonic-gate 		break;
18017c478bd9Sstevel@tonic-gate 	case F_FORW:
18027c478bd9Sstevel@tonic-gate 		DPRINT4(1, "writemsg(%u): Logging msg '%s' to %s %s\n",
18037c478bd9Sstevel@tonic-gate 			mythreadno, msg, TypeNames[f->f_type],
18047c478bd9Sstevel@tonic-gate 			f->f_un.f_forw.f_hname);
18057c478bd9Sstevel@tonic-gate 
18067c478bd9Sstevel@tonic-gate 		hlen = snprintf(head, sizeof (head),
18077c478bd9Sstevel@tonic-gate 			"<%d>%.15s ", pri, cp);
18087c478bd9Sstevel@tonic-gate 
18097c478bd9Sstevel@tonic-gate 		DPRINT2(5, "writemsg(%u): head = \"%s\"\n", mythreadno, head);
18107c478bd9Sstevel@tonic-gate 		DPRINT2(5, "writemsg(%u): hlen = %d\n", mythreadno, hlen);
18117c478bd9Sstevel@tonic-gate 
18127c478bd9Sstevel@tonic-gate 		l = strlen(text);
18137c478bd9Sstevel@tonic-gate 		p = text;
18147c478bd9Sstevel@tonic-gate 
18157c478bd9Sstevel@tonic-gate 		DPRINT2(5, "writemsg(%u): text = \"%s\"\n", mythreadno, text);
18167c478bd9Sstevel@tonic-gate 		DPRINT2(5, "writemsg(%u): strlen(text) = %d\n", mythreadno, l);
18177c478bd9Sstevel@tonic-gate 
18187c478bd9Sstevel@tonic-gate 		(void) strncpy(tmpbuf, head, hlen);
18197c478bd9Sstevel@tonic-gate 
18207c478bd9Sstevel@tonic-gate 		while (l > 0) {
18217c478bd9Sstevel@tonic-gate 			size_t	len;
18227c478bd9Sstevel@tonic-gate 
18237c478bd9Sstevel@tonic-gate 			len = copy_frwd(tmpbuf + hlen, sizeof (tmpbuf) - hlen,
18247c478bd9Sstevel@tonic-gate 					p, l);
18257c478bd9Sstevel@tonic-gate 
18267c478bd9Sstevel@tonic-gate 			DPRINT2(5, "writemsg(%u): tmpbuf = \"%s\"\n",
18277c478bd9Sstevel@tonic-gate 				mythreadno, tmpbuf);
18287c478bd9Sstevel@tonic-gate 			DPRINT2(5, "writemsg(%u): len = %d\n", mythreadno,
18297c478bd9Sstevel@tonic-gate 				len);
18307c478bd9Sstevel@tonic-gate 			DPRINT2(5, "writemsg(%u): strlen(tmpbuf) = %d\n",
18317c478bd9Sstevel@tonic-gate 				mythreadno, strlen(tmpbuf));
18327c478bd9Sstevel@tonic-gate 
18337c478bd9Sstevel@tonic-gate 			ud.opt.buf = NULL;
18347c478bd9Sstevel@tonic-gate 			ud.opt.len = 0;
18357c478bd9Sstevel@tonic-gate 			ud.udata.buf = tmpbuf;
18367c478bd9Sstevel@tonic-gate 			ud.udata.len = len + hlen;
18377c478bd9Sstevel@tonic-gate 			ud.addr.maxlen = f->f_un.f_forw.f_addr.maxlen;
18387c478bd9Sstevel@tonic-gate 			ud.addr.buf = f->f_un.f_forw.f_addr.buf;
18397c478bd9Sstevel@tonic-gate 			ud.addr.len = f->f_un.f_forw.f_addr.len;
18407c478bd9Sstevel@tonic-gate 			if (t_sndudata(f->f_file, &ud) < 0) {
18417c478bd9Sstevel@tonic-gate 				if ((hup_state & HUP_INPROGRESS) &&
18427c478bd9Sstevel@tonic-gate 					f->f_type == F_UNUSED) {
18437c478bd9Sstevel@tonic-gate 					break;
18447c478bd9Sstevel@tonic-gate 				}
18457c478bd9Sstevel@tonic-gate 				(void) t_close(f->f_file);
18467c478bd9Sstevel@tonic-gate 				f->f_type = F_UNUSED;
18477c478bd9Sstevel@tonic-gate 				logerror("t_sndudata");
18487c478bd9Sstevel@tonic-gate 
18497c478bd9Sstevel@tonic-gate 				/*
18507c478bd9Sstevel@tonic-gate 				 * Since it has already failed, it's not worth
18517c478bd9Sstevel@tonic-gate 				 * continuing output from the middle of
18527c478bd9Sstevel@tonic-gate 				 * message string.
18537c478bd9Sstevel@tonic-gate 				 */
18547c478bd9Sstevel@tonic-gate 				break;
18557c478bd9Sstevel@tonic-gate 			}
18567c478bd9Sstevel@tonic-gate 			p += len;
18577c478bd9Sstevel@tonic-gate 			l -= len;
18587c478bd9Sstevel@tonic-gate 		}
18597c478bd9Sstevel@tonic-gate 		break;
18607c478bd9Sstevel@tonic-gate 	case F_CONSOLE:
18617c478bd9Sstevel@tonic-gate 	case F_TTY:
18627c478bd9Sstevel@tonic-gate 	case F_FILE:
18637c478bd9Sstevel@tonic-gate 	case F_USERS:
18647c478bd9Sstevel@tonic-gate 	case F_WALL:
18657c478bd9Sstevel@tonic-gate 		DPRINT4(1, "writemsg(%u): Logging msg '%s' to %s %s\n",
18667c478bd9Sstevel@tonic-gate 			mythreadno, msg, TypeNames[f->f_type],
18677c478bd9Sstevel@tonic-gate 			((f->f_type == F_USERS) || (f->f_type == F_WALL)) ?
18687c478bd9Sstevel@tonic-gate 			"" : f->f_un.f_fname);
18697c478bd9Sstevel@tonic-gate 		/*
18707c478bd9Sstevel@tonic-gate 		 * filter the string in preparation for writing it
18717c478bd9Sstevel@tonic-gate 		 * save the original for possible forwarding.
18727c478bd9Sstevel@tonic-gate 		 * In case every byte in cp is a control character,
18737c478bd9Sstevel@tonic-gate 		 * allocates large enough buffer for filtered.
18747c478bd9Sstevel@tonic-gate 		 */
18757c478bd9Sstevel@tonic-gate 
18767c478bd9Sstevel@tonic-gate 		filter_len = strlen(cp) * 4 + 1;
18777c478bd9Sstevel@tonic-gate 		filtered = (char *)malloc(filter_len);
18787c478bd9Sstevel@tonic-gate 		if (!filtered) {
18797c478bd9Sstevel@tonic-gate 			MALLOC_FAIL("dropping message");
18807c478bd9Sstevel@tonic-gate 			/* seems we can just return */
18817c478bd9Sstevel@tonic-gate 			return;
18827c478bd9Sstevel@tonic-gate 		}
18837c478bd9Sstevel@tonic-gate 		DPRINT3(5, "writemsg(%u): "
18847c478bd9Sstevel@tonic-gate 			"filtered allocated (%p: %d bytes)\n",
1885*0ea5e3a5Sjjj 			mythreadno, (void *)filtered, filter_len);
18867c478bd9Sstevel@tonic-gate 		/* -3 : we may add "\r\n" to ecomp(filtered) later */
18877c478bd9Sstevel@tonic-gate 		filter_string(cp, filtered, filter_len - 3);
18887c478bd9Sstevel@tonic-gate 
18897c478bd9Sstevel@tonic-gate 		DPRINT2(5, "writemsg(%u): strlen(filtered) = %d\n",
18907c478bd9Sstevel@tonic-gate 			mythreadno, strlen(filtered));
18917c478bd9Sstevel@tonic-gate 		/*
18927c478bd9Sstevel@tonic-gate 		 * If we're writing to the console, strip out the message ID
18937c478bd9Sstevel@tonic-gate 		 * to reduce visual clutter.
18947c478bd9Sstevel@tonic-gate 		 */
18957c478bd9Sstevel@tonic-gate 		if ((msgid_start = strstr(filtered, "[ID ")) != NULL &&
18967c478bd9Sstevel@tonic-gate 			(msgid_end = strstr(msgid_start, "] ")) != NULL &&
18977c478bd9Sstevel@tonic-gate 			f->f_type == F_CONSOLE)
18987c478bd9Sstevel@tonic-gate 			(void) strcpy(msgid_start, msgid_end + 2);
18997c478bd9Sstevel@tonic-gate 
19007c478bd9Sstevel@tonic-gate 		eomp = filtered + strlen(filtered);
19017c478bd9Sstevel@tonic-gate 
19027c478bd9Sstevel@tonic-gate 		if ((f->f_type == F_USERS) || (f->f_type == F_WALL)) {
19037c478bd9Sstevel@tonic-gate 			/* CSTYLED */
19047c478bd9Sstevel@tonic-gate 			(void) strcat(eomp, "\r\n"); /*lint !e669*/
19057c478bd9Sstevel@tonic-gate 			/*
19067c478bd9Sstevel@tonic-gate 			 * Since wallmsg messes with utmpx we need
19077c478bd9Sstevel@tonic-gate 			 * to guarantee single threadedness...
19087c478bd9Sstevel@tonic-gate 			 */
19097c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_lock(&wmp);
19107c478bd9Sstevel@tonic-gate 			wallmsg(f, from, filtered);
19117c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&wmp);
19127c478bd9Sstevel@tonic-gate 
19137c478bd9Sstevel@tonic-gate 			/*
19147c478bd9Sstevel@tonic-gate 			 * The contents of filtered have been copied
19157c478bd9Sstevel@tonic-gate 			 * out to the struct walldev. We should free it here.
19167c478bd9Sstevel@tonic-gate 			 */
19177c478bd9Sstevel@tonic-gate 
19187c478bd9Sstevel@tonic-gate 			free(filtered);
19197c478bd9Sstevel@tonic-gate 
19207c478bd9Sstevel@tonic-gate 			/* exiting the switch */
19217c478bd9Sstevel@tonic-gate 			break;
19227c478bd9Sstevel@tonic-gate 		} else if (f->f_type != F_FILE) {
19237c478bd9Sstevel@tonic-gate 			/* CSTYLED */
19247c478bd9Sstevel@tonic-gate 			(void) strncpy(eomp, "\r\n", 3); /*lint !e669*/
19257c478bd9Sstevel@tonic-gate 		} else {
19267c478bd9Sstevel@tonic-gate 			if ((eomp2 = strchr(filtered, '\r')) != NULL) {
19277c478bd9Sstevel@tonic-gate 				(void) strncpy(eomp2, "\n", 2);
19287c478bd9Sstevel@tonic-gate 			} else {
19297c478bd9Sstevel@tonic-gate 				/* CSTYLED */
19307c478bd9Sstevel@tonic-gate 				(void) strncpy(eomp, "\n", 2); /*lint !e669*/
19317c478bd9Sstevel@tonic-gate 			}
19327c478bd9Sstevel@tonic-gate 		}
19337c478bd9Sstevel@tonic-gate 		if (write(f->f_file, filtered, strlen(filtered)) < 0) {
19347c478bd9Sstevel@tonic-gate 			int e = errno;
19357c478bd9Sstevel@tonic-gate 
19367c478bd9Sstevel@tonic-gate 			if ((hup_state & HUP_INPROGRESS) &&
19377c478bd9Sstevel@tonic-gate 				f->f_type == F_UNUSED) {
19387c478bd9Sstevel@tonic-gate 				free(filtered);
19397c478bd9Sstevel@tonic-gate 				break;
19407c478bd9Sstevel@tonic-gate 			}
19417c478bd9Sstevel@tonic-gate 			(void) close(f->f_file);
19427c478bd9Sstevel@tonic-gate 			/*
19437c478bd9Sstevel@tonic-gate 			 * Check for EBADF on TTY's due
19447c478bd9Sstevel@tonic-gate 			 * to vhangup() XXX
19457c478bd9Sstevel@tonic-gate 			 */
19467c478bd9Sstevel@tonic-gate 			if (e == EBADF && f->f_type != F_FILE) {
19477c478bd9Sstevel@tonic-gate 				f->f_file = open(f->f_un.f_fname,
19487c478bd9Sstevel@tonic-gate 					O_WRONLY|O_APPEND|O_NOCTTY);
19497c478bd9Sstevel@tonic-gate 				if (f->f_file < 0) {
19507c478bd9Sstevel@tonic-gate 					f->f_type = F_UNUSED;
19517c478bd9Sstevel@tonic-gate 					logerror(f->f_un.f_fname);
19527c478bd9Sstevel@tonic-gate 					f->f_stat.errs++;
19537c478bd9Sstevel@tonic-gate 				}
19547c478bd9Sstevel@tonic-gate 				untty();
19557c478bd9Sstevel@tonic-gate 			} else {
19567c478bd9Sstevel@tonic-gate 				f->f_type = F_UNUSED;
19577c478bd9Sstevel@tonic-gate 				f->f_stat.errs++;
19587c478bd9Sstevel@tonic-gate 				errno = e;
19597c478bd9Sstevel@tonic-gate 				logerror(f->f_un.f_fname);
19607c478bd9Sstevel@tonic-gate 			}
19617c478bd9Sstevel@tonic-gate 		} else if (flags & SYNC_FILE)
19627c478bd9Sstevel@tonic-gate 			if (((pri & LOG_FACMASK) >> 3) == LOG_KERN)
19637c478bd9Sstevel@tonic-gate 				(void) fsync(f->f_file);
19647c478bd9Sstevel@tonic-gate 
19657c478bd9Sstevel@tonic-gate 		DPRINT2(5, "writemsg(%u): freeing filtered (%p)\n",
1966*0ea5e3a5Sjjj 			mythreadno, (void *)filtered);
19677c478bd9Sstevel@tonic-gate 
19687c478bd9Sstevel@tonic-gate 		free(filtered);
19697c478bd9Sstevel@tonic-gate 		break;
19707c478bd9Sstevel@tonic-gate 	}
19717c478bd9Sstevel@tonic-gate }
19727c478bd9Sstevel@tonic-gate 
19737c478bd9Sstevel@tonic-gate /*
19747c478bd9Sstevel@tonic-gate  *  WALLMSG -- Write a message to the world at large
19757c478bd9Sstevel@tonic-gate  *
19767c478bd9Sstevel@tonic-gate  *	Write the specified message to either the entire
19777c478bd9Sstevel@tonic-gate  *	world, or a list of approved users.
19787c478bd9Sstevel@tonic-gate  */
19797c478bd9Sstevel@tonic-gate static void
19807c478bd9Sstevel@tonic-gate wallmsg(struct filed *f, char *from, char *msg)
19817c478bd9Sstevel@tonic-gate {
19827c478bd9Sstevel@tonic-gate 	int i;
19837c478bd9Sstevel@tonic-gate 	size_t	len, clen;
19847c478bd9Sstevel@tonic-gate 	char *buf = NULL;
19857c478bd9Sstevel@tonic-gate 	struct utmpx *utxp;
19867c478bd9Sstevel@tonic-gate 	time_t now;
19877c478bd9Sstevel@tonic-gate 	char line[512], dev[100];
19887c478bd9Sstevel@tonic-gate 	char cp[MAXLINE+1];
19897c478bd9Sstevel@tonic-gate 	struct stat statbuf;
19907c478bd9Sstevel@tonic-gate 	walldev_t *w;
19917c478bd9Sstevel@tonic-gate 	char cbuf[30];
19927c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
19937c478bd9Sstevel@tonic-gate 
19947c478bd9Sstevel@tonic-gate 	if (Debug) {
19957c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
19967c478bd9Sstevel@tonic-gate 	}
19977c478bd9Sstevel@tonic-gate 
19987c478bd9Sstevel@tonic-gate 	if (access(UTMPX_FILE, R_OK) != 0 || stat(UTMPX_FILE, &statbuf) != 0) {
19997c478bd9Sstevel@tonic-gate 		logerror(UTMPX_FILE);
20007c478bd9Sstevel@tonic-gate 		return;
20017c478bd9Sstevel@tonic-gate 	} else if (statbuf.st_uid != 0 || (statbuf.st_mode & 07777) != 0644) {
2002*0ea5e3a5Sjjj 		(void) snprintf(line, sizeof (line), "%s %s", UTMPX_FILE,
20037c478bd9Sstevel@tonic-gate 			"not owned by root or not mode 644.\n"
20047c478bd9Sstevel@tonic-gate 			"This file must be owned by root "
20057c478bd9Sstevel@tonic-gate 			"and not writable by\n"
20067c478bd9Sstevel@tonic-gate 			"anyone other than root.  This alert is being "
20077c478bd9Sstevel@tonic-gate 			"dropped because of\n"
20087c478bd9Sstevel@tonic-gate 			"this problem.");
20097c478bd9Sstevel@tonic-gate 		logerror(line);
20107c478bd9Sstevel@tonic-gate 		return;
20117c478bd9Sstevel@tonic-gate 	}
20127c478bd9Sstevel@tonic-gate 
20137c478bd9Sstevel@tonic-gate 	if (f->f_type == F_WALL) {
20147c478bd9Sstevel@tonic-gate 		(void) time(&now);
20157c478bd9Sstevel@tonic-gate 		len = snprintf(line, sizeof (line),
20167c478bd9Sstevel@tonic-gate 			"\r\n\7Message from syslogd@%s "
20177c478bd9Sstevel@tonic-gate 			"at %.24s ...\r\n", from, ctime_r(&now, cbuf));
20187c478bd9Sstevel@tonic-gate 		len += strlen(msg + 16);
20197c478bd9Sstevel@tonic-gate 		buf = (char *)malloc(len + 1);
20207c478bd9Sstevel@tonic-gate 		if (!buf) {
20217c478bd9Sstevel@tonic-gate 			MALLOC_FAIL("dropping message");
20227c478bd9Sstevel@tonic-gate 			return;
20237c478bd9Sstevel@tonic-gate 		}
20247c478bd9Sstevel@tonic-gate 		DPRINT3(5, "wallmsg(%u): buf allocated (%p: %d bytes)\n",
2025*0ea5e3a5Sjjj 			mythreadno, (void *)buf, len + 1);
20267c478bd9Sstevel@tonic-gate 		(void) strcpy(buf, line);
20277c478bd9Sstevel@tonic-gate 		(void) strcat(buf, msg + 16);
20287c478bd9Sstevel@tonic-gate 		clen = copy_frwd(cp, sizeof (cp), buf, len);
20297c478bd9Sstevel@tonic-gate 		DPRINT2(5, "wallmsg(%u): clen = %d\n",
20307c478bd9Sstevel@tonic-gate 			mythreadno, clen);
20317c478bd9Sstevel@tonic-gate 		DPRINT2(5, "wallmsg(%u): freeing buf (%p)\n",
2032*0ea5e3a5Sjjj 			mythreadno, (void *)buf);
20337c478bd9Sstevel@tonic-gate 		free(buf);
20347c478bd9Sstevel@tonic-gate 	} else {
20357c478bd9Sstevel@tonic-gate 		clen = copy_frwd(cp, sizeof (cp), msg, strlen(msg));
20367c478bd9Sstevel@tonic-gate 		DPRINT2(5, "wallmsg(%u): clen = %d\n",
20377c478bd9Sstevel@tonic-gate 			mythreadno, clen);
20387c478bd9Sstevel@tonic-gate 	}
20397c478bd9Sstevel@tonic-gate 	/* scan the user login file */
20407c478bd9Sstevel@tonic-gate 	setutxent();
20417c478bd9Sstevel@tonic-gate 	while ((utxp = getutxent()) != NULL) {
20427c478bd9Sstevel@tonic-gate 		/* is this slot used? */
20437c478bd9Sstevel@tonic-gate 		if (utxp->ut_name[0] == '\0' ||
20447c478bd9Sstevel@tonic-gate 			utxp->ut_line[0] == '\0' ||
20457c478bd9Sstevel@tonic-gate 			utxp->ut_type != USER_PROCESS)
20467c478bd9Sstevel@tonic-gate 			continue;
20477c478bd9Sstevel@tonic-gate 		/* should we send the message to this user? */
20487c478bd9Sstevel@tonic-gate 		if (f->f_type == F_USERS) {
20497c478bd9Sstevel@tonic-gate 			for (i = 0; i < MAXUNAMES; i++) {
20507c478bd9Sstevel@tonic-gate 				if (!f->f_un.f_uname[i][0]) {
20517c478bd9Sstevel@tonic-gate 					i = MAXUNAMES;
20527c478bd9Sstevel@tonic-gate 					break;
20537c478bd9Sstevel@tonic-gate 				}
20547c478bd9Sstevel@tonic-gate 				if (strncmp(f->f_un.f_uname[i],
20557c478bd9Sstevel@tonic-gate 					utxp->ut_name, UNAMESZ) == 0)
20567c478bd9Sstevel@tonic-gate 					break;
20577c478bd9Sstevel@tonic-gate 			}
20587c478bd9Sstevel@tonic-gate 			if (i >= MAXUNAMES)
20597c478bd9Sstevel@tonic-gate 				continue;
20607c478bd9Sstevel@tonic-gate 		}
20617c478bd9Sstevel@tonic-gate 
20627c478bd9Sstevel@tonic-gate 		/* compute the device name */
20637c478bd9Sstevel@tonic-gate 		if (utxp->ut_line[0] == '/') {
20647c478bd9Sstevel@tonic-gate 			(void) strncpy(dev, utxp->ut_line, UDEVSZ);
20657c478bd9Sstevel@tonic-gate 		} else {
20667c478bd9Sstevel@tonic-gate 			(void) strcpy(dev, "/dev/");
20677c478bd9Sstevel@tonic-gate 			(void) strncat(dev, utxp->ut_line, UDEVSZ);
20687c478bd9Sstevel@tonic-gate 		}
20697c478bd9Sstevel@tonic-gate 		DPRINT2(1, "wallmsg(%u): write to '%s'\n", mythreadno,
20707c478bd9Sstevel@tonic-gate 			dev);
20717c478bd9Sstevel@tonic-gate 
20727c478bd9Sstevel@tonic-gate 		if ((w = malloc(sizeof (walldev_t))) != NULL) {
20737c478bd9Sstevel@tonic-gate 			int rc;
20747c478bd9Sstevel@tonic-gate 			(void) pthread_attr_init(&w->thread_attr);
20757c478bd9Sstevel@tonic-gate 			(void) pthread_attr_setdetachstate(&w->thread_attr,
20767c478bd9Sstevel@tonic-gate 				PTHREAD_CREATE_DETACHED);
20777c478bd9Sstevel@tonic-gate 			(void) strncpy(w->dev, dev, PATH_MAX);
20787c478bd9Sstevel@tonic-gate 			(void) strncpy(w->msg, cp, MAXLINE+1);
20797c478bd9Sstevel@tonic-gate 			(void) strncpy(w->ut_name, utxp->ut_name,
20807c478bd9Sstevel@tonic-gate 			    sizeof (w->ut_name));
20817c478bd9Sstevel@tonic-gate 
20827c478bd9Sstevel@tonic-gate 			if ((rc = pthread_create(&w->thread, &w->thread_attr,
20837c478bd9Sstevel@tonic-gate 				writetodev, (void *) w)) != 0) {
20847c478bd9Sstevel@tonic-gate 				DPRINT2(5, "wallmsg(%u): wallmsg thread "
20857c478bd9Sstevel@tonic-gate 					"create failed rc = %d\n",
20867c478bd9Sstevel@tonic-gate 					mythreadno, rc);
20877c478bd9Sstevel@tonic-gate 				free(w);
20887c478bd9Sstevel@tonic-gate 				break;
20897c478bd9Sstevel@tonic-gate 			}
20907c478bd9Sstevel@tonic-gate 		} else {
20917c478bd9Sstevel@tonic-gate 			MALLOC_FAIL("dropping message to user");
20927c478bd9Sstevel@tonic-gate 		}
20937c478bd9Sstevel@tonic-gate 	}
20947c478bd9Sstevel@tonic-gate 	/* close the user login file */
20957c478bd9Sstevel@tonic-gate 	endutxent();
20967c478bd9Sstevel@tonic-gate }
20977c478bd9Sstevel@tonic-gate 
20987c478bd9Sstevel@tonic-gate /*
20997c478bd9Sstevel@tonic-gate  * Each time we need to write to a tty device (a potentially expensive
21007c478bd9Sstevel@tonic-gate  * or long-running operation) this routine gets called as a new
21017c478bd9Sstevel@tonic-gate  * detached, unbound thread. This allows writes to many devices
21027c478bd9Sstevel@tonic-gate  * to proceed nearly in parallel, without having to resort to
21037c478bd9Sstevel@tonic-gate  * asynchronous I/O or forking.
21047c478bd9Sstevel@tonic-gate  */
21057c478bd9Sstevel@tonic-gate static void *
21067c478bd9Sstevel@tonic-gate writetodev(void *ap)
21077c478bd9Sstevel@tonic-gate {
21087c478bd9Sstevel@tonic-gate 	walldev_t *w = ap;
21097c478bd9Sstevel@tonic-gate 	int ttyf;
21107c478bd9Sstevel@tonic-gate 	int len;
21117c478bd9Sstevel@tonic-gate 	struct stat statb;
21127c478bd9Sstevel@tonic-gate 	struct passwd pw, *pwp;
21137c478bd9Sstevel@tonic-gate 	char pwbuf[MAXLINE];
21147c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
21157c478bd9Sstevel@tonic-gate 
21167c478bd9Sstevel@tonic-gate 	if (Debug) {
21177c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
21187c478bd9Sstevel@tonic-gate 	}
21197c478bd9Sstevel@tonic-gate 
21207c478bd9Sstevel@tonic-gate 	DPRINT1(1, "writetodev(%u): Device writer thread started\n",
21217c478bd9Sstevel@tonic-gate 		mythreadno);
21227c478bd9Sstevel@tonic-gate 
21237c478bd9Sstevel@tonic-gate 	len = strlen(w->msg);
21247c478bd9Sstevel@tonic-gate 
21257c478bd9Sstevel@tonic-gate 	ttyf = open(w->dev, O_WRONLY|O_NOCTTY|O_NDELAY);
21267c478bd9Sstevel@tonic-gate 	if (ttyf >= 0) {
21277c478bd9Sstevel@tonic-gate 		if (fstat(ttyf, &statb) != 0) {
21287c478bd9Sstevel@tonic-gate 			DPRINT2(1, "writetodev(%u): Can't stat '%s'\n",
21297c478bd9Sstevel@tonic-gate 				mythreadno, w->dev);
21307c478bd9Sstevel@tonic-gate 			errno = 0;
21317c478bd9Sstevel@tonic-gate 			logerror("Can't stat '%s'", w->dev);
21327c478bd9Sstevel@tonic-gate 		} else if (!(statb.st_mode & S_IWRITE)) {
21337c478bd9Sstevel@tonic-gate 			DPRINT2(1, "writetodev(%u): Can't write to "
21347c478bd9Sstevel@tonic-gate 				"'%s'\n", mythreadno, w->dev);
21357c478bd9Sstevel@tonic-gate 		} else if (!isatty(ttyf)) {
21367c478bd9Sstevel@tonic-gate 			DPRINT2(1, "writetodev(%u): '%s' not a tty\n",
21377c478bd9Sstevel@tonic-gate 				mythreadno, w->dev);
21387c478bd9Sstevel@tonic-gate 			/*
21397c478bd9Sstevel@tonic-gate 			 * We might hit dtremote here. Don't generate
21407c478bd9Sstevel@tonic-gate 			 * error message.
21417c478bd9Sstevel@tonic-gate 			 */
21427c478bd9Sstevel@tonic-gate 		} else if (getpwuid_r(statb.st_uid, &pw, pwbuf,
21437c478bd9Sstevel@tonic-gate 				sizeof (pwbuf), &pwp) != 0) {
21447c478bd9Sstevel@tonic-gate 			DPRINT2(1, "writetodev(%u): Can't determine owner "
21457c478bd9Sstevel@tonic-gate 				"of '%s'\n", mythreadno, w->dev);
21467c478bd9Sstevel@tonic-gate 			errno = 0;
21477c478bd9Sstevel@tonic-gate 			logerror("Can't determine owner of '%s'", w->dev);
21487c478bd9Sstevel@tonic-gate 		} else if (strncmp(pw.pw_name, w->ut_name, UNAMESZ) != 0) {
21497c478bd9Sstevel@tonic-gate 			DPRINT2(1, "writetodev(%u): Bad terminal owner '%s'"
21507c478bd9Sstevel@tonic-gate 				"\n", mythreadno, w->dev);
21517c478bd9Sstevel@tonic-gate 			errno = 0;
21527c478bd9Sstevel@tonic-gate 			logerror("%s %s owns '%s' %s %.*s",
21537c478bd9Sstevel@tonic-gate 				"Bad terminal owner;", pw.pw_name, w->dev,
21547c478bd9Sstevel@tonic-gate 				"but utmpx says", UNAMESZ, w->ut_name);
21557c478bd9Sstevel@tonic-gate 		} else if (write(ttyf, w->msg, len) != len) {
21567c478bd9Sstevel@tonic-gate 			DPRINT2(1, "writetodev(%u): Write failed to "
21577c478bd9Sstevel@tonic-gate 				"'%s'\n", mythreadno, w->dev);
21587c478bd9Sstevel@tonic-gate 			errno = 0;
21597c478bd9Sstevel@tonic-gate 			logerror("Write failed to '%s'", w->dev);
21607c478bd9Sstevel@tonic-gate 		}
21617c478bd9Sstevel@tonic-gate 
21627c478bd9Sstevel@tonic-gate 		DPRINT2(1, "writetodev(%u): write to '%s' succeeded\n",
21637c478bd9Sstevel@tonic-gate 			mythreadno, w->dev);
21647c478bd9Sstevel@tonic-gate 
21657c478bd9Sstevel@tonic-gate 		(void) close(ttyf);
21667c478bd9Sstevel@tonic-gate 	} else {
21677c478bd9Sstevel@tonic-gate 		DPRINT2(1, "writetodev(%u): Can't open '%s'\n",
21687c478bd9Sstevel@tonic-gate 			mythreadno, w->dev);
21697c478bd9Sstevel@tonic-gate 	}
21707c478bd9Sstevel@tonic-gate 
2171*0ea5e3a5Sjjj 	(void) pthread_attr_destroy(&w->thread_attr);
21727c478bd9Sstevel@tonic-gate 	free(w);
21737c478bd9Sstevel@tonic-gate 
21747c478bd9Sstevel@tonic-gate 	DPRINT1(1, "writetodev(%u): Device writer thread exiting\n",
21757c478bd9Sstevel@tonic-gate 		mythreadno);
21767c478bd9Sstevel@tonic-gate 
21777c478bd9Sstevel@tonic-gate 	pthread_exit(0);
21787c478bd9Sstevel@tonic-gate 	return (NULL);
21797c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
21807c478bd9Sstevel@tonic-gate }
21817c478bd9Sstevel@tonic-gate 
21827c478bd9Sstevel@tonic-gate /*
21837c478bd9Sstevel@tonic-gate  * Return a printable representation of a host address. If unable to
21847c478bd9Sstevel@tonic-gate  * look up hostname, format the numeric address for display instead.
21857c478bd9Sstevel@tonic-gate  *
21867c478bd9Sstevel@tonic-gate  * First calls hnc_lookup to see if there is valid cache entry for
21877c478bd9Sstevel@tonic-gate  * given network address. If it failed, cvthname looks up hostname,
21887c478bd9Sstevel@tonic-gate  * and push the results into the hostname cache.
21897c478bd9Sstevel@tonic-gate  */
21907c478bd9Sstevel@tonic-gate static host_list_t *
21917c478bd9Sstevel@tonic-gate cvthname(struct netbuf *nbp, struct netconfig *ncp, char *failsafe_addr)
21927c478bd9Sstevel@tonic-gate {
21937c478bd9Sstevel@tonic-gate 	int i;
21947c478bd9Sstevel@tonic-gate 	host_list_t *h;
21957c478bd9Sstevel@tonic-gate 	struct nd_hostservlist *hsp;
21967c478bd9Sstevel@tonic-gate 	struct nd_hostserv *hspp;
21977c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
2198293d1fc4Spd155743 	int hindex;
21997c478bd9Sstevel@tonic-gate 	char *uap;
22007c478bd9Sstevel@tonic-gate 
22017c478bd9Sstevel@tonic-gate 	if (Debug) {
22027c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
22037c478bd9Sstevel@tonic-gate 	}
22047c478bd9Sstevel@tonic-gate 
22057c478bd9Sstevel@tonic-gate 	if (Debug)
22067c478bd9Sstevel@tonic-gate 		uap = taddr2uaddr(ncp, nbp);
22077c478bd9Sstevel@tonic-gate 
22087c478bd9Sstevel@tonic-gate 	DPRINT2(2, "cvthname(%u): looking up hostname for %s\n",
22097c478bd9Sstevel@tonic-gate 			mythreadno, uap ? uap : "<unknown>");
22107c478bd9Sstevel@tonic-gate 
2211293d1fc4Spd155743 	if ((h = hnc_lookup(nbp, ncp, &hindex)) != NULL) {
22127c478bd9Sstevel@tonic-gate 		DPRINT4(2, "cvthname(%u): Cache found %p for %s (%s)\n",
2213*0ea5e3a5Sjjj 			mythreadno, (void *)h, uap ? uap : "<unknown>",
22147c478bd9Sstevel@tonic-gate 				h->hl_hosts[0]);
22157c478bd9Sstevel@tonic-gate 		return (h);
22167c478bd9Sstevel@tonic-gate 	}
22177c478bd9Sstevel@tonic-gate 	DPRINT2(2, "cvthname(%u): No cache found for %s\n",
22187c478bd9Sstevel@tonic-gate 			mythreadno, uap ? uap : "<unknown>");
22197c478bd9Sstevel@tonic-gate 
22207c478bd9Sstevel@tonic-gate 	if (Debug)
22217c478bd9Sstevel@tonic-gate 		free(uap);
22227c478bd9Sstevel@tonic-gate 
22237c478bd9Sstevel@tonic-gate 	if (ncp->nc_semantics != NC_TPI_CLTS) {
22247c478bd9Sstevel@tonic-gate 		return (NULL);
22257c478bd9Sstevel@tonic-gate 	}
22267c478bd9Sstevel@tonic-gate 
22277c478bd9Sstevel@tonic-gate 	/* memory allocation failure here is fatal */
22287c478bd9Sstevel@tonic-gate 	if ((h = malloc(sizeof (host_list_t))) == NULL) {
22297c478bd9Sstevel@tonic-gate 		MALLOC_FAIL("host name conversion");
22307c478bd9Sstevel@tonic-gate 		return (NULL);
22317c478bd9Sstevel@tonic-gate 	}
22327c478bd9Sstevel@tonic-gate 
22337c478bd9Sstevel@tonic-gate 	if (netdir_getbyaddr(ncp, &hsp, nbp) == 0) {
22347c478bd9Sstevel@tonic-gate 		if (hsp->h_cnt <= 0) {
22357c478bd9Sstevel@tonic-gate out:			netdir_free((void *)hsp, ND_HOSTSERVLIST);
22367c478bd9Sstevel@tonic-gate 			free(h);
22377c478bd9Sstevel@tonic-gate 			return (NULL);
22387c478bd9Sstevel@tonic-gate 		}
22397c478bd9Sstevel@tonic-gate 
22407c478bd9Sstevel@tonic-gate 		hspp = hsp->h_hostservs;
22417c478bd9Sstevel@tonic-gate 		h->hl_cnt = hsp->h_cnt;
22427c478bd9Sstevel@tonic-gate 		h->hl_hosts = (char **)malloc(sizeof (char *) * (h->hl_cnt));
22437c478bd9Sstevel@tonic-gate 		if (h->hl_hosts == NULL) {
22447c478bd9Sstevel@tonic-gate 			MALLOC_FAIL("host name conversion");
22457c478bd9Sstevel@tonic-gate 			goto out;
22467c478bd9Sstevel@tonic-gate 		}
22477c478bd9Sstevel@tonic-gate 
22487c478bd9Sstevel@tonic-gate 		DPRINT2(2, "cvthname(%u): Found %d hostnames\n",
22497c478bd9Sstevel@tonic-gate 					mythreadno, h->hl_cnt);
22507c478bd9Sstevel@tonic-gate 		for (i = 0; i < h->hl_cnt; i++) {
22517c478bd9Sstevel@tonic-gate 			h->hl_hosts[i] = (char *)
22527c478bd9Sstevel@tonic-gate 			    malloc(sizeof (char) * (strlen(hspp->h_host) + 1));
22537c478bd9Sstevel@tonic-gate 			if (h->hl_hosts[i] == NULL) {
22547c478bd9Sstevel@tonic-gate 				int j;
22557c478bd9Sstevel@tonic-gate 				for (j = 0; j < i; j++) {
22567c478bd9Sstevel@tonic-gate 					free(h->hl_hosts[j]);
22577c478bd9Sstevel@tonic-gate 				}
22587c478bd9Sstevel@tonic-gate 				free(h->hl_hosts);
22597c478bd9Sstevel@tonic-gate 				MALLOC_FAIL("host name conversion");
22607c478bd9Sstevel@tonic-gate 				goto out;
22617c478bd9Sstevel@tonic-gate 			}
22627c478bd9Sstevel@tonic-gate 			(void) strcpy(h->hl_hosts[i], hspp->h_host);
22637c478bd9Sstevel@tonic-gate 			hspp++;
22647c478bd9Sstevel@tonic-gate 		}
22657c478bd9Sstevel@tonic-gate 		netdir_free((void *)hsp, ND_HOSTSERVLIST);
22667c478bd9Sstevel@tonic-gate 	} else { /* unknown address */
22677c478bd9Sstevel@tonic-gate 		h->hl_cnt = 1;
22687c478bd9Sstevel@tonic-gate 		h->hl_hosts = (char **)malloc(sizeof (char *));
22697c478bd9Sstevel@tonic-gate 		if (h->hl_hosts == NULL) {
22707c478bd9Sstevel@tonic-gate 			free(h);
22717c478bd9Sstevel@tonic-gate 			MALLOC_FAIL("host name conversion");
22727c478bd9Sstevel@tonic-gate 			return (NULL);
22737c478bd9Sstevel@tonic-gate 		}
22747c478bd9Sstevel@tonic-gate 		h->hl_hosts[0] = (char *)malloc(strlen(failsafe_addr) + 3);
22757c478bd9Sstevel@tonic-gate 		if (h->hl_hosts[0] == NULL) {
22767c478bd9Sstevel@tonic-gate 			free(h->hl_hosts);
22777c478bd9Sstevel@tonic-gate 			free(h);
22787c478bd9Sstevel@tonic-gate 			MALLOC_FAIL("host name conversion");
22797c478bd9Sstevel@tonic-gate 			return (NULL);
22807c478bd9Sstevel@tonic-gate 		}
2281*0ea5e3a5Sjjj 		/*LINTED*/
22827c478bd9Sstevel@tonic-gate 		(void) sprintf(h->hl_hosts[0], "[%s]", failsafe_addr);
22837c478bd9Sstevel@tonic-gate 		DPRINT2(1, "cvthname(%u): Hostname lookup failed "
22847c478bd9Sstevel@tonic-gate 			"- using address %s instead\n",
22857c478bd9Sstevel@tonic-gate 			mythreadno, h->hl_hosts[0]);
22867c478bd9Sstevel@tonic-gate 	}
22877c478bd9Sstevel@tonic-gate 
22887c478bd9Sstevel@tonic-gate 	h->hl_refcnt = 1;
22897c478bd9Sstevel@tonic-gate 	if (pthread_mutex_init(&h->hl_mutex, NULL) != 0) {
22907c478bd9Sstevel@tonic-gate 		logerror("pthread_mutex_init failed");
22917c478bd9Sstevel@tonic-gate 		/* This host_list won't be shared by the cache. */
22927c478bd9Sstevel@tonic-gate 		return (h);
22937c478bd9Sstevel@tonic-gate 	}
2294293d1fc4Spd155743 	hnc_register(nbp, ncp, h, hindex);
22957c478bd9Sstevel@tonic-gate 	DPRINT3(2, "cvthname(%u): returning %p for %s\n",
2296*0ea5e3a5Sjjj 		mythreadno, (void *)h, h->hl_hosts[0]);
22977c478bd9Sstevel@tonic-gate 	return (h);
22987c478bd9Sstevel@tonic-gate }
22997c478bd9Sstevel@tonic-gate 
23007c478bd9Sstevel@tonic-gate /*
23017c478bd9Sstevel@tonic-gate  * Print syslogd errors some place. Need to be careful here, because
23027c478bd9Sstevel@tonic-gate  * this routine is called at times when we're not initialized and
23037c478bd9Sstevel@tonic-gate  * ready to log messages...in this case, fall back to using the console.
23047c478bd9Sstevel@tonic-gate  */
23057c478bd9Sstevel@tonic-gate void
23067c478bd9Sstevel@tonic-gate logerror(const char *type, ...)
23077c478bd9Sstevel@tonic-gate {
23087c478bd9Sstevel@tonic-gate 	char buf[MAXLINE+1];
23097c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
23107c478bd9Sstevel@tonic-gate 	int flag;
23117c478bd9Sstevel@tonic-gate 	va_list ap;
23127c478bd9Sstevel@tonic-gate 
23137c478bd9Sstevel@tonic-gate 	if (Debug) {
23147c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
23157c478bd9Sstevel@tonic-gate 	}
23167c478bd9Sstevel@tonic-gate 
23177c478bd9Sstevel@tonic-gate 	va_start(ap, type);
23187c478bd9Sstevel@tonic-gate 	logerror_format(type, buf, ap);
23197c478bd9Sstevel@tonic-gate 	va_end(ap);
23207c478bd9Sstevel@tonic-gate 	DPRINT2(1, "logerror(%u): %s\n", mythreadno, buf);
23217c478bd9Sstevel@tonic-gate 
2322*0ea5e3a5Sjjj 	(void) pthread_mutex_lock(&logerror_lock);
23237c478bd9Sstevel@tonic-gate 	if (!interrorlog) {
23247c478bd9Sstevel@tonic-gate 		flag = 0;
23257c478bd9Sstevel@tonic-gate 		if (logerror_to_console(1, buf) == 0) {
23267c478bd9Sstevel@tonic-gate 			/* has written to the console */
23277c478bd9Sstevel@tonic-gate 			flag = IGN_CONS;
23287c478bd9Sstevel@tonic-gate 		}
23297c478bd9Sstevel@tonic-gate 		(void) logmymsg(LOG_SYSLOG|LOG_ERR, buf, ADDDATE|flag, 1);
23307c478bd9Sstevel@tonic-gate 	} else {
23317c478bd9Sstevel@tonic-gate 		if (logmymsg(LOG_SYSLOG|LOG_ERR, buf, ADDDATE, 0) == -1) {
23327c478bd9Sstevel@tonic-gate 			(void) logerror_to_console(1, buf);
23337c478bd9Sstevel@tonic-gate 		}
23347c478bd9Sstevel@tonic-gate 	}
2335*0ea5e3a5Sjjj 	(void) pthread_mutex_unlock(&logerror_lock);
23367c478bd9Sstevel@tonic-gate 
23377c478bd9Sstevel@tonic-gate 	errno = 0;
23387c478bd9Sstevel@tonic-gate 	t_errno = 0;
23397c478bd9Sstevel@tonic-gate }
23407c478bd9Sstevel@tonic-gate 
23417c478bd9Sstevel@tonic-gate static void
23427c478bd9Sstevel@tonic-gate logerror_format(const char *type, char *buf, va_list ap)
23437c478bd9Sstevel@tonic-gate {
23447c478bd9Sstevel@tonic-gate 	char tmpbuf[MAXLINE + 1];
23457c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
23467c478bd9Sstevel@tonic-gate 
23477c478bd9Sstevel@tonic-gate 	if (Debug) {
23487c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
23497c478bd9Sstevel@tonic-gate 	}
23507c478bd9Sstevel@tonic-gate 
23517c478bd9Sstevel@tonic-gate 	(void) vsnprintf(tmpbuf, MAXLINE, type, ap);
23527c478bd9Sstevel@tonic-gate 
23537c478bd9Sstevel@tonic-gate 	if (t_errno == 0 || t_errno == TSYSERR) {
23547c478bd9Sstevel@tonic-gate 		char *errstr;
23557c478bd9Sstevel@tonic-gate 
23567c478bd9Sstevel@tonic-gate 		if (errno == 0) {
23577c478bd9Sstevel@tonic-gate 			(void) snprintf(buf, MAXLINE, "syslogd: %.*s",
23587c478bd9Sstevel@tonic-gate 				MAXLINE, tmpbuf);
23597c478bd9Sstevel@tonic-gate 		} else if ((errstr = strerror(errno)) == (char *)NULL) {
23607c478bd9Sstevel@tonic-gate 			(void) snprintf(buf, MAXLINE, "syslogd: %s: error"
23617c478bd9Sstevel@tonic-gate 				" %d", tmpbuf, errno);
23627c478bd9Sstevel@tonic-gate 		} else {
23637c478bd9Sstevel@tonic-gate 			(void) snprintf(buf, MAXLINE, "syslogd: %s: %s",
23647c478bd9Sstevel@tonic-gate 				tmpbuf, errstr);
23657c478bd9Sstevel@tonic-gate 		}
23667c478bd9Sstevel@tonic-gate 	} else {
23677c478bd9Sstevel@tonic-gate 		if (t_errno > t_nerr) {
23687c478bd9Sstevel@tonic-gate 			(void) snprintf(buf, MAXLINE, "syslogd: %s:"
23697c478bd9Sstevel@tonic-gate 				" t_error %d", tmpbuf, t_errno);
23707c478bd9Sstevel@tonic-gate 		} else {
23717c478bd9Sstevel@tonic-gate 			(void) snprintf(buf, MAXLINE, "syslogd: %s: %s",
23727c478bd9Sstevel@tonic-gate 				tmpbuf, t_errlist[t_errno]);
23737c478bd9Sstevel@tonic-gate 		}
23747c478bd9Sstevel@tonic-gate 	}
23757c478bd9Sstevel@tonic-gate 
23767c478bd9Sstevel@tonic-gate 	DPRINT2(5, "logerror_format(%u): out %s\n", mythreadno, buf);
23777c478bd9Sstevel@tonic-gate }
23787c478bd9Sstevel@tonic-gate 
23797c478bd9Sstevel@tonic-gate static int
23807c478bd9Sstevel@tonic-gate logerror_to_console(int nonblock, const char *buf)
23817c478bd9Sstevel@tonic-gate {
23827c478bd9Sstevel@tonic-gate 	int cfd, modes;
23837c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
23847c478bd9Sstevel@tonic-gate 	int ret = 0, len;
23857c478bd9Sstevel@tonic-gate 	char tmpbuf[MAXLINE + 1];
23867c478bd9Sstevel@tonic-gate 
23877c478bd9Sstevel@tonic-gate 	if (Debug) {
23887c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
23897c478bd9Sstevel@tonic-gate 	}
23907c478bd9Sstevel@tonic-gate 
23917c478bd9Sstevel@tonic-gate 	DPRINT2(1, "logerror_to_console(%u): %s\n", mythreadno, buf);
23927c478bd9Sstevel@tonic-gate 
23937c478bd9Sstevel@tonic-gate 	/*
23947c478bd9Sstevel@tonic-gate 	 * must use open here instead of fopen, because
23957c478bd9Sstevel@tonic-gate 	 * we need the O_NOCTTY behavior - otherwise we
23967c478bd9Sstevel@tonic-gate 	 * could hang the console at boot time
23977c478bd9Sstevel@tonic-gate 	 */
23987c478bd9Sstevel@tonic-gate 
23997c478bd9Sstevel@tonic-gate 	modes = (nonblock) ?
24007c478bd9Sstevel@tonic-gate 		O_WRONLY|O_APPEND|O_NOCTTY|O_NONBLOCK :
24017c478bd9Sstevel@tonic-gate 		O_WRONLY|O_APPEND|O_NOCTTY;
24027c478bd9Sstevel@tonic-gate 
24037c478bd9Sstevel@tonic-gate 	if (((cfd = open(sysmsg, modes)) >= 0) ||
24047c478bd9Sstevel@tonic-gate 	    ((cfd = open(ctty, modes)) >= 0)) {
24057c478bd9Sstevel@tonic-gate 		(void) snprintf(tmpbuf, MAXLINE, "%s\n", buf);
24067c478bd9Sstevel@tonic-gate 		len = strlen(tmpbuf);
24077c478bd9Sstevel@tonic-gate 		if (write(cfd, tmpbuf, len) != len) {
24087c478bd9Sstevel@tonic-gate 			ret = 1;
24097c478bd9Sstevel@tonic-gate 		}
24107c478bd9Sstevel@tonic-gate 		(void) close(cfd);
24117c478bd9Sstevel@tonic-gate 	} else {
24127c478bd9Sstevel@tonic-gate 		ret = 1;
24137c478bd9Sstevel@tonic-gate 
24147c478bd9Sstevel@tonic-gate 		/* punt */
24157c478bd9Sstevel@tonic-gate 		DPRINT1(1, "logerror_console(%u): can't open console\n",
24167c478bd9Sstevel@tonic-gate 			mythreadno);
24177c478bd9Sstevel@tonic-gate 	}
24187c478bd9Sstevel@tonic-gate 	return (ret);
24197c478bd9Sstevel@tonic-gate }
24207c478bd9Sstevel@tonic-gate 
24217c478bd9Sstevel@tonic-gate /*
24227c478bd9Sstevel@tonic-gate  * copy current message to saved message in filed structure.
24237c478bd9Sstevel@tonic-gate  */
24247c478bd9Sstevel@tonic-gate static void
24257c478bd9Sstevel@tonic-gate copy_msg(struct filed *f)
24267c478bd9Sstevel@tonic-gate {
24277c478bd9Sstevel@tonic-gate 	(void) strlcpy(f->f_prevmsg.msg, f->f_current.msg, MAXLINE+1);
24287c478bd9Sstevel@tonic-gate 	(void) strlcpy(f->f_prevmsg.host, f->f_current.host, SYS_NMLN);
24297c478bd9Sstevel@tonic-gate 	f->f_prevmsg.pri = f->f_current.pri;
24307c478bd9Sstevel@tonic-gate 	f->f_prevmsg.flags = f->f_current.flags;
24317c478bd9Sstevel@tonic-gate 	f->f_prevmsg.time = f->f_current.time;
24327c478bd9Sstevel@tonic-gate 	f->f_msgflag |= OLD_VALID;
24337c478bd9Sstevel@tonic-gate }
24347c478bd9Sstevel@tonic-gate 
24357c478bd9Sstevel@tonic-gate 
24367c478bd9Sstevel@tonic-gate /*
24377c478bd9Sstevel@tonic-gate  * function to free a host_list_t struct that was allocated
24387c478bd9Sstevel@tonic-gate  * out of cvthname(). There is a special case where we don't
24397c478bd9Sstevel@tonic-gate  * free the hostname list in LocalHostName, because that's
24407c478bd9Sstevel@tonic-gate  * our own addresses, and we just want to have to look it
24417c478bd9Sstevel@tonic-gate  * up once and save it.  Also don't free it if it's
24427c478bd9Sstevel@tonic-gate  * NullHostName, because that's a special one we use if
24437c478bd9Sstevel@tonic-gate  * name service lookup fails.
24447c478bd9Sstevel@tonic-gate  *
24457c478bd9Sstevel@tonic-gate  * By having hostname cache, now host_list_t will be shared
24467c478bd9Sstevel@tonic-gate  * by messages and hostname cache. hl_refcnt is used for
24477c478bd9Sstevel@tonic-gate  * the purpose.
24487c478bd9Sstevel@tonic-gate  */
24497c478bd9Sstevel@tonic-gate static void
24507c478bd9Sstevel@tonic-gate freehl(host_list_t *h)
24517c478bd9Sstevel@tonic-gate {
24527c478bd9Sstevel@tonic-gate 	int i, refcnt;
24537c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
24547c478bd9Sstevel@tonic-gate 
24557c478bd9Sstevel@tonic-gate 	if (Debug) {
24567c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
24577c478bd9Sstevel@tonic-gate 	}
24587c478bd9Sstevel@tonic-gate 
2459*0ea5e3a5Sjjj 	DPRINT2(2, "freehl(%u): releasing %p\n", mythreadno, (void *)h);
24607c478bd9Sstevel@tonic-gate 
24617c478bd9Sstevel@tonic-gate 	if (h == NULL || h == &LocalHostName || h == &NullHostName) {
24627c478bd9Sstevel@tonic-gate 		return;
24637c478bd9Sstevel@tonic-gate 	}
24647c478bd9Sstevel@tonic-gate 
2465*0ea5e3a5Sjjj 	(void) pthread_mutex_lock(&h->hl_mutex);
24667c478bd9Sstevel@tonic-gate 	refcnt = --h->hl_refcnt;
2467*0ea5e3a5Sjjj 	(void) pthread_mutex_unlock(&h->hl_mutex);
24687c478bd9Sstevel@tonic-gate 
24697c478bd9Sstevel@tonic-gate 	if (refcnt != 0) {
24707c478bd9Sstevel@tonic-gate 		DPRINT3(5, "freehl(%u): %p has reference %d\n",
2471*0ea5e3a5Sjjj 			mythreadno, (void *)h, refcnt);
24727c478bd9Sstevel@tonic-gate 		return;
24737c478bd9Sstevel@tonic-gate 	}
24747c478bd9Sstevel@tonic-gate 
2475*0ea5e3a5Sjjj 	(void) pthread_mutex_destroy(&h->hl_mutex);
24767c478bd9Sstevel@tonic-gate 
2477*0ea5e3a5Sjjj 	DPRINT2(5, "freehl(%u): freeing %p\n", mythreadno, (void *)h);
24787c478bd9Sstevel@tonic-gate 
24797c478bd9Sstevel@tonic-gate 	for (i = 0; i < h->hl_cnt; i++) {
24807c478bd9Sstevel@tonic-gate 		free(h->hl_hosts[i]);
24817c478bd9Sstevel@tonic-gate 	}
24827c478bd9Sstevel@tonic-gate 
24837c478bd9Sstevel@tonic-gate 	free(h->hl_hosts);
24847c478bd9Sstevel@tonic-gate 	free(h);
24857c478bd9Sstevel@tonic-gate }
24867c478bd9Sstevel@tonic-gate 
24877c478bd9Sstevel@tonic-gate /*
24887c478bd9Sstevel@tonic-gate  * Create the door file and the pid file in /var/run.  If the filesystem
24897c478bd9Sstevel@tonic-gate  * containing /etc is writable, create symlinks /etc/.syslog_door and
24907c478bd9Sstevel@tonic-gate  * /etc/syslog.pid to them.  On systems that do not support /var/run, create
24917c478bd9Sstevel@tonic-gate  * /etc/.syslog_door and /etc/syslog.pid directly.
24927c478bd9Sstevel@tonic-gate  *
24937c478bd9Sstevel@tonic-gate  * Note: it is not considered fatal to fail to create the pid file or its
24947c478bd9Sstevel@tonic-gate  * symlink.  Attempts to use them in the usual way will fail, of course, but
24957c478bd9Sstevel@tonic-gate  * syslogd will function nicely without it (not so for the door file).
24967c478bd9Sstevel@tonic-gate  */
24977c478bd9Sstevel@tonic-gate 
24987c478bd9Sstevel@tonic-gate static void
24997c478bd9Sstevel@tonic-gate open_door(void)
25007c478bd9Sstevel@tonic-gate {
25017c478bd9Sstevel@tonic-gate 	struct stat buf;
25027c478bd9Sstevel@tonic-gate 	door_info_t info;
25037c478bd9Sstevel@tonic-gate 	char line[MAXLINE+1];
25047c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
25057c478bd9Sstevel@tonic-gate 	int err;
25067c478bd9Sstevel@tonic-gate 
25077c478bd9Sstevel@tonic-gate 	if (Debug) {
25087c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
25097c478bd9Sstevel@tonic-gate 	}
25107c478bd9Sstevel@tonic-gate 
25117c478bd9Sstevel@tonic-gate 	/*
25127c478bd9Sstevel@tonic-gate 	 * first see if another syslogd is running by trying
25137c478bd9Sstevel@tonic-gate 	 * a door call - if it succeeds, there is already
25147c478bd9Sstevel@tonic-gate 	 * a syslogd process active
25157c478bd9Sstevel@tonic-gate 	 */
25167c478bd9Sstevel@tonic-gate 
25177c478bd9Sstevel@tonic-gate 	if (!DoorCreated) {
25187c478bd9Sstevel@tonic-gate 		int door;
25197c478bd9Sstevel@tonic-gate 
25207c478bd9Sstevel@tonic-gate 		if ((door = open(DoorFileName, O_RDONLY)) >= 0) {
25217c478bd9Sstevel@tonic-gate 			DPRINT2(5, "open_door(%u): %s opened "
25227c478bd9Sstevel@tonic-gate 				"successfully\n", mythreadno, DoorFileName);
25237c478bd9Sstevel@tonic-gate 
25247c478bd9Sstevel@tonic-gate 			if (door_info(door, &info) >= 0) {
25257c478bd9Sstevel@tonic-gate 				DPRINT2(5, "open_door(%u): "
25267c478bd9Sstevel@tonic-gate 					"door_info:info.di_target = %ld\n",
25277c478bd9Sstevel@tonic-gate 					mythreadno, info.di_target);
25287c478bd9Sstevel@tonic-gate 
25297c478bd9Sstevel@tonic-gate 				if (info.di_target > 0) {
25307c478bd9Sstevel@tonic-gate 					(void) sprintf(line, "syslogd pid %ld"
25317c478bd9Sstevel@tonic-gate 						" already running. Cannot "
25327c478bd9Sstevel@tonic-gate 						"start another syslogd pid %ld",
25337c478bd9Sstevel@tonic-gate 						info.di_target, getpid());
25347c478bd9Sstevel@tonic-gate 					DPRINT2(5, "open_door(%u): error: "
25357c478bd9Sstevel@tonic-gate 						"%s\n", mythreadno, line);
25367c478bd9Sstevel@tonic-gate 					errno = 0;
25377c478bd9Sstevel@tonic-gate 					logerror(line);
25387c478bd9Sstevel@tonic-gate 					exit(1);
25397c478bd9Sstevel@tonic-gate 				}
25407c478bd9Sstevel@tonic-gate 			}
25417c478bd9Sstevel@tonic-gate 
25427c478bd9Sstevel@tonic-gate 			(void) close(door);
25437c478bd9Sstevel@tonic-gate 		} else {
25447c478bd9Sstevel@tonic-gate 			if (lstat(DoorFileName, &buf) < 0) {
25457c478bd9Sstevel@tonic-gate 				err = errno;
25467c478bd9Sstevel@tonic-gate 
25477c478bd9Sstevel@tonic-gate 				DPRINT3(5, "open_door(%u): lstat() of %s "
25487c478bd9Sstevel@tonic-gate 					"failed, errno=%d\n",
25497c478bd9Sstevel@tonic-gate 					mythreadno, DoorFileName, err);
25507c478bd9Sstevel@tonic-gate 
25517c478bd9Sstevel@tonic-gate 				if ((door = creat(DoorFileName, 0644)) < 0) {
25527c478bd9Sstevel@tonic-gate 					err = errno;
2553*0ea5e3a5Sjjj 					(void) snprintf(line, sizeof (line),
2554*0ea5e3a5Sjjj 					    "creat() of %s failed - fatal",
2555*0ea5e3a5Sjjj 					    DoorFileName);
25567c478bd9Sstevel@tonic-gate 					DPRINT3(1, "open_door(%u): error: %s, "
25577c478bd9Sstevel@tonic-gate 						"errno=%d\n", mythreadno, line,
25587c478bd9Sstevel@tonic-gate 						err);
25597c478bd9Sstevel@tonic-gate 					errno = err;
25607c478bd9Sstevel@tonic-gate 					logerror(line);
25617c478bd9Sstevel@tonic-gate 					delete_doorfiles();
25627c478bd9Sstevel@tonic-gate 					exit(1);
25637c478bd9Sstevel@tonic-gate 				}
25647c478bd9Sstevel@tonic-gate 
25657c478bd9Sstevel@tonic-gate 				(void) fchmod(door,
25667c478bd9Sstevel@tonic-gate 					S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
25677c478bd9Sstevel@tonic-gate 
25687c478bd9Sstevel@tonic-gate 				DPRINT2(5, "open_door(%u): creat() of %s "
25697c478bd9Sstevel@tonic-gate 					"succeeded\n", mythreadno,
25707c478bd9Sstevel@tonic-gate 					DoorFileName);
25717c478bd9Sstevel@tonic-gate 
25727c478bd9Sstevel@tonic-gate 				(void) close(door);
25737c478bd9Sstevel@tonic-gate 			}
25747c478bd9Sstevel@tonic-gate 		}
25757c478bd9Sstevel@tonic-gate 
25767c478bd9Sstevel@tonic-gate 		if (strcmp(DoorFileName, DOORFILE) == 0) {
25777c478bd9Sstevel@tonic-gate 			if (lstat(OLD_DOORFILE, &buf) == 0) {
25787c478bd9Sstevel@tonic-gate 				DPRINT2(5, "open_door(%u): lstat() of %s "
25797c478bd9Sstevel@tonic-gate 					"succeeded\n", mythreadno,
25807c478bd9Sstevel@tonic-gate 					OLD_DOORFILE);
25817c478bd9Sstevel@tonic-gate 
25827c478bd9Sstevel@tonic-gate 				if (S_ISDIR(buf.st_mode)) {
2583*0ea5e3a5Sjjj 					(void) snprintf(line, sizeof (line),
2584*0ea5e3a5Sjjj 					    "%s is a directory - fatal",
25857c478bd9Sstevel@tonic-gate 					    OLD_DOORFILE);
25867c478bd9Sstevel@tonic-gate 					DPRINT2(1, "open_door(%u): error: "
25877c478bd9Sstevel@tonic-gate 						"%s\n", mythreadno, line);
25887c478bd9Sstevel@tonic-gate 					errno = 0;
25897c478bd9Sstevel@tonic-gate 					logerror(line);
25907c478bd9Sstevel@tonic-gate 					delete_doorfiles();
25917c478bd9Sstevel@tonic-gate 					exit(1);
25927c478bd9Sstevel@tonic-gate 				}
25937c478bd9Sstevel@tonic-gate 
25947c478bd9Sstevel@tonic-gate 				DPRINT2(5, "open_door(%u): %s is not a "
25957c478bd9Sstevel@tonic-gate 					"directory\n",
25967c478bd9Sstevel@tonic-gate 					mythreadno, OLD_DOORFILE);
25977c478bd9Sstevel@tonic-gate 
25987c478bd9Sstevel@tonic-gate 				if (unlink(OLD_DOORFILE) < 0) {
25997c478bd9Sstevel@tonic-gate 					err = errno;
2600*0ea5e3a5Sjjj 					(void) snprintf(line, sizeof (line),
2601*0ea5e3a5Sjjj 					    "unlink() of %s failed",
2602*0ea5e3a5Sjjj 					    OLD_DOORFILE);
26037c478bd9Sstevel@tonic-gate 					DPRINT2(5, "open_door(%u): %s\n",
26047c478bd9Sstevel@tonic-gate 						mythreadno, line);
26057c478bd9Sstevel@tonic-gate 
26067c478bd9Sstevel@tonic-gate 					if (err != EROFS) {
26077c478bd9Sstevel@tonic-gate 						DPRINT3(1, "open_door(%u): "
26087c478bd9Sstevel@tonic-gate 							"error: %s, "
26097c478bd9Sstevel@tonic-gate 							"errno=%d\n",
26107c478bd9Sstevel@tonic-gate 							mythreadno, line, err);
26117c478bd9Sstevel@tonic-gate 						(void) strcat(line, " - fatal");
26127c478bd9Sstevel@tonic-gate 						errno = err;
26137c478bd9Sstevel@tonic-gate 						logerror(line);
26147c478bd9Sstevel@tonic-gate 						delete_doorfiles();
26157c478bd9Sstevel@tonic-gate 						exit(1);
26167c478bd9Sstevel@tonic-gate 					}
26177c478bd9Sstevel@tonic-gate 
26187c478bd9Sstevel@tonic-gate 					DPRINT1(5, "open_door(%u): unlink "
26197c478bd9Sstevel@tonic-gate 						"failure OK on RO file "
26207c478bd9Sstevel@tonic-gate 						"system\n", mythreadno);
26217c478bd9Sstevel@tonic-gate 				}
26227c478bd9Sstevel@tonic-gate 			} else {
26237c478bd9Sstevel@tonic-gate 				DPRINT2(5, "open_door(%u): file %s doesn't "
26247c478bd9Sstevel@tonic-gate 					"exist\n", mythreadno, OLD_DOORFILE);
26257c478bd9Sstevel@tonic-gate 			}
26267c478bd9Sstevel@tonic-gate 
26277c478bd9Sstevel@tonic-gate 			if (symlink(RELATIVE_DOORFILE, OLD_DOORFILE) < 0) {
26287c478bd9Sstevel@tonic-gate 				err = errno;
2629*0ea5e3a5Sjjj 				(void) snprintf(line, sizeof (line),
2630*0ea5e3a5Sjjj 				    "symlink %s -> %s failed", OLD_DOORFILE,
26317c478bd9Sstevel@tonic-gate 				    RELATIVE_DOORFILE);
26327c478bd9Sstevel@tonic-gate 				DPRINT2(5, "open_door(%u): %s\n", mythreadno,
26337c478bd9Sstevel@tonic-gate 					line);
26347c478bd9Sstevel@tonic-gate 
26357c478bd9Sstevel@tonic-gate 				if (err != EROFS) {
26367c478bd9Sstevel@tonic-gate 					DPRINT3(1, "open_door(%u): error: %s, "
26377c478bd9Sstevel@tonic-gate 						"errno=%d\n", mythreadno, line,
26387c478bd9Sstevel@tonic-gate 						err);
26397c478bd9Sstevel@tonic-gate 					errno = err;
26407c478bd9Sstevel@tonic-gate 					(void) strcat(line, " - fatal");
26417c478bd9Sstevel@tonic-gate 					logerror(line);
26427c478bd9Sstevel@tonic-gate 					delete_doorfiles();
26437c478bd9Sstevel@tonic-gate 					exit(1);
26447c478bd9Sstevel@tonic-gate 				}
26457c478bd9Sstevel@tonic-gate 
26467c478bd9Sstevel@tonic-gate 				DPRINT1(5, "open_door(%u): symlink failure OK "
26477c478bd9Sstevel@tonic-gate 					"on RO file system\n", mythreadno);
26487c478bd9Sstevel@tonic-gate 			} else {
26497c478bd9Sstevel@tonic-gate 				DPRINT3(5, "open_door(%u): symlink %s -> %s "
26507c478bd9Sstevel@tonic-gate 					"succeeded\n", mythreadno,
26517c478bd9Sstevel@tonic-gate 					OLD_DOORFILE, RELATIVE_DOORFILE);
26527c478bd9Sstevel@tonic-gate 			}
26537c478bd9Sstevel@tonic-gate 		}
26547c478bd9Sstevel@tonic-gate 
26557c478bd9Sstevel@tonic-gate 		if ((DoorFd = door_create(server, 0,
26567c478bd9Sstevel@tonic-gate 		    DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) < 0) {
26577c478bd9Sstevel@tonic-gate 			err = errno;
26587c478bd9Sstevel@tonic-gate 			(void) sprintf(line, "door_create() failed - fatal");
26597c478bd9Sstevel@tonic-gate 			DPRINT3(1, "open_door(%u): error: %s, errno=%d\n",
26607c478bd9Sstevel@tonic-gate 				mythreadno, line, err);
26617c478bd9Sstevel@tonic-gate 			errno = err;
26627c478bd9Sstevel@tonic-gate 			logerror(line);
26637c478bd9Sstevel@tonic-gate 			delete_doorfiles();
26647c478bd9Sstevel@tonic-gate 			exit(1);
26657c478bd9Sstevel@tonic-gate 		}
26667c478bd9Sstevel@tonic-gate 		(void) door_setparam(DoorFd, DOOR_PARAM_DATA_MAX, 0);
26677c478bd9Sstevel@tonic-gate 		DPRINT2(5, "open_door(%u): door_create() succeeded, "
26687c478bd9Sstevel@tonic-gate 			"DoorFd=%d\n", mythreadno, DoorFd);
26697c478bd9Sstevel@tonic-gate 
26707c478bd9Sstevel@tonic-gate 		DoorCreated = 1;
26717c478bd9Sstevel@tonic-gate 	}
26727c478bd9Sstevel@tonic-gate 
26737c478bd9Sstevel@tonic-gate 	(void) fdetach(DoorFileName);	/* just in case... */
26747c478bd9Sstevel@tonic-gate 
26757c478bd9Sstevel@tonic-gate 	if (fattach(DoorFd, DoorFileName) < 0) {
26767c478bd9Sstevel@tonic-gate 		err = errno;
2677*0ea5e3a5Sjjj 		(void) snprintf(line, sizeof (line), "fattach() of fd"
2678*0ea5e3a5Sjjj 			" %d to %s failed - fatal", DoorFd, DoorFileName);
26797c478bd9Sstevel@tonic-gate 		DPRINT3(1, "open_door(%u): error: %s, errno=%d\n", mythreadno,
26807c478bd9Sstevel@tonic-gate 			line, err);
26817c478bd9Sstevel@tonic-gate 		errno = err;
26827c478bd9Sstevel@tonic-gate 		logerror(line);
26837c478bd9Sstevel@tonic-gate 		delete_doorfiles();
26847c478bd9Sstevel@tonic-gate 		exit(1);
26857c478bd9Sstevel@tonic-gate 	}
26867c478bd9Sstevel@tonic-gate 
26877c478bd9Sstevel@tonic-gate 	DPRINT2(5, "open_door(%u): attached server() to %s\n", mythreadno,
26887c478bd9Sstevel@tonic-gate 		DoorFileName);
26897c478bd9Sstevel@tonic-gate 
26907c478bd9Sstevel@tonic-gate 	/*
26917c478bd9Sstevel@tonic-gate 	 * create pidfile anyway, so those using it to control
26927c478bd9Sstevel@tonic-gate 	 * syslogd (with kill `cat /etc/syslog.pid` perhaps)
26937c478bd9Sstevel@tonic-gate 	 * don't get broken.
26947c478bd9Sstevel@tonic-gate 	 */
26957c478bd9Sstevel@tonic-gate 
26967c478bd9Sstevel@tonic-gate 	if (!PidfileCreated) {
26977c478bd9Sstevel@tonic-gate 		int pidfd;
26987c478bd9Sstevel@tonic-gate 
26997c478bd9Sstevel@tonic-gate 		PidfileCreated = 1;
27007c478bd9Sstevel@tonic-gate 
27017c478bd9Sstevel@tonic-gate 		if ((pidfd = open(PidFileName, O_RDWR|O_CREAT|O_TRUNC, 0644))
27027c478bd9Sstevel@tonic-gate 		    < 0) {
27037c478bd9Sstevel@tonic-gate 			err = errno;
2704*0ea5e3a5Sjjj 			(void) snprintf(line, sizeof (line),
2705*0ea5e3a5Sjjj 			    "open() of %s failed", PidFileName);
27067c478bd9Sstevel@tonic-gate 			DPRINT3(1, "open_door(%u): warning: %s, errno=%d\n",
27077c478bd9Sstevel@tonic-gate 				mythreadno, line, err);
27087c478bd9Sstevel@tonic-gate 			errno = err;
27097c478bd9Sstevel@tonic-gate 			logerror(line);
27107c478bd9Sstevel@tonic-gate 			return;
27117c478bd9Sstevel@tonic-gate 		}
27127c478bd9Sstevel@tonic-gate 
27137c478bd9Sstevel@tonic-gate 		(void) fchmod(pidfd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
27147c478bd9Sstevel@tonic-gate 		(void) sprintf(line, "%ld\n", getpid());
27157c478bd9Sstevel@tonic-gate 
27167c478bd9Sstevel@tonic-gate 		if (write(pidfd, line, strlen(line)) < 0) {
27177c478bd9Sstevel@tonic-gate 			err = errno;
2718*0ea5e3a5Sjjj 			(void) snprintf(line, sizeof (line),
2719*0ea5e3a5Sjjj 			    "write to %s on fd %d failed", PidFileName, pidfd);
27207c478bd9Sstevel@tonic-gate 			DPRINT3(1, "open_door(%u): warning: %s, errno=%d\n",
27217c478bd9Sstevel@tonic-gate 				mythreadno, line, err);
27227c478bd9Sstevel@tonic-gate 			errno = err;
27237c478bd9Sstevel@tonic-gate 			logerror(line);
27247c478bd9Sstevel@tonic-gate 			return;
27257c478bd9Sstevel@tonic-gate 		}
27267c478bd9Sstevel@tonic-gate 
27277c478bd9Sstevel@tonic-gate 		(void) close(pidfd);
27287c478bd9Sstevel@tonic-gate 
27297c478bd9Sstevel@tonic-gate 		DPRINT2(5, "open_door(%u): %s created\n",
27307c478bd9Sstevel@tonic-gate 			mythreadno, PidFileName);
27317c478bd9Sstevel@tonic-gate 
27327c478bd9Sstevel@tonic-gate 		if (strcmp(PidFileName, PIDFILE) == 0) {
27337c478bd9Sstevel@tonic-gate 			if (lstat(OLD_PIDFILE, &buf) == 0) {
27347c478bd9Sstevel@tonic-gate 				DPRINT2(5, "open_door(%u): lstat() of %s "
27357c478bd9Sstevel@tonic-gate 					"succeded\n", mythreadno, OLD_PIDFILE);
27367c478bd9Sstevel@tonic-gate 
27377c478bd9Sstevel@tonic-gate 				if (S_ISDIR(buf.st_mode)) {
2738*0ea5e3a5Sjjj 					(void) snprintf(line, sizeof (line),
2739*0ea5e3a5Sjjj 					    "file %s is a directory",
27407c478bd9Sstevel@tonic-gate 					    OLD_PIDFILE);
27417c478bd9Sstevel@tonic-gate 					DPRINT2(1, "open_door(%u): warning: "
27427c478bd9Sstevel@tonic-gate 						"%s\n", mythreadno, line);
27437c478bd9Sstevel@tonic-gate 					errno = 0;
27447c478bd9Sstevel@tonic-gate 					logerror(line);
27457c478bd9Sstevel@tonic-gate 					return;
27467c478bd9Sstevel@tonic-gate 				}
27477c478bd9Sstevel@tonic-gate 
27487c478bd9Sstevel@tonic-gate 				if (unlink(OLD_PIDFILE) < 0) {
27497c478bd9Sstevel@tonic-gate 					err = errno;
2750*0ea5e3a5Sjjj 					(void) snprintf(line, sizeof (line),
2751*0ea5e3a5Sjjj 					    "unlink() of %s failed",
2752*0ea5e3a5Sjjj 					    OLD_PIDFILE);
27537c478bd9Sstevel@tonic-gate 					DPRINT2(5, "open_door(%u): %s\n",
27547c478bd9Sstevel@tonic-gate 						mythreadno, line);
27557c478bd9Sstevel@tonic-gate 
27567c478bd9Sstevel@tonic-gate 					if (err != EROFS) {
27577c478bd9Sstevel@tonic-gate 						DPRINT3(1, "open_door (%u): "
27587c478bd9Sstevel@tonic-gate 							"warning: %s, "
27597c478bd9Sstevel@tonic-gate 							"errno=%d\n",
27607c478bd9Sstevel@tonic-gate 							mythreadno, line, err);
27617c478bd9Sstevel@tonic-gate 						errno = err;
27627c478bd9Sstevel@tonic-gate 						logerror(line);
27637c478bd9Sstevel@tonic-gate 						return;
27647c478bd9Sstevel@tonic-gate 					}
27657c478bd9Sstevel@tonic-gate 
27667c478bd9Sstevel@tonic-gate 					DPRINT1(5, "open_door(%u): unlink "
27677c478bd9Sstevel@tonic-gate 						"failure OK on RO file "
27687c478bd9Sstevel@tonic-gate 						"system\n", mythreadno);
27697c478bd9Sstevel@tonic-gate 				}
27707c478bd9Sstevel@tonic-gate 			} else {
27717c478bd9Sstevel@tonic-gate 				DPRINT2(5, "open_door(%u): file %s doesn't "
27727c478bd9Sstevel@tonic-gate 					"exist\n", mythreadno, OLD_PIDFILE);
27737c478bd9Sstevel@tonic-gate 			}
27747c478bd9Sstevel@tonic-gate 
27757c478bd9Sstevel@tonic-gate 			if (symlink(RELATIVE_PIDFILE, OLD_PIDFILE) < 0) {
27767c478bd9Sstevel@tonic-gate 				err = errno;
2777*0ea5e3a5Sjjj 				(void) snprintf(line, sizeof (line),
2778*0ea5e3a5Sjjj 				    "symlink %s -> %s failed", OLD_PIDFILE,
27797c478bd9Sstevel@tonic-gate 					RELATIVE_PIDFILE);
27807c478bd9Sstevel@tonic-gate 				DPRINT2(5, "open_door(%u): %s\n", mythreadno,
27817c478bd9Sstevel@tonic-gate 					line);
27827c478bd9Sstevel@tonic-gate 
27837c478bd9Sstevel@tonic-gate 				if (err != EROFS) {
27847c478bd9Sstevel@tonic-gate 					DPRINT3(1, "open_door(%u): warning: "
27857c478bd9Sstevel@tonic-gate 						"%s, errno=%d\n", mythreadno,
27867c478bd9Sstevel@tonic-gate 						line, err);
27877c478bd9Sstevel@tonic-gate 					errno = err;
27887c478bd9Sstevel@tonic-gate 					logerror(line);
27897c478bd9Sstevel@tonic-gate 					return;
27907c478bd9Sstevel@tonic-gate 				}
27917c478bd9Sstevel@tonic-gate 
27927c478bd9Sstevel@tonic-gate 				DPRINT1(5, "open_door(%u): symlink failure OK "
27937c478bd9Sstevel@tonic-gate 					"on RO file system\n", mythreadno);
27947c478bd9Sstevel@tonic-gate 				return;
27957c478bd9Sstevel@tonic-gate 			}
27967c478bd9Sstevel@tonic-gate 
27977c478bd9Sstevel@tonic-gate 			DPRINT3(5, "open_door(%u): symlink %s -> %s "
27987c478bd9Sstevel@tonic-gate 				"succeeded\n", mythreadno, OLD_PIDFILE,
27997c478bd9Sstevel@tonic-gate 				RELATIVE_PIDFILE);
28007c478bd9Sstevel@tonic-gate 		}
28017c478bd9Sstevel@tonic-gate 	}
28027c478bd9Sstevel@tonic-gate }
28037c478bd9Sstevel@tonic-gate 
28047c478bd9Sstevel@tonic-gate /*
28057c478bd9Sstevel@tonic-gate  * the 'server' function that we export via the door. It does
28067c478bd9Sstevel@tonic-gate  * nothing but return.
28077c478bd9Sstevel@tonic-gate  */
28087c478bd9Sstevel@tonic-gate /*ARGSUSED*/
28097c478bd9Sstevel@tonic-gate static void
28107c478bd9Sstevel@tonic-gate server(void *cookie, char *argp, size_t arg_size,
28117c478bd9Sstevel@tonic-gate     door_desc_t *dp, uint_t n)
28127c478bd9Sstevel@tonic-gate {
28137c478bd9Sstevel@tonic-gate 	(void) door_return(NULL, 0, NULL, 0);
28147c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
28157c478bd9Sstevel@tonic-gate }
28167c478bd9Sstevel@tonic-gate 
28177c478bd9Sstevel@tonic-gate /*
28187c478bd9Sstevel@tonic-gate  * checkm4 - used to verify that the external utilities that
28197c478bd9Sstevel@tonic-gate  * syslogd depends on are where we expect them to be.
28207c478bd9Sstevel@tonic-gate  * Returns 0 if all utilities are found, > 0 if any are missing.
28217c478bd9Sstevel@tonic-gate  * Also logs errors so user knows what's missing
28227c478bd9Sstevel@tonic-gate  */
28237c478bd9Sstevel@tonic-gate static int
28247c478bd9Sstevel@tonic-gate checkm4(void)
28257c478bd9Sstevel@tonic-gate {
28267c478bd9Sstevel@tonic-gate 	int notfound = 0;
28277c478bd9Sstevel@tonic-gate 	int saverrno;
28287c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
28297c478bd9Sstevel@tonic-gate 
28307c478bd9Sstevel@tonic-gate 	if (Debug) {
28317c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
28327c478bd9Sstevel@tonic-gate 	}
28337c478bd9Sstevel@tonic-gate 
28347c478bd9Sstevel@tonic-gate 	if (access("/usr/ccs/bin/m4", X_OK) < 0) {
28357c478bd9Sstevel@tonic-gate 		saverrno = errno;
28367c478bd9Sstevel@tonic-gate 		logerror("/usr/ccs/bin/m4");
28377c478bd9Sstevel@tonic-gate 		DPRINT2(1, "checkm4(%u): /usr/ccs/bin/m4 - access "
28387c478bd9Sstevel@tonic-gate 			"returned %d\n", mythreadno, saverrno);
28397c478bd9Sstevel@tonic-gate 		notfound++;
28407c478bd9Sstevel@tonic-gate 	}
28417c478bd9Sstevel@tonic-gate 
28427c478bd9Sstevel@tonic-gate 	return (notfound);
28437c478bd9Sstevel@tonic-gate }
28447c478bd9Sstevel@tonic-gate 
28457c478bd9Sstevel@tonic-gate /*
28467c478bd9Sstevel@tonic-gate  *  INIT -- Initialize syslogd from configuration table, start up
28477c478bd9Sstevel@tonic-gate  *  input and logger threads. This routine is called only once.
28487c478bd9Sstevel@tonic-gate  */
28497c478bd9Sstevel@tonic-gate static void
28507c478bd9Sstevel@tonic-gate init(void)
28517c478bd9Sstevel@tonic-gate {
28527c478bd9Sstevel@tonic-gate 	struct utsname *up;
28537c478bd9Sstevel@tonic-gate 	pthread_attr_t sys_attr, net_attr, log_attr, hnl_attr;
28547c478bd9Sstevel@tonic-gate 	int nthread;
28557c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
28567c478bd9Sstevel@tonic-gate 
28577c478bd9Sstevel@tonic-gate 	if (Debug) {
28587c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
28597c478bd9Sstevel@tonic-gate 	}
28607c478bd9Sstevel@tonic-gate 
28617c478bd9Sstevel@tonic-gate 	DPRINT1(2, "init(%u): initializing\n", mythreadno);
28627c478bd9Sstevel@tonic-gate 
28637c478bd9Sstevel@tonic-gate 	/* hand-craft a host_list_t entry for our local host name */
28647c478bd9Sstevel@tonic-gate 	if ((up = malloc(sizeof (struct utsname))) == NULL) {
28657c478bd9Sstevel@tonic-gate 		MALLOC_FAIL_EXIT;
28667c478bd9Sstevel@tonic-gate 	}
28677c478bd9Sstevel@tonic-gate 	(void) uname(up);
28687c478bd9Sstevel@tonic-gate 	LocalHostName.hl_cnt = 1;
28697c478bd9Sstevel@tonic-gate 	if ((LocalHostName.hl_hosts = malloc(sizeof (char *))) == NULL) {
28707c478bd9Sstevel@tonic-gate 		MALLOC_FAIL_EXIT;
28717c478bd9Sstevel@tonic-gate 	}
28727c478bd9Sstevel@tonic-gate 	if ((LocalHostName.hl_hosts[0] = strdup(up->nodename)) == NULL) {
28737c478bd9Sstevel@tonic-gate 		free(LocalHostName.hl_hosts);
28747c478bd9Sstevel@tonic-gate 		MALLOC_FAIL_EXIT;
28757c478bd9Sstevel@tonic-gate 	}
28767c478bd9Sstevel@tonic-gate 	free(up);
28777c478bd9Sstevel@tonic-gate 	/* also hand craft one for use if name resolution fails */
28787c478bd9Sstevel@tonic-gate 	NullHostName.hl_cnt = 1;
28797c478bd9Sstevel@tonic-gate 	if ((NullHostName.hl_hosts = malloc(sizeof (char *))) == NULL) {
28807c478bd9Sstevel@tonic-gate 		MALLOC_FAIL_EXIT;
28817c478bd9Sstevel@tonic-gate 	}
28827c478bd9Sstevel@tonic-gate 	if ((NullHostName.hl_hosts[0] = strdup("name lookup failed")) == NULL) {
28837c478bd9Sstevel@tonic-gate 		MALLOC_FAIL_EXIT;
28847c478bd9Sstevel@tonic-gate 	}
28857c478bd9Sstevel@tonic-gate 
28867c478bd9Sstevel@tonic-gate 	hnc_init(0);
28877c478bd9Sstevel@tonic-gate 
28887c478bd9Sstevel@tonic-gate 	/*
28897c478bd9Sstevel@tonic-gate 	 * Note that getnets will allocate network resources, but won't be
28907c478bd9Sstevel@tonic-gate 	 * binding UDP port. This is because, there could be a race
28917c478bd9Sstevel@tonic-gate 	 * condition between door. If we bind here, one syslogd could grab
28927c478bd9Sstevel@tonic-gate 	 * UDP port first, but later another syslogd could take over without
28937c478bd9Sstevel@tonic-gate 	 * getting UDP port but grab the door file. The 2nd syslogd could
28947c478bd9Sstevel@tonic-gate 	 * continue to run without listening network.
28957c478bd9Sstevel@tonic-gate 	 * bindnet() will be called after door was successfully opened.
28967c478bd9Sstevel@tonic-gate 	 */
28977c478bd9Sstevel@tonic-gate 	getnets();
28987c478bd9Sstevel@tonic-gate 
28997c478bd9Sstevel@tonic-gate 	/*
29007c478bd9Sstevel@tonic-gate 	 * Start up configured theads
29017c478bd9Sstevel@tonic-gate 	 */
29027c478bd9Sstevel@tonic-gate 	conf_init();
29037c478bd9Sstevel@tonic-gate 
29047c478bd9Sstevel@tonic-gate 	/*
29057c478bd9Sstevel@tonic-gate 	 * allocate thread stacks for the persistant threads
29067c478bd9Sstevel@tonic-gate 	 */
29077c478bd9Sstevel@tonic-gate 	nthread = (turnoff == 0) ? 4 : 2;
29087c478bd9Sstevel@tonic-gate 
29097c478bd9Sstevel@tonic-gate 	if ((stack_ptr = alloc_stacks(nthread)) == NULL) {
29107c478bd9Sstevel@tonic-gate 		logerror("alloc_stacks failed - fatal");
29117c478bd9Sstevel@tonic-gate 		exit(1);
29127c478bd9Sstevel@tonic-gate 	}
29137c478bd9Sstevel@tonic-gate 
29147c478bd9Sstevel@tonic-gate 	if (Debug) {
29157c478bd9Sstevel@tonic-gate 		dumpstats(STDOUT_FILENO);
29167c478bd9Sstevel@tonic-gate 	}
29177c478bd9Sstevel@tonic-gate 
29187c478bd9Sstevel@tonic-gate 	(void) dataq_init(&inputq);	/* init the input queue */
29197c478bd9Sstevel@tonic-gate 
29207c478bd9Sstevel@tonic-gate 	if (pthread_attr_init(&sys_attr) != 0 ||
29217c478bd9Sstevel@tonic-gate 	    pthread_attr_init(&log_attr) != 0 ||
29227c478bd9Sstevel@tonic-gate 	    pthread_attr_init(&net_attr) != 0 ||
29237c478bd9Sstevel@tonic-gate 	    pthread_attr_init(&hnl_attr) != 0) {
29247c478bd9Sstevel@tonic-gate 		logerror("pthread_attr_init failed - fatal");
29257c478bd9Sstevel@tonic-gate 		exit(1);
29267c478bd9Sstevel@tonic-gate 	}
29277c478bd9Sstevel@tonic-gate 
29287c478bd9Sstevel@tonic-gate 	(void) pthread_attr_setscope(&sys_attr, PTHREAD_SCOPE_PROCESS);
29297c478bd9Sstevel@tonic-gate 	(void) pthread_attr_setscope(&log_attr, PTHREAD_SCOPE_PROCESS);
29307c478bd9Sstevel@tonic-gate 	(void) pthread_attr_setscope(&net_attr, PTHREAD_SCOPE_PROCESS);
29317c478bd9Sstevel@tonic-gate 	(void) pthread_attr_setscope(&hnl_attr, PTHREAD_SCOPE_PROCESS);
29327c478bd9Sstevel@tonic-gate 
29337c478bd9Sstevel@tonic-gate 	/* 1: logmsg thread */
29347c478bd9Sstevel@tonic-gate 	(void) pthread_attr_setstacksize(&log_attr, stacksize);
29357c478bd9Sstevel@tonic-gate 	(void) pthread_attr_setstackaddr(&log_attr, stack_ptr);
29367c478bd9Sstevel@tonic-gate 	stack_ptr += stacksize + redzonesize;
29377c478bd9Sstevel@tonic-gate 	if (pthread_create(&log_thread, &log_attr, logmsg, NULL) != 0) {
29387c478bd9Sstevel@tonic-gate 		logerror("pthread_create failed - fatal");
29397c478bd9Sstevel@tonic-gate 		exit(1);
29407c478bd9Sstevel@tonic-gate 	}
29417c478bd9Sstevel@tonic-gate 
29427c478bd9Sstevel@tonic-gate 	/*
29437c478bd9Sstevel@tonic-gate 	 * open the log device, and pull up all pending message
29447c478bd9Sstevel@tonic-gate 	 * from the log driver.
29457c478bd9Sstevel@tonic-gate 	 */
29467c478bd9Sstevel@tonic-gate 	prepare_sys_poll();
29477c478bd9Sstevel@tonic-gate 
29487c478bd9Sstevel@tonic-gate 	/*
29497c478bd9Sstevel@tonic-gate 	 * Now we can deliver the pending internal error messages.
29507c478bd9Sstevel@tonic-gate 	 */
29517c478bd9Sstevel@tonic-gate 	enable_errorlog();
29527c478bd9Sstevel@tonic-gate 
29537c478bd9Sstevel@tonic-gate 	/* 2: sys_poll thread */
29547c478bd9Sstevel@tonic-gate 	(void) pthread_attr_setstacksize(&sys_attr, stacksize);
29557c478bd9Sstevel@tonic-gate 	(void) pthread_attr_setstackaddr(&sys_attr, stack_ptr);
29567c478bd9Sstevel@tonic-gate 	stack_ptr += stacksize + redzonesize;
29577c478bd9Sstevel@tonic-gate 	if (pthread_create(&sys_thread, &sys_attr, sys_poll, NULL) != 0) {
29587c478bd9Sstevel@tonic-gate 		logerror("pthread_create failed - fatal");
29597c478bd9Sstevel@tonic-gate 		exit(1);
29607c478bd9Sstevel@tonic-gate 	}
29617c478bd9Sstevel@tonic-gate 
29627c478bd9Sstevel@tonic-gate 	/*
29637c478bd9Sstevel@tonic-gate 	 * We've started the sys_poll() and logmsg() threads.  Now we are ready
29647c478bd9Sstevel@tonic-gate 	 * to open the door.  This cannot happen before spawning sys_poll(),
29657c478bd9Sstevel@tonic-gate 	 * because after opening the door, syslog() will no longer take care of
29667c478bd9Sstevel@tonic-gate 	 * LOG_CONS.  Therefor, we should pull up all pending log messages and
29677c478bd9Sstevel@tonic-gate 	 * activate sys_poll() before opening the door, so that log driver
29687c478bd9Sstevel@tonic-gate 	 * won't drop messages.
29697c478bd9Sstevel@tonic-gate 	 */
29707c478bd9Sstevel@tonic-gate 	open_door();
29717c478bd9Sstevel@tonic-gate 
29727c478bd9Sstevel@tonic-gate 	DPRINT1(1, "init(%u): accepting messages from local system\n",
29737c478bd9Sstevel@tonic-gate 			mythreadno);
29747c478bd9Sstevel@tonic-gate 
29757c478bd9Sstevel@tonic-gate 	if (turnoff == 0) {
29767c478bd9Sstevel@tonic-gate 		/* init the hostname lookup queue */
29777c478bd9Sstevel@tonic-gate 		(void) dataq_init(&hnlq);
29787c478bd9Sstevel@tonic-gate 
29797c478bd9Sstevel@tonic-gate 		/* 3: hostname lookup thread */
29807c478bd9Sstevel@tonic-gate 		(void) pthread_attr_setstacksize(&hnl_attr, stacksize);
29817c478bd9Sstevel@tonic-gate 		(void) pthread_attr_setstackaddr(&hnl_attr, stack_ptr);
29827c478bd9Sstevel@tonic-gate 		stack_ptr += stacksize + redzonesize;
29837c478bd9Sstevel@tonic-gate 		if (pthread_create(&hnl_thread, &hnl_attr,
29847c478bd9Sstevel@tonic-gate 				hostname_lookup, NULL) != 0) {
29857c478bd9Sstevel@tonic-gate 			logerror("pthread_create failed - fatal");
29867c478bd9Sstevel@tonic-gate 			exit(1);
29877c478bd9Sstevel@tonic-gate 		}
29887c478bd9Sstevel@tonic-gate 
29897c478bd9Sstevel@tonic-gate 		/* 4: net_poll thread */
29907c478bd9Sstevel@tonic-gate 		(void) pthread_attr_setstacksize(&net_attr, stacksize);
29917c478bd9Sstevel@tonic-gate 		(void) pthread_attr_setstackaddr(&net_attr, stack_ptr);
29927c478bd9Sstevel@tonic-gate 		stack_ptr += stacksize + redzonesize;
29937c478bd9Sstevel@tonic-gate 
29947c478bd9Sstevel@tonic-gate 		/* grab UDP port */
29957c478bd9Sstevel@tonic-gate 		bindnet();
29967c478bd9Sstevel@tonic-gate 
29977c478bd9Sstevel@tonic-gate 		if (pthread_create(&net_thread, &net_attr, net_poll,
29987c478bd9Sstevel@tonic-gate 					NULL) != 0) {
29997c478bd9Sstevel@tonic-gate 			logerror("pthread_create failed - fatal");
30007c478bd9Sstevel@tonic-gate 			exit(1);
30017c478bd9Sstevel@tonic-gate 		}
30027c478bd9Sstevel@tonic-gate 		DPRINT1(1, "init(%u): accepting messages from remote\n",
30037c478bd9Sstevel@tonic-gate 				mythreadno);
30047c478bd9Sstevel@tonic-gate 	}
30057c478bd9Sstevel@tonic-gate 
30067c478bd9Sstevel@tonic-gate 	(void) pthread_attr_destroy(&sys_attr);
30077c478bd9Sstevel@tonic-gate 	(void) pthread_attr_destroy(&net_attr);
30087c478bd9Sstevel@tonic-gate 	(void) pthread_attr_destroy(&log_attr);
30097c478bd9Sstevel@tonic-gate 	(void) pthread_attr_destroy(&hnl_attr);
30107c478bd9Sstevel@tonic-gate 
30117c478bd9Sstevel@tonic-gate 	curalarm = MarkInterval * 60 / MARKCOUNT;
30127c478bd9Sstevel@tonic-gate 	(void) alarm((unsigned)curalarm);
30137c478bd9Sstevel@tonic-gate 	DPRINT2(2, "init(%u): Next alarm in %d seconds\n",
30147c478bd9Sstevel@tonic-gate 		mythreadno, curalarm);
30157c478bd9Sstevel@tonic-gate 	DPRINT1(1, "init(%u): syslogd: started\n", mythreadno);
30167c478bd9Sstevel@tonic-gate }
30177c478bd9Sstevel@tonic-gate 
30187c478bd9Sstevel@tonic-gate /*
30197c478bd9Sstevel@tonic-gate  * will print a bunch of debugging stats on 'fd'
30207c478bd9Sstevel@tonic-gate  */
30217c478bd9Sstevel@tonic-gate static void
30227c478bd9Sstevel@tonic-gate dumpstats(int fd)
30237c478bd9Sstevel@tonic-gate {
30247c478bd9Sstevel@tonic-gate 	FILE *out;
30257c478bd9Sstevel@tonic-gate 	struct filed *f;
30267c478bd9Sstevel@tonic-gate 	int i;
30277c478bd9Sstevel@tonic-gate 	char users[1024];
30287c478bd9Sstevel@tonic-gate 	char cbuf[30];
30297c478bd9Sstevel@tonic-gate 	char *dashes = "------------------------";
30307c478bd9Sstevel@tonic-gate 	static int conversion_printed;
30317c478bd9Sstevel@tonic-gate 
30327c478bd9Sstevel@tonic-gate 	if ((out = fdopen(fd, "w+")) == NULL)
30337c478bd9Sstevel@tonic-gate 		return;
30347c478bd9Sstevel@tonic-gate 
30357c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "\n  syslogd: version %s\n", Version);
30367c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "  Started: %s", ctime_r(&start_time, cbuf));
30377c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "Input message count: system %d, network %d\n",
30387c478bd9Sstevel@tonic-gate 		sys_msg_count, net_msg_count);
30397c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "# Outputs: %d\n\n", nlogs);
30407c478bd9Sstevel@tonic-gate 
30417c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "%s priority = [file, facility] %s\n\n",
30427c478bd9Sstevel@tonic-gate 		dashes, dashes);
30437c478bd9Sstevel@tonic-gate 
30447c478bd9Sstevel@tonic-gate 	for (i = 0; i < LOG_NFACILITIES + 1; i++) {
30457c478bd9Sstevel@tonic-gate 		(void) fprintf(out, "%d ", i / 10);
30467c478bd9Sstevel@tonic-gate 	}
30477c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "\n");
30487c478bd9Sstevel@tonic-gate 	for (i = 0; i < LOG_NFACILITIES + 1; i++) {
30497c478bd9Sstevel@tonic-gate 		(void) fprintf(out, "%d ", i % 10);
30507c478bd9Sstevel@tonic-gate 	}
30517c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "\n");
30527c478bd9Sstevel@tonic-gate 	for (i = 0; i < LOG_NFACILITIES + 1; i++) {
30537c478bd9Sstevel@tonic-gate 		(void) fprintf(out, "--");
30547c478bd9Sstevel@tonic-gate 	}
30557c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "\n");
30567c478bd9Sstevel@tonic-gate 
30577c478bd9Sstevel@tonic-gate 	for (f = Files; f < &Files[nlogs]; f++) {
30587c478bd9Sstevel@tonic-gate 		for (i = 0; i < LOG_NFACILITIES + 1; i++) {
30597c478bd9Sstevel@tonic-gate 			if (f->f_pmask[i] == NOPRI)
30607c478bd9Sstevel@tonic-gate 				(void) fprintf(out, "X ");
30617c478bd9Sstevel@tonic-gate 			else
30627c478bd9Sstevel@tonic-gate 				(void) fprintf(out, "%d ",
30637c478bd9Sstevel@tonic-gate 					f->f_pmask[i]);
30647c478bd9Sstevel@tonic-gate 		}
30657c478bd9Sstevel@tonic-gate 		(void) fprintf(out, "%s: ", TypeNames[f->f_type]);
30667c478bd9Sstevel@tonic-gate 		switch (f->f_type) {
30677c478bd9Sstevel@tonic-gate 		case F_FILE:
30687c478bd9Sstevel@tonic-gate 		case F_TTY:
30697c478bd9Sstevel@tonic-gate 		case F_CONSOLE:
30707c478bd9Sstevel@tonic-gate 			(void) fprintf(out, "%s", f->f_un.f_fname);
30717c478bd9Sstevel@tonic-gate 			break;
30727c478bd9Sstevel@tonic-gate 		case F_FORW:
30737c478bd9Sstevel@tonic-gate 			(void) fprintf(out, "%s", f->f_un.f_forw.f_hname);
30747c478bd9Sstevel@tonic-gate 			break;
30757c478bd9Sstevel@tonic-gate 		case F_USERS:
30767c478bd9Sstevel@tonic-gate 			for (i = 0; i < MAXUNAMES &&
30777c478bd9Sstevel@tonic-gate 				*f->f_un.f_uname[i]; i++) {
30787c478bd9Sstevel@tonic-gate 				if (!i)
30797c478bd9Sstevel@tonic-gate 					(void) fprintf(out, "%s",
30807c478bd9Sstevel@tonic-gate 						f->f_un.f_uname[i]);
30817c478bd9Sstevel@tonic-gate 				else
30827c478bd9Sstevel@tonic-gate 					(void) fprintf(out, ", %s",
30837c478bd9Sstevel@tonic-gate 						f->f_un.f_uname[i]);
30847c478bd9Sstevel@tonic-gate 			}
30857c478bd9Sstevel@tonic-gate 			break;
30867c478bd9Sstevel@tonic-gate 		}
30877c478bd9Sstevel@tonic-gate 		(void) fprintf(out, "\n");
30887c478bd9Sstevel@tonic-gate 	}
30897c478bd9Sstevel@tonic-gate 
30907c478bd9Sstevel@tonic-gate 	if (!conversion_printed) {
3091*0ea5e3a5Sjjj 		(void) fprintf(out, "\nFacilities:\n");
30927c478bd9Sstevel@tonic-gate 
30937c478bd9Sstevel@tonic-gate 		for (i = 0; FacNames[i].c_val != -1; i++) {
3094*0ea5e3a5Sjjj 			(void) fprintf(out, "  [%02d] %s: %3d\n", i,
30957c478bd9Sstevel@tonic-gate 				FacNames[i].c_name, FacNames[i].c_val);
30967c478bd9Sstevel@tonic-gate 		}
30977c478bd9Sstevel@tonic-gate 
3098*0ea5e3a5Sjjj 		(void) fprintf(out, "\nPriorities:\n");
30997c478bd9Sstevel@tonic-gate 
31007c478bd9Sstevel@tonic-gate 		for (i = 0; PriNames[i].c_val != -1; i++) {
3101*0ea5e3a5Sjjj 			(void) fprintf(out, "  [%02d] %s: %3d\n", i,
31027c478bd9Sstevel@tonic-gate 				PriNames[i].c_name, PriNames[i].c_val);
31037c478bd9Sstevel@tonic-gate 		}
31047c478bd9Sstevel@tonic-gate 
31057c478bd9Sstevel@tonic-gate 		conversion_printed = 1;
31067c478bd9Sstevel@tonic-gate 	}
31077c478bd9Sstevel@tonic-gate 
31087c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "\n\n\n\t\tPer File Statistics\n");
31097c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "%-24s\tTot\tDups\tNofwd\tErrs\n", "File");
31107c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "%-24s\t---\t----\t-----\t----\n", "----");
31117c478bd9Sstevel@tonic-gate 	for (f = Files; f < &Files[nlogs]; f++) {
31127c478bd9Sstevel@tonic-gate 		switch (f->f_type) {
31137c478bd9Sstevel@tonic-gate 		case F_FILE:
31147c478bd9Sstevel@tonic-gate 		case F_TTY:
31157c478bd9Sstevel@tonic-gate 		case F_CONSOLE:
31167c478bd9Sstevel@tonic-gate 			(void) fprintf(out, "%-24s", f->f_un.f_fname);
31177c478bd9Sstevel@tonic-gate 			break;
31187c478bd9Sstevel@tonic-gate 		case F_WALL:
31197c478bd9Sstevel@tonic-gate 			(void) fprintf(out, "%-24s", TypeNames[f->f_type]);
31207c478bd9Sstevel@tonic-gate 			break;
31217c478bd9Sstevel@tonic-gate 		case F_FORW:
31227c478bd9Sstevel@tonic-gate 			(void) fprintf(out, "%-24s", f->f_un.f_forw.f_hname);
31237c478bd9Sstevel@tonic-gate 			break;
31247c478bd9Sstevel@tonic-gate 		case F_USERS:
31257c478bd9Sstevel@tonic-gate 			for (i = 0; i < MAXUNAMES &&
31267c478bd9Sstevel@tonic-gate 				*f->f_un.f_uname[i]; i++) {
31277c478bd9Sstevel@tonic-gate 				if (!i)
31287c478bd9Sstevel@tonic-gate 					(void) strcpy(users,
31297c478bd9Sstevel@tonic-gate 						f->f_un.f_uname[i]);
31307c478bd9Sstevel@tonic-gate 				else {
31317c478bd9Sstevel@tonic-gate 					(void) strcat(users, ",");
31327c478bd9Sstevel@tonic-gate 					(void) strcat(users,
31337c478bd9Sstevel@tonic-gate 						f->f_un.f_uname[i]);
31347c478bd9Sstevel@tonic-gate 				}
31357c478bd9Sstevel@tonic-gate 			}
31367c478bd9Sstevel@tonic-gate 			(void) fprintf(out, "%-24s", users);
31377c478bd9Sstevel@tonic-gate 			break;
31387c478bd9Sstevel@tonic-gate 		}
31397c478bd9Sstevel@tonic-gate 		(void) fprintf(out, "\t%d\t%d\t%d\t%d\n",
31407c478bd9Sstevel@tonic-gate 			f->f_stat.total, f->f_stat.dups,
31417c478bd9Sstevel@tonic-gate 			f->f_stat.cantfwd, f->f_stat.errs);
31427c478bd9Sstevel@tonic-gate 	}
31437c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "\n\n");
31447c478bd9Sstevel@tonic-gate 	if (Debug && fd == 1)
31457c478bd9Sstevel@tonic-gate 		return;
31467c478bd9Sstevel@tonic-gate 	(void) fclose(out);
31477c478bd9Sstevel@tonic-gate }
31487c478bd9Sstevel@tonic-gate 
31497c478bd9Sstevel@tonic-gate /*
31507c478bd9Sstevel@tonic-gate  * conf_init - This routine is code seperated from the
31517c478bd9Sstevel@tonic-gate  * init routine in order to be re-callable when we get
31527c478bd9Sstevel@tonic-gate  * a SIGHUP signal.
31537c478bd9Sstevel@tonic-gate  */
31547c478bd9Sstevel@tonic-gate static void
31557c478bd9Sstevel@tonic-gate conf_init(void)
31567c478bd9Sstevel@tonic-gate {
31577c478bd9Sstevel@tonic-gate 	char *p;
31587c478bd9Sstevel@tonic-gate 	int i;
31597c478bd9Sstevel@tonic-gate 	struct filed *f;
31607c478bd9Sstevel@tonic-gate 	char *m4argv[4];
31617c478bd9Sstevel@tonic-gate 	int m4argc = 0;
31627c478bd9Sstevel@tonic-gate 	conf_t cf;
31637c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
31647c478bd9Sstevel@tonic-gate 
31657c478bd9Sstevel@tonic-gate 	if (Debug) {
31667c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
31677c478bd9Sstevel@tonic-gate 	}
31687c478bd9Sstevel@tonic-gate 
31697c478bd9Sstevel@tonic-gate 	DPRINT1(2, "conf_init(%u): starting logger threads\n",
31707c478bd9Sstevel@tonic-gate 		mythreadno);
31717c478bd9Sstevel@tonic-gate 
31727c478bd9Sstevel@tonic-gate 	m4argv[m4argc++] = "m4";
31737c478bd9Sstevel@tonic-gate 
31747c478bd9Sstevel@tonic-gate 	if (amiloghost() == 1) {
31757c478bd9Sstevel@tonic-gate 		DPRINT1(1, "conf_init(%u): I am loghost\n", mythreadno);
31767c478bd9Sstevel@tonic-gate 		m4argv[m4argc++] = "-DLOGHOST=1";
31777c478bd9Sstevel@tonic-gate 	}
31787c478bd9Sstevel@tonic-gate 
31797c478bd9Sstevel@tonic-gate 	m4argv[m4argc++] = ConfFile;
31807c478bd9Sstevel@tonic-gate 	m4argv[m4argc] = NULL;
31817c478bd9Sstevel@tonic-gate 
31827c478bd9Sstevel@tonic-gate 	/*
31837c478bd9Sstevel@tonic-gate 	 * Make sure the configuration file and m4 exist, and then parse
31847c478bd9Sstevel@tonic-gate 	 * the configuration file with m4.  If any of these fail, resort
31857c478bd9Sstevel@tonic-gate 	 * to our hardcoded fallback configuration.
31867c478bd9Sstevel@tonic-gate 	 */
31877c478bd9Sstevel@tonic-gate 
31887c478bd9Sstevel@tonic-gate 	if (access(ConfFile, R_OK) == -1) {
31897c478bd9Sstevel@tonic-gate 		DPRINT2(1, "conf_init(%u): %s does not exist\n", mythreadno,
31907c478bd9Sstevel@tonic-gate 			ConfFile);
31917c478bd9Sstevel@tonic-gate 		logerror("can't open configuration file");
31927c478bd9Sstevel@tonic-gate 		/* CSTYLED */
31937c478bd9Sstevel@tonic-gate 		Files = (struct filed *) &fallback; /*lint !e545 */
31947c478bd9Sstevel@tonic-gate 		cfline("*.ERR\t/dev/sysmsg", 0, &Files[0]);
31957c478bd9Sstevel@tonic-gate 		cfline("*.PANIC\t*", 0, &Files[1]);
31967c478bd9Sstevel@tonic-gate 		nlogs = 2;
31977c478bd9Sstevel@tonic-gate 		goto nofile;
31987c478bd9Sstevel@tonic-gate 	}
31997c478bd9Sstevel@tonic-gate 
32007c478bd9Sstevel@tonic-gate 	if (checkm4() != 0 || conf_open(&cf, "/usr/ccs/bin/m4", m4argv) == -1) {
32017c478bd9Sstevel@tonic-gate 		DPRINT2(1, "conf_init(%u): cannot open %s\n", mythreadno,
32027c478bd9Sstevel@tonic-gate 			ConfFile);
32037c478bd9Sstevel@tonic-gate 		/* CSTYLED */
32047c478bd9Sstevel@tonic-gate 		Files = (struct filed *) &fallback; /*lint !e545 */
32057c478bd9Sstevel@tonic-gate 		cfline("*.ERR\t/dev/sysmsg", 0, &Files[0]);
32067c478bd9Sstevel@tonic-gate 		cfline("*.PANIC\t*", 0, &Files[1]);
32077c478bd9Sstevel@tonic-gate 		nlogs = 2;
32087c478bd9Sstevel@tonic-gate 		goto nofile;
32097c478bd9Sstevel@tonic-gate 	}
32107c478bd9Sstevel@tonic-gate 
32117c478bd9Sstevel@tonic-gate 	/* Count the number of lines which are not blanks or comments */
32127c478bd9Sstevel@tonic-gate 	nlogs = 0;
32137c478bd9Sstevel@tonic-gate 	while ((p = conf_read(&cf)) != NULL) {
32147c478bd9Sstevel@tonic-gate 		if (p[0] != '\0' && p[0] != '#')
32157c478bd9Sstevel@tonic-gate 			nlogs++;
32167c478bd9Sstevel@tonic-gate 	}
32177c478bd9Sstevel@tonic-gate 
32187c478bd9Sstevel@tonic-gate 	Files = (struct filed *)malloc(sizeof (struct filed) * nlogs);
32197c478bd9Sstevel@tonic-gate 
32207c478bd9Sstevel@tonic-gate 	if (!Files) {
32217c478bd9Sstevel@tonic-gate 		DPRINT1(1, "conf_init(%u): malloc failed - can't "
32227c478bd9Sstevel@tonic-gate 			"allocate 'Files' array\n", mythreadno);
32237c478bd9Sstevel@tonic-gate 		MALLOC_FAIL("loading minimum configuration");
32247c478bd9Sstevel@tonic-gate 		/* CSTYLED */
32257c478bd9Sstevel@tonic-gate 		Files = (struct filed *) &fallback; /*lint !e545 */
32267c478bd9Sstevel@tonic-gate 		cfline("*.ERR\t/dev/sysmsg", 0, &Files[0]);
32277c478bd9Sstevel@tonic-gate 		cfline("*.PANIC\t*", 0, &Files[1]);
32287c478bd9Sstevel@tonic-gate 		nlogs = 2;
32297c478bd9Sstevel@tonic-gate 		conf_close(&cf);
32307c478bd9Sstevel@tonic-gate 		goto nofile;
32317c478bd9Sstevel@tonic-gate 	}
32327c478bd9Sstevel@tonic-gate 
32337c478bd9Sstevel@tonic-gate 	/*
32347c478bd9Sstevel@tonic-gate 	 *  Foreach line in the conf table, open that file.
32357c478bd9Sstevel@tonic-gate 	 */
32367c478bd9Sstevel@tonic-gate 	conf_rewind(&cf);
32377c478bd9Sstevel@tonic-gate 	f = Files;
32387c478bd9Sstevel@tonic-gate 	i = 0;
32397c478bd9Sstevel@tonic-gate 	while (((p = conf_read(&cf)) != NULL) && (f < &Files[nlogs])) {
32407c478bd9Sstevel@tonic-gate 		i++;
32417c478bd9Sstevel@tonic-gate 		/* check for end-of-section */
32427c478bd9Sstevel@tonic-gate 		if (p[0] == '\0' || p[0] == '#')
32437c478bd9Sstevel@tonic-gate 			continue;
32447c478bd9Sstevel@tonic-gate 
32457c478bd9Sstevel@tonic-gate 		cfline(p, i, f);
32467c478bd9Sstevel@tonic-gate 		if (f->f_type == F_UNUSED)
32477c478bd9Sstevel@tonic-gate 			nlogs--;
32487c478bd9Sstevel@tonic-gate 		else
32497c478bd9Sstevel@tonic-gate 			f++;
32507c478bd9Sstevel@tonic-gate 	}
32517c478bd9Sstevel@tonic-gate 
32527c478bd9Sstevel@tonic-gate 	conf_close(&cf);
32537c478bd9Sstevel@tonic-gate 
32547c478bd9Sstevel@tonic-gate 	/*
32557c478bd9Sstevel@tonic-gate 	 * See if marks are to be written to any files.  If so, set up a
32567c478bd9Sstevel@tonic-gate 	 * timeout for marks.
32577c478bd9Sstevel@tonic-gate 	 */
32587c478bd9Sstevel@tonic-gate nofile:
32597c478bd9Sstevel@tonic-gate 	Marking = 0;
32607c478bd9Sstevel@tonic-gate 
32617c478bd9Sstevel@tonic-gate 	/*
32627c478bd9Sstevel@tonic-gate 	 * allocate thread stacks - one for each logger thread.
32637c478bd9Sstevel@tonic-gate 	 */
32647c478bd9Sstevel@tonic-gate 	if ((cstack_ptr = alloc_stacks(nlogs)) == NULL) {
32657c478bd9Sstevel@tonic-gate 		logerror("alloc_stacks failed - fatal");
32667c478bd9Sstevel@tonic-gate 		exit(1);
32677c478bd9Sstevel@tonic-gate 	}
32687c478bd9Sstevel@tonic-gate 
32697c478bd9Sstevel@tonic-gate 	/* And now one thread for each configured file */
32707c478bd9Sstevel@tonic-gate 	for (f = Files; f < &Files[nlogs]; f++) {
32717c478bd9Sstevel@tonic-gate 		if (filed_init(f) != 0) {
32727c478bd9Sstevel@tonic-gate 			logerror("pthread_create failed - fatal");
32737c478bd9Sstevel@tonic-gate 			exit(1);
32747c478bd9Sstevel@tonic-gate 		}
32757c478bd9Sstevel@tonic-gate 
3276*0ea5e3a5Sjjj 		(void) pthread_mutex_lock(&cft);
32777c478bd9Sstevel@tonic-gate 		++conf_threads;
3278*0ea5e3a5Sjjj 		(void) pthread_mutex_unlock(&cft);
32797c478bd9Sstevel@tonic-gate 
32807c478bd9Sstevel@tonic-gate 		if (f->f_type != F_UNUSED &&
32817c478bd9Sstevel@tonic-gate 			f->f_pmask[LOG_NFACILITIES] != NOPRI)
32827c478bd9Sstevel@tonic-gate 			Marking = 1;
32837c478bd9Sstevel@tonic-gate 	}
32847c478bd9Sstevel@tonic-gate }
32857c478bd9Sstevel@tonic-gate 
32867c478bd9Sstevel@tonic-gate /*
32877c478bd9Sstevel@tonic-gate  * filed init - initialize fields in a file descriptor struct
32887c478bd9Sstevel@tonic-gate  * this is called before multiple threads are running, so no mutex
32897c478bd9Sstevel@tonic-gate  * needs to be held at this time.
32907c478bd9Sstevel@tonic-gate  */
329178eb75caSchin static int
32927c478bd9Sstevel@tonic-gate filed_init(struct filed *f)
32937c478bd9Sstevel@tonic-gate {
32947c478bd9Sstevel@tonic-gate 	pthread_attr_t stack_attr;
32957c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
32967c478bd9Sstevel@tonic-gate 
32977c478bd9Sstevel@tonic-gate 	if (Debug) {
32987c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
32997c478bd9Sstevel@tonic-gate 	}
33007c478bd9Sstevel@tonic-gate 
33017c478bd9Sstevel@tonic-gate 	if (pthread_mutex_init(&f->filed_mutex, NULL) != 0) {
33027c478bd9Sstevel@tonic-gate 		logerror("pthread_mutex_init failed");
33037c478bd9Sstevel@tonic-gate 		return (-1);
33047c478bd9Sstevel@tonic-gate 	}
33057c478bd9Sstevel@tonic-gate 
33067c478bd9Sstevel@tonic-gate 	DPRINT2(5, "filed_init(%u): dataq_init for queue %p\n",
3307*0ea5e3a5Sjjj 		mythreadno, (void *)&f->f_queue);
33087c478bd9Sstevel@tonic-gate 	(void) dataq_init(&f->f_queue);
33097c478bd9Sstevel@tonic-gate 
33107c478bd9Sstevel@tonic-gate 	if (pthread_attr_init(&stack_attr) != 0) {
33117c478bd9Sstevel@tonic-gate 		logerror("pthread_attr_init failed");
33127c478bd9Sstevel@tonic-gate 		return (-1);
33137c478bd9Sstevel@tonic-gate 	}
33147c478bd9Sstevel@tonic-gate 
33157c478bd9Sstevel@tonic-gate 	(void) pthread_attr_setstacksize(&stack_attr, stacksize);
33167c478bd9Sstevel@tonic-gate 	(void) pthread_attr_setstackaddr(&stack_attr, cstack_ptr);
33177c478bd9Sstevel@tonic-gate 	cstack_ptr += stacksize + redzonesize;
33187c478bd9Sstevel@tonic-gate 
33197c478bd9Sstevel@tonic-gate 	f->f_msgflag = 0;
33207c478bd9Sstevel@tonic-gate 	f->f_prevmsg.msg[0] = '\0';
33217c478bd9Sstevel@tonic-gate 	f->f_prevmsg.flags = 0;
33227c478bd9Sstevel@tonic-gate 	f->f_prevmsg.pri = 0;
33237c478bd9Sstevel@tonic-gate 	f->f_prevmsg.host[0] = '\0';
33247c478bd9Sstevel@tonic-gate 
33257c478bd9Sstevel@tonic-gate 	f->f_current.msg[0] = '\0';
33267c478bd9Sstevel@tonic-gate 	f->f_current.flags = 0;
33277c478bd9Sstevel@tonic-gate 	f->f_current.pri = 0;
33287c478bd9Sstevel@tonic-gate 	f->f_current.host[0] = '\0';
33297c478bd9Sstevel@tonic-gate 
33307c478bd9Sstevel@tonic-gate 	f->f_prevcount = 0;
33317c478bd9Sstevel@tonic-gate 
33327c478bd9Sstevel@tonic-gate 	f->f_stat.flag = 0;
33337c478bd9Sstevel@tonic-gate 	f->f_stat.total = 0;
33347c478bd9Sstevel@tonic-gate 	f->f_stat.dups = 0;
33357c478bd9Sstevel@tonic-gate 	f->f_stat.cantfwd = 0;
33367c478bd9Sstevel@tonic-gate 	f->f_stat.errs = 0;
33377c478bd9Sstevel@tonic-gate 
33387c478bd9Sstevel@tonic-gate 	if (pthread_create(&f->f_thread, NULL, logit, (void *)f) != 0) {
33397c478bd9Sstevel@tonic-gate 		logerror("pthread_create failed");
3340*0ea5e3a5Sjjj 		(void) pthread_attr_destroy(&stack_attr);
33417c478bd9Sstevel@tonic-gate 		return (-1);
33427c478bd9Sstevel@tonic-gate 	}
33437c478bd9Sstevel@tonic-gate 
3344*0ea5e3a5Sjjj 	(void) pthread_attr_destroy(&stack_attr);
33457c478bd9Sstevel@tonic-gate 	return (0);
33467c478bd9Sstevel@tonic-gate }
33477c478bd9Sstevel@tonic-gate 
33487c478bd9Sstevel@tonic-gate 
33497c478bd9Sstevel@tonic-gate /*
33507c478bd9Sstevel@tonic-gate  * Crack a configuration file line
33517c478bd9Sstevel@tonic-gate  */
33527c478bd9Sstevel@tonic-gate static void
33537c478bd9Sstevel@tonic-gate cfline(char *line, int lineno, struct filed *f)
33547c478bd9Sstevel@tonic-gate {
33557c478bd9Sstevel@tonic-gate 	char *p;
33567c478bd9Sstevel@tonic-gate 	char *q;
33577c478bd9Sstevel@tonic-gate 	int i;
33587c478bd9Sstevel@tonic-gate 	char *bp;
33597c478bd9Sstevel@tonic-gate 	int pri;
33607c478bd9Sstevel@tonic-gate 	char buf[MAXLINE];
33617c478bd9Sstevel@tonic-gate 	char ebuf[SYS_NMLN+1+40];
33627c478bd9Sstevel@tonic-gate 	mode_t fmode, omode = O_WRONLY|O_APPEND|O_NOCTTY;
33637c478bd9Sstevel@tonic-gate 	struct stat64 sbuf;
33647c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
33657c478bd9Sstevel@tonic-gate 
33667c478bd9Sstevel@tonic-gate 	if (Debug) {
33677c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
33687c478bd9Sstevel@tonic-gate 	}
33697c478bd9Sstevel@tonic-gate 
33707c478bd9Sstevel@tonic-gate 	DPRINT2(1, "cfline(%u): (%s)\n", mythreadno, line);
33717c478bd9Sstevel@tonic-gate 
3372ace1a5f1Sdp 	errno = 0;	/* keep errno related stuff out of logerror messages */
33737c478bd9Sstevel@tonic-gate 
33747c478bd9Sstevel@tonic-gate 	/* clear out file entry */
33757c478bd9Sstevel@tonic-gate 	bzero((char *)f, sizeof (*f));
33767c478bd9Sstevel@tonic-gate 	for (i = 0; i <= LOG_NFACILITIES; i++)
33777c478bd9Sstevel@tonic-gate 		f->f_pmask[i] = NOPRI;
33787c478bd9Sstevel@tonic-gate 
33797c478bd9Sstevel@tonic-gate 	/* scan through the list of selectors */
33807c478bd9Sstevel@tonic-gate 	for (p = line; *p && *p != '\t'; ) {
33817c478bd9Sstevel@tonic-gate 
33827c478bd9Sstevel@tonic-gate 		/* find the end of this facility name list */
33837c478bd9Sstevel@tonic-gate 		for (q = p; *q && *q != '\t' && *q++ != '.'; )
33847c478bd9Sstevel@tonic-gate 			continue;
33857c478bd9Sstevel@tonic-gate 
33867c478bd9Sstevel@tonic-gate 		/* collect priority name */
33877c478bd9Sstevel@tonic-gate 		for (bp = buf; *q && !strchr("\t,;", *q); )
33887c478bd9Sstevel@tonic-gate 			*bp++ = *q++;
33897c478bd9Sstevel@tonic-gate 		*bp = '\0';
33907c478bd9Sstevel@tonic-gate 
33917c478bd9Sstevel@tonic-gate 		/* skip cruft */
33927c478bd9Sstevel@tonic-gate 		while (strchr(", ;", *q))
33937c478bd9Sstevel@tonic-gate 			q++;
33947c478bd9Sstevel@tonic-gate 
33957c478bd9Sstevel@tonic-gate 		/* decode priority name */
33967c478bd9Sstevel@tonic-gate 		pri = decode(buf, PriNames);
33977c478bd9Sstevel@tonic-gate 		if (pri < 0) {
33987c478bd9Sstevel@tonic-gate 			logerror("line %d: unknown priority name \"%s\"",
33997c478bd9Sstevel@tonic-gate 					lineno, buf);
34007c478bd9Sstevel@tonic-gate 			return;
34017c478bd9Sstevel@tonic-gate 		}
34027c478bd9Sstevel@tonic-gate 
34037c478bd9Sstevel@tonic-gate 		/* scan facilities */
34047c478bd9Sstevel@tonic-gate 		while (*p && !strchr("\t.;", *p)) {
34057c478bd9Sstevel@tonic-gate 			for (bp = buf; *p && !strchr("\t,;.", *p); )
34067c478bd9Sstevel@tonic-gate 				*bp++ = *p++;
34077c478bd9Sstevel@tonic-gate 			*bp = '\0';
34087c478bd9Sstevel@tonic-gate 			if (*buf == '*')
34097c478bd9Sstevel@tonic-gate 				for (i = 0; i < LOG_NFACILITIES; i++)
34107c478bd9Sstevel@tonic-gate 					f->f_pmask[i] = (uchar_t)pri;
34117c478bd9Sstevel@tonic-gate 			else {
34127c478bd9Sstevel@tonic-gate 				i = decode(buf, FacNames);
34137c478bd9Sstevel@tonic-gate 				if (i < 0) {
34147c478bd9Sstevel@tonic-gate 					logerror("line %d: unknown facility"
34157c478bd9Sstevel@tonic-gate 						" name \"%s\"", lineno, buf);
34167c478bd9Sstevel@tonic-gate 					return;
34177c478bd9Sstevel@tonic-gate 				}
34187c478bd9Sstevel@tonic-gate 				f->f_pmask[i >> 3] = (uchar_t)pri;
34197c478bd9Sstevel@tonic-gate 			}
34207c478bd9Sstevel@tonic-gate 			while (*p == ',' || *p == ' ')
34217c478bd9Sstevel@tonic-gate 				p++;
34227c478bd9Sstevel@tonic-gate 		}
34237c478bd9Sstevel@tonic-gate 
34247c478bd9Sstevel@tonic-gate 		p = q;
34257c478bd9Sstevel@tonic-gate 	}
34267c478bd9Sstevel@tonic-gate 
34277c478bd9Sstevel@tonic-gate 	/* skip to action part */
34287c478bd9Sstevel@tonic-gate 	while (*p == '\t' || *p == ' ')
34297c478bd9Sstevel@tonic-gate 		p++;
34307c478bd9Sstevel@tonic-gate 
34317c478bd9Sstevel@tonic-gate 	switch (*p) {
34327c478bd9Sstevel@tonic-gate 	case '\0':
34337c478bd9Sstevel@tonic-gate 		errno = 0;
34347c478bd9Sstevel@tonic-gate 		logerror("line %d: no action part", lineno);
34357c478bd9Sstevel@tonic-gate 		break;
34367c478bd9Sstevel@tonic-gate 
34377c478bd9Sstevel@tonic-gate 	case '@':
34387c478bd9Sstevel@tonic-gate 		(void) strlcpy(f->f_un.f_forw.f_hname, ++p, SYS_NMLN);
3439*0ea5e3a5Sjjj 		if (logforward(f, ebuf, sizeof (ebuf)) != 0) {
34407c478bd9Sstevel@tonic-gate 			logerror("line %d: %s", lineno, ebuf);
34417c478bd9Sstevel@tonic-gate 			break;
34427c478bd9Sstevel@tonic-gate 		}
34437c478bd9Sstevel@tonic-gate 		f->f_type = F_FORW;
34447c478bd9Sstevel@tonic-gate 		break;
34457c478bd9Sstevel@tonic-gate 
34467c478bd9Sstevel@tonic-gate 	case '/':
34477c478bd9Sstevel@tonic-gate 		(void) strlcpy(f->f_un.f_fname, p, MAXPATHLEN);
34487c478bd9Sstevel@tonic-gate 		if (stat64(p, &sbuf) < 0) {
34497c478bd9Sstevel@tonic-gate 			logerror(p);
34507c478bd9Sstevel@tonic-gate 			break;
34517c478bd9Sstevel@tonic-gate 		}
34527c478bd9Sstevel@tonic-gate 		/*
34537c478bd9Sstevel@tonic-gate 		 * don't block trying to open a pipe
34547c478bd9Sstevel@tonic-gate 		 * with no reader on the other end
34557c478bd9Sstevel@tonic-gate 		 */
34567c478bd9Sstevel@tonic-gate 		fmode = 0; 	/* reset each pass */
34577c478bd9Sstevel@tonic-gate 		if (S_ISFIFO(sbuf.st_mode))
34587c478bd9Sstevel@tonic-gate 			fmode = O_NONBLOCK;
34597c478bd9Sstevel@tonic-gate 
34607c478bd9Sstevel@tonic-gate 		f->f_file = open64(p, omode|fmode);
34617c478bd9Sstevel@tonic-gate 		if (f->f_file < 0) {
34627c478bd9Sstevel@tonic-gate 			if (fmode && errno == ENXIO) {
34637c478bd9Sstevel@tonic-gate 				errno = 0;
34647c478bd9Sstevel@tonic-gate 				logerror("%s - no reader", p);
34657c478bd9Sstevel@tonic-gate 			} else
34667c478bd9Sstevel@tonic-gate 				logerror(p);
34677c478bd9Sstevel@tonic-gate 			break;
34687c478bd9Sstevel@tonic-gate 		}
34697c478bd9Sstevel@tonic-gate 
34707c478bd9Sstevel@tonic-gate 		/*
34717c478bd9Sstevel@tonic-gate 		 * Fifos are initially opened NONBLOCK
34727c478bd9Sstevel@tonic-gate 		 * to insure we don't hang, but once
34737c478bd9Sstevel@tonic-gate 		 * we are open, we need to change the
34747c478bd9Sstevel@tonic-gate 		 * behavior back to blocking, otherwise
34757c478bd9Sstevel@tonic-gate 		 * we may get write errors, and the log
34767c478bd9Sstevel@tonic-gate 		 * will get closed down the line.
34777c478bd9Sstevel@tonic-gate 		 */
34787c478bd9Sstevel@tonic-gate 		if (S_ISFIFO(sbuf.st_mode))
34797c478bd9Sstevel@tonic-gate 			(void) fcntl(f->f_file, F_SETFL, omode);
34807c478bd9Sstevel@tonic-gate 
34817c478bd9Sstevel@tonic-gate 		if (isatty(f->f_file)) {
34827c478bd9Sstevel@tonic-gate 			f->f_type = F_TTY;
34837c478bd9Sstevel@tonic-gate 			untty();
34847c478bd9Sstevel@tonic-gate 		} else
34857c478bd9Sstevel@tonic-gate 			f->f_type = F_FILE;
34867c478bd9Sstevel@tonic-gate 
34877c478bd9Sstevel@tonic-gate 		if ((strcmp(p, ctty) == 0) || (strcmp(p, sysmsg) == 0))
34887c478bd9Sstevel@tonic-gate 			f->f_type = F_CONSOLE;
34897c478bd9Sstevel@tonic-gate 		break;
34907c478bd9Sstevel@tonic-gate 
34917c478bd9Sstevel@tonic-gate 	case '*':
34927c478bd9Sstevel@tonic-gate 		f->f_type = F_WALL;
34937c478bd9Sstevel@tonic-gate 		break;
34947c478bd9Sstevel@tonic-gate 
34957c478bd9Sstevel@tonic-gate 	default:
34967c478bd9Sstevel@tonic-gate 		for (i = 0; i < MAXUNAMES && *p; i++) {
34977c478bd9Sstevel@tonic-gate 			for (q = p; *q && *q != ','; )
34987c478bd9Sstevel@tonic-gate 				q++;
34997c478bd9Sstevel@tonic-gate 			(void) strlcpy(f->f_un.f_uname[i], p, UNAMESZ);
35007c478bd9Sstevel@tonic-gate 			if ((q - p) > UNAMESZ)
35017c478bd9Sstevel@tonic-gate 				f->f_un.f_uname[i][UNAMESZ] = '\0';
35027c478bd9Sstevel@tonic-gate 			else
35037c478bd9Sstevel@tonic-gate 				f->f_un.f_uname[i][q - p] = '\0';
35047c478bd9Sstevel@tonic-gate 			while (*q == ',' || *q == ' ')
35057c478bd9Sstevel@tonic-gate 				q++;
35067c478bd9Sstevel@tonic-gate 			p = q;
35077c478bd9Sstevel@tonic-gate 		}
35087c478bd9Sstevel@tonic-gate 		f->f_type = F_USERS;
35097c478bd9Sstevel@tonic-gate 		break;
35107c478bd9Sstevel@tonic-gate 	}
35117c478bd9Sstevel@tonic-gate 	f->f_orig_type = f->f_type;
35127c478bd9Sstevel@tonic-gate }
35137c478bd9Sstevel@tonic-gate 
35147c478bd9Sstevel@tonic-gate 
35157c478bd9Sstevel@tonic-gate /*
35167c478bd9Sstevel@tonic-gate  *  Decode a symbolic name to a numeric value
35177c478bd9Sstevel@tonic-gate  */
35187c478bd9Sstevel@tonic-gate static int
35197c478bd9Sstevel@tonic-gate decode(char *name, struct code *codetab)
35207c478bd9Sstevel@tonic-gate {
35217c478bd9Sstevel@tonic-gate 	struct code *c;
35227c478bd9Sstevel@tonic-gate 	char *p;
35237c478bd9Sstevel@tonic-gate 	char buf[40];
35247c478bd9Sstevel@tonic-gate 
35257c478bd9Sstevel@tonic-gate 	if (isdigit(*name))
35267c478bd9Sstevel@tonic-gate 		return (atoi(name));
35277c478bd9Sstevel@tonic-gate 
35287c478bd9Sstevel@tonic-gate 	(void) strncpy(buf, name, sizeof (buf) - 1);
35297c478bd9Sstevel@tonic-gate 	for (p = buf; *p; p++)
35307c478bd9Sstevel@tonic-gate 		if (isupper(*p))
35317c478bd9Sstevel@tonic-gate 			*p = tolower(*p);
35327c478bd9Sstevel@tonic-gate 	for (c = codetab; c->c_name; c++)
35337c478bd9Sstevel@tonic-gate 		if (!(strcmp(buf, c->c_name)))
35347c478bd9Sstevel@tonic-gate 			return (c->c_val);
35357c478bd9Sstevel@tonic-gate 
35367c478bd9Sstevel@tonic-gate 	return (-1);
35377c478bd9Sstevel@tonic-gate }
35387c478bd9Sstevel@tonic-gate 
35397c478bd9Sstevel@tonic-gate static int
35407c478bd9Sstevel@tonic-gate ismyaddr(struct netbuf *nbp)
35417c478bd9Sstevel@tonic-gate {
35427c478bd9Sstevel@tonic-gate 	int i;
35437c478bd9Sstevel@tonic-gate 
35447c478bd9Sstevel@tonic-gate 	if (nbp == NULL)
35457c478bd9Sstevel@tonic-gate 		return (0);
35467c478bd9Sstevel@tonic-gate 
35477c478bd9Sstevel@tonic-gate 	for (i = 1; i < Ninputs; i++) {
35487c478bd9Sstevel@tonic-gate 		if (same_addr(nbp, Myaddrs[i]))
35497c478bd9Sstevel@tonic-gate 			return (1);
35507c478bd9Sstevel@tonic-gate 	}
35517c478bd9Sstevel@tonic-gate 	return (0);
35527c478bd9Sstevel@tonic-gate }
35537c478bd9Sstevel@tonic-gate 
35547c478bd9Sstevel@tonic-gate static void
35557c478bd9Sstevel@tonic-gate getnets(void)
35567c478bd9Sstevel@tonic-gate {
35577c478bd9Sstevel@tonic-gate 	struct nd_hostserv hs;
35587c478bd9Sstevel@tonic-gate 	struct netconfig *ncp;
35597c478bd9Sstevel@tonic-gate 	struct nd_addrlist *nap;
35607c478bd9Sstevel@tonic-gate 	struct netbuf *nbp;
35617c478bd9Sstevel@tonic-gate 	int i, inputs;
35627c478bd9Sstevel@tonic-gate 	void *handle;
35637c478bd9Sstevel@tonic-gate 	char *uap;
35647c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
35657c478bd9Sstevel@tonic-gate 
35667c478bd9Sstevel@tonic-gate 	if (Debug) {
35677c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
35687c478bd9Sstevel@tonic-gate 	}
35697c478bd9Sstevel@tonic-gate 
35707c478bd9Sstevel@tonic-gate 	if (turnoff) {
35717c478bd9Sstevel@tonic-gate 		DPRINT1(1, "getnets(%u): network is being turned off\n",
35727c478bd9Sstevel@tonic-gate 				mythreadno);
35737c478bd9Sstevel@tonic-gate 		return;
35747c478bd9Sstevel@tonic-gate 	}
35757c478bd9Sstevel@tonic-gate 
35767c478bd9Sstevel@tonic-gate 	hs.h_host = HOST_SELF;
35777c478bd9Sstevel@tonic-gate 	hs.h_serv = "syslog";
35787c478bd9Sstevel@tonic-gate 
35797c478bd9Sstevel@tonic-gate 	if ((handle = setnetconfig()) == NULL) {
35807c478bd9Sstevel@tonic-gate 		return;
35817c478bd9Sstevel@tonic-gate 	}
35827c478bd9Sstevel@tonic-gate 
35837c478bd9Sstevel@tonic-gate 	while ((ncp = getnetconfig(handle)) != NULL) {
35847c478bd9Sstevel@tonic-gate 		if (ncp->nc_semantics != NC_TPI_CLTS) {
35857c478bd9Sstevel@tonic-gate 			continue;
35867c478bd9Sstevel@tonic-gate 		}
35877c478bd9Sstevel@tonic-gate 
35887c478bd9Sstevel@tonic-gate 		if (netdir_getbyname(ncp, &hs, &nap) != 0) {
35897c478bd9Sstevel@tonic-gate 			continue;
35907c478bd9Sstevel@tonic-gate 		}
35917c478bd9Sstevel@tonic-gate 
35927c478bd9Sstevel@tonic-gate 		if (nap == NULL || nap->n_cnt <= 0) {
35937c478bd9Sstevel@tonic-gate 			DPRINT1(1, "getnets(%u): found no address\n",
35947c478bd9Sstevel@tonic-gate 					mythreadno);
35957c478bd9Sstevel@tonic-gate 			netdir_free((void *)nap, ND_ADDRLIST);
35967c478bd9Sstevel@tonic-gate 			continue;
35977c478bd9Sstevel@tonic-gate 		}
35987c478bd9Sstevel@tonic-gate 
35997c478bd9Sstevel@tonic-gate 		if (Debug) {
36007c478bd9Sstevel@tonic-gate 			DPRINT2(1, "getnets(%u): found %d addresses",
36017c478bd9Sstevel@tonic-gate 				mythreadno, nap->n_cnt);
36027c478bd9Sstevel@tonic-gate 			DPRINT0(1, ", they are: ");
36037c478bd9Sstevel@tonic-gate 			nbp = nap->n_addrs;
36047c478bd9Sstevel@tonic-gate 
36057c478bd9Sstevel@tonic-gate 			for (i = 0; i < nap->n_cnt; i++) {
36067c478bd9Sstevel@tonic-gate 				if ((uap = taddr2uaddr(ncp, nbp)) != NULL) {
36077c478bd9Sstevel@tonic-gate 					DPRINT1(1, "%s ", uap);
36087c478bd9Sstevel@tonic-gate 					free(uap);
36097c478bd9Sstevel@tonic-gate 				}
36107c478bd9Sstevel@tonic-gate 				nbp++;
36117c478bd9Sstevel@tonic-gate 			}
36127c478bd9Sstevel@tonic-gate 
36137c478bd9Sstevel@tonic-gate 			DPRINT0(1, "\n");
36147c478bd9Sstevel@tonic-gate 		}
36157c478bd9Sstevel@tonic-gate 
36167c478bd9Sstevel@tonic-gate 		inputs = Ninputs + nap->n_cnt;
36177c478bd9Sstevel@tonic-gate 
36187c478bd9Sstevel@tonic-gate 		Nfd = realloc(Nfd, inputs * sizeof (struct pollfd));
36197c478bd9Sstevel@tonic-gate 		Ncf = realloc(Ncf, inputs * sizeof (struct netconfig));
36207c478bd9Sstevel@tonic-gate 		Myaddrs = realloc(Myaddrs, inputs * sizeof (struct netbuf *));
36217c478bd9Sstevel@tonic-gate 		Udp = realloc(Udp, inputs * sizeof (struct t_unitdata *));
36227c478bd9Sstevel@tonic-gate 		Errp = realloc(Errp, inputs * sizeof (struct t_uderr *));
36237c478bd9Sstevel@tonic-gate 
36247c478bd9Sstevel@tonic-gate 		/*
36257c478bd9Sstevel@tonic-gate 		 * all malloc failures here are fatal
36267c478bd9Sstevel@tonic-gate 		 */
36277c478bd9Sstevel@tonic-gate 		if (Nfd == NULL || Ncf == NULL || Myaddrs == NULL ||
36287c478bd9Sstevel@tonic-gate 			Udp == NULL || Errp == NULL) {
36297c478bd9Sstevel@tonic-gate 			MALLOC_FAIL_EXIT;
36307c478bd9Sstevel@tonic-gate 		}
36317c478bd9Sstevel@tonic-gate 
36327c478bd9Sstevel@tonic-gate 		nbp = nap->n_addrs;
36337c478bd9Sstevel@tonic-gate 
36347c478bd9Sstevel@tonic-gate 		for (i = 0; i < nap->n_cnt; i++, nbp++) {
36357c478bd9Sstevel@tonic-gate 			char ebuf[128];
36367c478bd9Sstevel@tonic-gate 
36377c478bd9Sstevel@tonic-gate 			if (addnet(ncp, nbp) == 0) {
36387c478bd9Sstevel@tonic-gate 				/* no error */
36397c478bd9Sstevel@tonic-gate 				continue;
36407c478bd9Sstevel@tonic-gate 			}
36417c478bd9Sstevel@tonic-gate 
36427c478bd9Sstevel@tonic-gate 			(void) strcpy(ebuf, "Unable to configure syslog port");
36437c478bd9Sstevel@tonic-gate 
36447c478bd9Sstevel@tonic-gate 			if ((uap = taddr2uaddr(ncp, nbp)) != NULL) {
36457c478bd9Sstevel@tonic-gate 				size_t l = strlen(ebuf);
36467c478bd9Sstevel@tonic-gate 				(void) snprintf(ebuf + l, sizeof (ebuf) - l,
36477c478bd9Sstevel@tonic-gate 					" for %s", uap);
36487c478bd9Sstevel@tonic-gate 			}
36497c478bd9Sstevel@tonic-gate 
36507c478bd9Sstevel@tonic-gate 			DPRINT2(1, "getnets(%u): %s",
36517c478bd9Sstevel@tonic-gate 				mythreadno, ebuf);
36527c478bd9Sstevel@tonic-gate 
36537c478bd9Sstevel@tonic-gate 			if (uap) {
36547c478bd9Sstevel@tonic-gate 				free(uap);
36557c478bd9Sstevel@tonic-gate 			}
36567c478bd9Sstevel@tonic-gate 
36577c478bd9Sstevel@tonic-gate 			logerror(ebuf);
36587c478bd9Sstevel@tonic-gate 			/*
36597c478bd9Sstevel@tonic-gate 			 * Here maybe syslogd can quit. However, syslogd
36607c478bd9Sstevel@tonic-gate 			 * has been ignoring this error and keep running.
36617c478bd9Sstevel@tonic-gate 			 * So we won't break it.
36627c478bd9Sstevel@tonic-gate 			 */
36637c478bd9Sstevel@tonic-gate 		}
36647c478bd9Sstevel@tonic-gate 
36657c478bd9Sstevel@tonic-gate 		netdir_free((void *)nap, ND_ADDRLIST);
36667c478bd9Sstevel@tonic-gate 	}
36677c478bd9Sstevel@tonic-gate 
36687c478bd9Sstevel@tonic-gate 	(void) endnetconfig(handle);
36697c478bd9Sstevel@tonic-gate }
36707c478bd9Sstevel@tonic-gate 
36717c478bd9Sstevel@tonic-gate /*
36727c478bd9Sstevel@tonic-gate  * Open the network device, and allocate necessary resources.
36737c478bd9Sstevel@tonic-gate  * Myaddrs will also be filled, so that we can call ismyaddr() before
36747c478bd9Sstevel@tonic-gate  * being bound to the network.
36757c478bd9Sstevel@tonic-gate  */
36767c478bd9Sstevel@tonic-gate static int
36777c478bd9Sstevel@tonic-gate addnet(struct netconfig *ncp, struct netbuf *nbp)
36787c478bd9Sstevel@tonic-gate {
36797c478bd9Sstevel@tonic-gate 	int fd;
36807c478bd9Sstevel@tonic-gate 	struct netbuf *bp;
36817c478bd9Sstevel@tonic-gate 
36827c478bd9Sstevel@tonic-gate 	fd = t_open(ncp->nc_device, O_RDWR, NULL);
36837c478bd9Sstevel@tonic-gate 
36847c478bd9Sstevel@tonic-gate 	if (fd < 0) {
36857c478bd9Sstevel@tonic-gate 		return (1);
36867c478bd9Sstevel@tonic-gate 	}
36877c478bd9Sstevel@tonic-gate 
36887c478bd9Sstevel@tonic-gate 	(void) memcpy(&Ncf[Ninputs], ncp, sizeof (struct netconfig));
36897c478bd9Sstevel@tonic-gate 
36907c478bd9Sstevel@tonic-gate 	/*LINTED*/
36917c478bd9Sstevel@tonic-gate 	Udp[Ninputs] = (struct t_unitdata *)t_alloc(fd, T_UNITDATA, T_ADDR);
36927c478bd9Sstevel@tonic-gate 
36937c478bd9Sstevel@tonic-gate 	if (Udp[Ninputs] == NULL) {
3694*0ea5e3a5Sjjj 		(void) t_close(fd);
36957c478bd9Sstevel@tonic-gate 		return (1);
36967c478bd9Sstevel@tonic-gate 	}
36977c478bd9Sstevel@tonic-gate 
36987c478bd9Sstevel@tonic-gate 	/*LINTED*/
36997c478bd9Sstevel@tonic-gate 	Errp[Ninputs] = (struct t_uderr *)t_alloc(fd, T_UDERROR, T_ADDR);
37007c478bd9Sstevel@tonic-gate 
37017c478bd9Sstevel@tonic-gate 	if (Errp[Ninputs] == NULL) {
3702*0ea5e3a5Sjjj 		(void) t_close(fd);
3703*0ea5e3a5Sjjj 		(void) t_free((char *)Udp[Ninputs], T_UNITDATA);
37047c478bd9Sstevel@tonic-gate 		return (1);
37057c478bd9Sstevel@tonic-gate 	}
37067c478bd9Sstevel@tonic-gate 
37077c478bd9Sstevel@tonic-gate 	if ((bp = malloc(sizeof (struct netbuf))) == NULL ||
37087c478bd9Sstevel@tonic-gate 		(bp->buf = malloc(nbp->len)) == NULL) {
37097c478bd9Sstevel@tonic-gate 		MALLOC_FAIL("allocating address buffer");
3710*0ea5e3a5Sjjj 		(void) t_close(fd);
3711*0ea5e3a5Sjjj 		(void) t_free((char *)Udp[Ninputs], T_UNITDATA);
3712*0ea5e3a5Sjjj 		(void) t_free((char *)Errp[Ninputs], T_UDERROR);
37137c478bd9Sstevel@tonic-gate 
37147c478bd9Sstevel@tonic-gate 		if (bp) {
37157c478bd9Sstevel@tonic-gate 			free(bp);
37167c478bd9Sstevel@tonic-gate 		}
37177c478bd9Sstevel@tonic-gate 
37187c478bd9Sstevel@tonic-gate 		return (1);
37197c478bd9Sstevel@tonic-gate 	}
37207c478bd9Sstevel@tonic-gate 
37217c478bd9Sstevel@tonic-gate 	bp->len = nbp->len;
37227c478bd9Sstevel@tonic-gate 	(void) memcpy(bp->buf, nbp->buf, nbp->len);
37237c478bd9Sstevel@tonic-gate 	Myaddrs[Ninputs] = bp;
37247c478bd9Sstevel@tonic-gate 
37257c478bd9Sstevel@tonic-gate 	Nfd[Ninputs].fd = fd;
37267c478bd9Sstevel@tonic-gate 	Nfd[Ninputs].events = POLLIN;
37277c478bd9Sstevel@tonic-gate 	Ninputs++;
37287c478bd9Sstevel@tonic-gate 	return (0);
37297c478bd9Sstevel@tonic-gate }
37307c478bd9Sstevel@tonic-gate 
37317c478bd9Sstevel@tonic-gate /*
37327c478bd9Sstevel@tonic-gate  * Allocate UDP buffer to minimize packet loss.
37337c478bd9Sstevel@tonic-gate  */
37347c478bd9Sstevel@tonic-gate static void
37357c478bd9Sstevel@tonic-gate set_udp_buffer(int fd)
37367c478bd9Sstevel@tonic-gate {
37377c478bd9Sstevel@tonic-gate 	struct t_optmgmt req, resp;
37387c478bd9Sstevel@tonic-gate 	struct opthdr *opt;
37397c478bd9Sstevel@tonic-gate 	size_t optsize, bsize = 256 * 1024;
37407c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
37417c478bd9Sstevel@tonic-gate 
37427c478bd9Sstevel@tonic-gate 	if (Debug) {
37437c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
37447c478bd9Sstevel@tonic-gate 	}
37457c478bd9Sstevel@tonic-gate 
37467c478bd9Sstevel@tonic-gate 	optsize = sizeof (struct opthdr) + sizeof (int);
37477c478bd9Sstevel@tonic-gate 	if ((opt = malloc(optsize)) == NULL) {
37487c478bd9Sstevel@tonic-gate 		MALLOC_FAIL("will have no udp buffer");
37497c478bd9Sstevel@tonic-gate 		return;
37507c478bd9Sstevel@tonic-gate 	}
37517c478bd9Sstevel@tonic-gate 	opt->level = SOL_SOCKET;
37527c478bd9Sstevel@tonic-gate 	opt->name = SO_RCVBUF;
37537c478bd9Sstevel@tonic-gate 	opt->len = sizeof (int);
37547c478bd9Sstevel@tonic-gate 	*(int *)(opt + 1) = bsize;
37557c478bd9Sstevel@tonic-gate 
37567c478bd9Sstevel@tonic-gate 	req.flags = T_NEGOTIATE;
37577c478bd9Sstevel@tonic-gate 	req.opt.len = optsize;
37587c478bd9Sstevel@tonic-gate 	req.opt.buf = (char *)opt;
37597c478bd9Sstevel@tonic-gate 
37607c478bd9Sstevel@tonic-gate 	resp.flags = 0;
37617c478bd9Sstevel@tonic-gate 	resp.opt.maxlen = optsize;
37627c478bd9Sstevel@tonic-gate 	resp.opt.buf = (char *)opt;
37637c478bd9Sstevel@tonic-gate 
37647c478bd9Sstevel@tonic-gate 	while (t_optmgmt(fd, &req, &resp) == -1 || resp.flags != T_SUCCESS) {
37657c478bd9Sstevel@tonic-gate 		if (t_errno != TSYSERR || errno != ENOBUFS) {
37667c478bd9Sstevel@tonic-gate 			bsize = 0;
37677c478bd9Sstevel@tonic-gate 			break;
37687c478bd9Sstevel@tonic-gate 		}
37697c478bd9Sstevel@tonic-gate 		bsize >>= 1;
37707c478bd9Sstevel@tonic-gate 		if (bsize < 8192) {
37717c478bd9Sstevel@tonic-gate 			break;
37727c478bd9Sstevel@tonic-gate 		}
37737c478bd9Sstevel@tonic-gate 		*(int *)(opt + 1) = bsize;
37747c478bd9Sstevel@tonic-gate 	}
37757c478bd9Sstevel@tonic-gate 	if (bsize == 0) {
37767c478bd9Sstevel@tonic-gate 		logerror("failed to allocate UDP buffer");
37777c478bd9Sstevel@tonic-gate 	}
37787c478bd9Sstevel@tonic-gate 	DPRINT3(1, "set_udp_buffer(%u): allocate %d for fd %d\n",
37797c478bd9Sstevel@tonic-gate 		mythreadno, bsize, fd);
37807c478bd9Sstevel@tonic-gate 	free(opt);
37817c478bd9Sstevel@tonic-gate }
37827c478bd9Sstevel@tonic-gate 
37837c478bd9Sstevel@tonic-gate /*
37847c478bd9Sstevel@tonic-gate  * Attach the network, and allocate UDP buffer for the interface.
37857c478bd9Sstevel@tonic-gate  */
37867c478bd9Sstevel@tonic-gate static void
37877c478bd9Sstevel@tonic-gate bindnet(void)
37887c478bd9Sstevel@tonic-gate {
37897c478bd9Sstevel@tonic-gate 	struct t_bind bind, *bound;
37907c478bd9Sstevel@tonic-gate 	int cnt, i;
37917c478bd9Sstevel@tonic-gate 	char *uap;
37927c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
37937c478bd9Sstevel@tonic-gate 
37947c478bd9Sstevel@tonic-gate 	if (Debug) {
37957c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
37967c478bd9Sstevel@tonic-gate 	}
37977c478bd9Sstevel@tonic-gate 
37987c478bd9Sstevel@tonic-gate 	cnt = 0;
37997c478bd9Sstevel@tonic-gate 
38007c478bd9Sstevel@tonic-gate 	while (cnt < Ninputs) {
38017c478bd9Sstevel@tonic-gate 		char ebuf[128];
38027c478bd9Sstevel@tonic-gate 
38037c478bd9Sstevel@tonic-gate 		/*LINTED*/
38047c478bd9Sstevel@tonic-gate 		bound  = (struct t_bind *)t_alloc(Nfd[cnt].fd, T_BIND, T_ADDR);
38057c478bd9Sstevel@tonic-gate 		bind.addr = *Myaddrs[cnt];
38067c478bd9Sstevel@tonic-gate 		bind.qlen = 0;
38077c478bd9Sstevel@tonic-gate 
38087c478bd9Sstevel@tonic-gate 		if (t_bind(Nfd[cnt].fd, &bind, bound) == 0) {
38097c478bd9Sstevel@tonic-gate 			if (same_addr(&bind.addr, &bound->addr)) {
3810*0ea5e3a5Sjjj 				(void) t_free((char *)bound, T_BIND);
38117c478bd9Sstevel@tonic-gate 				set_udp_buffer(Nfd[cnt].fd);
38127c478bd9Sstevel@tonic-gate 				cnt++;
38137c478bd9Sstevel@tonic-gate 				continue;
38147c478bd9Sstevel@tonic-gate 			}
38157c478bd9Sstevel@tonic-gate 		}
38167c478bd9Sstevel@tonic-gate 
38177c478bd9Sstevel@tonic-gate 		/* failed to bind port */
3818*0ea5e3a5Sjjj 		(void) t_free((char *)bound, T_BIND);
38197c478bd9Sstevel@tonic-gate 
38207c478bd9Sstevel@tonic-gate 		(void) strcpy(ebuf, "Unable to bind syslog port");
38217c478bd9Sstevel@tonic-gate 
38227c478bd9Sstevel@tonic-gate 		uap = taddr2uaddr(&Ncf[cnt], Myaddrs[cnt]);
38237c478bd9Sstevel@tonic-gate 		if (uap) {
38247c478bd9Sstevel@tonic-gate 			i = strlen(ebuf);
38257c478bd9Sstevel@tonic-gate 			(void) snprintf(ebuf + i, sizeof (ebuf) - i,
38267c478bd9Sstevel@tonic-gate 				" for %s", uap);
38277c478bd9Sstevel@tonic-gate 		}
38287c478bd9Sstevel@tonic-gate 
38297c478bd9Sstevel@tonic-gate 		DPRINT2(1, "bindnet(%u): failed to bind port (%s)\n",
38307c478bd9Sstevel@tonic-gate 			mythreadno, uap ? uap : "<unknown>");
38317c478bd9Sstevel@tonic-gate 
38327c478bd9Sstevel@tonic-gate 		if (uap) {
38337c478bd9Sstevel@tonic-gate 			free(uap);
38347c478bd9Sstevel@tonic-gate 		}
38357c478bd9Sstevel@tonic-gate 
38367c478bd9Sstevel@tonic-gate 		errno = 0;
38377c478bd9Sstevel@tonic-gate 		logerror(ebuf);
38387c478bd9Sstevel@tonic-gate 
3839*0ea5e3a5Sjjj 		(void) t_close(Nfd[cnt].fd);
38407c478bd9Sstevel@tonic-gate 		free(Myaddrs[cnt]->buf);
38417c478bd9Sstevel@tonic-gate 		free(Myaddrs[cnt]);
3842*0ea5e3a5Sjjj 		(void) t_free((char *)Udp[cnt], T_UNITDATA);
3843*0ea5e3a5Sjjj 		(void) t_free((char *)Errp[cnt], T_UDERROR);
38447c478bd9Sstevel@tonic-gate 
38457c478bd9Sstevel@tonic-gate 		for (i = cnt; i < (Ninputs-1); i++) {
38467c478bd9Sstevel@tonic-gate 			Nfd[i] = Nfd[i + 1];
38477c478bd9Sstevel@tonic-gate 			Ncf[i] = Ncf[i + 1];
38487c478bd9Sstevel@tonic-gate 			Myaddrs[i] = Myaddrs[i + 1];
38497c478bd9Sstevel@tonic-gate 			Udp[i] = Udp[i + 1];
38507c478bd9Sstevel@tonic-gate 			Errp[i] = Errp[i + 1];
38517c478bd9Sstevel@tonic-gate 		}
38527c478bd9Sstevel@tonic-gate 
38537c478bd9Sstevel@tonic-gate 		Ninputs--;
38547c478bd9Sstevel@tonic-gate 	}
38557c478bd9Sstevel@tonic-gate }
38567c478bd9Sstevel@tonic-gate 
38577c478bd9Sstevel@tonic-gate static int
3858*0ea5e3a5Sjjj logforward(struct filed *f, char *ebuf, size_t elen)
38597c478bd9Sstevel@tonic-gate {
38607c478bd9Sstevel@tonic-gate 	struct nd_hostserv hs;
38617c478bd9Sstevel@tonic-gate 	struct netbuf *nbp;
38627c478bd9Sstevel@tonic-gate 	struct netconfig *ncp;
38637c478bd9Sstevel@tonic-gate 	struct nd_addrlist *nap;
38647c478bd9Sstevel@tonic-gate 	void *handle;
38657c478bd9Sstevel@tonic-gate 	char *hp;
38667c478bd9Sstevel@tonic-gate 
38677c478bd9Sstevel@tonic-gate 	hp = f->f_un.f_forw.f_hname;
38687c478bd9Sstevel@tonic-gate 	hs.h_host = hp;
38697c478bd9Sstevel@tonic-gate 	hs.h_serv = "syslog";
38707c478bd9Sstevel@tonic-gate 
38717c478bd9Sstevel@tonic-gate 	if ((handle = setnetconfig()) == NULL) {
3872*0ea5e3a5Sjjj 		(void) strlcpy(ebuf,
3873*0ea5e3a5Sjjj 			"unable to rewind the netconfig database", elen);
38747c478bd9Sstevel@tonic-gate 		errno = 0;
38757c478bd9Sstevel@tonic-gate 		return (-1);
38767c478bd9Sstevel@tonic-gate 	}
38777c478bd9Sstevel@tonic-gate 	nap = (struct nd_addrlist *)NULL;
38787c478bd9Sstevel@tonic-gate 	while ((ncp = getnetconfig(handle)) != NULL) {
38797c478bd9Sstevel@tonic-gate 		if (ncp->nc_semantics == NC_TPI_CLTS) {
38807c478bd9Sstevel@tonic-gate 			if (netdir_getbyname(ncp, &hs, &nap) == 0) {
38817c478bd9Sstevel@tonic-gate 				if (!nap)
38827c478bd9Sstevel@tonic-gate 					continue;
38837c478bd9Sstevel@tonic-gate 				nbp = nap->n_addrs;
38847c478bd9Sstevel@tonic-gate 				break;
38857c478bd9Sstevel@tonic-gate 			}
38867c478bd9Sstevel@tonic-gate 		}
38877c478bd9Sstevel@tonic-gate 	}
38887c478bd9Sstevel@tonic-gate 	if (ncp == NULL) {
3889*0ea5e3a5Sjjj 		(void) endnetconfig(handle);
3890*0ea5e3a5Sjjj 		(void) snprintf(ebuf, elen,
3891*0ea5e3a5Sjjj 		    "WARNING: %s could not be resolved", hp);
38927c478bd9Sstevel@tonic-gate 		errno = 0;
38937c478bd9Sstevel@tonic-gate 		return (-1);
38947c478bd9Sstevel@tonic-gate 	}
38957c478bd9Sstevel@tonic-gate 	if (nap == (struct nd_addrlist *)NULL) {
3896*0ea5e3a5Sjjj 		(void) endnetconfig(handle);
3897*0ea5e3a5Sjjj 		(void) snprintf(ebuf, elen, "unknown host %s", hp);
38987c478bd9Sstevel@tonic-gate 		errno = 0;
38997c478bd9Sstevel@tonic-gate 		return (-1);
39007c478bd9Sstevel@tonic-gate 	}
39017c478bd9Sstevel@tonic-gate 	/* CSTYLED */
39027c478bd9Sstevel@tonic-gate 	if (ismyaddr(nbp)) { /*lint !e644 */
39037c478bd9Sstevel@tonic-gate 		netdir_free((void *)nap, ND_ADDRLIST);
3904*0ea5e3a5Sjjj 		(void) endnetconfig(handle);
3905*0ea5e3a5Sjjj 		(void) snprintf(ebuf, elen,
3906*0ea5e3a5Sjjj 		    "host %s is this host - logging loop", hp);
39077c478bd9Sstevel@tonic-gate 		errno = 0;
39087c478bd9Sstevel@tonic-gate 		return (-1);
39097c478bd9Sstevel@tonic-gate 	}
39107c478bd9Sstevel@tonic-gate 	f->f_un.f_forw.f_addr.buf = malloc(nbp->len);
39117c478bd9Sstevel@tonic-gate 	if (f->f_un.f_forw.f_addr.buf == NULL) {
39127c478bd9Sstevel@tonic-gate 		netdir_free((void *)nap, ND_ADDRLIST);
3913*0ea5e3a5Sjjj 		(void) endnetconfig(handle);
3914*0ea5e3a5Sjjj 		(void) strlcpy(ebuf, "malloc failed", elen);
39157c478bd9Sstevel@tonic-gate 		return (-1);
39167c478bd9Sstevel@tonic-gate 	}
39177c478bd9Sstevel@tonic-gate 	bcopy(nbp->buf, f->f_un.f_forw.f_addr.buf, nbp->len);
39187c478bd9Sstevel@tonic-gate 	f->f_un.f_forw.f_addr.len = nbp->len;
39197c478bd9Sstevel@tonic-gate 	f->f_file = t_open(ncp->nc_device, O_RDWR, NULL);
39207c478bd9Sstevel@tonic-gate 	if (f->f_file < 0) {
39217c478bd9Sstevel@tonic-gate 		netdir_free((void *)nap, ND_ADDRLIST);
3922*0ea5e3a5Sjjj 		(void) endnetconfig(handle);
39237c478bd9Sstevel@tonic-gate 		free(f->f_un.f_forw.f_addr.buf);
3924*0ea5e3a5Sjjj 		(void) strlcpy(ebuf, "t_open", elen);
39257c478bd9Sstevel@tonic-gate 		return (-1);
39267c478bd9Sstevel@tonic-gate 	}
39277c478bd9Sstevel@tonic-gate 	netdir_free((void *)nap, ND_ADDRLIST);
3928*0ea5e3a5Sjjj 	(void) endnetconfig(handle);
39297c478bd9Sstevel@tonic-gate 	if (t_bind(f->f_file, NULL, NULL) < 0) {
3930*0ea5e3a5Sjjj 		(void) strlcpy(ebuf, "t_bind", elen);
39317c478bd9Sstevel@tonic-gate 		free(f->f_un.f_forw.f_addr.buf);
3932*0ea5e3a5Sjjj 		(void) t_close(f->f_file);
39337c478bd9Sstevel@tonic-gate 		return (-1);
39347c478bd9Sstevel@tonic-gate 	}
39357c478bd9Sstevel@tonic-gate 	return (0);
39367c478bd9Sstevel@tonic-gate }
39377c478bd9Sstevel@tonic-gate 
39387c478bd9Sstevel@tonic-gate static int
39397c478bd9Sstevel@tonic-gate amiloghost(void)
39407c478bd9Sstevel@tonic-gate {
39417c478bd9Sstevel@tonic-gate 	struct nd_hostserv hs;
39427c478bd9Sstevel@tonic-gate 	struct netconfig *ncp;
39437c478bd9Sstevel@tonic-gate 	struct nd_addrlist *nap;
39447c478bd9Sstevel@tonic-gate 	struct netbuf *nbp;
39457c478bd9Sstevel@tonic-gate 	int i, fd;
39467c478bd9Sstevel@tonic-gate 	void *handle;
39477c478bd9Sstevel@tonic-gate 	char *uap;
39487c478bd9Sstevel@tonic-gate 	struct t_bind bind, *bound;
39497c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
39507c478bd9Sstevel@tonic-gate 
39517c478bd9Sstevel@tonic-gate 	if (Debug) {
39527c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
39537c478bd9Sstevel@tonic-gate 	}
39547c478bd9Sstevel@tonic-gate 
39557c478bd9Sstevel@tonic-gate 	/*
39567c478bd9Sstevel@tonic-gate 	 * we need to know if we are running on the loghost. This is
39577c478bd9Sstevel@tonic-gate 	 * checked by binding to the address associated with "loghost"
39587c478bd9Sstevel@tonic-gate 	 * and "syslogd" service over the connectionless transport
39597c478bd9Sstevel@tonic-gate 	 */
39607c478bd9Sstevel@tonic-gate 	hs.h_host = "loghost";
39617c478bd9Sstevel@tonic-gate 	hs.h_serv = "syslog";
39627c478bd9Sstevel@tonic-gate 
39637c478bd9Sstevel@tonic-gate 	if ((handle = setnetconfig()) == NULL) {
39647c478bd9Sstevel@tonic-gate 		return (0);
39657c478bd9Sstevel@tonic-gate 	}
39667c478bd9Sstevel@tonic-gate 
39677c478bd9Sstevel@tonic-gate 	while ((ncp = getnetconfig(handle)) != NULL) {
39687c478bd9Sstevel@tonic-gate 		if (ncp->nc_semantics != NC_TPI_CLTS) {
39697c478bd9Sstevel@tonic-gate 			continue;
39707c478bd9Sstevel@tonic-gate 		}
39717c478bd9Sstevel@tonic-gate 
39727c478bd9Sstevel@tonic-gate 		if (netdir_getbyname(ncp, &hs, &nap) != 0) {
39737c478bd9Sstevel@tonic-gate 			continue;
39747c478bd9Sstevel@tonic-gate 		}
39757c478bd9Sstevel@tonic-gate 
39767c478bd9Sstevel@tonic-gate 		if (nap == NULL) {
39777c478bd9Sstevel@tonic-gate 			continue;
39787c478bd9Sstevel@tonic-gate 		}
39797c478bd9Sstevel@tonic-gate 
39807c478bd9Sstevel@tonic-gate 		nbp = nap->n_addrs;
39817c478bd9Sstevel@tonic-gate 
39827c478bd9Sstevel@tonic-gate 		for (i = 0; i < nap->n_cnt; i++) {
39837c478bd9Sstevel@tonic-gate 			if ((uap = taddr2uaddr(ncp, nbp)) != (char *)NULL) {
39847c478bd9Sstevel@tonic-gate 				DPRINT2(1, "amiloghost(%u): testing %s\n",
39857c478bd9Sstevel@tonic-gate 					mythreadno, uap);
39867c478bd9Sstevel@tonic-gate 			}
39877c478bd9Sstevel@tonic-gate 
39887c478bd9Sstevel@tonic-gate 			free(uap);
39897c478bd9Sstevel@tonic-gate 
39907c478bd9Sstevel@tonic-gate 			fd = t_open(ncp->nc_device, O_RDWR, NULL);
39917c478bd9Sstevel@tonic-gate 
39927c478bd9Sstevel@tonic-gate 			if (fd < 0) {
39937c478bd9Sstevel@tonic-gate 				netdir_free((void *)nap, ND_ADDRLIST);
3994*0ea5e3a5Sjjj 				(void) endnetconfig(handle);
39957c478bd9Sstevel@tonic-gate 				return (0);
39967c478bd9Sstevel@tonic-gate 			}
39977c478bd9Sstevel@tonic-gate 
39987c478bd9Sstevel@tonic-gate 			/*LINTED*/
39997c478bd9Sstevel@tonic-gate 			bound = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR);
40007c478bd9Sstevel@tonic-gate 			bind.addr = *nbp;
40017c478bd9Sstevel@tonic-gate 			bind.qlen = 0;
40027c478bd9Sstevel@tonic-gate 
40037c478bd9Sstevel@tonic-gate 			if (t_bind(fd, &bind, bound) == 0) {
4004*0ea5e3a5Sjjj 				(void) t_close(fd);
4005*0ea5e3a5Sjjj 				(void) t_free((char *)bound, T_BIND);
40067c478bd9Sstevel@tonic-gate 				netdir_free((void *)nap, ND_ADDRLIST);
4007*0ea5e3a5Sjjj 				(void) endnetconfig(handle);
40087c478bd9Sstevel@tonic-gate 				return (1);
40097c478bd9Sstevel@tonic-gate 			} else {
4010*0ea5e3a5Sjjj 				(void) t_close(fd);
4011*0ea5e3a5Sjjj 				(void) t_free((char *)bound, T_BIND);
40127c478bd9Sstevel@tonic-gate 			}
40137c478bd9Sstevel@tonic-gate 
40147c478bd9Sstevel@tonic-gate 			nbp++;
40157c478bd9Sstevel@tonic-gate 		}
40167c478bd9Sstevel@tonic-gate 
40177c478bd9Sstevel@tonic-gate 		netdir_free((void *)nap, ND_ADDRLIST);
40187c478bd9Sstevel@tonic-gate 	}
40197c478bd9Sstevel@tonic-gate 
4020*0ea5e3a5Sjjj 	(void) endnetconfig(handle);
40217c478bd9Sstevel@tonic-gate 	return (0);
40227c478bd9Sstevel@tonic-gate }
40237c478bd9Sstevel@tonic-gate 
40247c478bd9Sstevel@tonic-gate int
40257c478bd9Sstevel@tonic-gate same_addr(struct netbuf *na, struct netbuf *nb)
40267c478bd9Sstevel@tonic-gate {
40277c478bd9Sstevel@tonic-gate 	char *a, *b;
40287c478bd9Sstevel@tonic-gate 	size_t n;
40297c478bd9Sstevel@tonic-gate 
4030*0ea5e3a5Sjjj 	assert(na->buf != NULL && nb->buf != NULL);
40317c478bd9Sstevel@tonic-gate 
40327c478bd9Sstevel@tonic-gate 	if (na->len != nb->len) {
40337c478bd9Sstevel@tonic-gate 		return (0);
40347c478bd9Sstevel@tonic-gate 	}
40357c478bd9Sstevel@tonic-gate 
40367c478bd9Sstevel@tonic-gate 	a = na->buf;
40377c478bd9Sstevel@tonic-gate 	b = nb->buf;
40387c478bd9Sstevel@tonic-gate 	n = nb->len;
40397c478bd9Sstevel@tonic-gate 
40407c478bd9Sstevel@tonic-gate 	while (n-- > 0) {
40417c478bd9Sstevel@tonic-gate 		if (*a++ != *b++) {
40427c478bd9Sstevel@tonic-gate 			return (0);
40437c478bd9Sstevel@tonic-gate 		}
40447c478bd9Sstevel@tonic-gate 	}
40457c478bd9Sstevel@tonic-gate 
40467c478bd9Sstevel@tonic-gate 	return (1);
40477c478bd9Sstevel@tonic-gate }
40487c478bd9Sstevel@tonic-gate 
40497c478bd9Sstevel@tonic-gate /*
40507c478bd9Sstevel@tonic-gate  * allocates a new message structure, initializes it
40517c478bd9Sstevel@tonic-gate  * and returns a pointer to it
40527c478bd9Sstevel@tonic-gate  */
40537c478bd9Sstevel@tonic-gate static log_message_t *
40547c478bd9Sstevel@tonic-gate new_msg(void)
40557c478bd9Sstevel@tonic-gate {
40567c478bd9Sstevel@tonic-gate 	log_message_t *lm;
40577c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
40587c478bd9Sstevel@tonic-gate 
40597c478bd9Sstevel@tonic-gate 	if (Debug) {
40607c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
40617c478bd9Sstevel@tonic-gate 	}
40627c478bd9Sstevel@tonic-gate 
40637c478bd9Sstevel@tonic-gate 	if ((lm = malloc(sizeof (log_message_t))) == NULL)
40647c478bd9Sstevel@tonic-gate 		return ((log_message_t *)NULL);
40657c478bd9Sstevel@tonic-gate 
40667c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lm))
40677c478bd9Sstevel@tonic-gate 
40687c478bd9Sstevel@tonic-gate 	if (pthread_mutex_init(&lm->msg_mutex, NULL) != 0)
40697c478bd9Sstevel@tonic-gate 		return ((log_message_t *)NULL);
40707c478bd9Sstevel@tonic-gate 	lm->refcnt = 0;
40717c478bd9Sstevel@tonic-gate 	lm->pri = 0;
40727c478bd9Sstevel@tonic-gate 	lm->flags = 0;
40737c478bd9Sstevel@tonic-gate 	lm->hlp = NULL;
40747c478bd9Sstevel@tonic-gate 	lm->msg[0] = '\0';
40757c478bd9Sstevel@tonic-gate 	lm->ptr = NULL;
40767c478bd9Sstevel@tonic-gate 
4077*0ea5e3a5Sjjj 	DPRINT2(3, "new_msg(%u): creating msg %p\n", mythreadno, (void *)lm);
40787c478bd9Sstevel@tonic-gate 	return (lm);
40797c478bd9Sstevel@tonic-gate }
40807c478bd9Sstevel@tonic-gate 
40817c478bd9Sstevel@tonic-gate /*
40827c478bd9Sstevel@tonic-gate  * frees a message structure - should only be called if
40837c478bd9Sstevel@tonic-gate  * the refcount is 0
40847c478bd9Sstevel@tonic-gate  */
40857c478bd9Sstevel@tonic-gate static void
40867c478bd9Sstevel@tonic-gate free_msg(log_message_t *lm)
40877c478bd9Sstevel@tonic-gate {
40887c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
40897c478bd9Sstevel@tonic-gate 
40907c478bd9Sstevel@tonic-gate 	if (Debug) {
40917c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
40927c478bd9Sstevel@tonic-gate 	}
40937c478bd9Sstevel@tonic-gate 
40947c478bd9Sstevel@tonic-gate 	assert(lm != NULL && lm->refcnt == 0);
40957c478bd9Sstevel@tonic-gate 	if (lm->hlp != NULL)
40967c478bd9Sstevel@tonic-gate 		freehl(lm->hlp);
4097*0ea5e3a5Sjjj 	DPRINT2(3, "free_msg(%u): freeing msg %p\n", mythreadno, (void *)lm);
40987c478bd9Sstevel@tonic-gate 	free(lm);
40997c478bd9Sstevel@tonic-gate }
41007c478bd9Sstevel@tonic-gate 
41017c478bd9Sstevel@tonic-gate /*
41027c478bd9Sstevel@tonic-gate  *  Make sure that the message makes sense in the current locale, and
41037c478bd9Sstevel@tonic-gate  *  does not contain stray control characters.
41047c478bd9Sstevel@tonic-gate  */
41057c478bd9Sstevel@tonic-gate static void
41067c478bd9Sstevel@tonic-gate filter_string(char *mbstr, char *filtered, size_t max)
41077c478bd9Sstevel@tonic-gate {
41087c478bd9Sstevel@tonic-gate 	size_t	cs = 0;
41097c478bd9Sstevel@tonic-gate 	size_t	mb_cur_max;
41107c478bd9Sstevel@tonic-gate 	unsigned char	*p = (unsigned char *)mbstr;
41117c478bd9Sstevel@tonic-gate 	pthread_t mythreadno = 0;
41127c478bd9Sstevel@tonic-gate 
41137c478bd9Sstevel@tonic-gate 	if (Debug) {
41147c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
41157c478bd9Sstevel@tonic-gate 	}
41167c478bd9Sstevel@tonic-gate 
41177c478bd9Sstevel@tonic-gate 	assert(mbstr != NULL && filtered != NULL);
41187c478bd9Sstevel@tonic-gate 
41197c478bd9Sstevel@tonic-gate 	/*
41207c478bd9Sstevel@tonic-gate 	 * Since the access to MB_CUR_MAX is expensive (because
41217c478bd9Sstevel@tonic-gate 	 * MB_CUR_MAX lives in a global area), it should be
41227c478bd9Sstevel@tonic-gate 	 * restrained for the better performance.
41237c478bd9Sstevel@tonic-gate 	 */
41247c478bd9Sstevel@tonic-gate 	mb_cur_max = (size_t)MB_CUR_MAX;
41257c478bd9Sstevel@tonic-gate 	if (mb_cur_max > 1) {
41267c478bd9Sstevel@tonic-gate 		/* multibyte locale */
41277c478bd9Sstevel@tonic-gate 		int	mlen;
41287c478bd9Sstevel@tonic-gate 		wchar_t	wc;
41297c478bd9Sstevel@tonic-gate 
41307c478bd9Sstevel@tonic-gate 		while (*p != '\0') {
41317c478bd9Sstevel@tonic-gate 			if ((mlen = mbtowc(&wc, (char *)p,
41327c478bd9Sstevel@tonic-gate 				mb_cur_max)) == -1) {
41337c478bd9Sstevel@tonic-gate 				/*
41347c478bd9Sstevel@tonic-gate 				 * Invalid byte sequence found.
41357c478bd9Sstevel@tonic-gate 				 *
41367c478bd9Sstevel@tonic-gate 				 * try to print one byte
41377c478bd9Sstevel@tonic-gate 				 * in ASCII format.
41387c478bd9Sstevel@tonic-gate 				 */
41397c478bd9Sstevel@tonic-gate 				DPRINT2(9, "filter_string(%u): Invalid "
4140*0ea5e3a5Sjjj 					"MB sequence: %ld\n", mythreadno,
41417c478bd9Sstevel@tonic-gate 					wc);
41427c478bd9Sstevel@tonic-gate 
41437c478bd9Sstevel@tonic-gate 				if (!putctrlc(*p++, &filtered, &cs, max)) {
41447c478bd9Sstevel@tonic-gate 					/* not enough buffer */
41457c478bd9Sstevel@tonic-gate 					goto end;
41467c478bd9Sstevel@tonic-gate 				} else {
41477c478bd9Sstevel@tonic-gate 					continue;
41487c478bd9Sstevel@tonic-gate 				}
41497c478bd9Sstevel@tonic-gate 			} else {
41507c478bd9Sstevel@tonic-gate 				/*
41517c478bd9Sstevel@tonic-gate 				 * Since *p is not a null byte here,
41527c478bd9Sstevel@tonic-gate 				 * mbtowc should have never returned 0.
41537c478bd9Sstevel@tonic-gate 				 *
41547c478bd9Sstevel@tonic-gate 				 * A valid wide character found.
41557c478bd9Sstevel@tonic-gate 				 */
41567c478bd9Sstevel@tonic-gate 
41577c478bd9Sstevel@tonic-gate 				if (wc != L'\t' && iswcntrl(wc)) {
41587c478bd9Sstevel@tonic-gate 					/*
41597c478bd9Sstevel@tonic-gate 					 * non-tab, non-newline, and
41607c478bd9Sstevel@tonic-gate 					 * control character found.
41617c478bd9Sstevel@tonic-gate 					 *
41627c478bd9Sstevel@tonic-gate 					 * try to print this wide character
41637c478bd9Sstevel@tonic-gate 					 * in ASCII-format.
41647c478bd9Sstevel@tonic-gate 					 */
41657c478bd9Sstevel@tonic-gate 					char	*q = filtered;
41667c478bd9Sstevel@tonic-gate 
41677c478bd9Sstevel@tonic-gate 					DPRINT2(9, "filter_string(%u): MB"
4168*0ea5e3a5Sjjj 						" control character: %ld\n",
41697c478bd9Sstevel@tonic-gate 						mythreadno, wc);
41707c478bd9Sstevel@tonic-gate 
41717c478bd9Sstevel@tonic-gate 					while (mlen--) {
41727c478bd9Sstevel@tonic-gate 						if (!putctrlc(*p++, &filtered,
41737c478bd9Sstevel@tonic-gate 							&cs, max)) {
41747c478bd9Sstevel@tonic-gate 							/*
41757c478bd9Sstevel@tonic-gate 							 * not enough buffer in
41767c478bd9Sstevel@tonic-gate 							 * filtered
41777c478bd9Sstevel@tonic-gate 							 *
41787c478bd9Sstevel@tonic-gate 							 * cancel already
41797c478bd9Sstevel@tonic-gate 							 * stored bytes in
41807c478bd9Sstevel@tonic-gate 							 * filtered for this
41817c478bd9Sstevel@tonic-gate 							 * wide character.
41827c478bd9Sstevel@tonic-gate 							 */
41837c478bd9Sstevel@tonic-gate 							filtered = q;
41847c478bd9Sstevel@tonic-gate 							goto end;
41857c478bd9Sstevel@tonic-gate 						}
41867c478bd9Sstevel@tonic-gate 					}
41877c478bd9Sstevel@tonic-gate 					continue;
41887c478bd9Sstevel@tonic-gate 				} else {
41897c478bd9Sstevel@tonic-gate 					/*
41907c478bd9Sstevel@tonic-gate 					 * tab, newline, or non-control
41917c478bd9Sstevel@tonic-gate 					 * character found.
41927c478bd9Sstevel@tonic-gate 					 */
41937c478bd9Sstevel@tonic-gate 					if (cs + mlen < max) {
41947c478bd9Sstevel@tonic-gate 						/* enough buffer */
41957c478bd9Sstevel@tonic-gate 						cs += mlen;
41967c478bd9Sstevel@tonic-gate 						while (mlen--) {
41977c478bd9Sstevel@tonic-gate 							*filtered++ = *p++;
41987c478bd9Sstevel@tonic-gate 						}
41997c478bd9Sstevel@tonic-gate 						continue;
42007c478bd9Sstevel@tonic-gate 					} else {
42017c478bd9Sstevel@tonic-gate 						/* not enough buffer */
42027c478bd9Sstevel@tonic-gate 						goto end;
42037c478bd9Sstevel@tonic-gate 					}
42047c478bd9Sstevel@tonic-gate 				}
42057c478bd9Sstevel@tonic-gate 			}
42067c478bd9Sstevel@tonic-gate 		}
42077c478bd9Sstevel@tonic-gate 	} else {
42087c478bd9Sstevel@tonic-gate 		/* singlebyte locale */
42097c478bd9Sstevel@tonic-gate 
42107c478bd9Sstevel@tonic-gate 		while (*p != '\0') {
42117c478bd9Sstevel@tonic-gate 			if (*p != '\t' && iscntrl(*p)) {
42127c478bd9Sstevel@tonic-gate 				/*
42137c478bd9Sstevel@tonic-gate 				 * non-tab, non-newline,
42147c478bd9Sstevel@tonic-gate 				 * and control character found.
42157c478bd9Sstevel@tonic-gate 				 *
42167c478bd9Sstevel@tonic-gate 				 * try to print this singlebyte character
42177c478bd9Sstevel@tonic-gate 				 * in ASCII format.
42187c478bd9Sstevel@tonic-gate 				 */
42197c478bd9Sstevel@tonic-gate 				DPRINT2(9, "filter_string(%u): control "
42207c478bd9Sstevel@tonic-gate 					"character: %d\n", mythreadno, *p);
42217c478bd9Sstevel@tonic-gate 
42227c478bd9Sstevel@tonic-gate 				if (!putctrlc(*p++, &filtered, &cs, max)) {
42237c478bd9Sstevel@tonic-gate 					/* not enough buffer */
42247c478bd9Sstevel@tonic-gate 					goto end;
42257c478bd9Sstevel@tonic-gate 				} else {
42267c478bd9Sstevel@tonic-gate 					continue;
42277c478bd9Sstevel@tonic-gate 				}
42287c478bd9Sstevel@tonic-gate 			} else if (*p != '\t' && !isprint(*p)) {
42297c478bd9Sstevel@tonic-gate 				/*
42307c478bd9Sstevel@tonic-gate 				 * non-tab and non printable character found
42317c478bd9Sstevel@tonic-gate 				 * this check is required for the C locale
42327c478bd9Sstevel@tonic-gate 				 */
42337c478bd9Sstevel@tonic-gate 				DPRINT2(9, "filter_string(%u): non-printable "
42347c478bd9Sstevel@tonic-gate 					"character: %d\n", mythreadno, *p);
42357c478bd9Sstevel@tonic-gate 				if (!putctrlc(*p++, &filtered, &cs, max)) {
42367c478bd9Sstevel@tonic-gate 					/* not enough buffer */
42377c478bd9Sstevel@tonic-gate 					goto end;
42387c478bd9Sstevel@tonic-gate 				} else {
42397c478bd9Sstevel@tonic-gate 					continue;
42407c478bd9Sstevel@tonic-gate 				}
42417c478bd9Sstevel@tonic-gate 			} else {
42427c478bd9Sstevel@tonic-gate 				/*
42437c478bd9Sstevel@tonic-gate 				 * tab, newline, non-control character, or
42447c478bd9Sstevel@tonic-gate 				 * printable found.
42457c478bd9Sstevel@tonic-gate 				 */
42467c478bd9Sstevel@tonic-gate 				if (cs + 1 < max) {
42477c478bd9Sstevel@tonic-gate 					*filtered++ = *p++;
42487c478bd9Sstevel@tonic-gate 					cs++;
42497c478bd9Sstevel@tonic-gate 					continue;
42507c478bd9Sstevel@tonic-gate 				} else {
42517c478bd9Sstevel@tonic-gate 					/* not enough buffer */
42527c478bd9Sstevel@tonic-gate 					goto end;
42537c478bd9Sstevel@tonic-gate 				}
42547c478bd9Sstevel@tonic-gate 			}
42557c478bd9Sstevel@tonic-gate 		}
42567c478bd9Sstevel@tonic-gate 	}
42577c478bd9Sstevel@tonic-gate 
42587c478bd9Sstevel@tonic-gate end:
42597c478bd9Sstevel@tonic-gate 	*filtered = '\0';
42607c478bd9Sstevel@tonic-gate 
42617c478bd9Sstevel@tonic-gate 	if (cs >= 2 &&
42627c478bd9Sstevel@tonic-gate 		filtered[-2] == '\\' && filtered[-1] == 'n') {
42637c478bd9Sstevel@tonic-gate 		filtered[-2] = '\0';
42647c478bd9Sstevel@tonic-gate 	}
42657c478bd9Sstevel@tonic-gate }
42667c478bd9Sstevel@tonic-gate 
42677c478bd9Sstevel@tonic-gate static char *
42687c478bd9Sstevel@tonic-gate alloc_stacks(int numstacks)
42697c478bd9Sstevel@tonic-gate {
42707c478bd9Sstevel@tonic-gate 	size_t pagesize, mapsize;
42717c478bd9Sstevel@tonic-gate 	char *stack_top;
42727c478bd9Sstevel@tonic-gate 	char *addr;
42737c478bd9Sstevel@tonic-gate 	int i;
42747c478bd9Sstevel@tonic-gate 
42757c478bd9Sstevel@tonic-gate 	pagesize = (size_t)sysconf(_SC_PAGESIZE);
42767c478bd9Sstevel@tonic-gate 	/*
42777c478bd9Sstevel@tonic-gate 	 * stacksize and redzonesize are global so threads
42787c478bd9Sstevel@tonic-gate 	 * can be created elsewhere and refer to the sizes
42797c478bd9Sstevel@tonic-gate 	 */
42807c478bd9Sstevel@tonic-gate 	stacksize = (size_t)roundup(sysconf(_SC_THREAD_STACK_MIN) +
42817c478bd9Sstevel@tonic-gate 		DEFAULT_STACKSIZE, pagesize);
42827c478bd9Sstevel@tonic-gate 	redzonesize = (size_t)roundup(DEFAULT_REDZONESIZE, pagesize);
42837c478bd9Sstevel@tonic-gate 
42847c478bd9Sstevel@tonic-gate 	/*
42857c478bd9Sstevel@tonic-gate 	 * allocate an additional "redzonesize" chunk in addition
42867c478bd9Sstevel@tonic-gate 	 * to what we require, so we can create a redzone at the
42877c478bd9Sstevel@tonic-gate 	 * bottom of the last stack as well.
42887c478bd9Sstevel@tonic-gate 	 */
42897c478bd9Sstevel@tonic-gate 	mapsize = redzonesize + numstacks * (stacksize + redzonesize);
42907c478bd9Sstevel@tonic-gate 	stack_top = mmap(NULL, mapsize, PROT_READ|PROT_WRITE,
42917c478bd9Sstevel@tonic-gate 		MAP_PRIVATE|MAP_ANON, -1, 0);
42927c478bd9Sstevel@tonic-gate 	if (stack_top == MAP_FAILED)
42937c478bd9Sstevel@tonic-gate 		return (NULL);
42947c478bd9Sstevel@tonic-gate 
42957c478bd9Sstevel@tonic-gate 	addr = stack_top;
42967c478bd9Sstevel@tonic-gate 	/*
42977c478bd9Sstevel@tonic-gate 	 * this loop is intentionally <= instead of <, so we can
42987c478bd9Sstevel@tonic-gate 	 * protect the redzone at the bottom of the last stack
42997c478bd9Sstevel@tonic-gate 	 */
43007c478bd9Sstevel@tonic-gate 	for (i = 0; i <= numstacks; i++) {
43017c478bd9Sstevel@tonic-gate 		(void) mprotect(addr, redzonesize, PROT_NONE);
43027c478bd9Sstevel@tonic-gate 		addr += stacksize + redzonesize;
43037c478bd9Sstevel@tonic-gate 	}
43047c478bd9Sstevel@tonic-gate 	return ((char *)(stack_top + redzonesize));
43057c478bd9Sstevel@tonic-gate }
43067c478bd9Sstevel@tonic-gate 
43077c478bd9Sstevel@tonic-gate static void
43087c478bd9Sstevel@tonic-gate dealloc_stacks(int numstacks)
43097c478bd9Sstevel@tonic-gate {
43107c478bd9Sstevel@tonic-gate 	size_t pagesize, mapsize;
43117c478bd9Sstevel@tonic-gate 
43127c478bd9Sstevel@tonic-gate 	pagesize = (size_t)sysconf(_SC_PAGESIZE);
43137c478bd9Sstevel@tonic-gate 
43147c478bd9Sstevel@tonic-gate 	stacksize = (size_t)roundup(sysconf(_SC_THREAD_STACK_MIN) +
43157c478bd9Sstevel@tonic-gate 	    DEFAULT_STACKSIZE, pagesize);
43167c478bd9Sstevel@tonic-gate 
43177c478bd9Sstevel@tonic-gate 	redzonesize = (size_t)roundup(DEFAULT_REDZONESIZE, pagesize);
43187c478bd9Sstevel@tonic-gate 
43197c478bd9Sstevel@tonic-gate 	mapsize = redzonesize + numstacks * (stacksize + redzonesize);
43207c478bd9Sstevel@tonic-gate 	(void) munmap(cstack_ptr - mapsize, mapsize);
43217c478bd9Sstevel@tonic-gate }
43227c478bd9Sstevel@tonic-gate 
43237c478bd9Sstevel@tonic-gate static void
43247c478bd9Sstevel@tonic-gate filed_destroy(struct filed *f)
43257c478bd9Sstevel@tonic-gate {
43267c478bd9Sstevel@tonic-gate 	(void) dataq_destroy(&f->f_queue);
4327*0ea5e3a5Sjjj 	(void) pthread_mutex_destroy(&f->filed_mutex);
43287c478bd9Sstevel@tonic-gate }
43297c478bd9Sstevel@tonic-gate 
43307c478bd9Sstevel@tonic-gate static void
43317c478bd9Sstevel@tonic-gate close_door(void)
43327c478bd9Sstevel@tonic-gate {
43337c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
43347c478bd9Sstevel@tonic-gate 
43357c478bd9Sstevel@tonic-gate 	if (Debug) {
43367c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
43377c478bd9Sstevel@tonic-gate 	}
43387c478bd9Sstevel@tonic-gate 
43397c478bd9Sstevel@tonic-gate 	(void) fdetach(DoorFileName);
43407c478bd9Sstevel@tonic-gate 
43417c478bd9Sstevel@tonic-gate 	DPRINT2(5, "close_door(%u): detached server() from %s\n",
43427c478bd9Sstevel@tonic-gate 		mythreadno, DoorFileName);
43437c478bd9Sstevel@tonic-gate }
43447c478bd9Sstevel@tonic-gate 
43457c478bd9Sstevel@tonic-gate static void
43467c478bd9Sstevel@tonic-gate delete_doorfiles(void)
43477c478bd9Sstevel@tonic-gate {
43487c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
43497c478bd9Sstevel@tonic-gate 	struct stat sb;
43507c478bd9Sstevel@tonic-gate 	int err;
43517c478bd9Sstevel@tonic-gate 	char line[MAXLINE+1];
43527c478bd9Sstevel@tonic-gate 
43537c478bd9Sstevel@tonic-gate 	if (Debug) {
43547c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
43557c478bd9Sstevel@tonic-gate 	}
43567c478bd9Sstevel@tonic-gate 
43577c478bd9Sstevel@tonic-gate 
43587c478bd9Sstevel@tonic-gate 	if (lstat(DoorFileName, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
43597c478bd9Sstevel@tonic-gate 		if (unlink(DoorFileName) < 0) {
43607c478bd9Sstevel@tonic-gate 			err = errno;
4361*0ea5e3a5Sjjj 			(void) snprintf(line, sizeof (line),
4362*0ea5e3a5Sjjj 			    "unlink() of %s failed - fatal", DoorFileName);
43637c478bd9Sstevel@tonic-gate 			errno = err;
43647c478bd9Sstevel@tonic-gate 			logerror(line);
43657c478bd9Sstevel@tonic-gate 			DPRINT3(1, "delete_doorfiles(%u): error: %s, "
43667c478bd9Sstevel@tonic-gate 				"errno=%d\n", mythreadno, line, err);
43677c478bd9Sstevel@tonic-gate 			exit(1);
43687c478bd9Sstevel@tonic-gate 		}
43697c478bd9Sstevel@tonic-gate 
43707c478bd9Sstevel@tonic-gate 		DPRINT2(5, "delete_doorfiles(%u): deleted %s\n",
43717c478bd9Sstevel@tonic-gate 			mythreadno, DoorFileName);
43727c478bd9Sstevel@tonic-gate 	}
43737c478bd9Sstevel@tonic-gate 
43747c478bd9Sstevel@tonic-gate 	if (strcmp(DoorFileName, DOORFILE) == 0) {
43757c478bd9Sstevel@tonic-gate 		if (lstat(OLD_DOORFILE, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
43767c478bd9Sstevel@tonic-gate 			if (unlink(OLD_DOORFILE) < 0) {
43777c478bd9Sstevel@tonic-gate 				err = errno;
4378*0ea5e3a5Sjjj 				(void) snprintf(line, sizeof (line),
4379*0ea5e3a5Sjjj 				    "unlink() of %s failed", OLD_DOORFILE);
43807c478bd9Sstevel@tonic-gate 				DPRINT2(5, "delete_doorfiles(%u): %s\n",
43817c478bd9Sstevel@tonic-gate 					mythreadno, line);
43827c478bd9Sstevel@tonic-gate 
43837c478bd9Sstevel@tonic-gate 				if (err != EROFS) {
43847c478bd9Sstevel@tonic-gate 					errno = err;
4385*0ea5e3a5Sjjj 					(void) strlcat(line, " - fatal",
4386*0ea5e3a5Sjjj 					    sizeof (line));
43877c478bd9Sstevel@tonic-gate 					logerror(line);
43887c478bd9Sstevel@tonic-gate 					DPRINT3(1, "delete_doorfiles(%u): "
43897c478bd9Sstevel@tonic-gate 						"error: %s, errno=%d\n",
43907c478bd9Sstevel@tonic-gate 						mythreadno, line, err);
43917c478bd9Sstevel@tonic-gate 					exit(1);
43927c478bd9Sstevel@tonic-gate 				}
43937c478bd9Sstevel@tonic-gate 
43947c478bd9Sstevel@tonic-gate 				DPRINT1(5, "delete_doorfiles(%u): unlink() "
43957c478bd9Sstevel@tonic-gate 					"failure OK on RO file system\n",
43967c478bd9Sstevel@tonic-gate 					mythreadno);
43977c478bd9Sstevel@tonic-gate 			}
43987c478bd9Sstevel@tonic-gate 
43997c478bd9Sstevel@tonic-gate 			DPRINT2(5, "delete_doorfiles(%u): deleted %s\n",
44007c478bd9Sstevel@tonic-gate 				mythreadno, OLD_DOORFILE);
44017c478bd9Sstevel@tonic-gate 		}
44027c478bd9Sstevel@tonic-gate 	}
44037c478bd9Sstevel@tonic-gate 
44047c478bd9Sstevel@tonic-gate 	if (lstat(PidFileName, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
44057c478bd9Sstevel@tonic-gate 		if (unlink(PidFileName) < 0) {
44067c478bd9Sstevel@tonic-gate 			err = errno;
4407*0ea5e3a5Sjjj 			(void) snprintf(line, sizeof (line),
4408*0ea5e3a5Sjjj 			    "unlink() of %s failed - fatal", PidFileName);
44097c478bd9Sstevel@tonic-gate 			errno = err;
44107c478bd9Sstevel@tonic-gate 			logerror(line);
44117c478bd9Sstevel@tonic-gate 			DPRINT3(1, "delete_doorfiles(%u): error: %s, "
44127c478bd9Sstevel@tonic-gate 				"errno=%d\n", mythreadno, line, err);
44137c478bd9Sstevel@tonic-gate 			exit(1);
44147c478bd9Sstevel@tonic-gate 		}
44157c478bd9Sstevel@tonic-gate 
44167c478bd9Sstevel@tonic-gate 		DPRINT2(5, "delete_doorfiles(%u): deleted %s\n", mythreadno,
44177c478bd9Sstevel@tonic-gate 			PidFileName);
44187c478bd9Sstevel@tonic-gate 	}
44197c478bd9Sstevel@tonic-gate 
44207c478bd9Sstevel@tonic-gate 	if (strcmp(PidFileName, PIDFILE) == 0) {
44217c478bd9Sstevel@tonic-gate 		if (lstat(OLD_PIDFILE, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
44227c478bd9Sstevel@tonic-gate 			if (unlink(OLD_PIDFILE) < 0) {
44237c478bd9Sstevel@tonic-gate 				err = errno;
4424*0ea5e3a5Sjjj 				(void) snprintf(line, sizeof (line),
4425*0ea5e3a5Sjjj 				    "unlink() of %s failed", OLD_PIDFILE);
44267c478bd9Sstevel@tonic-gate 				DPRINT2(5, "delete_doorfiles(%u): %s, \n",
44277c478bd9Sstevel@tonic-gate 					mythreadno, line);
44287c478bd9Sstevel@tonic-gate 
44297c478bd9Sstevel@tonic-gate 				if (err != EROFS) {
44307c478bd9Sstevel@tonic-gate 					errno = err;
4431*0ea5e3a5Sjjj 					(void) strlcat(line, " - fatal",
4432*0ea5e3a5Sjjj 					    sizeof (line));
44337c478bd9Sstevel@tonic-gate 					logerror(line);
44347c478bd9Sstevel@tonic-gate 					DPRINT3(1, "delete_doorfiles(%u): "
44357c478bd9Sstevel@tonic-gate 						"error: %s, errno=%d\n",
44367c478bd9Sstevel@tonic-gate 						mythreadno, line, err);
44377c478bd9Sstevel@tonic-gate 					exit(1);
44387c478bd9Sstevel@tonic-gate 				}
44397c478bd9Sstevel@tonic-gate 
44407c478bd9Sstevel@tonic-gate 				DPRINT1(5, "delete_doorfiles(%u): unlink "
44417c478bd9Sstevel@tonic-gate 					"failure OK on RO file system\n",
44427c478bd9Sstevel@tonic-gate 					mythreadno);
44437c478bd9Sstevel@tonic-gate 			}
44447c478bd9Sstevel@tonic-gate 
44457c478bd9Sstevel@tonic-gate 			DPRINT2(5, "delete_doorfiles(%u): deleted %s\n",
44467c478bd9Sstevel@tonic-gate 				mythreadno, OLD_PIDFILE);
44477c478bd9Sstevel@tonic-gate 		}
44487c478bd9Sstevel@tonic-gate 	}
44497c478bd9Sstevel@tonic-gate 
44507c478bd9Sstevel@tonic-gate 	if (DoorFd != -1) {
44517c478bd9Sstevel@tonic-gate 		(void) door_revoke(DoorFd);
44527c478bd9Sstevel@tonic-gate 	}
44537c478bd9Sstevel@tonic-gate 
44547c478bd9Sstevel@tonic-gate 	DPRINT2(1, "delete_doorfiles(%u): revoked door: DoorFd=%d\n",
44557c478bd9Sstevel@tonic-gate 		mythreadno, DoorFd);
44567c478bd9Sstevel@tonic-gate }
44577c478bd9Sstevel@tonic-gate 
44587c478bd9Sstevel@tonic-gate 
44597c478bd9Sstevel@tonic-gate /*ARGSUSED*/
44607c478bd9Sstevel@tonic-gate static void
44617c478bd9Sstevel@tonic-gate signull(int sig, siginfo_t *sip, void *utp)
44627c478bd9Sstevel@tonic-gate {
44637c478bd9Sstevel@tonic-gate 	DPRINT1(1, "signull(%u): THIS CALL SHOULD NEVER HAPPEN\n",
44647c478bd9Sstevel@tonic-gate 		pthread_self());
44657c478bd9Sstevel@tonic-gate 	/*
44667c478bd9Sstevel@tonic-gate 	 * Do nothing, as this is a place-holder used in conjunction with
44677c478bd9Sstevel@tonic-gate 	 * sigaction()/sigwait() to ensure that the proper disposition is
44687c478bd9Sstevel@tonic-gate 	 * given to the signals we handle in main().
44697c478bd9Sstevel@tonic-gate 	 */
44707c478bd9Sstevel@tonic-gate }
44717c478bd9Sstevel@tonic-gate 
44727c478bd9Sstevel@tonic-gate /*
44737c478bd9Sstevel@tonic-gate  * putctrlc returns zero, if failed due to not enough buffer.
44747c478bd9Sstevel@tonic-gate  * Otherwise, putctrlc returns non-zero.
44757c478bd9Sstevel@tonic-gate  *
44767c478bd9Sstevel@tonic-gate  * c:     a byte to print in ASCII format
44777c478bd9Sstevel@tonic-gate  * **buf: a pointer to the pointer to the output buffer.
44787c478bd9Sstevel@tonic-gate  * *cl:   current length of characters in the output buffer
44797c478bd9Sstevel@tonic-gate  * max:   maximum length of the buffer
44807c478bd9Sstevel@tonic-gate  */
44817c478bd9Sstevel@tonic-gate 
44827c478bd9Sstevel@tonic-gate static int
44837c478bd9Sstevel@tonic-gate putctrlc(int c, char **buf, size_t *cl, size_t max)
44847c478bd9Sstevel@tonic-gate {
44857c478bd9Sstevel@tonic-gate 	char	*p = *buf;
44867c478bd9Sstevel@tonic-gate 
44877c478bd9Sstevel@tonic-gate 	if (c == '\n') {
44887c478bd9Sstevel@tonic-gate 		if (*cl + 2 < max) {
44897c478bd9Sstevel@tonic-gate 			*p++ = '\\';
44907c478bd9Sstevel@tonic-gate 			*p++ = 'n';
44917c478bd9Sstevel@tonic-gate 			*cl += 2;
44927c478bd9Sstevel@tonic-gate 			*buf = p;
44937c478bd9Sstevel@tonic-gate 			return (2);
44947c478bd9Sstevel@tonic-gate 		} else {
44957c478bd9Sstevel@tonic-gate 			return (0);
44967c478bd9Sstevel@tonic-gate 		}
44977c478bd9Sstevel@tonic-gate 	} else if (c < 0200) {
44987c478bd9Sstevel@tonic-gate 		/* ascii control character */
44997c478bd9Sstevel@tonic-gate 		if (*cl + 2 < max) {
45007c478bd9Sstevel@tonic-gate 			*p++ = '^';
45017c478bd9Sstevel@tonic-gate 			*p++ = c ^ 0100;
45027c478bd9Sstevel@tonic-gate 			*cl += 2;
45037c478bd9Sstevel@tonic-gate 			*buf = p;
45047c478bd9Sstevel@tonic-gate 			return (2);
45057c478bd9Sstevel@tonic-gate 		} else {
45067c478bd9Sstevel@tonic-gate 			return (0);
45077c478bd9Sstevel@tonic-gate 		}
45087c478bd9Sstevel@tonic-gate 	} else {
45097c478bd9Sstevel@tonic-gate 		if (*cl + 4 < max) {
45107c478bd9Sstevel@tonic-gate 			*p++ = '\\';
45117c478bd9Sstevel@tonic-gate 			*p++ = ((c >> 6) & 07) + '0';
45127c478bd9Sstevel@tonic-gate 			*p++ = ((c >> 3) & 07) + '0';
45137c478bd9Sstevel@tonic-gate 			*p++ = (c & 07) + '0';
45147c478bd9Sstevel@tonic-gate 			*cl += 4;
45157c478bd9Sstevel@tonic-gate 			*buf = p;
45167c478bd9Sstevel@tonic-gate 			return (4);
45177c478bd9Sstevel@tonic-gate 		} else {
45187c478bd9Sstevel@tonic-gate 			return (0);
45197c478bd9Sstevel@tonic-gate 		}
45207c478bd9Sstevel@tonic-gate 	}
45217c478bd9Sstevel@tonic-gate }
45227c478bd9Sstevel@tonic-gate 
45237c478bd9Sstevel@tonic-gate /*
45247c478bd9Sstevel@tonic-gate  * findnl_bkwd:
45257c478bd9Sstevel@tonic-gate  *	Scans each character in buf until it finds the last newline in buf,
45267c478bd9Sstevel@tonic-gate  *	or the scanned character becomes the last COMPLETE character in buf.
45277c478bd9Sstevel@tonic-gate  *	Returns the number of scanned bytes.
45287c478bd9Sstevel@tonic-gate  *
45297c478bd9Sstevel@tonic-gate  *	buf - pointer to a buffer containing the message string
45307c478bd9Sstevel@tonic-gate  *	len - the length of the buffer
45317c478bd9Sstevel@tonic-gate  */
45327c478bd9Sstevel@tonic-gate size_t
45337c478bd9Sstevel@tonic-gate findnl_bkwd(const char *buf, const size_t len)
45347c478bd9Sstevel@tonic-gate {
45357c478bd9Sstevel@tonic-gate 	const char *p;
45367c478bd9Sstevel@tonic-gate 	size_t	mb_cur_max;
45377c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
45387c478bd9Sstevel@tonic-gate 
45397c478bd9Sstevel@tonic-gate 	if (Debug) {
45407c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
45417c478bd9Sstevel@tonic-gate 	}
45427c478bd9Sstevel@tonic-gate 
45437c478bd9Sstevel@tonic-gate 	if (len == 0) {
45447c478bd9Sstevel@tonic-gate 		return (0);
45457c478bd9Sstevel@tonic-gate 	}
45467c478bd9Sstevel@tonic-gate 
45477c478bd9Sstevel@tonic-gate 	mb_cur_max = MB_CUR_MAX;
45487c478bd9Sstevel@tonic-gate 
45497c478bd9Sstevel@tonic-gate 	if (mb_cur_max == 1) {
45507c478bd9Sstevel@tonic-gate 		/* single-byte locale */
45517c478bd9Sstevel@tonic-gate 		for (p = buf + len - 1; p != buf; p--) {
45527c478bd9Sstevel@tonic-gate 			if (*p == '\n') {
45537c478bd9Sstevel@tonic-gate 				return ((size_t)(p - buf));
45547c478bd9Sstevel@tonic-gate 			}
45557c478bd9Sstevel@tonic-gate 		}
45567c478bd9Sstevel@tonic-gate 		return ((size_t)len);
45577c478bd9Sstevel@tonic-gate 	} else {
45587c478bd9Sstevel@tonic-gate 		/* multi-byte locale */
45597c478bd9Sstevel@tonic-gate 		int mlen;
45607c478bd9Sstevel@tonic-gate 		const char *nl;
45617c478bd9Sstevel@tonic-gate 		size_t	rem;
45627c478bd9Sstevel@tonic-gate 
45637c478bd9Sstevel@tonic-gate 		p = buf;
45647c478bd9Sstevel@tonic-gate 		nl = NULL;
45657c478bd9Sstevel@tonic-gate 		for (rem = len; rem >= mb_cur_max; ) {
45667c478bd9Sstevel@tonic-gate 			mlen = mblen(p, mb_cur_max);
45677c478bd9Sstevel@tonic-gate 			if (mlen == -1) {
45687c478bd9Sstevel@tonic-gate 				/*
45697c478bd9Sstevel@tonic-gate 				 * Invalid character found.
45707c478bd9Sstevel@tonic-gate 				 */
45717c478bd9Sstevel@tonic-gate 				DPRINT1(9, "findnl_bkwd(%u): Invalid MB "
45727c478bd9Sstevel@tonic-gate 					"sequence\n", mythreadno);
45737c478bd9Sstevel@tonic-gate 				/*
45747c478bd9Sstevel@tonic-gate 				 * handle as a single byte character.
45757c478bd9Sstevel@tonic-gate 				 */
45767c478bd9Sstevel@tonic-gate 				p++;
45777c478bd9Sstevel@tonic-gate 				rem--;
45787c478bd9Sstevel@tonic-gate 			} else {
45797c478bd9Sstevel@tonic-gate 				/*
45807c478bd9Sstevel@tonic-gate 				 * It's guaranteed that *p points to
45817c478bd9Sstevel@tonic-gate 				 * the 1st byte of a multibyte character.
45827c478bd9Sstevel@tonic-gate 				 */
45837c478bd9Sstevel@tonic-gate 				if (*p == '\n') {
45847c478bd9Sstevel@tonic-gate 					nl = p;
45857c478bd9Sstevel@tonic-gate 				}
45867c478bd9Sstevel@tonic-gate 				p += mlen;
45877c478bd9Sstevel@tonic-gate 				rem -= mlen;
45887c478bd9Sstevel@tonic-gate 			}
45897c478bd9Sstevel@tonic-gate 		}
45907c478bd9Sstevel@tonic-gate 		if (nl) {
45917c478bd9Sstevel@tonic-gate 			return ((size_t)(nl - buf));
45927c478bd9Sstevel@tonic-gate 		}
45937c478bd9Sstevel@tonic-gate 		/*
45947c478bd9Sstevel@tonic-gate 		 * no newline nor null byte found.
45957c478bd9Sstevel@tonic-gate 		 * Also it's guaranteed that *p points to
45967c478bd9Sstevel@tonic-gate 		 * the 1st byte of a (multibyte) character
45977c478bd9Sstevel@tonic-gate 		 * at this point.
45987c478bd9Sstevel@tonic-gate 		 */
45997c478bd9Sstevel@tonic-gate 		return (len - rem);
46007c478bd9Sstevel@tonic-gate 	}
46017c478bd9Sstevel@tonic-gate }
46027c478bd9Sstevel@tonic-gate 
46037c478bd9Sstevel@tonic-gate /*
46047c478bd9Sstevel@tonic-gate  * copynl_frwd:
46057c478bd9Sstevel@tonic-gate  *	Scans each character in buf and copies the scanned character to obuf
46067c478bd9Sstevel@tonic-gate  *	until it finds a null byte or a newline, or
46077c478bd9Sstevel@tonic-gate  *	the number of the remaining bytes in obuf gets to exceed obuflen
46087c478bd9Sstevel@tonic-gate  *	if copying the scanned character to obuf.
46097c478bd9Sstevel@tonic-gate  *	Returns the number of scanned bytes.
46107c478bd9Sstevel@tonic-gate  *
46117c478bd9Sstevel@tonic-gate  *	obuf - buffer to be copied the scanned character
46127c478bd9Sstevel@tonic-gate  *	obuflen - the size of obuf
46137c478bd9Sstevel@tonic-gate  *	buf - pointer to a buffer containing the message string
46147c478bd9Sstevel@tonic-gate  *	len - the length of the buffer
46157c478bd9Sstevel@tonic-gate  */
46167c478bd9Sstevel@tonic-gate size_t
46177c478bd9Sstevel@tonic-gate copynl_frwd(char *obuf, const size_t obuflen,
46187c478bd9Sstevel@tonic-gate 	    const char *buf, const size_t len)
46197c478bd9Sstevel@tonic-gate {
46207c478bd9Sstevel@tonic-gate 	const char *p;
46217c478bd9Sstevel@tonic-gate 	char	*q = obuf;
46227c478bd9Sstevel@tonic-gate 	size_t	olen = 0;
46237c478bd9Sstevel@tonic-gate 	size_t	mb_cur_max;
46247c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
46257c478bd9Sstevel@tonic-gate 
46267c478bd9Sstevel@tonic-gate 	if (Debug) {
46277c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
46287c478bd9Sstevel@tonic-gate 	}
46297c478bd9Sstevel@tonic-gate 
46307c478bd9Sstevel@tonic-gate 	if (len == 0) {
46317c478bd9Sstevel@tonic-gate 		return (0);
46327c478bd9Sstevel@tonic-gate 	}
46337c478bd9Sstevel@tonic-gate 
46347c478bd9Sstevel@tonic-gate 	mb_cur_max = MB_CUR_MAX;
46357c478bd9Sstevel@tonic-gate 
46367c478bd9Sstevel@tonic-gate 	if (mb_cur_max == 1) {
46377c478bd9Sstevel@tonic-gate 		/* single-byte locale */
46387c478bd9Sstevel@tonic-gate 		for (p = buf; *p; ) {
46397c478bd9Sstevel@tonic-gate 			if (obuflen > olen + 1) {
46407c478bd9Sstevel@tonic-gate 				if (*p != '\n') {
46417c478bd9Sstevel@tonic-gate 					*q++ = *p++;
46427c478bd9Sstevel@tonic-gate 					olen++;
46437c478bd9Sstevel@tonic-gate 				} else {
46447c478bd9Sstevel@tonic-gate 					*q = '\0';
46457c478bd9Sstevel@tonic-gate 					return ((size_t)(p - buf));
46467c478bd9Sstevel@tonic-gate 				}
46477c478bd9Sstevel@tonic-gate 			} else {
46487c478bd9Sstevel@tonic-gate 				*q = '\0';
46497c478bd9Sstevel@tonic-gate 				return ((size_t)(p - buf));
46507c478bd9Sstevel@tonic-gate 			}
46517c478bd9Sstevel@tonic-gate 		}
46527c478bd9Sstevel@tonic-gate 		*q = '\0';
46537c478bd9Sstevel@tonic-gate 		return ((size_t)(p - buf));
46547c478bd9Sstevel@tonic-gate 	} else {
46557c478bd9Sstevel@tonic-gate 		/* multi-byte locale */
46567c478bd9Sstevel@tonic-gate 		int mlen;
46577c478bd9Sstevel@tonic-gate 
46587c478bd9Sstevel@tonic-gate 		for (p = buf; *p; ) {
46597c478bd9Sstevel@tonic-gate 			mlen = mblen(p, mb_cur_max);
46607c478bd9Sstevel@tonic-gate 			if (mlen == -1) {
46617c478bd9Sstevel@tonic-gate 				/*
46627c478bd9Sstevel@tonic-gate 				 * Invalid character found.
46637c478bd9Sstevel@tonic-gate 				 */
46647c478bd9Sstevel@tonic-gate 				DPRINT1(9, "copynl_frwd(%u): Invalid MB "
46657c478bd9Sstevel@tonic-gate 					"sequence\n", mythreadno);
46667c478bd9Sstevel@tonic-gate 				/*
46677c478bd9Sstevel@tonic-gate 				 * handle as a single byte character.
46687c478bd9Sstevel@tonic-gate 				 */
46697c478bd9Sstevel@tonic-gate 				if (obuflen > olen + 1) {
46707c478bd9Sstevel@tonic-gate 					*q++ = *p++;
46717c478bd9Sstevel@tonic-gate 					olen++;
46727c478bd9Sstevel@tonic-gate 				} else {
46737c478bd9Sstevel@tonic-gate 					*q = '\0';
46747c478bd9Sstevel@tonic-gate 					return ((size_t)(p - buf));
46757c478bd9Sstevel@tonic-gate 				}
46767c478bd9Sstevel@tonic-gate 			} else {
46777c478bd9Sstevel@tonic-gate 				/*
46787c478bd9Sstevel@tonic-gate 				 * It's guaranteed that *p points to
46797c478bd9Sstevel@tonic-gate 				 * the 1st byte of a multibyte character.
46807c478bd9Sstevel@tonic-gate 				 */
46817c478bd9Sstevel@tonic-gate 				if (*p == '\n') {
46827c478bd9Sstevel@tonic-gate 					*q = '\0';
46837c478bd9Sstevel@tonic-gate 					return ((size_t)(p - buf));
46847c478bd9Sstevel@tonic-gate 				}
46857c478bd9Sstevel@tonic-gate 				if (obuflen > olen + mlen) {
46867c478bd9Sstevel@tonic-gate 					int	n;
46877c478bd9Sstevel@tonic-gate 					for (n = 0; n < mlen; n++) {
46887c478bd9Sstevel@tonic-gate 						*q++ = *p++;
46897c478bd9Sstevel@tonic-gate 					}
46907c478bd9Sstevel@tonic-gate 					olen += mlen;
46917c478bd9Sstevel@tonic-gate 				} else {
46927c478bd9Sstevel@tonic-gate 					*q = '\0';
46937c478bd9Sstevel@tonic-gate 					return ((size_t)(p - buf));
46947c478bd9Sstevel@tonic-gate 				}
46957c478bd9Sstevel@tonic-gate 			}
46967c478bd9Sstevel@tonic-gate 		}
46977c478bd9Sstevel@tonic-gate 		/*
46987c478bd9Sstevel@tonic-gate 		 * no newline nor null byte found.
46997c478bd9Sstevel@tonic-gate 		 * Also it's guaranteed that *p points to
47007c478bd9Sstevel@tonic-gate 		 * the 1st byte of a (multibyte) character
47017c478bd9Sstevel@tonic-gate 		 * at this point.
47027c478bd9Sstevel@tonic-gate 		 */
47037c478bd9Sstevel@tonic-gate 		*q = '\0';
47047c478bd9Sstevel@tonic-gate 		return ((size_t)(p - buf));
47057c478bd9Sstevel@tonic-gate 	}
47067c478bd9Sstevel@tonic-gate }
47077c478bd9Sstevel@tonic-gate 
47087c478bd9Sstevel@tonic-gate /*
47097c478bd9Sstevel@tonic-gate  * copy_frwd:
47107c478bd9Sstevel@tonic-gate  *	Scans each character in buf and copies the scanned character to obuf
47117c478bd9Sstevel@tonic-gate  *	until the number of the remaining bytes in obuf gets to exceed obuflen
47127c478bd9Sstevel@tonic-gate  *	if copying the scanned character to obuf.
47137c478bd9Sstevel@tonic-gate  *	Returns the number of scanned (copied) bytes.
47147c478bd9Sstevel@tonic-gate  *
47157c478bd9Sstevel@tonic-gate  *	obuf - buffer to be copied the scanned character
47167c478bd9Sstevel@tonic-gate  *	obuflen - the size of obuf
47177c478bd9Sstevel@tonic-gate  *	buf - pointer to a buffer containing the message string
47187c478bd9Sstevel@tonic-gate  *	len - the length of the buffer
47197c478bd9Sstevel@tonic-gate  */
47207c478bd9Sstevel@tonic-gate size_t
47217c478bd9Sstevel@tonic-gate copy_frwd(char *obuf, const size_t obuflen,
47227c478bd9Sstevel@tonic-gate 	const char *buf, const size_t len)
47237c478bd9Sstevel@tonic-gate {
47247c478bd9Sstevel@tonic-gate 	const char *p;
47257c478bd9Sstevel@tonic-gate 	char	*q = obuf;
47267c478bd9Sstevel@tonic-gate 	size_t	olen = 0;
47277c478bd9Sstevel@tonic-gate 	size_t	mb_cur_max;
47287c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
47297c478bd9Sstevel@tonic-gate 
47307c478bd9Sstevel@tonic-gate 	if (Debug) {
47317c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
47327c478bd9Sstevel@tonic-gate 	}
47337c478bd9Sstevel@tonic-gate 
47347c478bd9Sstevel@tonic-gate 	if (len == 0) {
47357c478bd9Sstevel@tonic-gate 		return (0);
47367c478bd9Sstevel@tonic-gate 	}
47377c478bd9Sstevel@tonic-gate 
47387c478bd9Sstevel@tonic-gate 	mb_cur_max = MB_CUR_MAX;
47397c478bd9Sstevel@tonic-gate 
47407c478bd9Sstevel@tonic-gate 	if (mb_cur_max == 1) {
47417c478bd9Sstevel@tonic-gate 		/* single-byte locale */
47427c478bd9Sstevel@tonic-gate 		if (obuflen > len) {
47437c478bd9Sstevel@tonic-gate 			(void) memcpy(obuf, buf, len);
47447c478bd9Sstevel@tonic-gate 			obuf[len] = '\0';
47457c478bd9Sstevel@tonic-gate 			return ((size_t)len);
47467c478bd9Sstevel@tonic-gate 		} else {
47477c478bd9Sstevel@tonic-gate 			(void) memcpy(obuf, buf, obuflen - 1);
47487c478bd9Sstevel@tonic-gate 			obuf[obuflen - 1] = '\0';
47497c478bd9Sstevel@tonic-gate 			return (obuflen - 1);
47507c478bd9Sstevel@tonic-gate 		}
47517c478bd9Sstevel@tonic-gate 	} else {
47527c478bd9Sstevel@tonic-gate 		/* multi-byte locale */
47537c478bd9Sstevel@tonic-gate 		int mlen;
47547c478bd9Sstevel@tonic-gate 
47557c478bd9Sstevel@tonic-gate 		for (p = buf; *p; ) {
47567c478bd9Sstevel@tonic-gate 			mlen = mblen(p, mb_cur_max);
47577c478bd9Sstevel@tonic-gate 			if (mlen == -1) {
47587c478bd9Sstevel@tonic-gate 				/*
47597c478bd9Sstevel@tonic-gate 				 * Invalid character found.
47607c478bd9Sstevel@tonic-gate 				 */
47617c478bd9Sstevel@tonic-gate 				DPRINT1(9, "copy_frwd(%u): Invalid MB "
47627c478bd9Sstevel@tonic-gate 					"sequence\n", mythreadno);
47637c478bd9Sstevel@tonic-gate 				/*
47647c478bd9Sstevel@tonic-gate 				 * handle as a single byte character.
47657c478bd9Sstevel@tonic-gate 				 */
47667c478bd9Sstevel@tonic-gate 				if (obuflen > olen + 1) {
47677c478bd9Sstevel@tonic-gate 					*q++ = *p++;
47687c478bd9Sstevel@tonic-gate 					olen++;
47697c478bd9Sstevel@tonic-gate 				} else {
47707c478bd9Sstevel@tonic-gate 					*q = '\0';
47717c478bd9Sstevel@tonic-gate 					return ((size_t)(p - buf));
47727c478bd9Sstevel@tonic-gate 				}
47737c478bd9Sstevel@tonic-gate 			} else {
47747c478bd9Sstevel@tonic-gate 				if (obuflen > olen + mlen) {
47757c478bd9Sstevel@tonic-gate 					int	n;
47767c478bd9Sstevel@tonic-gate 					for (n = 0; n < mlen; n++) {
47777c478bd9Sstevel@tonic-gate 						*q++ = *p++;
47787c478bd9Sstevel@tonic-gate 					}
47797c478bd9Sstevel@tonic-gate 					olen += mlen;
47807c478bd9Sstevel@tonic-gate 				} else {
47817c478bd9Sstevel@tonic-gate 					*q = '\0';
47827c478bd9Sstevel@tonic-gate 					return ((size_t)(p - buf));
47837c478bd9Sstevel@tonic-gate 				}
47847c478bd9Sstevel@tonic-gate 			}
47857c478bd9Sstevel@tonic-gate 		}
47867c478bd9Sstevel@tonic-gate 		*q = '\0';
47877c478bd9Sstevel@tonic-gate 		return ((size_t)(p - buf));
47887c478bd9Sstevel@tonic-gate 	}
47897c478bd9Sstevel@tonic-gate }
47907c478bd9Sstevel@tonic-gate 
47917c478bd9Sstevel@tonic-gate /*
4792*0ea5e3a5Sjjj  * properties:
4793*0ea5e3a5Sjjj  *	Get properties from SMF framework.
47947c478bd9Sstevel@tonic-gate  */
47957c478bd9Sstevel@tonic-gate static void
4796*0ea5e3a5Sjjj properties(void)
47977c478bd9Sstevel@tonic-gate {
4798*0ea5e3a5Sjjj 	scf_simple_prop_t *prop;
4799*0ea5e3a5Sjjj 	uint8_t *bool;
48007c478bd9Sstevel@tonic-gate 
4801*0ea5e3a5Sjjj 	if ((prop = scf_simple_prop_get(NULL, NULL, "config",
4802*0ea5e3a5Sjjj 	    "log_from_remote")) != NULL) {
4803*0ea5e3a5Sjjj 		if ((bool = scf_simple_prop_next_boolean(prop)) != NULL) {
4804*0ea5e3a5Sjjj 			if (*bool == 0)
4805*0ea5e3a5Sjjj 				turnoff = 1; /* log_from_remote = false */
4806*0ea5e3a5Sjjj 			else
4807*0ea5e3a5Sjjj 				turnoff = 0; /* log_from_remote = true */
48087c478bd9Sstevel@tonic-gate 		}
4809*0ea5e3a5Sjjj 		scf_simple_prop_free(prop);
4810*0ea5e3a5Sjjj 		DPRINT1(1, "properties: setting turnoff to %s\n",
4811*0ea5e3a5Sjjj 		    turnoff ? "true" : "false");
48127c478bd9Sstevel@tonic-gate 	}
48137c478bd9Sstevel@tonic-gate }
48147c478bd9Sstevel@tonic-gate 
48157c478bd9Sstevel@tonic-gate /*
48167c478bd9Sstevel@tonic-gate  * close all the input devices.
48177c478bd9Sstevel@tonic-gate  */
48187c478bd9Sstevel@tonic-gate static void
48197c478bd9Sstevel@tonic-gate shutdown_input(void)
48207c478bd9Sstevel@tonic-gate {
48217c478bd9Sstevel@tonic-gate 	int cnt;
48227c478bd9Sstevel@tonic-gate 
48237c478bd9Sstevel@tonic-gate 	shutting_down = 1;
48247c478bd9Sstevel@tonic-gate 
48257c478bd9Sstevel@tonic-gate 	for (cnt = 0; cnt < Ninputs; cnt++) {
48267c478bd9Sstevel@tonic-gate 		(void) t_close(Nfd[cnt].fd);
48277c478bd9Sstevel@tonic-gate 	}
48287c478bd9Sstevel@tonic-gate 
48297c478bd9Sstevel@tonic-gate 	(void) close(Pfd.fd);
48307c478bd9Sstevel@tonic-gate }
48317c478bd9Sstevel@tonic-gate 
48327c478bd9Sstevel@tonic-gate /*
48337c478bd9Sstevel@tonic-gate  * This is for the one thread that dedicates to resolve the
48347c478bd9Sstevel@tonic-gate  * hostname. This will get the messages from net_poll() through
48357c478bd9Sstevel@tonic-gate  * hnlq, and resolve the hostname, and push the messages back
48367c478bd9Sstevel@tonic-gate  * into the inputq.
48377c478bd9Sstevel@tonic-gate  */
48387c478bd9Sstevel@tonic-gate /*ARGSUSED*/
48397c478bd9Sstevel@tonic-gate static void *
48407c478bd9Sstevel@tonic-gate hostname_lookup(void *ap)
48417c478bd9Sstevel@tonic-gate {
48427c478bd9Sstevel@tonic-gate 	char *uap;
48437c478bd9Sstevel@tonic-gate 	log_message_t *mp;
48447c478bd9Sstevel@tonic-gate 	host_info_t *hip;
48457c478bd9Sstevel@tonic-gate 	char failsafe_addr[SYS_NMLN + 1];
48467c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
48477c478bd9Sstevel@tonic-gate 
48487c478bd9Sstevel@tonic-gate 	if (Debug) {
48497c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
48507c478bd9Sstevel@tonic-gate 	}
48517c478bd9Sstevel@tonic-gate 
48527c478bd9Sstevel@tonic-gate 	DPRINT1(1, "hostname_lookup(%u): hostname_lookup started\n",
48537c478bd9Sstevel@tonic-gate 		mythreadno);
48547c478bd9Sstevel@tonic-gate 
48557c478bd9Sstevel@tonic-gate 	for (;;) {
48567c478bd9Sstevel@tonic-gate 		(void) dataq_dequeue(&hnlq, (void **)&mp, 0);
48577c478bd9Sstevel@tonic-gate 
48587c478bd9Sstevel@tonic-gate 		DPRINT3(5, "hostname_lookup(%u): dequeued msg %p"
4859*0ea5e3a5Sjjj 			" from queue %p\n", mythreadno, (void *)mp,
4860*0ea5e3a5Sjjj 			(void *)&hnlq);
48617c478bd9Sstevel@tonic-gate 
48627c478bd9Sstevel@tonic-gate 		hip = (host_info_t *)mp->ptr;
48637c478bd9Sstevel@tonic-gate 		if ((uap = taddr2uaddr(hip->ncp, &hip->addr)) != NULL) {
48647c478bd9Sstevel@tonic-gate 			(void) strlcpy(failsafe_addr, uap, SYS_NMLN);
48657c478bd9Sstevel@tonic-gate 			free(uap);
48667c478bd9Sstevel@tonic-gate 		} else {
48677c478bd9Sstevel@tonic-gate 			(void) strlcpy(failsafe_addr, "<unknown>", SYS_NMLN);
48687c478bd9Sstevel@tonic-gate 		}
48697c478bd9Sstevel@tonic-gate 
48707c478bd9Sstevel@tonic-gate 		mp->hlp = cvthname(&hip->addr, hip->ncp, failsafe_addr);
48717c478bd9Sstevel@tonic-gate 
48727c478bd9Sstevel@tonic-gate 		if (mp->hlp == NULL) {
48737c478bd9Sstevel@tonic-gate 			mp->hlp = &NullHostName;
48747c478bd9Sstevel@tonic-gate 		}
48757c478bd9Sstevel@tonic-gate 
48767c478bd9Sstevel@tonic-gate 		free(hip->addr.buf);
48777c478bd9Sstevel@tonic-gate 		free(hip);
48787c478bd9Sstevel@tonic-gate 		mp->ptr = NULL;
48797c478bd9Sstevel@tonic-gate 
48807c478bd9Sstevel@tonic-gate 		if (dataq_enqueue(&inputq, (void *)mp) == -1) {
48817c478bd9Sstevel@tonic-gate 			MALLOC_FAIL("dropping message from remote");
48827c478bd9Sstevel@tonic-gate 			free_msg(mp);
48837c478bd9Sstevel@tonic-gate 			continue;
48847c478bd9Sstevel@tonic-gate 		}
48857c478bd9Sstevel@tonic-gate 
4886*0ea5e3a5Sjjj 		DPRINT3(5, "hostname_lookup(%u): enqueued msg %p on queue "
4887*0ea5e3a5Sjjj 			"%p\n", mythreadno, (void *)mp, (void *)&inputq);
48887c478bd9Sstevel@tonic-gate 	}
48897c478bd9Sstevel@tonic-gate 
48907c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
48917c478bd9Sstevel@tonic-gate 	return (NULL);
48927c478bd9Sstevel@tonic-gate }
48937c478bd9Sstevel@tonic-gate 
48947c478bd9Sstevel@tonic-gate /*
48957c478bd9Sstevel@tonic-gate  * Does all HUP(re-configuration) process.
48967c478bd9Sstevel@tonic-gate  */
48977c478bd9Sstevel@tonic-gate static void
48987c478bd9Sstevel@tonic-gate reconfigure()
48997c478bd9Sstevel@tonic-gate {
49007c478bd9Sstevel@tonic-gate 	int cnt, loop, drops;
49017c478bd9Sstevel@tonic-gate 	int really_stuck;
49027c478bd9Sstevel@tonic-gate 	int console_stuck = 0;
49037c478bd9Sstevel@tonic-gate 	struct filed *f;
49047c478bd9Sstevel@tonic-gate 	char buf[LINE_MAX];
49057c478bd9Sstevel@tonic-gate 	struct utsname up;
49067c478bd9Sstevel@tonic-gate 	char cbuf[30];
49077c478bd9Sstevel@tonic-gate 	time_t tim;
49087c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
49097c478bd9Sstevel@tonic-gate 
49107c478bd9Sstevel@tonic-gate 	if (Debug) {
49117c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
49127c478bd9Sstevel@tonic-gate 	}
49137c478bd9Sstevel@tonic-gate 
49147c478bd9Sstevel@tonic-gate 	/* If we get here then we must need to regen */
49157c478bd9Sstevel@tonic-gate 	flushmsg(0);
49167c478bd9Sstevel@tonic-gate 
49177c478bd9Sstevel@tonic-gate 	if (logmymsg(LOG_SYSLOG|LOG_INFO, "syslogd: configuration restart",
49187c478bd9Sstevel@tonic-gate 		ADDDATE, 0) == -1) {
49197c478bd9Sstevel@tonic-gate 		MALLOC_FAIL("dropping message");
49207c478bd9Sstevel@tonic-gate 	}
49217c478bd9Sstevel@tonic-gate 
49227c478bd9Sstevel@tonic-gate 	/*
49237c478bd9Sstevel@tonic-gate 	 * make sure the logmsg thread is not in the waiting state.
49247c478bd9Sstevel@tonic-gate 	 * Otherwise, changing hup_state will prevent the logmsg thread
49257c478bd9Sstevel@tonic-gate 	 * getting out from the waiting loop.
49267c478bd9Sstevel@tonic-gate 	 */
49277c478bd9Sstevel@tonic-gate 
49287c478bd9Sstevel@tonic-gate 	if (Debug) {
49297c478bd9Sstevel@tonic-gate 		tim = time(NULL);
49307c478bd9Sstevel@tonic-gate 		DPRINT2(3, "reconfigure(%u): %.15s: awaiting logmsg()"
49317c478bd9Sstevel@tonic-gate 			" moving to the safe place\n",
49327c478bd9Sstevel@tonic-gate 			mythreadno, ctime_r(&tim, cbuf)+4);
49337c478bd9Sstevel@tonic-gate 	}
49347c478bd9Sstevel@tonic-gate 
49357c478bd9Sstevel@tonic-gate 	for (loop = 0; loop < LOOP_MAX; loop++) {
49367c478bd9Sstevel@tonic-gate 		/* we don't need the mutex to read */
49377c478bd9Sstevel@tonic-gate 		if (hup_state == HUP_ACCEPTABLE)
49387c478bd9Sstevel@tonic-gate 			break;
49397c478bd9Sstevel@tonic-gate 		(void) sleep(1);
49407c478bd9Sstevel@tonic-gate 	}
49417c478bd9Sstevel@tonic-gate 	if (hup_state != HUP_ACCEPTABLE) {
49427c478bd9Sstevel@tonic-gate 		goto thread_stuck;
49437c478bd9Sstevel@tonic-gate 	}
49447c478bd9Sstevel@tonic-gate 
49457c478bd9Sstevel@tonic-gate 	if (Debug) {
49467c478bd9Sstevel@tonic-gate 		tim = time(NULL);
49477c478bd9Sstevel@tonic-gate 		DPRINT2(3, "reconfigure(%u): %.15s: logmsg() will accept HUP\n",
49487c478bd9Sstevel@tonic-gate 			mythreadno, ctime_r(&tim, cbuf)+4);
49497c478bd9Sstevel@tonic-gate 	}
49507c478bd9Sstevel@tonic-gate 
49517c478bd9Sstevel@tonic-gate 	/*
49527c478bd9Sstevel@tonic-gate 	 * Prevent logging until we are truly done processing the HUP
49537c478bd9Sstevel@tonic-gate 	 */
49547c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&hup_lock);
49557c478bd9Sstevel@tonic-gate 	hup_state = HUP_INPROGRESS;
49567c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&hup_lock);
49577c478bd9Sstevel@tonic-gate 
49587c478bd9Sstevel@tonic-gate 	/*
49597c478bd9Sstevel@tonic-gate 	 * We will be going into a critical state. Any error message
49607c478bd9Sstevel@tonic-gate 	 * from syslogd needs to be dumped to the console by default
49617c478bd9Sstevel@tonic-gate 	 * immediately. Also, those error messages are quened in a temporary
49627c478bd9Sstevel@tonic-gate 	 * queue to be able to post into the regular stream later.
49637c478bd9Sstevel@tonic-gate 	 */
49647c478bd9Sstevel@tonic-gate 	disable_errorlog();
49657c478bd9Sstevel@tonic-gate 
49667c478bd9Sstevel@tonic-gate 	if (Debug) {
49677c478bd9Sstevel@tonic-gate 		tim = time(NULL);
49687c478bd9Sstevel@tonic-gate 		DPRINT2(3, "reconfigure(%u): %.15s: sending SHUTDOWN\n",
49697c478bd9Sstevel@tonic-gate 			mythreadno, ctime_r(&tim, cbuf)+4);
49707c478bd9Sstevel@tonic-gate 	}
49717c478bd9Sstevel@tonic-gate 
49727c478bd9Sstevel@tonic-gate 	/* stop configured threads */
49737c478bd9Sstevel@tonic-gate 	if (shutdown_msg() == -1) {
49747c478bd9Sstevel@tonic-gate 		/*
49757c478bd9Sstevel@tonic-gate 		 * No memory, message will be dumped to the console.
49767c478bd9Sstevel@tonic-gate 		 */
49777c478bd9Sstevel@tonic-gate 		MALLOC_FAIL("unable to restart syslogd");
49787c478bd9Sstevel@tonic-gate 		goto out;
49797c478bd9Sstevel@tonic-gate 	}
49807c478bd9Sstevel@tonic-gate 
49817c478bd9Sstevel@tonic-gate 	/* make sure logmsg() is in suspended state */
49827c478bd9Sstevel@tonic-gate 	for (loop = 0; loop < LOOP_INTERVAL; loop++) {
49837c478bd9Sstevel@tonic-gate 		if (hup_state & HUP_LOGMSG_SUSPENDED)
49847c478bd9Sstevel@tonic-gate 			break;
49857c478bd9Sstevel@tonic-gate 		(void) sleep(1);
49867c478bd9Sstevel@tonic-gate 	}
49877c478bd9Sstevel@tonic-gate 
49887c478bd9Sstevel@tonic-gate 	if ((hup_state & HUP_LOGMSG_SUSPENDED) == 0) {
49897c478bd9Sstevel@tonic-gate 		if (Debug) {
49907c478bd9Sstevel@tonic-gate 			tim = time(NULL);
49917c478bd9Sstevel@tonic-gate 			DPRINT2(3, "reconfigure(%u): %.15s: logmsg() does not "
49927c478bd9Sstevel@tonic-gate 				"stop. enforcing\n",
49937c478bd9Sstevel@tonic-gate 				mythreadno, ctime_r(&tim, cbuf)+4);
49947c478bd9Sstevel@tonic-gate 		}
49957c478bd9Sstevel@tonic-gate 
49967c478bd9Sstevel@tonic-gate 		/* probably we have too long input queue, or really stuck */
49977c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&hup_lock);
49987c478bd9Sstevel@tonic-gate 		hup_state |= HUP_SUSP_LOGMSG_REQD;
49997c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&hup_lock);
50007c478bd9Sstevel@tonic-gate 
50017c478bd9Sstevel@tonic-gate 		for (loop = 0; loop < LOOP_MAX; loop++) {
50027c478bd9Sstevel@tonic-gate 			if (hup_state & HUP_LOGMSG_SUSPENDED)
50037c478bd9Sstevel@tonic-gate 				break;
50047c478bd9Sstevel@tonic-gate 			(void) sleep(1);
50057c478bd9Sstevel@tonic-gate 		}
50067c478bd9Sstevel@tonic-gate 		if ((hup_state & HUP_LOGMSG_SUSPENDED) == 0) {
50077c478bd9Sstevel@tonic-gate 			if (Debug) {
50087c478bd9Sstevel@tonic-gate 				tim = time(NULL);
50097c478bd9Sstevel@tonic-gate 				DPRINT2(3, "reconfigure(%u): %.15s: logmsg()"
50107c478bd9Sstevel@tonic-gate 					" does not stop. give up\n",
50117c478bd9Sstevel@tonic-gate 					mythreadno, ctime_r(&tim, cbuf)+4);
50127c478bd9Sstevel@tonic-gate 			}
50137c478bd9Sstevel@tonic-gate 			logerror("could not suspend logmsg - fatal");
50147c478bd9Sstevel@tonic-gate 			goto thread_stuck;
50157c478bd9Sstevel@tonic-gate 		}
50167c478bd9Sstevel@tonic-gate 	}
50177c478bd9Sstevel@tonic-gate 
50187c478bd9Sstevel@tonic-gate 	if (Debug) {
50197c478bd9Sstevel@tonic-gate 		tim = time(NULL);
50207c478bd9Sstevel@tonic-gate 		DPRINT2(3, "reconfigure(%u): %.15s: logmsg() suspended\n",
50217c478bd9Sstevel@tonic-gate 			mythreadno, ctime_r(&tim, cbuf)+4);
50227c478bd9Sstevel@tonic-gate 	}
50237c478bd9Sstevel@tonic-gate 
50247c478bd9Sstevel@tonic-gate 	/*
50257c478bd9Sstevel@tonic-gate 	 * Will wait for LOOP_MAX secs with watching queue lengths for the
50267c478bd9Sstevel@tonic-gate 	 * each logger threads. If they have backlogs, and no change in the
50277c478bd9Sstevel@tonic-gate 	 * length of queue found in 30 seconds, those will be counted as
50287c478bd9Sstevel@tonic-gate 	 * "really stuck".
50297c478bd9Sstevel@tonic-gate 	 * If all running logger threads become "really stuck" state, there
50307c478bd9Sstevel@tonic-gate 	 * should be no worth waiting for them to quit.
50317c478bd9Sstevel@tonic-gate 	 * In that case, we will go ahead and close out file descriptors to
50327c478bd9Sstevel@tonic-gate 	 * have them pull out from hanging system call, and give them a last
50337c478bd9Sstevel@tonic-gate 	 * chance(LOOP_INTERVAL sec) to quit.
50347c478bd9Sstevel@tonic-gate 	 */
50357c478bd9Sstevel@tonic-gate 
50367c478bd9Sstevel@tonic-gate 	if (Debug) {
50377c478bd9Sstevel@tonic-gate 		tim = time(NULL);
50387c478bd9Sstevel@tonic-gate 		DPRINT2(3, "reconfigure(%u): %.15s: awaiting logit() to be"
50397c478bd9Sstevel@tonic-gate 			" shutdown\n", mythreadno, ctime_r(&tim, cbuf)+4);
50407c478bd9Sstevel@tonic-gate 	}
50417c478bd9Sstevel@tonic-gate 
50427c478bd9Sstevel@tonic-gate 	cnt = 0;
50437c478bd9Sstevel@tonic-gate 	really_stuck = 0;
50447c478bd9Sstevel@tonic-gate 	while (cnt < (LOOP_MAX/LOOP_INTERVAL) &&
50457c478bd9Sstevel@tonic-gate 		conf_threads > really_stuck) {
50467c478bd9Sstevel@tonic-gate 
50477c478bd9Sstevel@tonic-gate 		/* save initial queue count */
50487c478bd9Sstevel@tonic-gate 		for (f = Files; f < &Files[nlogs]; f++) {
50497c478bd9Sstevel@tonic-gate 			f->f_prev_queue_count = (f->f_type == F_UNUSED) ?
50507c478bd9Sstevel@tonic-gate 				-1 : f->f_queue_count;
50517c478bd9Sstevel@tonic-gate 		}
50527c478bd9Sstevel@tonic-gate 
50537c478bd9Sstevel@tonic-gate 		for (loop = 0; loop < LOOP_INTERVAL; loop++) {
50547c478bd9Sstevel@tonic-gate 			if (conf_threads == 0)
50557c478bd9Sstevel@tonic-gate 				break;
50567c478bd9Sstevel@tonic-gate 			(void) sleep(1);
50577c478bd9Sstevel@tonic-gate 		}
50587c478bd9Sstevel@tonic-gate 
50597c478bd9Sstevel@tonic-gate 		if (conf_threads == 0)
50607c478bd9Sstevel@tonic-gate 			break;
50617c478bd9Sstevel@tonic-gate 
50627c478bd9Sstevel@tonic-gate 		if (Debug) {
50637c478bd9Sstevel@tonic-gate 			tim = time(NULL);
50647c478bd9Sstevel@tonic-gate 			DPRINT3(3, "reconfigure(%u): %.15s: "
50657c478bd9Sstevel@tonic-gate 				"%d threads are still alive.\n",
50667c478bd9Sstevel@tonic-gate 				mythreadno, ctime_r(&tim, cbuf)+4,
50677c478bd9Sstevel@tonic-gate 				conf_threads);
50687c478bd9Sstevel@tonic-gate 		}
50697c478bd9Sstevel@tonic-gate 
50707c478bd9Sstevel@tonic-gate 		really_stuck = 0;
50717c478bd9Sstevel@tonic-gate 		for (f = Files; f < &Files[nlogs]; f++) {
50727c478bd9Sstevel@tonic-gate 			if (f->f_type == F_UNUSED) {
50737c478bd9Sstevel@tonic-gate 				f->f_prev_queue_count = -1;
50747c478bd9Sstevel@tonic-gate 				continue;
50757c478bd9Sstevel@tonic-gate 			}
50767c478bd9Sstevel@tonic-gate 			if (f->f_prev_queue_count == f->f_queue_count) {
50777c478bd9Sstevel@tonic-gate 				really_stuck++;
50787c478bd9Sstevel@tonic-gate 				f->f_prev_queue_count = 1;
50797c478bd9Sstevel@tonic-gate 				DPRINT2(3, "reconfigure(%u): "
50807c478bd9Sstevel@tonic-gate 					"tid=%d is really stuck.\n",
50817c478bd9Sstevel@tonic-gate 					mythreadno, f->f_thread);
50827c478bd9Sstevel@tonic-gate 			} else {
50837c478bd9Sstevel@tonic-gate 				f->f_prev_queue_count = 0;
50847c478bd9Sstevel@tonic-gate 				DPRINT2(3, "reconfigure(%u): "
50857c478bd9Sstevel@tonic-gate 					"tid=%d is still active.\n",
50867c478bd9Sstevel@tonic-gate 					mythreadno, f->f_thread);
50877c478bd9Sstevel@tonic-gate 			}
50887c478bd9Sstevel@tonic-gate 		}
50897c478bd9Sstevel@tonic-gate 		/*
50907c478bd9Sstevel@tonic-gate 		 * Here we have one of following values in the
50917c478bd9Sstevel@tonic-gate 		 * f_prev_queue_count:
50927c478bd9Sstevel@tonic-gate 		 *  0: logger thread is still actively working.
50937c478bd9Sstevel@tonic-gate 		 *  1: logger thread is really stuck.
50947c478bd9Sstevel@tonic-gate 		 * -1: logger thread has already died.
50957c478bd9Sstevel@tonic-gate 		 */
50967c478bd9Sstevel@tonic-gate 
50977c478bd9Sstevel@tonic-gate 		cnt++;
50987c478bd9Sstevel@tonic-gate 	}
50997c478bd9Sstevel@tonic-gate 
51007c478bd9Sstevel@tonic-gate 	if (Debug) {
51017c478bd9Sstevel@tonic-gate 		tim = time(NULL);
51027c478bd9Sstevel@tonic-gate 		DPRINT2(3, "reconfigure(%u): %.15s:"
51037c478bd9Sstevel@tonic-gate 			" complete awaiting logit()\n",
51047c478bd9Sstevel@tonic-gate 			mythreadno, ctime_r(&tim, cbuf)+4);
51057c478bd9Sstevel@tonic-gate 		DPRINT3(3, "reconfigure(%u): %d threads alive."
51067c478bd9Sstevel@tonic-gate 			" %d threads stuck\n",
51077c478bd9Sstevel@tonic-gate 			mythreadno, conf_threads, really_stuck);
51087c478bd9Sstevel@tonic-gate 	}
51097c478bd9Sstevel@tonic-gate 
51107c478bd9Sstevel@tonic-gate 	/*
51117c478bd9Sstevel@tonic-gate 	 * Still running? If so, mark it as UNUSED, and close
51127c478bd9Sstevel@tonic-gate 	 * the fd so that logger threads can bail out from the loop.
51137c478bd9Sstevel@tonic-gate 	 */
51147c478bd9Sstevel@tonic-gate 	drops = 0;
51157c478bd9Sstevel@tonic-gate 	if (conf_threads) {
51167c478bd9Sstevel@tonic-gate 		for (f = Files; f < &Files[nlogs]; f++) {
51177c478bd9Sstevel@tonic-gate 			if (f->f_type == F_CONSOLE &&
51187c478bd9Sstevel@tonic-gate 				f->f_prev_queue_count == 1) {
51197c478bd9Sstevel@tonic-gate 				/* console is really stuck */
51207c478bd9Sstevel@tonic-gate 				console_stuck = 1;
51217c478bd9Sstevel@tonic-gate 			}
51227c478bd9Sstevel@tonic-gate 			if (f->f_type == F_USERS || f->f_type == F_WALL ||
51237c478bd9Sstevel@tonic-gate 				f->f_type == F_UNUSED)
51247c478bd9Sstevel@tonic-gate 				continue;
51257c478bd9Sstevel@tonic-gate 			cnt = f->f_queue_count;
51267c478bd9Sstevel@tonic-gate 			drops += (cnt > 0) ? cnt - 1: 0;
51277c478bd9Sstevel@tonic-gate 			f->f_type = F_UNUSED;
51287c478bd9Sstevel@tonic-gate 
51297c478bd9Sstevel@tonic-gate 			if (f->f_orig_type == F_FORW)
5130*0ea5e3a5Sjjj 				(void) t_close(f->f_file);
51317c478bd9Sstevel@tonic-gate 			else
5132*0ea5e3a5Sjjj 				(void) close(f->f_file);
51337c478bd9Sstevel@tonic-gate 		}
51347c478bd9Sstevel@tonic-gate 
51357c478bd9Sstevel@tonic-gate 		if (Debug) {
51367c478bd9Sstevel@tonic-gate 			tim = time(NULL);
51377c478bd9Sstevel@tonic-gate 			DPRINT1(3, "reconfigure(%u): terminating logit()\n",
51387c478bd9Sstevel@tonic-gate 				mythreadno);
51397c478bd9Sstevel@tonic-gate 		}
51407c478bd9Sstevel@tonic-gate 
51417c478bd9Sstevel@tonic-gate 		/* last chance to exit */
51427c478bd9Sstevel@tonic-gate 		for (loop = 0; loop < LOOP_MAX; loop++) {
51437c478bd9Sstevel@tonic-gate 			if (conf_threads == 0)
51447c478bd9Sstevel@tonic-gate 				break;
51457c478bd9Sstevel@tonic-gate 			(void) sleep(1);
51467c478bd9Sstevel@tonic-gate 		}
51477c478bd9Sstevel@tonic-gate 
51487c478bd9Sstevel@tonic-gate 		if (Debug) {
51497c478bd9Sstevel@tonic-gate 			tim = time(NULL);
51507c478bd9Sstevel@tonic-gate 			DPRINT3(3, "reconfigure(%u): %.15s: %d alive\n",
51517c478bd9Sstevel@tonic-gate 				mythreadno, ctime_r(&tim, cbuf)+4,
51527c478bd9Sstevel@tonic-gate 				conf_threads);
51537c478bd9Sstevel@tonic-gate 		}
51547c478bd9Sstevel@tonic-gate 	}
51557c478bd9Sstevel@tonic-gate 
51567c478bd9Sstevel@tonic-gate 	if (conf_threads == 0 && drops) {
51577c478bd9Sstevel@tonic-gate 		errno = 0;
51587c478bd9Sstevel@tonic-gate 		logerror("Could not completely output pending messages"
51597c478bd9Sstevel@tonic-gate 			" while preparing re-configuration");
51607c478bd9Sstevel@tonic-gate 		logerror("discarded %d messages and restart configuration.",
51617c478bd9Sstevel@tonic-gate 			drops);
51627c478bd9Sstevel@tonic-gate 		if (Debug) {
51637c478bd9Sstevel@tonic-gate 			tim = time(NULL);
51647c478bd9Sstevel@tonic-gate 			DPRINT3(3, "reconfigure(%u): %.15s: "
51657c478bd9Sstevel@tonic-gate 				"discarded %d messages\n",
51667c478bd9Sstevel@tonic-gate 				mythreadno, ctime_r(&tim, cbuf)+4, drops);
51677c478bd9Sstevel@tonic-gate 		}
51687c478bd9Sstevel@tonic-gate 	}
51697c478bd9Sstevel@tonic-gate 
51707c478bd9Sstevel@tonic-gate 	/*
51717c478bd9Sstevel@tonic-gate 	 * If all threads still haven't exited
51727c478bd9Sstevel@tonic-gate 	 * something is stuck or hosed. We just
51737c478bd9Sstevel@tonic-gate 	 * have no option but to exit.
51747c478bd9Sstevel@tonic-gate 	 */
51757c478bd9Sstevel@tonic-gate 	if (conf_threads) {
51767c478bd9Sstevel@tonic-gate thread_stuck:
51777c478bd9Sstevel@tonic-gate 		if (Debug) {
51787c478bd9Sstevel@tonic-gate 			tim = time(NULL);
51797c478bd9Sstevel@tonic-gate 			DPRINT2(3, "reconfigure(%u): %.15s: really stuck\n",
51807c478bd9Sstevel@tonic-gate 				mythreadno, ctime_r(&tim, cbuf)+4);
51817c478bd9Sstevel@tonic-gate 		}
51827c478bd9Sstevel@tonic-gate 
51837c478bd9Sstevel@tonic-gate 		shutdown_input();
51847c478bd9Sstevel@tonic-gate 		delete_doorfiles();
5185*0ea5e3a5Sjjj 		(void) uname(&up);
51867c478bd9Sstevel@tonic-gate 
5187*0ea5e3a5Sjjj 		(void) snprintf(buf, sizeof (buf),
51887c478bd9Sstevel@tonic-gate 			"syslogd(%s): some logger thread(s) "
51897c478bd9Sstevel@tonic-gate 			"are stuck%s; syslogd is shutting down.",
51907c478bd9Sstevel@tonic-gate 			up.nodename,
51917c478bd9Sstevel@tonic-gate 			console_stuck ? " (including the console)" : "");
51927c478bd9Sstevel@tonic-gate 
51937c478bd9Sstevel@tonic-gate 		if (console_stuck) {
51947c478bd9Sstevel@tonic-gate 			FILE *m = popen(MAILCMD, "w");
51957c478bd9Sstevel@tonic-gate 
51967c478bd9Sstevel@tonic-gate 			if (m != NULL) {
5197*0ea5e3a5Sjjj 				(void) fprintf(m, "%s\n", buf);
5198*0ea5e3a5Sjjj 				(void) pclose(m);
51997c478bd9Sstevel@tonic-gate 			}
52007c478bd9Sstevel@tonic-gate 		}
52017c478bd9Sstevel@tonic-gate 
52027c478bd9Sstevel@tonic-gate 		disable_errorlog();
52037c478bd9Sstevel@tonic-gate 		logerror(buf);
52047c478bd9Sstevel@tonic-gate 		exit(1);
52057c478bd9Sstevel@tonic-gate 	}
52067c478bd9Sstevel@tonic-gate 
52077c478bd9Sstevel@tonic-gate 	/* Free up some resources */
52087c478bd9Sstevel@tonic-gate 	if (Files != (struct filed *)&fallback) {
52097c478bd9Sstevel@tonic-gate 		for (f = Files; f < &Files[nlogs]; f++) {
52107c478bd9Sstevel@tonic-gate 			(void) pthread_join(f->f_thread, NULL);
52117c478bd9Sstevel@tonic-gate 			filed_destroy(f);
52127c478bd9Sstevel@tonic-gate 		}
52137c478bd9Sstevel@tonic-gate 		free(Files);
52147c478bd9Sstevel@tonic-gate 	}
52157c478bd9Sstevel@tonic-gate 
52167c478bd9Sstevel@tonic-gate 	dealloc_stacks(nlogs);
52177c478bd9Sstevel@tonic-gate 
52187c478bd9Sstevel@tonic-gate 	if (Debug) {
52197c478bd9Sstevel@tonic-gate 		tim = time(NULL);
52207c478bd9Sstevel@tonic-gate 		DPRINT2(3, "reconfigure(%u): %.15s: cleanup complete\n",
52217c478bd9Sstevel@tonic-gate 			mythreadno, ctime_r(&tim, cbuf)+4);
52227c478bd9Sstevel@tonic-gate 	}
52237c478bd9Sstevel@tonic-gate 
52247c478bd9Sstevel@tonic-gate 	hnc_init(1);	/* purge hostname cache */
52257c478bd9Sstevel@tonic-gate 	conf_init();	/* start reconfigure */
52267c478bd9Sstevel@tonic-gate 
52277c478bd9Sstevel@tonic-gate out:;
52287c478bd9Sstevel@tonic-gate 	/* Now should be ready to dispatch error messages from syslogd. */
52297c478bd9Sstevel@tonic-gate 	enable_errorlog();
52307c478bd9Sstevel@tonic-gate 
52317c478bd9Sstevel@tonic-gate 	/* Wake up the log thread */
52327c478bd9Sstevel@tonic-gate 
52337c478bd9Sstevel@tonic-gate 	if (Debug) {
52347c478bd9Sstevel@tonic-gate 		tim = time(NULL);
52357c478bd9Sstevel@tonic-gate 		DPRINT2(3, "reconfigure(%u): %.15s: resuming logmsg()\n",
52367c478bd9Sstevel@tonic-gate 			mythreadno, ctime_r(&tim, cbuf)+4);
52377c478bd9Sstevel@tonic-gate 	}
52387c478bd9Sstevel@tonic-gate 
52397c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&hup_lock);
52407c478bd9Sstevel@tonic-gate 	hup_state = HUP_COMPLETED;
52417c478bd9Sstevel@tonic-gate 	(void) pthread_cond_signal(&hup_done);
52427c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&hup_lock);
52437c478bd9Sstevel@tonic-gate }
52447c478bd9Sstevel@tonic-gate 
52457c478bd9Sstevel@tonic-gate /*
52467c478bd9Sstevel@tonic-gate  * The following function implements simple hostname cache mechanism.
5247293d1fc4Spd155743  * Host name cache is implemented through hash table bucket chaining method.
5248293d1fc4Spd155743  * Collisions are handled by bucket chaining.
52497c478bd9Sstevel@tonic-gate  *
52507c478bd9Sstevel@tonic-gate  * hnc_init():
52517c478bd9Sstevel@tonic-gate  * 	allocate and initialize the cache. If reinit is set,
52527c478bd9Sstevel@tonic-gate  *	invalidate all cache entries.
52537c478bd9Sstevel@tonic-gate  * hnc_look():
5254293d1fc4Spd155743  *	It hashes the ipaddress gets the index and walks thru the
5255293d1fc4Spd155743  *	single linked list. if cached entry was found, it will
52567c478bd9Sstevel@tonic-gate  *	put in the head of the list, and return.While going through
52577c478bd9Sstevel@tonic-gate  *	the entries, an entry which has already expired will be invalidated.
52587c478bd9Sstevel@tonic-gate  * hnc_register():
5259293d1fc4Spd155743  *	Hashes the ipaddress finds the index and puts current entry to the list.
52607c478bd9Sstevel@tonic-gate  * hnc_unreg():
5261293d1fc4Spd155743  *	invalidate the cachep.
52627c478bd9Sstevel@tonic-gate  */
52637c478bd9Sstevel@tonic-gate 
52647c478bd9Sstevel@tonic-gate static void
52657c478bd9Sstevel@tonic-gate hnc_init(int reinit)
52667c478bd9Sstevel@tonic-gate {
52677c478bd9Sstevel@tonic-gate 	struct hostname_cache **hpp;
52687c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
5269293d1fc4Spd155743 	int i;
52707c478bd9Sstevel@tonic-gate 
52717c478bd9Sstevel@tonic-gate 	if (Debug) {
52727c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
52737c478bd9Sstevel@tonic-gate 	}
52747c478bd9Sstevel@tonic-gate 
52757c478bd9Sstevel@tonic-gate 	if (reinit) {
5276*0ea5e3a5Sjjj 		(void) pthread_mutex_lock(&hnc_mutex);
52777c478bd9Sstevel@tonic-gate 
5278293d1fc4Spd155743 		for (i = 0; i < hnc_size; i++) {
5279293d1fc4Spd155743 			for (hpp = &hnc_cache[i]; *hpp != NULL; ) {
52807c478bd9Sstevel@tonic-gate 				hnc_unreg(hpp);
52817c478bd9Sstevel@tonic-gate 			}
5282293d1fc4Spd155743 		}
52837c478bd9Sstevel@tonic-gate 
5284*0ea5e3a5Sjjj 		(void) pthread_mutex_unlock(&hnc_mutex);
52857c478bd9Sstevel@tonic-gate 		DPRINT1(2, "hnc_init(%u): hostname cache re-configured\n",
52867c478bd9Sstevel@tonic-gate 			mythreadno);
52877c478bd9Sstevel@tonic-gate 	} else {
52887c478bd9Sstevel@tonic-gate 
5289293d1fc4Spd155743 		hnc_cache = calloc(hnc_size, sizeof (struct hostname_cache *));
52907c478bd9Sstevel@tonic-gate 
52917c478bd9Sstevel@tonic-gate 		if (hnc_cache == NULL) {
52927c478bd9Sstevel@tonic-gate 			MALLOC_FAIL("hostname cache");
52937c478bd9Sstevel@tonic-gate 			logerror("hostname cache disabled");
52947c478bd9Sstevel@tonic-gate 			return;
52957c478bd9Sstevel@tonic-gate 		}
52967c478bd9Sstevel@tonic-gate 
52977c478bd9Sstevel@tonic-gate 		DPRINT3(1, "hnc_init(%u): hostname cache configured %d entry"
52987c478bd9Sstevel@tonic-gate 			" ttl:%d\n", mythreadno, hnc_size, hnc_ttl);
52997c478bd9Sstevel@tonic-gate 	}
53007c478bd9Sstevel@tonic-gate }
53017c478bd9Sstevel@tonic-gate 
53027c478bd9Sstevel@tonic-gate static host_list_t *
5303293d1fc4Spd155743 hnc_lookup(struct netbuf *nbp, struct netconfig *ncp, int *hindex)
53047c478bd9Sstevel@tonic-gate {
53057c478bd9Sstevel@tonic-gate 	struct hostname_cache **hpp, *hp;
53067c478bd9Sstevel@tonic-gate 	time_t now;
53077c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
5308293d1fc4Spd155743 	int index;
53097c478bd9Sstevel@tonic-gate 
53107c478bd9Sstevel@tonic-gate 	if (Debug) {
53117c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
53127c478bd9Sstevel@tonic-gate 	}
53137c478bd9Sstevel@tonic-gate 
53147c478bd9Sstevel@tonic-gate 	if (hnc_cache == NULL) {
53157c478bd9Sstevel@tonic-gate 		return (NULL);
53167c478bd9Sstevel@tonic-gate 	}
53177c478bd9Sstevel@tonic-gate 
5318*0ea5e3a5Sjjj 	(void) pthread_mutex_lock(&hnc_mutex);
53197c478bd9Sstevel@tonic-gate 	now = time(0);
53207c478bd9Sstevel@tonic-gate 
5321293d1fc4Spd155743 	*hindex = index = addr_hash(nbp);
5322293d1fc4Spd155743 
5323293d1fc4Spd155743 	for (hpp = &hnc_cache[index]; (hp = *hpp) != NULL; ) {
53247c478bd9Sstevel@tonic-gate 		DPRINT4(10, "hnc_lookup(%u): check %p on %p for %s\n",
5325*0ea5e3a5Sjjj 			mythreadno, (void *)hp->h, (void *)hp,
5326*0ea5e3a5Sjjj 			hp->h->hl_hosts[0]);
53277c478bd9Sstevel@tonic-gate 
53287c478bd9Sstevel@tonic-gate 		if (hp->expire < now) {
53297c478bd9Sstevel@tonic-gate 			DPRINT2(9, "hnc_lookup(%u): purge %p\n",
5330*0ea5e3a5Sjjj 				mythreadno, (void *)hp);
53317c478bd9Sstevel@tonic-gate 			hnc_unreg(hpp);
53327c478bd9Sstevel@tonic-gate 			continue;
53337c478bd9Sstevel@tonic-gate 		}
53347c478bd9Sstevel@tonic-gate 
53357c478bd9Sstevel@tonic-gate 		if (ncp == hp->ncp && same_addr(&hp->addr, nbp)) {
53367c478bd9Sstevel@tonic-gate 			/*
53377c478bd9Sstevel@tonic-gate 			 * found!
53387c478bd9Sstevel@tonic-gate 			 * Put the entry at the top.
53397c478bd9Sstevel@tonic-gate 			 */
53407c478bd9Sstevel@tonic-gate 
5341293d1fc4Spd155743 			if (hp != hnc_cache[index]) {
53427c478bd9Sstevel@tonic-gate 				/* unlink from active list */
53437c478bd9Sstevel@tonic-gate 				*hpp = (*hpp)->next;
53447c478bd9Sstevel@tonic-gate 				/* push it onto the top */
5345293d1fc4Spd155743 				hp->next = hnc_cache[index];
5346293d1fc4Spd155743 				hnc_cache[index] = hp;
53477c478bd9Sstevel@tonic-gate 			}
53487c478bd9Sstevel@tonic-gate 
5349*0ea5e3a5Sjjj 			(void) pthread_mutex_lock(&hp->h->hl_mutex);
53507c478bd9Sstevel@tonic-gate 			hp->h->hl_refcnt++;
5351*0ea5e3a5Sjjj 			(void) pthread_mutex_unlock(&hp->h->hl_mutex);
53527c478bd9Sstevel@tonic-gate 
53537c478bd9Sstevel@tonic-gate 			DPRINT4(9, "hnc_lookup(%u): found %p on %p for %s\n",
5354*0ea5e3a5Sjjj 				mythreadno, (void *)hp->h, (void *)hp,
5355*0ea5e3a5Sjjj 				hp->h->hl_hosts[0]);
53567c478bd9Sstevel@tonic-gate 
5357*0ea5e3a5Sjjj 			(void) pthread_mutex_unlock(&hnc_mutex);
53587c478bd9Sstevel@tonic-gate 			return (hp->h);
53597c478bd9Sstevel@tonic-gate 		}
53607c478bd9Sstevel@tonic-gate 
53617c478bd9Sstevel@tonic-gate 		hpp = &hp->next;
53627c478bd9Sstevel@tonic-gate 	}
53637c478bd9Sstevel@tonic-gate 
5364*0ea5e3a5Sjjj 	(void) pthread_mutex_unlock(&hnc_mutex);
53657c478bd9Sstevel@tonic-gate 	return (NULL);
53667c478bd9Sstevel@tonic-gate }
53677c478bd9Sstevel@tonic-gate 
53687c478bd9Sstevel@tonic-gate static void
5369293d1fc4Spd155743 hnc_register(struct netbuf *nbp, struct netconfig *ncp,
5370293d1fc4Spd155743 		    host_list_t *h, int hindex)
53717c478bd9Sstevel@tonic-gate {
5372293d1fc4Spd155743 	struct hostname_cache **hpp, **tailp, *hp, *entry;
53737c478bd9Sstevel@tonic-gate 	void *addrbuf;
53747c478bd9Sstevel@tonic-gate 	time_t now;
53757c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
5376293d1fc4Spd155743 	int i;
53777c478bd9Sstevel@tonic-gate 
53787c478bd9Sstevel@tonic-gate 	if (Debug) {
53797c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
53807c478bd9Sstevel@tonic-gate 	}
53817c478bd9Sstevel@tonic-gate 
53827c478bd9Sstevel@tonic-gate 	if (hnc_cache == NULL) {
53837c478bd9Sstevel@tonic-gate 		return;
53847c478bd9Sstevel@tonic-gate 	}
53857c478bd9Sstevel@tonic-gate 
53867c478bd9Sstevel@tonic-gate 	if ((addrbuf = malloc(nbp->len)) == NULL) {
53877c478bd9Sstevel@tonic-gate 		MALLOC_FAIL("pushing hostname cache");
53887c478bd9Sstevel@tonic-gate 		return;
53897c478bd9Sstevel@tonic-gate 	}
53907c478bd9Sstevel@tonic-gate 
5391293d1fc4Spd155743 	if ((entry = malloc(sizeof (struct hostname_cache))) == NULL) {
5392293d1fc4Spd155743 		MALLOC_FAIL("pushing hostname entry");
5393293d1fc4Spd155743 		free(addrbuf);
5394293d1fc4Spd155743 		return;
5395293d1fc4Spd155743 	}
5396293d1fc4Spd155743 
5397*0ea5e3a5Sjjj 	(void) pthread_mutex_lock(&hnc_mutex);
53987c478bd9Sstevel@tonic-gate 
5399293d1fc4Spd155743 	i = 0;
5400293d1fc4Spd155743 
5401293d1fc4Spd155743 	now = time(0);
54027c478bd9Sstevel@tonic-gate 	/*
54037c478bd9Sstevel@tonic-gate 	 * first go through active list, and discard the
5404293d1fc4Spd155743 	 * caches which has been invalid. Count number of
5405293d1fc4Spd155743 	 * non-expired buckets.
54067c478bd9Sstevel@tonic-gate 	 */
5407293d1fc4Spd155743 
5408293d1fc4Spd155743 	for (hpp = &hnc_cache[hindex]; (hp = *hpp) != NULL; ) {
54097c478bd9Sstevel@tonic-gate 		tailp = hpp;
54107c478bd9Sstevel@tonic-gate 
54117c478bd9Sstevel@tonic-gate 		if (hp->expire < now) {
54127c478bd9Sstevel@tonic-gate 			DPRINT2(9, "hnc_register(%u): discard %p\n",
5413*0ea5e3a5Sjjj 				mythreadno, (void *)hp);
54147c478bd9Sstevel@tonic-gate 			hnc_unreg(hpp);
54157c478bd9Sstevel@tonic-gate 		} else {
5416293d1fc4Spd155743 			i++;
54177c478bd9Sstevel@tonic-gate 			hpp = &hp->next;
54187c478bd9Sstevel@tonic-gate 		}
54197c478bd9Sstevel@tonic-gate 	}
54207c478bd9Sstevel@tonic-gate 
54217c478bd9Sstevel@tonic-gate 	/*
5422293d1fc4Spd155743 	 * If max limit of chained hash buckets has been used up
5423293d1fc4Spd155743 	 * delete the least active element in the chain.
54247c478bd9Sstevel@tonic-gate 	 */
5425293d1fc4Spd155743 	if (i == MAX_BUCKETS) {
54267c478bd9Sstevel@tonic-gate 		hnc_unreg(tailp);
54277c478bd9Sstevel@tonic-gate 	}
54287c478bd9Sstevel@tonic-gate 
54297c478bd9Sstevel@tonic-gate 	(void) memcpy(addrbuf, nbp->buf, nbp->len);
5430293d1fc4Spd155743 	entry->addr.len = nbp->len;
5431293d1fc4Spd155743 	entry->addr.buf = addrbuf;
5432293d1fc4Spd155743 	entry->ncp = ncp;
5433293d1fc4Spd155743 	entry->h = h;
5434293d1fc4Spd155743 	entry->expire = time(NULL) + hnc_ttl;
5435293d1fc4Spd155743 
5436293d1fc4Spd155743 	/* insert it at the top */
5437293d1fc4Spd155743 	entry->next = hnc_cache[hindex];
5438293d1fc4Spd155743 	hnc_cache[hindex] = entry;
54397c478bd9Sstevel@tonic-gate 
54407c478bd9Sstevel@tonic-gate 	/*
54417c478bd9Sstevel@tonic-gate 	 * As far as cache is valid, corresponding host_list must
54427c478bd9Sstevel@tonic-gate 	 * also be valid. Increments the refcnt to avoid freeing
54437c478bd9Sstevel@tonic-gate 	 * host_list.
54447c478bd9Sstevel@tonic-gate 	 */
54457c478bd9Sstevel@tonic-gate 	h->hl_refcnt++;
54467c478bd9Sstevel@tonic-gate 	DPRINT4(9, "hnc_register(%u): reg %p onto %p for %s\n",
5447*0ea5e3a5Sjjj 		mythreadno, (void *)h, (void *)hp, hp->h->hl_hosts[0]);
5448*0ea5e3a5Sjjj 	(void) pthread_mutex_unlock(&hnc_mutex);
54497c478bd9Sstevel@tonic-gate }
54507c478bd9Sstevel@tonic-gate 
54517c478bd9Sstevel@tonic-gate static void
54527c478bd9Sstevel@tonic-gate hnc_unreg(struct hostname_cache **hpp)
54537c478bd9Sstevel@tonic-gate {
54547c478bd9Sstevel@tonic-gate 	struct hostname_cache *hp = *hpp;
54557c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
54567c478bd9Sstevel@tonic-gate 
54577c478bd9Sstevel@tonic-gate 	if (Debug) {
54587c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
54597c478bd9Sstevel@tonic-gate 	}
54607c478bd9Sstevel@tonic-gate 
54617c478bd9Sstevel@tonic-gate 	DPRINT4(9, "hnc_unreg(%u): unreg %p on %p for %s\n",
5462*0ea5e3a5Sjjj 		mythreadno, (void *)hp->h, (void *)hp, hp->h->hl_hosts[0]);
54637c478bd9Sstevel@tonic-gate 	free(hp->addr.buf);
54647c478bd9Sstevel@tonic-gate 	freehl(hp->h);
54657c478bd9Sstevel@tonic-gate 
54667c478bd9Sstevel@tonic-gate 	/* unlink from active list */
54677c478bd9Sstevel@tonic-gate 	*hpp = (*hpp)->next;
54687c478bd9Sstevel@tonic-gate 
5469293d1fc4Spd155743 	free(hp);
54707c478bd9Sstevel@tonic-gate }
54717c478bd9Sstevel@tonic-gate 
54727c478bd9Sstevel@tonic-gate /*
54737c478bd9Sstevel@tonic-gate  * Once this is called, error messages through logerror() will go to
54747c478bd9Sstevel@tonic-gate  * the console immediately. Also, messages are queued into the tmpq
54757c478bd9Sstevel@tonic-gate  * to be able to later put them into inputq.
54767c478bd9Sstevel@tonic-gate  */
54777c478bd9Sstevel@tonic-gate static void
54787c478bd9Sstevel@tonic-gate disable_errorlog()
54797c478bd9Sstevel@tonic-gate {
5480*0ea5e3a5Sjjj 	(void) dataq_init(&tmpq);
54817c478bd9Sstevel@tonic-gate 
5482*0ea5e3a5Sjjj 	(void) pthread_mutex_lock(&logerror_lock);
54837c478bd9Sstevel@tonic-gate 	interrorlog = 0;
5484*0ea5e3a5Sjjj 	(void) pthread_mutex_unlock(&logerror_lock);
54857c478bd9Sstevel@tonic-gate }
54867c478bd9Sstevel@tonic-gate 
54877c478bd9Sstevel@tonic-gate /*
54887c478bd9Sstevel@tonic-gate  * Turn internal error messages to regular input stream.
54897c478bd9Sstevel@tonic-gate  * All pending messages are pulled and pushed into the regular
54907c478bd9Sstevel@tonic-gate  * input queue.
54917c478bd9Sstevel@tonic-gate  */
54927c478bd9Sstevel@tonic-gate static void
54937c478bd9Sstevel@tonic-gate enable_errorlog()
54947c478bd9Sstevel@tonic-gate {
54957c478bd9Sstevel@tonic-gate 	log_message_t *mp;
54967c478bd9Sstevel@tonic-gate 
5497*0ea5e3a5Sjjj 	(void) pthread_mutex_lock(&logerror_lock);
54987c478bd9Sstevel@tonic-gate 	interrorlog = 1;
5499*0ea5e3a5Sjjj 	(void) pthread_mutex_unlock(&logerror_lock);
55007c478bd9Sstevel@tonic-gate 
55017c478bd9Sstevel@tonic-gate 	/*
55027c478bd9Sstevel@tonic-gate 	 * push all the pending messages into inputq.
55037c478bd9Sstevel@tonic-gate 	 */
55047c478bd9Sstevel@tonic-gate 	while (dataq_dequeue(&tmpq, (void **)&mp, 1) == 0) {
55057c478bd9Sstevel@tonic-gate 		(void) dataq_enqueue(&inputq, mp);
55067c478bd9Sstevel@tonic-gate 	}
5507*0ea5e3a5Sjjj 	(void) dataq_destroy(&tmpq);
55087c478bd9Sstevel@tonic-gate }
5509293d1fc4Spd155743 
5510293d1fc4Spd155743 /*
5511293d1fc4Spd155743  * Generate a hash value of the given address and derive
5512293d1fc4Spd155743  * an index into the hnc_cache hashtable.
5513293d1fc4Spd155743  * The hashing method is similar to what Java does for strings.
5514293d1fc4Spd155743  */
5515293d1fc4Spd155743 static int
5516293d1fc4Spd155743 addr_hash(struct netbuf *nbp)
5517293d1fc4Spd155743 {
5518293d1fc4Spd155743 	char *uap;
5519293d1fc4Spd155743 	int i;
5520293d1fc4Spd155743 	unsigned long hcode = 0;
5521293d1fc4Spd155743 
5522293d1fc4Spd155743 	uap = nbp->buf;
5523293d1fc4Spd155743 
5524293d1fc4Spd155743 	if (uap == NULL) {
5525293d1fc4Spd155743 		return (0);
5526293d1fc4Spd155743 	}
5527293d1fc4Spd155743 
5528293d1fc4Spd155743 	/*
5529293d1fc4Spd155743 	 * Compute a hashcode of the address string
5530293d1fc4Spd155743 	 */
5531293d1fc4Spd155743 	for (i = 0; i < nbp->len; i++)
5532293d1fc4Spd155743 		hcode = (31 * hcode) + uap[i];
5533293d1fc4Spd155743 
5534293d1fc4Spd155743 	/*
5535293d1fc4Spd155743 	 * Scramble the hashcode for better distribution
5536293d1fc4Spd155743 	 */
5537293d1fc4Spd155743 	hcode += ~(hcode << 9);
5538293d1fc4Spd155743 	hcode ^=  (hcode >> 14);
5539293d1fc4Spd155743 	hcode +=  (hcode << 4);
5540293d1fc4Spd155743 	hcode ^=  (hcode >> 10);
5541293d1fc4Spd155743 
5542293d1fc4Spd155743 	return ((int)(hcode % hnc_size));
5543293d1fc4Spd155743 }
5544