xref: /titanic_50/usr/src/cmd/syslogd/syslogd.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*
28*7c478bd9Sstevel@tonic-gate  *	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T
29*7c478bd9Sstevel@tonic-gate  *	All Rights Reserved
30*7c478bd9Sstevel@tonic-gate  */
31*7c478bd9Sstevel@tonic-gate 
32*7c478bd9Sstevel@tonic-gate /*
33*7c478bd9Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
34*7c478bd9Sstevel@tonic-gate  * The Regents of the University of California
35*7c478bd9Sstevel@tonic-gate  * All Rights Reserved
36*7c478bd9Sstevel@tonic-gate  *
37*7c478bd9Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
38*7c478bd9Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
39*7c478bd9Sstevel@tonic-gate  * contributors.
40*7c478bd9Sstevel@tonic-gate  */
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate /*
45*7c478bd9Sstevel@tonic-gate  *  syslogd -- log system messages
46*7c478bd9Sstevel@tonic-gate  *
47*7c478bd9Sstevel@tonic-gate  * This program implements a system log. It takes a series of lines.
48*7c478bd9Sstevel@tonic-gate  * Each line may have a priority, signified as "<n>" as
49*7c478bd9Sstevel@tonic-gate  * the first characters of the line.  If this is
50*7c478bd9Sstevel@tonic-gate  * not present, a default priority is used.
51*7c478bd9Sstevel@tonic-gate  *
52*7c478bd9Sstevel@tonic-gate  * To kill syslogd, send a signal 15 (terminate).  A signal 1 (hup) will
53*7c478bd9Sstevel@tonic-gate  * cause it to reconfigure.
54*7c478bd9Sstevel@tonic-gate  *
55*7c478bd9Sstevel@tonic-gate  * Defined Constants:
56*7c478bd9Sstevel@tonic-gate  *
57*7c478bd9Sstevel@tonic-gate  * MAXLINE -- the maximimum line length that can be handled.
58*7c478bd9Sstevel@tonic-gate  * DEFUPRI -- the default priority for user messages.
59*7c478bd9Sstevel@tonic-gate  * DEFSPRI -- the default priority for kernel messages.
60*7c478bd9Sstevel@tonic-gate  *
61*7c478bd9Sstevel@tonic-gate  */
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate #include <unistd.h>
64*7c478bd9Sstevel@tonic-gate #include <note.h>
65*7c478bd9Sstevel@tonic-gate #include <errno.h>
66*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
67*7c478bd9Sstevel@tonic-gate #include <stdio.h>
68*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
69*7c478bd9Sstevel@tonic-gate #include <ctype.h>
70*7c478bd9Sstevel@tonic-gate #include <signal.h>
71*7c478bd9Sstevel@tonic-gate #include <string.h>
72*7c478bd9Sstevel@tonic-gate #include <strings.h>
73*7c478bd9Sstevel@tonic-gate #include <deflt.h>
74*7c478bd9Sstevel@tonic-gate #include <netconfig.h>
75*7c478bd9Sstevel@tonic-gate #include <netdir.h>
76*7c478bd9Sstevel@tonic-gate #include <pwd.h>
77*7c478bd9Sstevel@tonic-gate #include <sys/socket.h>
78*7c478bd9Sstevel@tonic-gate #include <tiuser.h>
79*7c478bd9Sstevel@tonic-gate #include <utmpx.h>
80*7c478bd9Sstevel@tonic-gate #include <limits.h>
81*7c478bd9Sstevel@tonic-gate #include <pthread.h>
82*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
83*7c478bd9Sstevel@tonic-gate #include <stropts.h>
84*7c478bd9Sstevel@tonic-gate #include <assert.h>
85*7c478bd9Sstevel@tonic-gate #include <sys/statvfs.h>
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
88*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
89*7c478bd9Sstevel@tonic-gate #include <sys/syslog.h>
90*7c478bd9Sstevel@tonic-gate #include <sys/strlog.h>
91*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
92*7c478bd9Sstevel@tonic-gate #include <sys/time.h>
93*7c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
94*7c478bd9Sstevel@tonic-gate #include <sys/poll.h>
95*7c478bd9Sstevel@tonic-gate #include <sys/wait.h>
96*7c478bd9Sstevel@tonic-gate #include <sys/resource.h>
97*7c478bd9Sstevel@tonic-gate #include <sys/mman.h>
98*7c478bd9Sstevel@tonic-gate #include <sys/note.h>
99*7c478bd9Sstevel@tonic-gate #include <door.h>
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate #include <wchar.h>
102*7c478bd9Sstevel@tonic-gate #include <locale.h>
103*7c478bd9Sstevel@tonic-gate #include <stdarg.h>
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate #include "dataq.h"
106*7c478bd9Sstevel@tonic-gate #include "conf.h"
107*7c478bd9Sstevel@tonic-gate #include "syslogd.h"
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate #define	DOORFILE		"/var/run/syslog_door"
110*7c478bd9Sstevel@tonic-gate #define	RELATIVE_DOORFILE	"../var/run/syslog_door"
111*7c478bd9Sstevel@tonic-gate #define	OLD_DOORFILE		"/etc/.syslog_door"
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate #define	PIDFILE			"/var/run/syslog.pid"
114*7c478bd9Sstevel@tonic-gate #define	RELATIVE_PIDFILE	"../var/run/syslog.pid"
115*7c478bd9Sstevel@tonic-gate #define	OLD_PIDFILE		"/etc/syslog.pid"
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate static char		*Version = "%I%";
118*7c478bd9Sstevel@tonic-gate static char		*LogName = "/dev/log";
119*7c478bd9Sstevel@tonic-gate static char		*ConfFile = "/etc/syslog.conf";
120*7c478bd9Sstevel@tonic-gate static char		*DflFile = "/etc/default/syslogd";
121*7c478bd9Sstevel@tonic-gate static char		ctty[] = "/dev/console";
122*7c478bd9Sstevel@tonic-gate static char		sysmsg[] = "/dev/sysmsg";
123*7c478bd9Sstevel@tonic-gate static int		DoorFd = -1;
124*7c478bd9Sstevel@tonic-gate static int		DoorCreated = 0;
125*7c478bd9Sstevel@tonic-gate static int		PidfileCreated = 0;
126*7c478bd9Sstevel@tonic-gate static char		*DoorFileName = DOORFILE;
127*7c478bd9Sstevel@tonic-gate static char		*PidFileName = PIDFILE;
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate /*
130*7c478bd9Sstevel@tonic-gate  * configuration file directives
131*7c478bd9Sstevel@tonic-gate  */
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate static struct code	PriNames[] = {
134*7c478bd9Sstevel@tonic-gate 	"panic",	LOG_EMERG,
135*7c478bd9Sstevel@tonic-gate 	"emerg",	LOG_EMERG,
136*7c478bd9Sstevel@tonic-gate 	"alert",	LOG_ALERT,
137*7c478bd9Sstevel@tonic-gate 	"crit",		LOG_CRIT,
138*7c478bd9Sstevel@tonic-gate 	"err",		LOG_ERR,
139*7c478bd9Sstevel@tonic-gate 	"error",	LOG_ERR,
140*7c478bd9Sstevel@tonic-gate 	"warn",		LOG_WARNING,
141*7c478bd9Sstevel@tonic-gate 	"warning",	LOG_WARNING,
142*7c478bd9Sstevel@tonic-gate 	"notice",	LOG_NOTICE,
143*7c478bd9Sstevel@tonic-gate 	"info",		LOG_INFO,
144*7c478bd9Sstevel@tonic-gate 	"debug",	LOG_DEBUG,
145*7c478bd9Sstevel@tonic-gate 	"none",		NOPRI,
146*7c478bd9Sstevel@tonic-gate 	NULL,		-1
147*7c478bd9Sstevel@tonic-gate };
148*7c478bd9Sstevel@tonic-gate 
149*7c478bd9Sstevel@tonic-gate static struct code	FacNames[] = {
150*7c478bd9Sstevel@tonic-gate 	"kern",		LOG_KERN,
151*7c478bd9Sstevel@tonic-gate 	"user",		LOG_USER,
152*7c478bd9Sstevel@tonic-gate 	"mail",		LOG_MAIL,
153*7c478bd9Sstevel@tonic-gate 	"daemon",	LOG_DAEMON,
154*7c478bd9Sstevel@tonic-gate 	"auth",		LOG_AUTH,
155*7c478bd9Sstevel@tonic-gate 	"security",	LOG_AUTH,
156*7c478bd9Sstevel@tonic-gate 	"mark",		LOG_MARK,
157*7c478bd9Sstevel@tonic-gate 	"syslog",	LOG_SYSLOG,
158*7c478bd9Sstevel@tonic-gate 	"lpr",		LOG_LPR,
159*7c478bd9Sstevel@tonic-gate 	"news",		LOG_NEWS,
160*7c478bd9Sstevel@tonic-gate 	"uucp",		LOG_UUCP,
161*7c478bd9Sstevel@tonic-gate 	"audit",	LOG_AUDIT,
162*7c478bd9Sstevel@tonic-gate 	"cron",		LOG_CRON,
163*7c478bd9Sstevel@tonic-gate 	"local0",	LOG_LOCAL0,
164*7c478bd9Sstevel@tonic-gate 	"local1",	LOG_LOCAL1,
165*7c478bd9Sstevel@tonic-gate 	"local2",	LOG_LOCAL2,
166*7c478bd9Sstevel@tonic-gate 	"local3",	LOG_LOCAL3,
167*7c478bd9Sstevel@tonic-gate 	"local4",	LOG_LOCAL4,
168*7c478bd9Sstevel@tonic-gate 	"local5",	LOG_LOCAL5,
169*7c478bd9Sstevel@tonic-gate 	"local6",	LOG_LOCAL6,
170*7c478bd9Sstevel@tonic-gate 	"local7",	LOG_LOCAL7,
171*7c478bd9Sstevel@tonic-gate 	NULL,		-1
172*7c478bd9Sstevel@tonic-gate };
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate static char		*TypeNames[7] = {
175*7c478bd9Sstevel@tonic-gate 	"UNUSED",	"FILE",		"TTY",		"CONSOLE",
176*7c478bd9Sstevel@tonic-gate 	"FORW",		"USERS",	"WALL"
177*7c478bd9Sstevel@tonic-gate };
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate /*
180*7c478bd9Sstevel@tonic-gate  * we allocate our own thread stacks so we can create them
181*7c478bd9Sstevel@tonic-gate  * without the MAP_NORESERVE option. We need to be sure
182*7c478bd9Sstevel@tonic-gate  * we have stack space even if the machine runs out of swap
183*7c478bd9Sstevel@tonic-gate  */
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate #define	DEFAULT_STACKSIZE (100 * 1024)  /* 100 k stack */
186*7c478bd9Sstevel@tonic-gate #define	DEFAULT_REDZONESIZE (8 * 1024)	/* 8k redzone */
187*7c478bd9Sstevel@tonic-gate 
188*7c478bd9Sstevel@tonic-gate static pthread_mutex_t wmp = PTHREAD_MUTEX_INITIALIZER;	/* wallmsg lock */
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate static pthread_mutex_t cft = PTHREAD_MUTEX_INITIALIZER;
191*7c478bd9Sstevel@tonic-gate static int conf_threads = 0;
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate static pthread_mutex_t hup_lock = PTHREAD_MUTEX_INITIALIZER;
194*7c478bd9Sstevel@tonic-gate static pthread_cond_t hup_done = PTHREAD_COND_INITIALIZER;
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate static pthread_mutex_t logerror_lock = PTHREAD_MUTEX_INITIALIZER;
197*7c478bd9Sstevel@tonic-gate 
198*7c478bd9Sstevel@tonic-gate #define	HUP_ACCEPTABLE		0x0000	/* can start SIGHUP process */
199*7c478bd9Sstevel@tonic-gate #define	HUP_INPROGRESS		0x0001	/* SIGHUP process in progress */
200*7c478bd9Sstevel@tonic-gate #define	HUP_COMPLETED		0x0002	/* SIGHUP process completed */
201*7c478bd9Sstevel@tonic-gate #define	HUP_SUSP_LOGMSG_REQD	0x1000	/* request to suspend */
202*7c478bd9Sstevel@tonic-gate #define	HUP_LOGMSG_SUSPENDED	0x2000	/* logmsg is suspended */
203*7c478bd9Sstevel@tonic-gate static int hup_state = HUP_ACCEPTABLE;
204*7c478bd9Sstevel@tonic-gate 
205*7c478bd9Sstevel@tonic-gate static size_t stacksize;		/* thread stack size */
206*7c478bd9Sstevel@tonic-gate static size_t redzonesize;		/* thread stack redzone size */
207*7c478bd9Sstevel@tonic-gate static char *stack_ptr;			/* ptr to allocated stacks */
208*7c478bd9Sstevel@tonic-gate static char *cstack_ptr;		/* ptr to conf_thr stacks */
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate static time_t start_time;
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate static pthread_t sys_thread;		/* queues messages from us */
213*7c478bd9Sstevel@tonic-gate static pthread_t net_thread;		/* queues messages from the net */
214*7c478bd9Sstevel@tonic-gate static pthread_t log_thread;		/* message processing thread */
215*7c478bd9Sstevel@tonic-gate static pthread_t hnl_thread;		/* hostname lookup thread */
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate static dataq_t inputq;			/* the input queue */
218*7c478bd9Sstevel@tonic-gate static dataq_t tmpq;			/* temporary queue for err msg */
219*7c478bd9Sstevel@tonic-gate static dataq_t hnlq;			/* hostname lookup queue */
220*7c478bd9Sstevel@tonic-gate 
221*7c478bd9Sstevel@tonic-gate static struct filed fallback[2];
222*7c478bd9Sstevel@tonic-gate static struct filed *Files;
223*7c478bd9Sstevel@tonic-gate static int nlogs;
224*7c478bd9Sstevel@tonic-gate static int Debug;			/* debug flag */
225*7c478bd9Sstevel@tonic-gate static host_list_t LocalHostName;	/* our hostname */
226*7c478bd9Sstevel@tonic-gate static host_list_t NullHostName;	/* in case of lookup failure */
227*7c478bd9Sstevel@tonic-gate static int debuglev = 1;		/* debug print level */
228*7c478bd9Sstevel@tonic-gate static int interrorlog;			/* internal error logging */
229*7c478bd9Sstevel@tonic-gate 
230*7c478bd9Sstevel@tonic-gate static int MarkInterval = 20;		/* interval between marks (mins) */
231*7c478bd9Sstevel@tonic-gate static int Marking = 0;			/* non-zero if marking some file */
232*7c478bd9Sstevel@tonic-gate static int Ninputs = 0;			/* number of network inputs */
233*7c478bd9Sstevel@tonic-gate static int curalarm = 0;		/* current timeout value (secs) */
234*7c478bd9Sstevel@tonic-gate static int sys_msg_count = 0;		/* total msgs rcvd from local log */
235*7c478bd9Sstevel@tonic-gate static int sys_init_msg_count = 0;	/* initially received */
236*7c478bd9Sstevel@tonic-gate static int net_msg_count = 0;		/* total msgs rcvd from net */
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate static struct pollfd Pfd;		/* Pollfd for local the log device */
239*7c478bd9Sstevel@tonic-gate static struct pollfd *Nfd;		/* Array of pollfds for udp ports */
240*7c478bd9Sstevel@tonic-gate static struct netconfig *Ncf;
241*7c478bd9Sstevel@tonic-gate static struct netbuf **Myaddrs;
242*7c478bd9Sstevel@tonic-gate static struct t_unitdata **Udp;
243*7c478bd9Sstevel@tonic-gate static struct t_uderr **Errp;
244*7c478bd9Sstevel@tonic-gate static int turnoff = 0;
245*7c478bd9Sstevel@tonic-gate static int shutting_down;
246*7c478bd9Sstevel@tonic-gate 
247*7c478bd9Sstevel@tonic-gate static struct hostname_cache *hnc_cache, *hnc_active, *hnc_freeq;
248*7c478bd9Sstevel@tonic-gate static pthread_mutex_t hnc_mutex = PTHREAD_MUTEX_INITIALIZER;
249*7c478bd9Sstevel@tonic-gate static size_t hnc_size = DEF_HNC_SIZE;
250*7c478bd9Sstevel@tonic-gate static unsigned int hnc_ttl = DEF_HNC_TTL;
251*7c478bd9Sstevel@tonic-gate 
252*7c478bd9Sstevel@tonic-gate #define	DPRINT0(d, m)		if ((Debug) && debuglev >= (d)) \
253*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, m)
254*7c478bd9Sstevel@tonic-gate #define	DPRINT1(d, m, a)	if ((Debug) && debuglev >= (d)) \
255*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, m, a)
256*7c478bd9Sstevel@tonic-gate #define	DPRINT2(d, m, a, b)	if ((Debug) && debuglev >= (d)) \
257*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, m, a, b)
258*7c478bd9Sstevel@tonic-gate #define	DPRINT3(d, m, a, b, c)	if ((Debug) && debuglev >= (d)) \
259*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, m, a, b, c)
260*7c478bd9Sstevel@tonic-gate #define	DPRINT4(d, m, a, b, c, e)	if ((Debug) && debuglev >= (d)) \
261*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, m, a, b, c, e)
262*7c478bd9Sstevel@tonic-gate #define	MALLOC_FAIL(x)	\
263*7c478bd9Sstevel@tonic-gate 		logerror("malloc failed: " x)
264*7c478bd9Sstevel@tonic-gate #define	MALLOC_FAIL_EXIT	\
265*7c478bd9Sstevel@tonic-gate 		logerror("malloc failed - fatal"); \
266*7c478bd9Sstevel@tonic-gate 		exit(1)
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate #define	MAILCMD "mailx -s \"syslogd shut down\" root"
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate /*
272*7c478bd9Sstevel@tonic-gate  * Number of seconds to wait before giving up on threads that won't
273*7c478bd9Sstevel@tonic-gate  * shutdown: (that's right, 10 minutes!)
274*7c478bd9Sstevel@tonic-gate  */
275*7c478bd9Sstevel@tonic-gate #define	LOOP_MAX	(10 * 60)
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate /*
278*7c478bd9Sstevel@tonic-gate  * Interval(sec) to check the status of output queue while processing
279*7c478bd9Sstevel@tonic-gate  * HUP signal.
280*7c478bd9Sstevel@tonic-gate  */
281*7c478bd9Sstevel@tonic-gate #define	LOOP_INTERVAL	(15)
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate int
284*7c478bd9Sstevel@tonic-gate main(int argc, char **argv)
285*7c478bd9Sstevel@tonic-gate {
286*7c478bd9Sstevel@tonic-gate 	int i;
287*7c478bd9Sstevel@tonic-gate 	char *pstr;
288*7c478bd9Sstevel@tonic-gate 	int sig, fd;
289*7c478bd9Sstevel@tonic-gate 	int tflag = 0, Tflag = 0;
290*7c478bd9Sstevel@tonic-gate 	sigset_t sigs, allsigs;
291*7c478bd9Sstevel@tonic-gate 	struct rlimit rlim;
292*7c478bd9Sstevel@tonic-gate 	char *debugstr;
293*7c478bd9Sstevel@tonic-gate 	int mcount = 0;
294*7c478bd9Sstevel@tonic-gate 	struct sigaction act;
295*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno = 0;
296*7c478bd9Sstevel@tonic-gate 	char cbuf [30];
297*7c478bd9Sstevel@tonic-gate 	struct stat sb;
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
300*7c478bd9Sstevel@tonic-gate #define	DEBUGDIR "/var/tmp"
301*7c478bd9Sstevel@tonic-gate 	if (chdir(DEBUGDIR))
302*7c478bd9Sstevel@tonic-gate 		DPRINT2(1, "main(%u): Unable to cd to %s\n", mythreadno,
303*7c478bd9Sstevel@tonic-gate 			DEBUGDIR);
304*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */
305*7c478bd9Sstevel@tonic-gate 
306*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate 	if ((debugstr = getenv("SYSLOGD_DEBUG")) != NULL)
309*7c478bd9Sstevel@tonic-gate 		if ((debuglev = atoi(debugstr)) == 0)
310*7c478bd9Sstevel@tonic-gate 			debuglev = 1;
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate #if ! defined(TEXT_DOMAIN)	/* should be defined by cc -D */
313*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
314*7c478bd9Sstevel@tonic-gate #endif
315*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate 	(void) time(&start_time);
318*7c478bd9Sstevel@tonic-gate 
319*7c478bd9Sstevel@tonic-gate 	if (lstat("/var/run", &sb) != 0 || !(S_ISDIR(sb.st_mode))) {
320*7c478bd9Sstevel@tonic-gate 		DoorFileName = OLD_DOORFILE;
321*7c478bd9Sstevel@tonic-gate 		PidFileName  = OLD_PIDFILE;
322*7c478bd9Sstevel@tonic-gate 	}
323*7c478bd9Sstevel@tonic-gate 
324*7c478bd9Sstevel@tonic-gate 	defaults();
325*7c478bd9Sstevel@tonic-gate 
326*7c478bd9Sstevel@tonic-gate 	while ((i = getopt(argc, argv, "df:p:m:tT")) != EOF) {
327*7c478bd9Sstevel@tonic-gate 		switch (i) {
328*7c478bd9Sstevel@tonic-gate 		case 'f':		/* configuration file */
329*7c478bd9Sstevel@tonic-gate 			ConfFile = optarg;
330*7c478bd9Sstevel@tonic-gate 			break;
331*7c478bd9Sstevel@tonic-gate 
332*7c478bd9Sstevel@tonic-gate 		case 'd':		/* debug */
333*7c478bd9Sstevel@tonic-gate 			Debug++;
334*7c478bd9Sstevel@tonic-gate 			break;
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate 		case 'p':		/* path */
337*7c478bd9Sstevel@tonic-gate 			LogName = optarg;
338*7c478bd9Sstevel@tonic-gate 			break;
339*7c478bd9Sstevel@tonic-gate 
340*7c478bd9Sstevel@tonic-gate 		case 'm':		/* mark interval */
341*7c478bd9Sstevel@tonic-gate 			for (pstr = optarg; *pstr; pstr++) {
342*7c478bd9Sstevel@tonic-gate 				if (! (isdigit(*pstr))) {
343*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
344*7c478bd9Sstevel@tonic-gate 						"Illegal interval\n");
345*7c478bd9Sstevel@tonic-gate 					usage();
346*7c478bd9Sstevel@tonic-gate 				}
347*7c478bd9Sstevel@tonic-gate 			}
348*7c478bd9Sstevel@tonic-gate 			MarkInterval = atoi(optarg);
349*7c478bd9Sstevel@tonic-gate 			if (MarkInterval < 1 || MarkInterval > INT_MAX) {
350*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
351*7c478bd9Sstevel@tonic-gate 					"Interval must be between 1 and %d\n",
352*7c478bd9Sstevel@tonic-gate 					INT_MAX);
353*7c478bd9Sstevel@tonic-gate 				usage();
354*7c478bd9Sstevel@tonic-gate 			}
355*7c478bd9Sstevel@tonic-gate 			break;
356*7c478bd9Sstevel@tonic-gate 		case 't':		/* turn off remote reception */
357*7c478bd9Sstevel@tonic-gate 			tflag++;
358*7c478bd9Sstevel@tonic-gate 			turnoff++;
359*7c478bd9Sstevel@tonic-gate 			break;
360*7c478bd9Sstevel@tonic-gate 		case 'T':		/* turn on remote reception */
361*7c478bd9Sstevel@tonic-gate 			Tflag++;
362*7c478bd9Sstevel@tonic-gate 			turnoff = 0;
363*7c478bd9Sstevel@tonic-gate 			break;
364*7c478bd9Sstevel@tonic-gate 		default:
365*7c478bd9Sstevel@tonic-gate 			usage();
366*7c478bd9Sstevel@tonic-gate 		}
367*7c478bd9Sstevel@tonic-gate 	}
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate 	if (optind < argc)
370*7c478bd9Sstevel@tonic-gate 		usage();
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate 	if (tflag && Tflag) {
373*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "specify only one of -t and -T\n");
374*7c478bd9Sstevel@tonic-gate 		usage();
375*7c478bd9Sstevel@tonic-gate 	}
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate 	/*
378*7c478bd9Sstevel@tonic-gate 	 * close all fd's except 0-2
379*7c478bd9Sstevel@tonic-gate 	 */
380*7c478bd9Sstevel@tonic-gate 
381*7c478bd9Sstevel@tonic-gate 	closefrom(3);
382*7c478bd9Sstevel@tonic-gate 
383*7c478bd9Sstevel@tonic-gate 	if (!Debug) {
384*7c478bd9Sstevel@tonic-gate 		if (fork())
385*7c478bd9Sstevel@tonic-gate 			return (0);
386*7c478bd9Sstevel@tonic-gate 		(void) close(0);
387*7c478bd9Sstevel@tonic-gate 		(void) open("/", 0);
388*7c478bd9Sstevel@tonic-gate 		(void) dup2(0, 1);
389*7c478bd9Sstevel@tonic-gate 		(void) dup2(0, 2);
390*7c478bd9Sstevel@tonic-gate 		untty();
391*7c478bd9Sstevel@tonic-gate 	}
392*7c478bd9Sstevel@tonic-gate 
393*7c478bd9Sstevel@tonic-gate 	if (Debug) {
394*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
395*7c478bd9Sstevel@tonic-gate 	}
396*7c478bd9Sstevel@tonic-gate 
397*7c478bd9Sstevel@tonic-gate 	/*
398*7c478bd9Sstevel@tonic-gate 	 * DO NOT call logerror() until tmpq is initialized.
399*7c478bd9Sstevel@tonic-gate 	 */
400*7c478bd9Sstevel@tonic-gate 	disable_errorlog();
401*7c478bd9Sstevel@tonic-gate 
402*7c478bd9Sstevel@tonic-gate 	/*
403*7c478bd9Sstevel@tonic-gate 	 * ensure that file descriptor limit is "high enough"
404*7c478bd9Sstevel@tonic-gate 	 */
405*7c478bd9Sstevel@tonic-gate 	(void) getrlimit(RLIMIT_NOFILE, &rlim);
406*7c478bd9Sstevel@tonic-gate 	if (rlim.rlim_cur < rlim.rlim_max)
407*7c478bd9Sstevel@tonic-gate 		rlim.rlim_cur = rlim.rlim_max;
408*7c478bd9Sstevel@tonic-gate 	if (setrlimit(RLIMIT_NOFILE, &rlim) < 0)
409*7c478bd9Sstevel@tonic-gate 		logerror("Unable to increase file descriptor limit.");
410*7c478bd9Sstevel@tonic-gate 
411*7c478bd9Sstevel@tonic-gate 	/* block all signals from all threads initially */
412*7c478bd9Sstevel@tonic-gate 	(void) sigfillset(&allsigs);
413*7c478bd9Sstevel@tonic-gate 	(void) pthread_sigmask(SIG_BLOCK, &allsigs, NULL);
414*7c478bd9Sstevel@tonic-gate 
415*7c478bd9Sstevel@tonic-gate 	DPRINT2(1, "main(%u): Started at time %s", mythreadno,
416*7c478bd9Sstevel@tonic-gate 		ctime_r(&start_time, cbuf));
417*7c478bd9Sstevel@tonic-gate 
418*7c478bd9Sstevel@tonic-gate 	init();			/* read configuration, start threads */
419*7c478bd9Sstevel@tonic-gate 
420*7c478bd9Sstevel@tonic-gate 	DPRINT1(1, "main(%u): off & running....\n", mythreadno);
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate 	/* now set up to catch signals we care about */
423*7c478bd9Sstevel@tonic-gate 
424*7c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&sigs);
425*7c478bd9Sstevel@tonic-gate 	(void) sigaddset(&sigs, SIGHUP);	/* reconfigure */
426*7c478bd9Sstevel@tonic-gate 	(void) sigaddset(&sigs, SIGALRM);	/* mark & flush timer */
427*7c478bd9Sstevel@tonic-gate 	(void) sigaddset(&sigs, SIGTERM);	/* exit */
428*7c478bd9Sstevel@tonic-gate 	(void) sigaddset(&sigs, SIGINT);	/* exit if debugging */
429*7c478bd9Sstevel@tonic-gate 	(void) sigaddset(&sigs, SIGQUIT);	/* exit if debugging */
430*7c478bd9Sstevel@tonic-gate 	(void) sigaddset(&sigs, SIGPIPE);	/* catch & discard */
431*7c478bd9Sstevel@tonic-gate 	(void) sigaddset(&sigs, SIGUSR1);	/* dump debug stats */
432*7c478bd9Sstevel@tonic-gate 
433*7c478bd9Sstevel@tonic-gate 	/*
434*7c478bd9Sstevel@tonic-gate 	 * We must set up to catch these signals, even though sigwait
435*7c478bd9Sstevel@tonic-gate 	 * will get them before the isr does.  Setting SA_SIGINFO ensures
436*7c478bd9Sstevel@tonic-gate 	 * that signals will be enqueued.
437*7c478bd9Sstevel@tonic-gate 	 */
438*7c478bd9Sstevel@tonic-gate 
439*7c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
440*7c478bd9Sstevel@tonic-gate 	act.sa_sigaction = signull;
441*7c478bd9Sstevel@tonic-gate 
442*7c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGHUP, &act, NULL);
443*7c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGALRM, &act, NULL);
444*7c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGTERM, &act, NULL);
445*7c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGINT, &act, NULL);
446*7c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGQUIT, &act, NULL);
447*7c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGPIPE, &act, NULL);
448*7c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGUSR1, &act, NULL);
449*7c478bd9Sstevel@tonic-gate 
450*7c478bd9Sstevel@tonic-gate 	/* we now turn into the signal handling thread */
451*7c478bd9Sstevel@tonic-gate 
452*7c478bd9Sstevel@tonic-gate 	DPRINT1(2, "main(%u): now handling signals\n", mythreadno);
453*7c478bd9Sstevel@tonic-gate 	for (;;) {
454*7c478bd9Sstevel@tonic-gate 		(void) sigwait(&sigs, &sig);
455*7c478bd9Sstevel@tonic-gate 		DPRINT2(2, "main(%u): received signal %d\n", mythreadno, sig);
456*7c478bd9Sstevel@tonic-gate 		switch (sig) {
457*7c478bd9Sstevel@tonic-gate 		case SIGALRM:
458*7c478bd9Sstevel@tonic-gate 			DPRINT1(1, "main(%u): Got SIGALRM\n",
459*7c478bd9Sstevel@tonic-gate 				mythreadno);
460*7c478bd9Sstevel@tonic-gate 			flushmsg(NOCOPY);
461*7c478bd9Sstevel@tonic-gate 			if (Marking && (++mcount % MARKCOUNT == 0)) {
462*7c478bd9Sstevel@tonic-gate 				if (logmymsg(LOG_INFO, "-- MARK --",
463*7c478bd9Sstevel@tonic-gate 					ADDDATE|MARK|NOCOPY, 0) == -1) {
464*7c478bd9Sstevel@tonic-gate 					MALLOC_FAIL(
465*7c478bd9Sstevel@tonic-gate 						"dropping MARK message");
466*7c478bd9Sstevel@tonic-gate 				}
467*7c478bd9Sstevel@tonic-gate 
468*7c478bd9Sstevel@tonic-gate 				mcount = 0;
469*7c478bd9Sstevel@tonic-gate 			}
470*7c478bd9Sstevel@tonic-gate 			curalarm = MarkInterval * 60 / MARKCOUNT;
471*7c478bd9Sstevel@tonic-gate 			(void) alarm((unsigned)curalarm);
472*7c478bd9Sstevel@tonic-gate 			DPRINT2(2, "main(%u): Next alarm in %d "
473*7c478bd9Sstevel@tonic-gate 				"seconds\n", mythreadno, curalarm);
474*7c478bd9Sstevel@tonic-gate 			break;
475*7c478bd9Sstevel@tonic-gate 		case SIGHUP:
476*7c478bd9Sstevel@tonic-gate 			DPRINT1(1, "main(%u): got SIGHUP - "
477*7c478bd9Sstevel@tonic-gate 				"reconfiguring\n", mythreadno);
478*7c478bd9Sstevel@tonic-gate 
479*7c478bd9Sstevel@tonic-gate 			reconfigure();
480*7c478bd9Sstevel@tonic-gate 
481*7c478bd9Sstevel@tonic-gate 			DPRINT1(1, "main(%u): done processing SIGHUP\n",
482*7c478bd9Sstevel@tonic-gate 				mythreadno);
483*7c478bd9Sstevel@tonic-gate 			break;
484*7c478bd9Sstevel@tonic-gate 		case SIGQUIT:
485*7c478bd9Sstevel@tonic-gate 		case SIGINT:
486*7c478bd9Sstevel@tonic-gate 			if (!Debug) {
487*7c478bd9Sstevel@tonic-gate 				/* allow these signals if debugging */
488*7c478bd9Sstevel@tonic-gate 				break;
489*7c478bd9Sstevel@tonic-gate 			}
490*7c478bd9Sstevel@tonic-gate 			/* FALLTHROUGH */
491*7c478bd9Sstevel@tonic-gate 		case SIGTERM:
492*7c478bd9Sstevel@tonic-gate 			DPRINT2(1, "main(%u): going down on signal %d\n",
493*7c478bd9Sstevel@tonic-gate 				mythreadno, sig);
494*7c478bd9Sstevel@tonic-gate 			(void) alarm(0);
495*7c478bd9Sstevel@tonic-gate 			flushmsg(0);
496*7c478bd9Sstevel@tonic-gate 			errno = 0;
497*7c478bd9Sstevel@tonic-gate 			t_errno = 0;
498*7c478bd9Sstevel@tonic-gate 			logerror("going down on signal %d", sig);
499*7c478bd9Sstevel@tonic-gate 			disable_errorlog();	/* force msg to console */
500*7c478bd9Sstevel@tonic-gate 			(void) shutdown_msg();	/* stop threads */
501*7c478bd9Sstevel@tonic-gate 			shutdown_input();
502*7c478bd9Sstevel@tonic-gate 			close_door();
503*7c478bd9Sstevel@tonic-gate 			delete_doorfiles();
504*7c478bd9Sstevel@tonic-gate 			return (0);
505*7c478bd9Sstevel@tonic-gate 			break;
506*7c478bd9Sstevel@tonic-gate 		case SIGUSR1:			/* secret debug dump mode */
507*7c478bd9Sstevel@tonic-gate 			/* if in debug mode, use stdout */
508*7c478bd9Sstevel@tonic-gate 
509*7c478bd9Sstevel@tonic-gate 			if (Debug) {
510*7c478bd9Sstevel@tonic-gate 				dumpstats(STDOUT_FILENO);
511*7c478bd9Sstevel@tonic-gate 				break;
512*7c478bd9Sstevel@tonic-gate 			}
513*7c478bd9Sstevel@tonic-gate 			/* otherwise dump to a debug file */
514*7c478bd9Sstevel@tonic-gate 			if ((fd = open(DEBUGFILE,
515*7c478bd9Sstevel@tonic-gate 				(O_WRONLY|O_CREAT|O_TRUNC|O_EXCL),
516*7c478bd9Sstevel@tonic-gate 					0644)) < 0)
517*7c478bd9Sstevel@tonic-gate 				break;
518*7c478bd9Sstevel@tonic-gate 			dumpstats(fd);
519*7c478bd9Sstevel@tonic-gate 			(void) close(fd);
520*7c478bd9Sstevel@tonic-gate 			break;
521*7c478bd9Sstevel@tonic-gate 		default:
522*7c478bd9Sstevel@tonic-gate 			DPRINT2(2, "main(%u): unexpected signal %d\n",
523*7c478bd9Sstevel@tonic-gate 				mythreadno, sig);
524*7c478bd9Sstevel@tonic-gate 			break;
525*7c478bd9Sstevel@tonic-gate 		}
526*7c478bd9Sstevel@tonic-gate 	}
527*7c478bd9Sstevel@tonic-gate }
528*7c478bd9Sstevel@tonic-gate 
529*7c478bd9Sstevel@tonic-gate /*
530*7c478bd9Sstevel@tonic-gate  * Attempts to open the local log device
531*7c478bd9Sstevel@tonic-gate  * and return a file descriptor.
532*7c478bd9Sstevel@tonic-gate  */
533*7c478bd9Sstevel@tonic-gate static int
534*7c478bd9Sstevel@tonic-gate openklog(char *name, int mode)
535*7c478bd9Sstevel@tonic-gate {
536*7c478bd9Sstevel@tonic-gate 	int fd;
537*7c478bd9Sstevel@tonic-gate 	struct strioctl str;
538*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
539*7c478bd9Sstevel@tonic-gate 
540*7c478bd9Sstevel@tonic-gate 	if (Debug) {
541*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
542*7c478bd9Sstevel@tonic-gate 	}
543*7c478bd9Sstevel@tonic-gate 
544*7c478bd9Sstevel@tonic-gate 	if ((fd = open(name, mode)) < 0) {
545*7c478bd9Sstevel@tonic-gate 		logerror("cannot open %s", name);
546*7c478bd9Sstevel@tonic-gate 		DPRINT3(1, "openklog(%u): cannot create %s (%d)\n",
547*7c478bd9Sstevel@tonic-gate 			mythreadno, name, errno);
548*7c478bd9Sstevel@tonic-gate 		return (-1);
549*7c478bd9Sstevel@tonic-gate 	}
550*7c478bd9Sstevel@tonic-gate 	str.ic_cmd = I_CONSLOG;
551*7c478bd9Sstevel@tonic-gate 	str.ic_timout = 0;
552*7c478bd9Sstevel@tonic-gate 	str.ic_len = 0;
553*7c478bd9Sstevel@tonic-gate 	str.ic_dp = NULL;
554*7c478bd9Sstevel@tonic-gate 	if (ioctl(fd, I_STR, &str) < 0) {
555*7c478bd9Sstevel@tonic-gate 		logerror("cannot register to log console messages");
556*7c478bd9Sstevel@tonic-gate 		DPRINT2(1, "openklog(%u): cannot register to log "
557*7c478bd9Sstevel@tonic-gate 			"console messages (%d)\n", mythreadno, errno);
558*7c478bd9Sstevel@tonic-gate 		return (-1);
559*7c478bd9Sstevel@tonic-gate 	}
560*7c478bd9Sstevel@tonic-gate 	return (fd);
561*7c478bd9Sstevel@tonic-gate }
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate 
564*7c478bd9Sstevel@tonic-gate /*
565*7c478bd9Sstevel@tonic-gate  * Open the log device, and pull up all pending messages.
566*7c478bd9Sstevel@tonic-gate  */
567*7c478bd9Sstevel@tonic-gate static void
568*7c478bd9Sstevel@tonic-gate prepare_sys_poll()
569*7c478bd9Sstevel@tonic-gate {
570*7c478bd9Sstevel@tonic-gate 	int nfds, funix;
571*7c478bd9Sstevel@tonic-gate 
572*7c478bd9Sstevel@tonic-gate 	if ((funix = openklog(LogName, O_RDONLY)) < 0) {
573*7c478bd9Sstevel@tonic-gate 		logerror("can't open kernel log device - fatal");
574*7c478bd9Sstevel@tonic-gate 		exit(1);
575*7c478bd9Sstevel@tonic-gate 	}
576*7c478bd9Sstevel@tonic-gate 
577*7c478bd9Sstevel@tonic-gate 	Pfd.fd = funix;
578*7c478bd9Sstevel@tonic-gate 	Pfd.events = POLLIN;
579*7c478bd9Sstevel@tonic-gate 
580*7c478bd9Sstevel@tonic-gate 	for (;;) {
581*7c478bd9Sstevel@tonic-gate 		nfds = poll(&Pfd, 1, 0);
582*7c478bd9Sstevel@tonic-gate 		if (nfds <= 0) {
583*7c478bd9Sstevel@tonic-gate 			if (sys_init_msg_count > 0)
584*7c478bd9Sstevel@tonic-gate 				flushmsg(SYNC_FILE);
585*7c478bd9Sstevel@tonic-gate 			break;
586*7c478bd9Sstevel@tonic-gate 		}
587*7c478bd9Sstevel@tonic-gate 
588*7c478bd9Sstevel@tonic-gate 		if (Pfd.revents & POLLIN) {
589*7c478bd9Sstevel@tonic-gate 			getkmsg(0);
590*7c478bd9Sstevel@tonic-gate 		} else if (Pfd.revents & (POLLNVAL|POLLHUP|POLLERR)) {
591*7c478bd9Sstevel@tonic-gate 			logerror("kernel log driver poll error");
592*7c478bd9Sstevel@tonic-gate 			break;
593*7c478bd9Sstevel@tonic-gate 		}
594*7c478bd9Sstevel@tonic-gate 	}
595*7c478bd9Sstevel@tonic-gate 
596*7c478bd9Sstevel@tonic-gate }
597*7c478bd9Sstevel@tonic-gate 
598*7c478bd9Sstevel@tonic-gate /*
599*7c478bd9Sstevel@tonic-gate  * this thread listens to the local stream log driver for log messages
600*7c478bd9Sstevel@tonic-gate  * generated by this host, formats them, and queues them to the logger
601*7c478bd9Sstevel@tonic-gate  * thread.
602*7c478bd9Sstevel@tonic-gate  */
603*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
604*7c478bd9Sstevel@tonic-gate static void *
605*7c478bd9Sstevel@tonic-gate sys_poll(void *ap)
606*7c478bd9Sstevel@tonic-gate {
607*7c478bd9Sstevel@tonic-gate 	int nfds;
608*7c478bd9Sstevel@tonic-gate 	static int klogerrs = 0;
609*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
610*7c478bd9Sstevel@tonic-gate 
611*7c478bd9Sstevel@tonic-gate 	if (Debug) {
612*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
613*7c478bd9Sstevel@tonic-gate 	}
614*7c478bd9Sstevel@tonic-gate 
615*7c478bd9Sstevel@tonic-gate 	DPRINT1(1, "sys_poll(%u): sys_thread started\n", mythreadno);
616*7c478bd9Sstevel@tonic-gate 
617*7c478bd9Sstevel@tonic-gate 	/*
618*7c478bd9Sstevel@tonic-gate 	 * Try to process as many messages as we can without blocking on poll.
619*7c478bd9Sstevel@tonic-gate 	 * We count such "initial" messages with sys_init_msg_count and
620*7c478bd9Sstevel@tonic-gate 	 * enqueue them without the SYNC_FILE flag.  When no more data is
621*7c478bd9Sstevel@tonic-gate 	 * waiting on the local log device, we set timeout to INFTIM,
622*7c478bd9Sstevel@tonic-gate 	 * clear sys_init_msg_count, and generate a flush message to sync
623*7c478bd9Sstevel@tonic-gate 	 * the previously counted initial messages out to disk.
624*7c478bd9Sstevel@tonic-gate 	 */
625*7c478bd9Sstevel@tonic-gate 
626*7c478bd9Sstevel@tonic-gate 	sys_init_msg_count = 0;
627*7c478bd9Sstevel@tonic-gate 
628*7c478bd9Sstevel@tonic-gate 	for (;;) {
629*7c478bd9Sstevel@tonic-gate 		errno = 0;
630*7c478bd9Sstevel@tonic-gate 		t_errno = 0;
631*7c478bd9Sstevel@tonic-gate 
632*7c478bd9Sstevel@tonic-gate 		nfds = poll(&Pfd, 1, INFTIM);
633*7c478bd9Sstevel@tonic-gate 
634*7c478bd9Sstevel@tonic-gate 		if (nfds == 0)
635*7c478bd9Sstevel@tonic-gate 			continue;
636*7c478bd9Sstevel@tonic-gate 
637*7c478bd9Sstevel@tonic-gate 		if (nfds < 0) {
638*7c478bd9Sstevel@tonic-gate 			if (errno != EINTR)
639*7c478bd9Sstevel@tonic-gate 				logerror("poll");
640*7c478bd9Sstevel@tonic-gate 			continue;
641*7c478bd9Sstevel@tonic-gate 		}
642*7c478bd9Sstevel@tonic-gate 		if (Pfd.revents & POLLIN) {
643*7c478bd9Sstevel@tonic-gate 			getkmsg(INFTIM);
644*7c478bd9Sstevel@tonic-gate 		} else {
645*7c478bd9Sstevel@tonic-gate 			if (shutting_down) {
646*7c478bd9Sstevel@tonic-gate 				pthread_exit(0);
647*7c478bd9Sstevel@tonic-gate 			}
648*7c478bd9Sstevel@tonic-gate 			if (Pfd.revents & (POLLNVAL|POLLHUP|POLLERR)) {
649*7c478bd9Sstevel@tonic-gate 				logerror("kernel log driver poll error");
650*7c478bd9Sstevel@tonic-gate 				(void) close(Pfd.fd);
651*7c478bd9Sstevel@tonic-gate 				Pfd.fd = -1;
652*7c478bd9Sstevel@tonic-gate 			}
653*7c478bd9Sstevel@tonic-gate 		}
654*7c478bd9Sstevel@tonic-gate 
655*7c478bd9Sstevel@tonic-gate 		while (Pfd.fd == -1 && klogerrs++ < 10) {
656*7c478bd9Sstevel@tonic-gate 			Pfd.fd = openklog(LogName, O_RDONLY);
657*7c478bd9Sstevel@tonic-gate 		}
658*7c478bd9Sstevel@tonic-gate 		if (klogerrs >= 10) {
659*7c478bd9Sstevel@tonic-gate 			logerror("can't reopen kernel log device - fatal");
660*7c478bd9Sstevel@tonic-gate 			exit(1);
661*7c478bd9Sstevel@tonic-gate 		}
662*7c478bd9Sstevel@tonic-gate 	}
663*7c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
664*7c478bd9Sstevel@tonic-gate 	return (NULL);
665*7c478bd9Sstevel@tonic-gate }
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate /*
668*7c478bd9Sstevel@tonic-gate  * Pull up one message from log driver.
669*7c478bd9Sstevel@tonic-gate  */
670*7c478bd9Sstevel@tonic-gate static void
671*7c478bd9Sstevel@tonic-gate getkmsg(int timeout)
672*7c478bd9Sstevel@tonic-gate {
673*7c478bd9Sstevel@tonic-gate 	int flags = 0, i;
674*7c478bd9Sstevel@tonic-gate 	char *lastline;
675*7c478bd9Sstevel@tonic-gate 	struct strbuf ctl, dat;
676*7c478bd9Sstevel@tonic-gate 	struct log_ctl hdr;
677*7c478bd9Sstevel@tonic-gate 	char buf[MAXLINE+1];
678*7c478bd9Sstevel@tonic-gate 	size_t buflen;
679*7c478bd9Sstevel@tonic-gate 	size_t len;
680*7c478bd9Sstevel@tonic-gate 	char tmpbuf[MAXLINE+1];
681*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
682*7c478bd9Sstevel@tonic-gate 
683*7c478bd9Sstevel@tonic-gate 	if (Debug) {
684*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
685*7c478bd9Sstevel@tonic-gate 	}
686*7c478bd9Sstevel@tonic-gate 
687*7c478bd9Sstevel@tonic-gate 	dat.maxlen = MAXLINE;
688*7c478bd9Sstevel@tonic-gate 	dat.buf = buf;
689*7c478bd9Sstevel@tonic-gate 	ctl.maxlen = sizeof (struct log_ctl);
690*7c478bd9Sstevel@tonic-gate 	ctl.buf = (caddr_t)&hdr;
691*7c478bd9Sstevel@tonic-gate 
692*7c478bd9Sstevel@tonic-gate 	while ((i = getmsg(Pfd.fd, &ctl, &dat, &flags)) == MOREDATA) {
693*7c478bd9Sstevel@tonic-gate 		lastline = &dat.buf[dat.len];
694*7c478bd9Sstevel@tonic-gate 		*lastline = '\0';
695*7c478bd9Sstevel@tonic-gate 
696*7c478bd9Sstevel@tonic-gate 		DPRINT2(5, "sys_poll:(%u): getmsg: dat.len = %d\n",
697*7c478bd9Sstevel@tonic-gate 			mythreadno, dat.len);
698*7c478bd9Sstevel@tonic-gate 		buflen = strlen(buf);
699*7c478bd9Sstevel@tonic-gate 		len = findnl_bkwd(buf, buflen);
700*7c478bd9Sstevel@tonic-gate 
701*7c478bd9Sstevel@tonic-gate 		(void) memcpy(tmpbuf, buf, len);
702*7c478bd9Sstevel@tonic-gate 		tmpbuf[len] = '\0';
703*7c478bd9Sstevel@tonic-gate 
704*7c478bd9Sstevel@tonic-gate 		/*
705*7c478bd9Sstevel@tonic-gate 		 * Format sys will enqueue the log message.
706*7c478bd9Sstevel@tonic-gate 		 * Set the sync flag if timeout != 0, which
707*7c478bd9Sstevel@tonic-gate 		 * means that we're done handling all the
708*7c478bd9Sstevel@tonic-gate 		 * initial messages ready during startup.
709*7c478bd9Sstevel@tonic-gate 		 */
710*7c478bd9Sstevel@tonic-gate 		if (timeout == 0) {
711*7c478bd9Sstevel@tonic-gate 			formatsys(&hdr, tmpbuf, 0);
712*7c478bd9Sstevel@tonic-gate 			sys_init_msg_count++;
713*7c478bd9Sstevel@tonic-gate 		} else {
714*7c478bd9Sstevel@tonic-gate 			formatsys(&hdr, tmpbuf, 1);
715*7c478bd9Sstevel@tonic-gate 		}
716*7c478bd9Sstevel@tonic-gate 		sys_msg_count++;
717*7c478bd9Sstevel@tonic-gate 
718*7c478bd9Sstevel@tonic-gate 		if (len != buflen) {
719*7c478bd9Sstevel@tonic-gate 			/* If anything remains in buf */
720*7c478bd9Sstevel@tonic-gate 			size_t remlen;
721*7c478bd9Sstevel@tonic-gate 
722*7c478bd9Sstevel@tonic-gate 			if (buf[len] == '\n') {
723*7c478bd9Sstevel@tonic-gate 				/* skip newline */
724*7c478bd9Sstevel@tonic-gate 				len++;
725*7c478bd9Sstevel@tonic-gate 			}
726*7c478bd9Sstevel@tonic-gate 
727*7c478bd9Sstevel@tonic-gate 			/*
728*7c478bd9Sstevel@tonic-gate 			 *  Move the remaining bytes to
729*7c478bd9Sstevel@tonic-gate 			 * the beginnning of buf.
730*7c478bd9Sstevel@tonic-gate 			 */
731*7c478bd9Sstevel@tonic-gate 
732*7c478bd9Sstevel@tonic-gate 			remlen = buflen - len;
733*7c478bd9Sstevel@tonic-gate 			(void) memcpy(buf, &buf[len], remlen);
734*7c478bd9Sstevel@tonic-gate 			dat.maxlen = MAXLINE - remlen;
735*7c478bd9Sstevel@tonic-gate 			dat.buf = &buf[remlen];
736*7c478bd9Sstevel@tonic-gate 		} else {
737*7c478bd9Sstevel@tonic-gate 			dat.maxlen = MAXLINE;
738*7c478bd9Sstevel@tonic-gate 			dat.buf = buf;
739*7c478bd9Sstevel@tonic-gate 		}
740*7c478bd9Sstevel@tonic-gate 	}
741*7c478bd9Sstevel@tonic-gate 
742*7c478bd9Sstevel@tonic-gate 	if (i == 0 && dat.len > 0) {
743*7c478bd9Sstevel@tonic-gate 		dat.buf[dat.len] = '\0';
744*7c478bd9Sstevel@tonic-gate 		/*
745*7c478bd9Sstevel@tonic-gate 		 * Format sys will enqueue the log message.
746*7c478bd9Sstevel@tonic-gate 		 * Set the sync flag if timeout != 0, which
747*7c478bd9Sstevel@tonic-gate 		 * means that we're done handling all the
748*7c478bd9Sstevel@tonic-gate 		 * initial messages ready during startup.
749*7c478bd9Sstevel@tonic-gate 		 */
750*7c478bd9Sstevel@tonic-gate 		DPRINT2(5, "getkmsg(%u): getmsg: dat.maxlen = %d\n",
751*7c478bd9Sstevel@tonic-gate 			mythreadno, dat.maxlen);
752*7c478bd9Sstevel@tonic-gate 		DPRINT2(5, "getkmsg(%u): getmsg: dat.len = %d\n",
753*7c478bd9Sstevel@tonic-gate 			mythreadno, dat.len);
754*7c478bd9Sstevel@tonic-gate 		DPRINT2(5, "getkmsg(%u): getmsg: strlen(dat.buf) = %d\n",
755*7c478bd9Sstevel@tonic-gate 			mythreadno, strlen(dat.buf));
756*7c478bd9Sstevel@tonic-gate 		DPRINT2(5, "getkmsg(%u): getmsg: dat.buf = \"%s\"\n",
757*7c478bd9Sstevel@tonic-gate 			mythreadno, dat.buf);
758*7c478bd9Sstevel@tonic-gate 		DPRINT2(5, "getkmsg(%u): buf len = %d\n",
759*7c478bd9Sstevel@tonic-gate 			mythreadno, strlen(buf));
760*7c478bd9Sstevel@tonic-gate 		if (timeout == 0) {
761*7c478bd9Sstevel@tonic-gate 			formatsys(&hdr, buf, 0);
762*7c478bd9Sstevel@tonic-gate 			sys_init_msg_count++;
763*7c478bd9Sstevel@tonic-gate 		} else {
764*7c478bd9Sstevel@tonic-gate 			formatsys(&hdr, buf, 1);
765*7c478bd9Sstevel@tonic-gate 		}
766*7c478bd9Sstevel@tonic-gate 		sys_msg_count++;
767*7c478bd9Sstevel@tonic-gate 	} else if (i < 0 && errno != EINTR) {
768*7c478bd9Sstevel@tonic-gate 		if (!shutting_down) {
769*7c478bd9Sstevel@tonic-gate 			logerror("kernel log driver read error");
770*7c478bd9Sstevel@tonic-gate 		}
771*7c478bd9Sstevel@tonic-gate 		(void) close(Pfd.fd);
772*7c478bd9Sstevel@tonic-gate 		Pfd.fd = -1;
773*7c478bd9Sstevel@tonic-gate 	}
774*7c478bd9Sstevel@tonic-gate }
775*7c478bd9Sstevel@tonic-gate 
776*7c478bd9Sstevel@tonic-gate /*
777*7c478bd9Sstevel@tonic-gate  * this thread polls all the network interfaces for syslog messages
778*7c478bd9Sstevel@tonic-gate  * forwarded to us, tags them with the hostname they are received
779*7c478bd9Sstevel@tonic-gate  * from, and queues them to the logger thread.
780*7c478bd9Sstevel@tonic-gate  */
781*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
782*7c478bd9Sstevel@tonic-gate static void *
783*7c478bd9Sstevel@tonic-gate net_poll(void *ap)
784*7c478bd9Sstevel@tonic-gate {
785*7c478bd9Sstevel@tonic-gate 	int nfds, i;
786*7c478bd9Sstevel@tonic-gate 	int flags = 0;
787*7c478bd9Sstevel@tonic-gate 	struct t_unitdata *udp;
788*7c478bd9Sstevel@tonic-gate 	struct t_uderr *errp;
789*7c478bd9Sstevel@tonic-gate 	char buf[MAXLINE+1];
790*7c478bd9Sstevel@tonic-gate 	char *uap;
791*7c478bd9Sstevel@tonic-gate 	log_message_t *mp;
792*7c478bd9Sstevel@tonic-gate 	host_info_t *hinfo;
793*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
794*7c478bd9Sstevel@tonic-gate 
795*7c478bd9Sstevel@tonic-gate 	if (Debug) {
796*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
797*7c478bd9Sstevel@tonic-gate 	}
798*7c478bd9Sstevel@tonic-gate 
799*7c478bd9Sstevel@tonic-gate 	DPRINT1(1, "net_poll(%u): net_thread started\n", mythreadno);
800*7c478bd9Sstevel@tonic-gate 
801*7c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp))
802*7c478bd9Sstevel@tonic-gate 
803*7c478bd9Sstevel@tonic-gate 	for (;;) {
804*7c478bd9Sstevel@tonic-gate 		errno = 0;
805*7c478bd9Sstevel@tonic-gate 		t_errno = 0;
806*7c478bd9Sstevel@tonic-gate 		nfds = poll(Nfd, Ninputs, -1);
807*7c478bd9Sstevel@tonic-gate 		if (nfds == 0)
808*7c478bd9Sstevel@tonic-gate 			continue;
809*7c478bd9Sstevel@tonic-gate 
810*7c478bd9Sstevel@tonic-gate 		if (nfds < 0) {
811*7c478bd9Sstevel@tonic-gate 			if (errno != EINTR)
812*7c478bd9Sstevel@tonic-gate 				logerror("poll");
813*7c478bd9Sstevel@tonic-gate 			continue;
814*7c478bd9Sstevel@tonic-gate 		}
815*7c478bd9Sstevel@tonic-gate 		for (i = 0; nfds > 0 && i < Ninputs; i++) {
816*7c478bd9Sstevel@tonic-gate 			if ((Nfd[i].revents & POLLIN) == 0) {
817*7c478bd9Sstevel@tonic-gate 				if (shutting_down) {
818*7c478bd9Sstevel@tonic-gate 					pthread_exit(0);
819*7c478bd9Sstevel@tonic-gate 				}
820*7c478bd9Sstevel@tonic-gate 				if (Nfd[i].revents &
821*7c478bd9Sstevel@tonic-gate 					(POLLNVAL|POLLHUP|POLLERR)) {
822*7c478bd9Sstevel@tonic-gate 					logerror("POLLNVAL|POLLHUP|POLLERR");
823*7c478bd9Sstevel@tonic-gate 					(void) t_close(Nfd[i].fd);
824*7c478bd9Sstevel@tonic-gate 					Nfd[i].fd = -1;
825*7c478bd9Sstevel@tonic-gate 					nfds--;
826*7c478bd9Sstevel@tonic-gate 				}
827*7c478bd9Sstevel@tonic-gate 				continue;
828*7c478bd9Sstevel@tonic-gate 			}
829*7c478bd9Sstevel@tonic-gate 
830*7c478bd9Sstevel@tonic-gate 			udp = Udp[i];
831*7c478bd9Sstevel@tonic-gate 			udp->udata.buf = buf;
832*7c478bd9Sstevel@tonic-gate 			udp->udata.maxlen = MAXLINE;
833*7c478bd9Sstevel@tonic-gate 			udp->udata.len = 0;
834*7c478bd9Sstevel@tonic-gate 			flags = 0;
835*7c478bd9Sstevel@tonic-gate 			if (t_rcvudata(Nfd[i].fd, udp, &flags) < 0) {
836*7c478bd9Sstevel@tonic-gate 				errp = Errp[i];
837*7c478bd9Sstevel@tonic-gate 				if (t_errno == TLOOK) {
838*7c478bd9Sstevel@tonic-gate 					if (t_rcvuderr(Nfd[i].fd, errp) < 0) {
839*7c478bd9Sstevel@tonic-gate 						if (!shutting_down) {
840*7c478bd9Sstevel@tonic-gate 							logerror("t_rcvuderr");
841*7c478bd9Sstevel@tonic-gate 						}
842*7c478bd9Sstevel@tonic-gate 						t_close(Nfd[i].fd);
843*7c478bd9Sstevel@tonic-gate 						Nfd[i].fd = -1;
844*7c478bd9Sstevel@tonic-gate 					}
845*7c478bd9Sstevel@tonic-gate 				} else {
846*7c478bd9Sstevel@tonic-gate 					if (!shutting_down) {
847*7c478bd9Sstevel@tonic-gate 						logerror("t_rcvudata");
848*7c478bd9Sstevel@tonic-gate 					}
849*7c478bd9Sstevel@tonic-gate 					t_close(Nfd[i].fd);
850*7c478bd9Sstevel@tonic-gate 					Nfd[i].fd = -1;
851*7c478bd9Sstevel@tonic-gate 				}
852*7c478bd9Sstevel@tonic-gate 				nfds--;
853*7c478bd9Sstevel@tonic-gate 				if (shutting_down) {
854*7c478bd9Sstevel@tonic-gate 					pthread_exit(0);
855*7c478bd9Sstevel@tonic-gate 				}
856*7c478bd9Sstevel@tonic-gate 				continue;
857*7c478bd9Sstevel@tonic-gate 			}
858*7c478bd9Sstevel@tonic-gate 			nfds--;
859*7c478bd9Sstevel@tonic-gate 
860*7c478bd9Sstevel@tonic-gate 			if (udp->udata.len == 0) {
861*7c478bd9Sstevel@tonic-gate 				if (Debug) {
862*7c478bd9Sstevel@tonic-gate 					uap = NULL;
863*7c478bd9Sstevel@tonic-gate 					if (udp->addr.len > 0) {
864*7c478bd9Sstevel@tonic-gate 						uap = taddr2uaddr(&Ncf[i],
865*7c478bd9Sstevel@tonic-gate 							&udp->addr);
866*7c478bd9Sstevel@tonic-gate 					}
867*7c478bd9Sstevel@tonic-gate 					DPRINT2(1, "net_poll(%u):"
868*7c478bd9Sstevel@tonic-gate 						" received empty packet"
869*7c478bd9Sstevel@tonic-gate 						" from %s\n", mythreadno,
870*7c478bd9Sstevel@tonic-gate 						uap ? uap : "<unknown>");
871*7c478bd9Sstevel@tonic-gate 					if (uap)
872*7c478bd9Sstevel@tonic-gate 						free(uap);
873*7c478bd9Sstevel@tonic-gate 				}
874*7c478bd9Sstevel@tonic-gate 				continue;	/* No data */
875*7c478bd9Sstevel@tonic-gate 			}
876*7c478bd9Sstevel@tonic-gate 			if (udp->addr.len == 0) {
877*7c478bd9Sstevel@tonic-gate 				/*
878*7c478bd9Sstevel@tonic-gate 				 * The previous message was larger than
879*7c478bd9Sstevel@tonic-gate 				 * MAXLINE, and T_MORE should have been set.
880*7c478bd9Sstevel@tonic-gate 				 * Further data needs to be discarded as
881*7c478bd9Sstevel@tonic-gate 				 * we've already received MAXLINE.
882*7c478bd9Sstevel@tonic-gate 				 */
883*7c478bd9Sstevel@tonic-gate 				DPRINT1(1, "net_poll(%u): discarding packet "
884*7c478bd9Sstevel@tonic-gate 					"exceeds max line size\n", mythreadno);
885*7c478bd9Sstevel@tonic-gate 				continue;
886*7c478bd9Sstevel@tonic-gate 			}
887*7c478bd9Sstevel@tonic-gate 
888*7c478bd9Sstevel@tonic-gate 			net_msg_count++;
889*7c478bd9Sstevel@tonic-gate 
890*7c478bd9Sstevel@tonic-gate 			if ((mp = new_msg()) == NULL) {
891*7c478bd9Sstevel@tonic-gate 				MALLOC_FAIL("dropping message from "
892*7c478bd9Sstevel@tonic-gate 					"remote");
893*7c478bd9Sstevel@tonic-gate 				continue;
894*7c478bd9Sstevel@tonic-gate 			}
895*7c478bd9Sstevel@tonic-gate 
896*7c478bd9Sstevel@tonic-gate 			buf[udp->udata.len] = '\0';
897*7c478bd9Sstevel@tonic-gate 			formatnet(&udp->udata, mp);
898*7c478bd9Sstevel@tonic-gate 
899*7c478bd9Sstevel@tonic-gate 			if (Debug) {
900*7c478bd9Sstevel@tonic-gate 				uap = taddr2uaddr(&Ncf[i], &udp->addr);
901*7c478bd9Sstevel@tonic-gate 				DPRINT2(1, "net_poll(%u): received message"
902*7c478bd9Sstevel@tonic-gate 					" from %s\n", mythreadno,
903*7c478bd9Sstevel@tonic-gate 					uap ? uap : "<unknown>");
904*7c478bd9Sstevel@tonic-gate 				free(uap);
905*7c478bd9Sstevel@tonic-gate 			}
906*7c478bd9Sstevel@tonic-gate 			if ((hinfo = malloc(sizeof (*hinfo))) == NULL ||
907*7c478bd9Sstevel@tonic-gate 				(hinfo->addr.buf =
908*7c478bd9Sstevel@tonic-gate 					malloc(udp->addr.len)) == NULL) {
909*7c478bd9Sstevel@tonic-gate 				MALLOC_FAIL("dropping message from "
910*7c478bd9Sstevel@tonic-gate 					"remote");
911*7c478bd9Sstevel@tonic-gate 				if (hinfo) {
912*7c478bd9Sstevel@tonic-gate 					free(hinfo);
913*7c478bd9Sstevel@tonic-gate 				}
914*7c478bd9Sstevel@tonic-gate 				free_msg(mp);
915*7c478bd9Sstevel@tonic-gate 				continue;
916*7c478bd9Sstevel@tonic-gate 			}
917*7c478bd9Sstevel@tonic-gate 
918*7c478bd9Sstevel@tonic-gate 			hinfo->ncp = &Ncf[i];
919*7c478bd9Sstevel@tonic-gate 			hinfo->addr.len = udp->addr.len;
920*7c478bd9Sstevel@tonic-gate 			(void) memcpy(hinfo->addr.buf, udp->addr.buf,
921*7c478bd9Sstevel@tonic-gate 					udp->addr.len);
922*7c478bd9Sstevel@tonic-gate 			mp->ptr = hinfo;
923*7c478bd9Sstevel@tonic-gate 			if (dataq_enqueue(&hnlq, (void *)mp) == -1) {
924*7c478bd9Sstevel@tonic-gate 				MALLOC_FAIL("dropping message from "
925*7c478bd9Sstevel@tonic-gate 					"remote");
926*7c478bd9Sstevel@tonic-gate 				free_msg(mp);
927*7c478bd9Sstevel@tonic-gate 				free(hinfo->addr.buf);
928*7c478bd9Sstevel@tonic-gate 				free(hinfo);
929*7c478bd9Sstevel@tonic-gate 				continue;
930*7c478bd9Sstevel@tonic-gate 			}
931*7c478bd9Sstevel@tonic-gate 			DPRINT3(5, "net_poll(%u): enqueued msg %p "
932*7c478bd9Sstevel@tonic-gate 				"on queue %p\n", mythreadno, mp, &hnlq);
933*7c478bd9Sstevel@tonic-gate 		}
934*7c478bd9Sstevel@tonic-gate 	}
935*7c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
936*7c478bd9Sstevel@tonic-gate 	return (NULL);
937*7c478bd9Sstevel@tonic-gate }
938*7c478bd9Sstevel@tonic-gate 
939*7c478bd9Sstevel@tonic-gate static void
940*7c478bd9Sstevel@tonic-gate usage(void)
941*7c478bd9Sstevel@tonic-gate {
942*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
943*7c478bd9Sstevel@tonic-gate 	    "usage: syslogd [-d] [-t|-T] [-mmarkinterval] [-ppath]"
944*7c478bd9Sstevel@tonic-gate 	    " [-fconffile]\n");
945*7c478bd9Sstevel@tonic-gate 	exit(1);
946*7c478bd9Sstevel@tonic-gate }
947*7c478bd9Sstevel@tonic-gate 
948*7c478bd9Sstevel@tonic-gate static void
949*7c478bd9Sstevel@tonic-gate untty(void)
950*7c478bd9Sstevel@tonic-gate {
951*7c478bd9Sstevel@tonic-gate 	if (!Debug)
952*7c478bd9Sstevel@tonic-gate 		(void) setsid();
953*7c478bd9Sstevel@tonic-gate }
954*7c478bd9Sstevel@tonic-gate 
955*7c478bd9Sstevel@tonic-gate /*
956*7c478bd9Sstevel@tonic-gate  * generate a log message internally. The original version of syslogd
957*7c478bd9Sstevel@tonic-gate  * simply called logmsg directly, but because everything is now based
958*7c478bd9Sstevel@tonic-gate  * on message passing, we need an internal way to generate and queue
959*7c478bd9Sstevel@tonic-gate  * log messages from within syslogd itself.
960*7c478bd9Sstevel@tonic-gate  */
961*7c478bd9Sstevel@tonic-gate static int
962*7c478bd9Sstevel@tonic-gate logmymsg(int pri, char *msg, int flags, int pending)
963*7c478bd9Sstevel@tonic-gate {
964*7c478bd9Sstevel@tonic-gate 	log_message_t *mp;
965*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
966*7c478bd9Sstevel@tonic-gate 	dataq_t *qptr;
967*7c478bd9Sstevel@tonic-gate 
968*7c478bd9Sstevel@tonic-gate 	if (Debug) {
969*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
970*7c478bd9Sstevel@tonic-gate 	}
971*7c478bd9Sstevel@tonic-gate 
972*7c478bd9Sstevel@tonic-gate 	if ((mp = new_msg()) == NULL) {
973*7c478bd9Sstevel@tonic-gate 		return (-1);
974*7c478bd9Sstevel@tonic-gate 	}
975*7c478bd9Sstevel@tonic-gate 
976*7c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp))
977*7c478bd9Sstevel@tonic-gate 	mp->pri = pri;
978*7c478bd9Sstevel@tonic-gate 	mp->hlp = &LocalHostName;
979*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(mp->msg, msg, MAXLINE+1);
980*7c478bd9Sstevel@tonic-gate 	mp->flags = flags;
981*7c478bd9Sstevel@tonic-gate 	(void) time(&mp->ts);
982*7c478bd9Sstevel@tonic-gate 
983*7c478bd9Sstevel@tonic-gate 	qptr = pending ? &tmpq : &inputq;
984*7c478bd9Sstevel@tonic-gate 	if (dataq_enqueue(qptr, (void *)mp) == -1) {
985*7c478bd9Sstevel@tonic-gate 		free_msg(mp);
986*7c478bd9Sstevel@tonic-gate 		return (-1);
987*7c478bd9Sstevel@tonic-gate 	}
988*7c478bd9Sstevel@tonic-gate 
989*7c478bd9Sstevel@tonic-gate 	DPRINT3(5, "logmymsg(%u): enqueued msg %p on queue %p\n",
990*7c478bd9Sstevel@tonic-gate 		mythreadno, mp, qptr);
991*7c478bd9Sstevel@tonic-gate 	DPRINT2(5, "logmymsg(%u): Message content: %s\n", mythreadno, msg);
992*7c478bd9Sstevel@tonic-gate 	return (0);
993*7c478bd9Sstevel@tonic-gate }
994*7c478bd9Sstevel@tonic-gate 
995*7c478bd9Sstevel@tonic-gate /*
996*7c478bd9Sstevel@tonic-gate  * Generate an internal shutdown message
997*7c478bd9Sstevel@tonic-gate  */
998*7c478bd9Sstevel@tonic-gate static int
999*7c478bd9Sstevel@tonic-gate shutdown_msg(void)
1000*7c478bd9Sstevel@tonic-gate {
1001*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
1002*7c478bd9Sstevel@tonic-gate 	log_message_t *mp;
1003*7c478bd9Sstevel@tonic-gate 
1004*7c478bd9Sstevel@tonic-gate 	if (Debug) {
1005*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
1006*7c478bd9Sstevel@tonic-gate 	}
1007*7c478bd9Sstevel@tonic-gate 
1008*7c478bd9Sstevel@tonic-gate 	if ((mp = new_msg()) == NULL) {
1009*7c478bd9Sstevel@tonic-gate 		return (-1);
1010*7c478bd9Sstevel@tonic-gate 	}
1011*7c478bd9Sstevel@tonic-gate 
1012*7c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp));
1013*7c478bd9Sstevel@tonic-gate 	mp->flags = SHUTDOWN;
1014*7c478bd9Sstevel@tonic-gate 	mp->hlp = &LocalHostName;
1015*7c478bd9Sstevel@tonic-gate 
1016*7c478bd9Sstevel@tonic-gate 	if (dataq_enqueue(&inputq, (void *)mp) == -1) {
1017*7c478bd9Sstevel@tonic-gate 		free_msg(mp);
1018*7c478bd9Sstevel@tonic-gate 		return (-1);
1019*7c478bd9Sstevel@tonic-gate 	}
1020*7c478bd9Sstevel@tonic-gate 
1021*7c478bd9Sstevel@tonic-gate 	DPRINT3(5, "shutdown_msg(%u): enqueued msg %p on queue %p\n",
1022*7c478bd9Sstevel@tonic-gate 		mythreadno, mp, &inputq);
1023*7c478bd9Sstevel@tonic-gate 	return (0);
1024*7c478bd9Sstevel@tonic-gate }
1025*7c478bd9Sstevel@tonic-gate 
1026*7c478bd9Sstevel@tonic-gate /*
1027*7c478bd9Sstevel@tonic-gate  * Generate an internal flush message
1028*7c478bd9Sstevel@tonic-gate  */
1029*7c478bd9Sstevel@tonic-gate static void
1030*7c478bd9Sstevel@tonic-gate flushmsg(int flags)
1031*7c478bd9Sstevel@tonic-gate {
1032*7c478bd9Sstevel@tonic-gate 	log_message_t *mp;
1033*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
1034*7c478bd9Sstevel@tonic-gate 
1035*7c478bd9Sstevel@tonic-gate 	if (Debug) {
1036*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
1037*7c478bd9Sstevel@tonic-gate 	}
1038*7c478bd9Sstevel@tonic-gate 
1039*7c478bd9Sstevel@tonic-gate 	if ((mp = new_msg()) == NULL) {
1040*7c478bd9Sstevel@tonic-gate 		MALLOC_FAIL("dropping flush msg");
1041*7c478bd9Sstevel@tonic-gate 		return;
1042*7c478bd9Sstevel@tonic-gate 	}
1043*7c478bd9Sstevel@tonic-gate 
1044*7c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp));
1045*7c478bd9Sstevel@tonic-gate 	mp->flags = FLUSHMSG | flags;
1046*7c478bd9Sstevel@tonic-gate 	mp->hlp = &LocalHostName;
1047*7c478bd9Sstevel@tonic-gate 
1048*7c478bd9Sstevel@tonic-gate 	if (dataq_enqueue(&inputq, (void *)mp) == -1) {
1049*7c478bd9Sstevel@tonic-gate 		free_msg(mp);
1050*7c478bd9Sstevel@tonic-gate 		MALLOC_FAIL("dropping flush msg");
1051*7c478bd9Sstevel@tonic-gate 		return;
1052*7c478bd9Sstevel@tonic-gate 	}
1053*7c478bd9Sstevel@tonic-gate 
1054*7c478bd9Sstevel@tonic-gate 	DPRINT4(5, "flush_msg(%u): enqueued msg %p on queue %p, flags "
1055*7c478bd9Sstevel@tonic-gate 		"0x%x\n", mythreadno, mp, &inputq, flags);
1056*7c478bd9Sstevel@tonic-gate }
1057*7c478bd9Sstevel@tonic-gate 
1058*7c478bd9Sstevel@tonic-gate /*
1059*7c478bd9Sstevel@tonic-gate  * Do some processing on messages received from the net
1060*7c478bd9Sstevel@tonic-gate  */
1061*7c478bd9Sstevel@tonic-gate static void
1062*7c478bd9Sstevel@tonic-gate formatnet(struct netbuf *nbp, log_message_t *mp)
1063*7c478bd9Sstevel@tonic-gate {
1064*7c478bd9Sstevel@tonic-gate 	char *p;
1065*7c478bd9Sstevel@tonic-gate 	int pri;
1066*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
1067*7c478bd9Sstevel@tonic-gate 
1068*7c478bd9Sstevel@tonic-gate 	if (Debug) {
1069*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
1070*7c478bd9Sstevel@tonic-gate 	}
1071*7c478bd9Sstevel@tonic-gate 
1072*7c478bd9Sstevel@tonic-gate 	DPRINT2(5, "formatnet(%u): called for msg %p\n", mythreadno, mp);
1073*7c478bd9Sstevel@tonic-gate 
1074*7c478bd9Sstevel@tonic-gate 	mp->flags = NETWORK;
1075*7c478bd9Sstevel@tonic-gate 	(void) time(&mp->ts);
1076*7c478bd9Sstevel@tonic-gate 
1077*7c478bd9Sstevel@tonic-gate 	/* test for special codes */
1078*7c478bd9Sstevel@tonic-gate 	pri = DEFUPRI;
1079*7c478bd9Sstevel@tonic-gate 	p = nbp->buf;
1080*7c478bd9Sstevel@tonic-gate 	DPRINT2(9, "formatnet(%u): Message content:\n>%s<\n", mythreadno,
1081*7c478bd9Sstevel@tonic-gate 		p);
1082*7c478bd9Sstevel@tonic-gate 	if (*p == '<' && isdigit(*(p+1))) {
1083*7c478bd9Sstevel@tonic-gate 		pri = 0;
1084*7c478bd9Sstevel@tonic-gate 		while (isdigit(*++p))
1085*7c478bd9Sstevel@tonic-gate 			pri = 10 * pri + (*p - '0');
1086*7c478bd9Sstevel@tonic-gate 		if (*p == '>')
1087*7c478bd9Sstevel@tonic-gate 			++p;
1088*7c478bd9Sstevel@tonic-gate 		if (pri <= 0 || pri >= (LOG_NFACILITIES << 3))
1089*7c478bd9Sstevel@tonic-gate 			pri = DEFUPRI;
1090*7c478bd9Sstevel@tonic-gate 	}
1091*7c478bd9Sstevel@tonic-gate 
1092*7c478bd9Sstevel@tonic-gate 	mp->pri = pri;
1093*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(mp->msg, p, MAXLINE+1);
1094*7c478bd9Sstevel@tonic-gate }
1095*7c478bd9Sstevel@tonic-gate 
1096*7c478bd9Sstevel@tonic-gate /*
1097*7c478bd9Sstevel@tonic-gate  * Do some processing on messages generated by this host
1098*7c478bd9Sstevel@tonic-gate  * and then enqueue the log message.
1099*7c478bd9Sstevel@tonic-gate  */
1100*7c478bd9Sstevel@tonic-gate static void
1101*7c478bd9Sstevel@tonic-gate formatsys(struct log_ctl *lp, char *msg, int sync)
1102*7c478bd9Sstevel@tonic-gate {
1103*7c478bd9Sstevel@tonic-gate 	char *p, *q;
1104*7c478bd9Sstevel@tonic-gate 	char line[MAXLINE + 1];
1105*7c478bd9Sstevel@tonic-gate 	size_t msglen;
1106*7c478bd9Sstevel@tonic-gate 	log_message_t	*mp;
1107*7c478bd9Sstevel@tonic-gate 	char cbuf[30];
1108*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
1109*7c478bd9Sstevel@tonic-gate 
1110*7c478bd9Sstevel@tonic-gate 	if (Debug) {
1111*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
1112*7c478bd9Sstevel@tonic-gate 	}
1113*7c478bd9Sstevel@tonic-gate 
1114*7c478bd9Sstevel@tonic-gate 	DPRINT3(3, "formatsys(%u): log_ctl.mid = %d, log_ctl.sid = %d\n",
1115*7c478bd9Sstevel@tonic-gate 		mythreadno, lp->mid, lp->sid);
1116*7c478bd9Sstevel@tonic-gate 	DPRINT2(9, "formatsys(%u): Message Content:\n>%s<\n", mythreadno,
1117*7c478bd9Sstevel@tonic-gate 		msg);
1118*7c478bd9Sstevel@tonic-gate 
1119*7c478bd9Sstevel@tonic-gate 	/* msglen includes the null termination */
1120*7c478bd9Sstevel@tonic-gate 	msglen = strlen(msg) + 1;
1121*7c478bd9Sstevel@tonic-gate 
1122*7c478bd9Sstevel@tonic-gate 	for (p = msg; *p != '\0'; ) {
1123*7c478bd9Sstevel@tonic-gate 		size_t linelen;
1124*7c478bd9Sstevel@tonic-gate 		size_t len;
1125*7c478bd9Sstevel@tonic-gate 
1126*7c478bd9Sstevel@tonic-gate 		/*
1127*7c478bd9Sstevel@tonic-gate 		 * Allocate a log_message_t structure.
1128*7c478bd9Sstevel@tonic-gate 		 * We should do it here since a single message (msg)
1129*7c478bd9Sstevel@tonic-gate 		 * could be composed of many lines.
1130*7c478bd9Sstevel@tonic-gate 		 */
1131*7c478bd9Sstevel@tonic-gate 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp));
1132*7c478bd9Sstevel@tonic-gate 
1133*7c478bd9Sstevel@tonic-gate 		if ((mp = new_msg()) == NULL) {
1134*7c478bd9Sstevel@tonic-gate 			MALLOC_FAIL("dropping message");
1135*7c478bd9Sstevel@tonic-gate 			/*
1136*7c478bd9Sstevel@tonic-gate 			 * Should bail out from the loop.
1137*7c478bd9Sstevel@tonic-gate 			 */
1138*7c478bd9Sstevel@tonic-gate 			break;
1139*7c478bd9Sstevel@tonic-gate 		}
1140*7c478bd9Sstevel@tonic-gate 
1141*7c478bd9Sstevel@tonic-gate 		mp->flags &= ~NETWORK;
1142*7c478bd9Sstevel@tonic-gate 		mp->hlp = &LocalHostName;
1143*7c478bd9Sstevel@tonic-gate 		mp->ts = lp->ttime;
1144*7c478bd9Sstevel@tonic-gate 		if (lp->flags & SL_LOGONLY)
1145*7c478bd9Sstevel@tonic-gate 			mp->flags |= IGN_CONS;
1146*7c478bd9Sstevel@tonic-gate 		if (lp->flags & SL_CONSONLY)
1147*7c478bd9Sstevel@tonic-gate 			mp->flags |= IGN_FILE;
1148*7c478bd9Sstevel@tonic-gate 
1149*7c478bd9Sstevel@tonic-gate 		/* extract facility */
1150*7c478bd9Sstevel@tonic-gate 		if ((lp->pri & LOG_FACMASK) == LOG_KERN) {
1151*7c478bd9Sstevel@tonic-gate 			(void) sprintf(line, "%.15s ",
1152*7c478bd9Sstevel@tonic-gate 				ctime_r(&mp->ts, cbuf) + 4);
1153*7c478bd9Sstevel@tonic-gate 		} else {
1154*7c478bd9Sstevel@tonic-gate 			(void) sprintf(line, "");
1155*7c478bd9Sstevel@tonic-gate 		}
1156*7c478bd9Sstevel@tonic-gate 
1157*7c478bd9Sstevel@tonic-gate 		linelen = strlen(line);
1158*7c478bd9Sstevel@tonic-gate 		q = line + linelen;
1159*7c478bd9Sstevel@tonic-gate 
1160*7c478bd9Sstevel@tonic-gate 		DPRINT2(5, "formatsys(%u): msglen = %d\n", mythreadno, msglen);
1161*7c478bd9Sstevel@tonic-gate 		len = copynl_frwd(q, MAXLINE + 1 - linelen, p, msglen);
1162*7c478bd9Sstevel@tonic-gate 		DPRINT2(5, "formatsys(%u): len (copynl_frwd) = %d\n",
1163*7c478bd9Sstevel@tonic-gate 			mythreadno, len);
1164*7c478bd9Sstevel@tonic-gate 
1165*7c478bd9Sstevel@tonic-gate 		p += len;
1166*7c478bd9Sstevel@tonic-gate 		msglen -= len;
1167*7c478bd9Sstevel@tonic-gate 
1168*7c478bd9Sstevel@tonic-gate 		if (*p == '\n') {
1169*7c478bd9Sstevel@tonic-gate 			/* skip newline */
1170*7c478bd9Sstevel@tonic-gate 			p++;
1171*7c478bd9Sstevel@tonic-gate 		}
1172*7c478bd9Sstevel@tonic-gate 
1173*7c478bd9Sstevel@tonic-gate 		if (sync && ((lp->pri & LOG_FACMASK) == LOG_KERN))
1174*7c478bd9Sstevel@tonic-gate 			mp->flags |= SYNC_FILE;	/* fsync file after write */
1175*7c478bd9Sstevel@tonic-gate 
1176*7c478bd9Sstevel@tonic-gate 		if (len != 0) {
1177*7c478bd9Sstevel@tonic-gate 			(void) strlcpy(mp->msg, line, MAXLINE+1);
1178*7c478bd9Sstevel@tonic-gate 			mp->pri = lp->pri;
1179*7c478bd9Sstevel@tonic-gate 
1180*7c478bd9Sstevel@tonic-gate 			if (dataq_enqueue(&inputq, (void *)mp) == -1) {
1181*7c478bd9Sstevel@tonic-gate 				free_msg(mp);
1182*7c478bd9Sstevel@tonic-gate 				MALLOC_FAIL("dropping message");
1183*7c478bd9Sstevel@tonic-gate 				break;
1184*7c478bd9Sstevel@tonic-gate 			}
1185*7c478bd9Sstevel@tonic-gate 
1186*7c478bd9Sstevel@tonic-gate 			DPRINT3(5, "formatsys(%u): sys_thread enqueued msg "
1187*7c478bd9Sstevel@tonic-gate 				"%p on queue %p\n", mythreadno, mp, &inputq);
1188*7c478bd9Sstevel@tonic-gate 		} else
1189*7c478bd9Sstevel@tonic-gate 			free_msg(mp);
1190*7c478bd9Sstevel@tonic-gate 	}
1191*7c478bd9Sstevel@tonic-gate }
1192*7c478bd9Sstevel@tonic-gate 
1193*7c478bd9Sstevel@tonic-gate /*
1194*7c478bd9Sstevel@tonic-gate  * Log a message to the appropriate log files, users, etc. based on
1195*7c478bd9Sstevel@tonic-gate  * the priority.
1196*7c478bd9Sstevel@tonic-gate  */
1197*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1198*7c478bd9Sstevel@tonic-gate static void *
1199*7c478bd9Sstevel@tonic-gate logmsg(void *ap)
1200*7c478bd9Sstevel@tonic-gate {
1201*7c478bd9Sstevel@tonic-gate 	struct filed *f;
1202*7c478bd9Sstevel@tonic-gate 	int fac, prilev, flags, refcnt;
1203*7c478bd9Sstevel@tonic-gate 	int fake_shutdown, skip_shutdown;
1204*7c478bd9Sstevel@tonic-gate 	log_message_t *mp, *save_mp;
1205*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
1206*7c478bd9Sstevel@tonic-gate 
1207*7c478bd9Sstevel@tonic-gate 	if (Debug) {
1208*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
1209*7c478bd9Sstevel@tonic-gate 	}
1210*7c478bd9Sstevel@tonic-gate 
1211*7c478bd9Sstevel@tonic-gate 	DPRINT1(1, "logmsg(%u): msg dispatcher started\n", mythreadno);
1212*7c478bd9Sstevel@tonic-gate 
1213*7c478bd9Sstevel@tonic-gate 	fake_shutdown = skip_shutdown = 0;
1214*7c478bd9Sstevel@tonic-gate 	save_mp = NULL;
1215*7c478bd9Sstevel@tonic-gate 	for (;;) {
1216*7c478bd9Sstevel@tonic-gate 		if (save_mp) {
1217*7c478bd9Sstevel@tonic-gate 			/*
1218*7c478bd9Sstevel@tonic-gate 			 * If we have set aside a message in order to fake a
1219*7c478bd9Sstevel@tonic-gate 			 * SHUTDOWN, use that message before picking from the
1220*7c478bd9Sstevel@tonic-gate 			 * queue again.
1221*7c478bd9Sstevel@tonic-gate 			 */
1222*7c478bd9Sstevel@tonic-gate 			mp = save_mp;
1223*7c478bd9Sstevel@tonic-gate 			save_mp = NULL;
1224*7c478bd9Sstevel@tonic-gate 		} else {
1225*7c478bd9Sstevel@tonic-gate 			(void) dataq_dequeue(&inputq, (void **)&mp, 0);
1226*7c478bd9Sstevel@tonic-gate 		}
1227*7c478bd9Sstevel@tonic-gate 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mp))
1228*7c478bd9Sstevel@tonic-gate 		DPRINT3(5, "logmsg(%u): msg dispatcher dequeued %p from "
1229*7c478bd9Sstevel@tonic-gate 			"queue %p\n", mythreadno, mp, &inputq);
1230*7c478bd9Sstevel@tonic-gate 
1231*7c478bd9Sstevel@tonic-gate 		/*
1232*7c478bd9Sstevel@tonic-gate 		 * In most cases, if the message traffic is low, logmsg() wakes
1233*7c478bd9Sstevel@tonic-gate 		 * up when it receives the SHUTDOWN msg, and will sleep until
1234*7c478bd9Sstevel@tonic-gate 		 * HUP process is complete.  However, if the inputq is too
1235*7c478bd9Sstevel@tonic-gate 		 * long, logmsg() may not receive SHUTDOWN before reconfigure()
1236*7c478bd9Sstevel@tonic-gate 		 * releases the logger fds, filed and logit threads.  That, in
1237*7c478bd9Sstevel@tonic-gate 		 * turn, will cause logmsg to refer to invalid fileds.
1238*7c478bd9Sstevel@tonic-gate 		 *
1239*7c478bd9Sstevel@tonic-gate 		 * logmsg() needs to respond to the SHUTDOWN message within
1240*7c478bd9Sstevel@tonic-gate 		 * LOOP_INTERVAL seconds when reconfigure() enqueues it. It
1241*7c478bd9Sstevel@tonic-gate 		 * does so in most cases.  When it does not respond in time,
1242*7c478bd9Sstevel@tonic-gate 		 * logmsg() needs to be in suspended state immediately, since
1243*7c478bd9Sstevel@tonic-gate 		 * filed may have been invalidated. reconfigure() will set the
1244*7c478bd9Sstevel@tonic-gate 		 * HUP_SUSP_LOGMSG_REQD bit in hup_state and wait another
1245*7c478bd9Sstevel@tonic-gate 		 * LOOP_INTERVAL seconds before proceeding.
1246*7c478bd9Sstevel@tonic-gate 		 *
1247*7c478bd9Sstevel@tonic-gate 		 * When HUP_SUSP_LOGMSG_REQD is set, we will create a fake
1248*7c478bd9Sstevel@tonic-gate 		 * SHUTDOWN message, and dispatch it to the various logit
1249*7c478bd9Sstevel@tonic-gate 		 * threads, and logmsg() itself will suspend.  In order to
1250*7c478bd9Sstevel@tonic-gate 		 * ignore the real SHUTDOWN which will arrive later, we keep a
1251*7c478bd9Sstevel@tonic-gate 		 * counter (skip_shutdown) and decrement it when the SHUTDOWN
1252*7c478bd9Sstevel@tonic-gate 		 * message arrives.
1253*7c478bd9Sstevel@tonic-gate 		 */
1254*7c478bd9Sstevel@tonic-gate 		if ((hup_state & HUP_SUSP_LOGMSG_REQD) &&
1255*7c478bd9Sstevel@tonic-gate 			(mp->flags & SHUTDOWN) == 0) {
1256*7c478bd9Sstevel@tonic-gate 			DPRINT1(3, "logmsg(%u): suspend request\n",
1257*7c478bd9Sstevel@tonic-gate 				mythreadno);
1258*7c478bd9Sstevel@tonic-gate 
1259*7c478bd9Sstevel@tonic-gate 			save_mp = mp;
1260*7c478bd9Sstevel@tonic-gate 
1261*7c478bd9Sstevel@tonic-gate 			/* create a fake SHUTDOWN msg */
1262*7c478bd9Sstevel@tonic-gate 			if ((mp = new_msg()) == NULL) {
1263*7c478bd9Sstevel@tonic-gate 				MALLOC_FAIL("dropping message");
1264*7c478bd9Sstevel@tonic-gate 				if (mp->flags & SHUTDOWN) {
1265*7c478bd9Sstevel@tonic-gate 					(void) logerror_to_console(1,
1266*7c478bd9Sstevel@tonic-gate 						"unable to shutdown "
1267*7c478bd9Sstevel@tonic-gate 						"logger thread");
1268*7c478bd9Sstevel@tonic-gate 				}
1269*7c478bd9Sstevel@tonic-gate 				continue;
1270*7c478bd9Sstevel@tonic-gate 			}
1271*7c478bd9Sstevel@tonic-gate 			mp->flags = SHUTDOWN;
1272*7c478bd9Sstevel@tonic-gate 			mp->hlp = &LocalHostName;
1273*7c478bd9Sstevel@tonic-gate 			fake_shutdown = 1;
1274*7c478bd9Sstevel@tonic-gate 			skip_shutdown++;
1275*7c478bd9Sstevel@tonic-gate 			DPRINT2(3, "logmsg(%u): pending SHUTDOWN %d\n",
1276*7c478bd9Sstevel@tonic-gate 				mythreadno, skip_shutdown);
1277*7c478bd9Sstevel@tonic-gate 		}
1278*7c478bd9Sstevel@tonic-gate 
1279*7c478bd9Sstevel@tonic-gate 		/*
1280*7c478bd9Sstevel@tonic-gate 		 * is it a shutdown or flush message ?
1281*7c478bd9Sstevel@tonic-gate 		 */
1282*7c478bd9Sstevel@tonic-gate 		if ((mp->flags & SHUTDOWN) || (mp->flags & FLUSHMSG)) {
1283*7c478bd9Sstevel@tonic-gate 			pthread_mutex_lock(&mp->msg_mutex);
1284*7c478bd9Sstevel@tonic-gate 
1285*7c478bd9Sstevel@tonic-gate 			if ((mp->flags & SHUTDOWN) &&
1286*7c478bd9Sstevel@tonic-gate 				!fake_shutdown && skip_shutdown > 0) {
1287*7c478bd9Sstevel@tonic-gate 				skip_shutdown--;
1288*7c478bd9Sstevel@tonic-gate 				pthread_mutex_unlock(&mp->msg_mutex);
1289*7c478bd9Sstevel@tonic-gate 				free_msg(mp);
1290*7c478bd9Sstevel@tonic-gate 				DPRINT2(3, "logmsg(%u): released late "
1291*7c478bd9Sstevel@tonic-gate 					"arrived SHUTDOWN. pending %d\n",
1292*7c478bd9Sstevel@tonic-gate 					mythreadno, skip_shutdown);
1293*7c478bd9Sstevel@tonic-gate 				continue;
1294*7c478bd9Sstevel@tonic-gate 			}
1295*7c478bd9Sstevel@tonic-gate 
1296*7c478bd9Sstevel@tonic-gate 			for (f = Files; f < &Files[nlogs]; f++) {
1297*7c478bd9Sstevel@tonic-gate 				pthread_mutex_lock(&f->filed_mutex);
1298*7c478bd9Sstevel@tonic-gate 
1299*7c478bd9Sstevel@tonic-gate 				if (f->f_type == F_UNUSED) {
1300*7c478bd9Sstevel@tonic-gate 					pthread_mutex_unlock(&f->filed_mutex);
1301*7c478bd9Sstevel@tonic-gate 					continue;
1302*7c478bd9Sstevel@tonic-gate 				}
1303*7c478bd9Sstevel@tonic-gate 
1304*7c478bd9Sstevel@tonic-gate 				f->f_queue_count++;
1305*7c478bd9Sstevel@tonic-gate 				mp->refcnt++;
1306*7c478bd9Sstevel@tonic-gate 
1307*7c478bd9Sstevel@tonic-gate 				if (dataq_enqueue(&f->f_queue,
1308*7c478bd9Sstevel@tonic-gate 					(void *)mp) == -1) {
1309*7c478bd9Sstevel@tonic-gate 					f->f_queue_count--;
1310*7c478bd9Sstevel@tonic-gate 					mp->refcnt--;
1311*7c478bd9Sstevel@tonic-gate 					pthread_mutex_unlock(&f->filed_mutex);
1312*7c478bd9Sstevel@tonic-gate 					MALLOC_FAIL("dropping message");
1313*7c478bd9Sstevel@tonic-gate 
1314*7c478bd9Sstevel@tonic-gate 					if (mp->flags & SHUTDOWN) {
1315*7c478bd9Sstevel@tonic-gate 						(void) logerror_to_console(1,
1316*7c478bd9Sstevel@tonic-gate 							"unable to shutdown "
1317*7c478bd9Sstevel@tonic-gate 							"logger thread");
1318*7c478bd9Sstevel@tonic-gate 					}
1319*7c478bd9Sstevel@tonic-gate 
1320*7c478bd9Sstevel@tonic-gate 					continue;
1321*7c478bd9Sstevel@tonic-gate 				}
1322*7c478bd9Sstevel@tonic-gate 				DPRINT3(5, "logmsg(%u): enqueued msg %p "
1323*7c478bd9Sstevel@tonic-gate 					"on queue %p\n", mythreadno, mp,
1324*7c478bd9Sstevel@tonic-gate 					&f->f_queue);
1325*7c478bd9Sstevel@tonic-gate 				pthread_mutex_unlock(&f->filed_mutex);
1326*7c478bd9Sstevel@tonic-gate 			}
1327*7c478bd9Sstevel@tonic-gate 
1328*7c478bd9Sstevel@tonic-gate 			/*
1329*7c478bd9Sstevel@tonic-gate 			 * flags value needs to be saved because mp may
1330*7c478bd9Sstevel@tonic-gate 			 * have been freed before SHUTDOWN test below.
1331*7c478bd9Sstevel@tonic-gate 			 */
1332*7c478bd9Sstevel@tonic-gate 			flags = mp->flags;
1333*7c478bd9Sstevel@tonic-gate 			refcnt = mp->refcnt;
1334*7c478bd9Sstevel@tonic-gate 
1335*7c478bd9Sstevel@tonic-gate 			pthread_mutex_unlock(&mp->msg_mutex);
1336*7c478bd9Sstevel@tonic-gate 			if (refcnt == 0)
1337*7c478bd9Sstevel@tonic-gate 				free_msg(mp);
1338*7c478bd9Sstevel@tonic-gate 
1339*7c478bd9Sstevel@tonic-gate 			if (flags & SHUTDOWN) {
1340*7c478bd9Sstevel@tonic-gate 				pthread_mutex_lock(&hup_lock);
1341*7c478bd9Sstevel@tonic-gate 				while (hup_state != HUP_COMPLETED) {
1342*7c478bd9Sstevel@tonic-gate 					hup_state |= HUP_LOGMSG_SUSPENDED;
1343*7c478bd9Sstevel@tonic-gate 					(void) pthread_cond_wait(&hup_done,
1344*7c478bd9Sstevel@tonic-gate 						&hup_lock);
1345*7c478bd9Sstevel@tonic-gate 					hup_state &= ~HUP_LOGMSG_SUSPENDED;
1346*7c478bd9Sstevel@tonic-gate 				}
1347*7c478bd9Sstevel@tonic-gate 				hup_state = HUP_ACCEPTABLE;
1348*7c478bd9Sstevel@tonic-gate 				pthread_mutex_unlock(&hup_lock);
1349*7c478bd9Sstevel@tonic-gate 				fake_shutdown = 0;
1350*7c478bd9Sstevel@tonic-gate 			}
1351*7c478bd9Sstevel@tonic-gate 			continue;
1352*7c478bd9Sstevel@tonic-gate 		}
1353*7c478bd9Sstevel@tonic-gate 
1354*7c478bd9Sstevel@tonic-gate 		/*
1355*7c478bd9Sstevel@tonic-gate 		 * Check to see if msg looks non-standard.
1356*7c478bd9Sstevel@tonic-gate 		 */
1357*7c478bd9Sstevel@tonic-gate 		if ((int)strlen(mp->msg) < 16 || mp->msg[3] != ' ' ||
1358*7c478bd9Sstevel@tonic-gate 			mp->msg[6] != ' ' || mp->msg[9] != ':' ||
1359*7c478bd9Sstevel@tonic-gate 			mp->msg[12] != ':' || mp->msg[15] != ' ')
1360*7c478bd9Sstevel@tonic-gate 			mp->flags |= ADDDATE;
1361*7c478bd9Sstevel@tonic-gate 
1362*7c478bd9Sstevel@tonic-gate 		/* extract facility and priority level */
1363*7c478bd9Sstevel@tonic-gate 		fac = (mp->pri & LOG_FACMASK) >> 3;
1364*7c478bd9Sstevel@tonic-gate 		if (mp->flags & MARK)
1365*7c478bd9Sstevel@tonic-gate 			fac = LOG_NFACILITIES;
1366*7c478bd9Sstevel@tonic-gate 		prilev = mp->pri & LOG_PRIMASK;
1367*7c478bd9Sstevel@tonic-gate 
1368*7c478bd9Sstevel@tonic-gate 		DPRINT3(3, "logmsg(%u): fac = %d, pri = %d\n",
1369*7c478bd9Sstevel@tonic-gate 			mythreadno, fac, prilev);
1370*7c478bd9Sstevel@tonic-gate 
1371*7c478bd9Sstevel@tonic-gate 		/*
1372*7c478bd9Sstevel@tonic-gate 		 * Because different devices log at different speeds,
1373*7c478bd9Sstevel@tonic-gate 		 * it's important to hold the mutex for the current
1374*7c478bd9Sstevel@tonic-gate 		 * message until it's been enqueued to all log files,
1375*7c478bd9Sstevel@tonic-gate 		 * so the reference count is accurate before any
1376*7c478bd9Sstevel@tonic-gate 		 * of the log threads can decrement it.
1377*7c478bd9Sstevel@tonic-gate 		 */
1378*7c478bd9Sstevel@tonic-gate 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mp))
1379*7c478bd9Sstevel@tonic-gate 		_NOTE(COMPETING_THREADS_NOW)
1380*7c478bd9Sstevel@tonic-gate 		pthread_mutex_lock(&mp->msg_mutex);
1381*7c478bd9Sstevel@tonic-gate 
1382*7c478bd9Sstevel@tonic-gate 		for (f = Files; f < &Files[nlogs]; f++) {
1383*7c478bd9Sstevel@tonic-gate 			/* skip messages that are incorrect priority */
1384*7c478bd9Sstevel@tonic-gate 			if (f->f_pmask[fac] < (unsigned)prilev ||
1385*7c478bd9Sstevel@tonic-gate 				f->f_pmask[fac] == NOPRI)
1386*7c478bd9Sstevel@tonic-gate 				continue;
1387*7c478bd9Sstevel@tonic-gate 			if (f->f_queue_count > Q_HIGHWATER_MARK) {
1388*7c478bd9Sstevel@tonic-gate 				DPRINT4(5, "logmsg(%u): Dropping message "
1389*7c478bd9Sstevel@tonic-gate 					"%p on file %p, count = %d\n",
1390*7c478bd9Sstevel@tonic-gate 					mythreadno, mp, f,
1391*7c478bd9Sstevel@tonic-gate 					f->f_queue_count);
1392*7c478bd9Sstevel@tonic-gate 				continue;
1393*7c478bd9Sstevel@tonic-gate 			}
1394*7c478bd9Sstevel@tonic-gate 
1395*7c478bd9Sstevel@tonic-gate 			/*
1396*7c478bd9Sstevel@tonic-gate 			 * Need to grab filed_mutex before testing the f_type.
1397*7c478bd9Sstevel@tonic-gate 			 * Otherwise logit() may set F_UNUSED after the test
1398*7c478bd9Sstevel@tonic-gate 			 * below, and start pulling out the pending messages.
1399*7c478bd9Sstevel@tonic-gate 			 */
1400*7c478bd9Sstevel@tonic-gate 
1401*7c478bd9Sstevel@tonic-gate 			pthread_mutex_lock(&f->filed_mutex);
1402*7c478bd9Sstevel@tonic-gate 
1403*7c478bd9Sstevel@tonic-gate 			if (f->f_type == F_UNUSED ||
1404*7c478bd9Sstevel@tonic-gate 			    (f->f_type == F_FILE && (mp->flags & IGN_FILE)) ||
1405*7c478bd9Sstevel@tonic-gate 			    (f->f_type == F_CONSOLE &&
1406*7c478bd9Sstevel@tonic-gate 				(mp->flags & IGN_CONS))) {
1407*7c478bd9Sstevel@tonic-gate 				pthread_mutex_unlock(&f->filed_mutex);
1408*7c478bd9Sstevel@tonic-gate 				continue;
1409*7c478bd9Sstevel@tonic-gate 			}
1410*7c478bd9Sstevel@tonic-gate 
1411*7c478bd9Sstevel@tonic-gate 			f->f_queue_count++;
1412*7c478bd9Sstevel@tonic-gate 			mp->refcnt++;
1413*7c478bd9Sstevel@tonic-gate 
1414*7c478bd9Sstevel@tonic-gate 			if (dataq_enqueue(&f->f_queue, (void *)mp) == -1) {
1415*7c478bd9Sstevel@tonic-gate 				f->f_queue_count--;
1416*7c478bd9Sstevel@tonic-gate 				mp->refcnt--;
1417*7c478bd9Sstevel@tonic-gate 				pthread_mutex_unlock(&f->filed_mutex);
1418*7c478bd9Sstevel@tonic-gate 				MALLOC_FAIL("dropping message");
1419*7c478bd9Sstevel@tonic-gate 				continue;
1420*7c478bd9Sstevel@tonic-gate 			}
1421*7c478bd9Sstevel@tonic-gate 
1422*7c478bd9Sstevel@tonic-gate 			DPRINT3(5, "logmsg(%u): enqueued msg %p on queue "
1423*7c478bd9Sstevel@tonic-gate 				"%p\n", mythreadno, mp, &f->f_queue);
1424*7c478bd9Sstevel@tonic-gate 			pthread_mutex_unlock(&f->filed_mutex);
1425*7c478bd9Sstevel@tonic-gate 		}
1426*7c478bd9Sstevel@tonic-gate 		refcnt = mp->refcnt;
1427*7c478bd9Sstevel@tonic-gate 		pthread_mutex_unlock(&mp->msg_mutex);
1428*7c478bd9Sstevel@tonic-gate 		if (refcnt == 0)
1429*7c478bd9Sstevel@tonic-gate 			free_msg(mp);
1430*7c478bd9Sstevel@tonic-gate 	}
1431*7c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
1432*7c478bd9Sstevel@tonic-gate 	return (NULL);
1433*7c478bd9Sstevel@tonic-gate }
1434*7c478bd9Sstevel@tonic-gate 
1435*7c478bd9Sstevel@tonic-gate /*
1436*7c478bd9Sstevel@tonic-gate  * function to actually write the log message to the selected file.
1437*7c478bd9Sstevel@tonic-gate  * each file has a logger thread that runs this routine. The function
1438*7c478bd9Sstevel@tonic-gate  * is called with a pointer to its file structure.
1439*7c478bd9Sstevel@tonic-gate  */
1440*7c478bd9Sstevel@tonic-gate static void *
1441*7c478bd9Sstevel@tonic-gate logit(void *ap)
1442*7c478bd9Sstevel@tonic-gate {
1443*7c478bd9Sstevel@tonic-gate 	struct filed *f = ap;
1444*7c478bd9Sstevel@tonic-gate 	log_message_t *mp;
1445*7c478bd9Sstevel@tonic-gate 	int forwardingloop = 0;
1446*7c478bd9Sstevel@tonic-gate 	char *errmsg = "logit(%u): %s to %s forwarding loop detected\n";
1447*7c478bd9Sstevel@tonic-gate 	int i, currofst, prevofst, refcnt;
1448*7c478bd9Sstevel@tonic-gate 	host_list_t *hlp;
1449*7c478bd9Sstevel@tonic-gate 
1450*7c478bd9Sstevel@tonic-gate 	assert(f != NULL);
1451*7c478bd9Sstevel@tonic-gate 
1452*7c478bd9Sstevel@tonic-gate 	DPRINT4(5, "logit(%u): logger started for \"%s\" (queue %p, filed "
1453*7c478bd9Sstevel@tonic-gate 		"%p)\n", f->f_thread, f->f_un.f_fname, &f->f_queue, f);
1454*7c478bd9Sstevel@tonic-gate 	_NOTE(COMPETING_THREADS_NOW);
1455*7c478bd9Sstevel@tonic-gate 
1456*7c478bd9Sstevel@tonic-gate 	while (f->f_type != F_UNUSED) {
1457*7c478bd9Sstevel@tonic-gate 		(void) dataq_dequeue(&f->f_queue, (void **)&mp, 0);
1458*7c478bd9Sstevel@tonic-gate 		DPRINT3(5, "logit(%u): logger dequeued msg %p from queue "
1459*7c478bd9Sstevel@tonic-gate 			"%p\n",
1460*7c478bd9Sstevel@tonic-gate 			f->f_thread, mp, &f->f_queue);
1461*7c478bd9Sstevel@tonic-gate 		pthread_mutex_lock(&f->filed_mutex);
1462*7c478bd9Sstevel@tonic-gate 		assert(f->f_queue_count > 0);
1463*7c478bd9Sstevel@tonic-gate 		f->f_queue_count--;
1464*7c478bd9Sstevel@tonic-gate 		pthread_mutex_unlock(&f->filed_mutex);
1465*7c478bd9Sstevel@tonic-gate 		assert(mp->refcnt > 0);
1466*7c478bd9Sstevel@tonic-gate 
1467*7c478bd9Sstevel@tonic-gate 		/*
1468*7c478bd9Sstevel@tonic-gate 		 * is it a shutdown message ?
1469*7c478bd9Sstevel@tonic-gate 		 */
1470*7c478bd9Sstevel@tonic-gate 		if (mp->flags & SHUTDOWN) {
1471*7c478bd9Sstevel@tonic-gate 			pthread_mutex_lock(&mp->msg_mutex);
1472*7c478bd9Sstevel@tonic-gate 			refcnt = --mp->refcnt;
1473*7c478bd9Sstevel@tonic-gate 			pthread_mutex_unlock(&mp->msg_mutex);
1474*7c478bd9Sstevel@tonic-gate 			if (refcnt == 0)
1475*7c478bd9Sstevel@tonic-gate 				free_msg(mp);
1476*7c478bd9Sstevel@tonic-gate 			break;
1477*7c478bd9Sstevel@tonic-gate 		}
1478*7c478bd9Sstevel@tonic-gate 
1479*7c478bd9Sstevel@tonic-gate 		/*
1480*7c478bd9Sstevel@tonic-gate 		 * Is it a logsync message?
1481*7c478bd9Sstevel@tonic-gate 		 */
1482*7c478bd9Sstevel@tonic-gate 		if ((mp->flags & (FLUSHMSG | LOGSYNC)) ==
1483*7c478bd9Sstevel@tonic-gate 		    (FLUSHMSG | LOGSYNC)) {
1484*7c478bd9Sstevel@tonic-gate 			if (f->f_type != F_FILE)
1485*7c478bd9Sstevel@tonic-gate 				goto out;	/* nothing to do */
1486*7c478bd9Sstevel@tonic-gate 			(void) close(f->f_file);
1487*7c478bd9Sstevel@tonic-gate 			f->f_file = open64(f->f_un.f_fname,
1488*7c478bd9Sstevel@tonic-gate 					O_WRONLY|O_APPEND|O_NOCTTY);
1489*7c478bd9Sstevel@tonic-gate 			if (f->f_file < 0) {
1490*7c478bd9Sstevel@tonic-gate 				f->f_type = F_UNUSED;
1491*7c478bd9Sstevel@tonic-gate 				logerror(f->f_un.f_fname);
1492*7c478bd9Sstevel@tonic-gate 				f->f_stat.errs++;
1493*7c478bd9Sstevel@tonic-gate 			}
1494*7c478bd9Sstevel@tonic-gate 			goto out;
1495*7c478bd9Sstevel@tonic-gate 		}
1496*7c478bd9Sstevel@tonic-gate 
1497*7c478bd9Sstevel@tonic-gate 		/*
1498*7c478bd9Sstevel@tonic-gate 		 * If the message flags include both flush and sync,
1499*7c478bd9Sstevel@tonic-gate 		 * then just sync the file out to disk if appropriate.
1500*7c478bd9Sstevel@tonic-gate 		 */
1501*7c478bd9Sstevel@tonic-gate 		if ((mp->flags & (FLUSHMSG | SYNC_FILE)) ==
1502*7c478bd9Sstevel@tonic-gate 		    (FLUSHMSG | SYNC_FILE)) {
1503*7c478bd9Sstevel@tonic-gate 			if (f->f_type == F_FILE) {
1504*7c478bd9Sstevel@tonic-gate 				DPRINT2(5, "logit(%u): got FLUSH|SYNC "
1505*7c478bd9Sstevel@tonic-gate 					"for filed %p\n", f->f_thread,
1506*7c478bd9Sstevel@tonic-gate 					f);
1507*7c478bd9Sstevel@tonic-gate 				(void) fsync(f->f_file);
1508*7c478bd9Sstevel@tonic-gate 			}
1509*7c478bd9Sstevel@tonic-gate 			goto out;
1510*7c478bd9Sstevel@tonic-gate 		}
1511*7c478bd9Sstevel@tonic-gate 
1512*7c478bd9Sstevel@tonic-gate 		/*
1513*7c478bd9Sstevel@tonic-gate 		 * Otherwise if it's a standard flush message, write
1514*7c478bd9Sstevel@tonic-gate 		 * out any saved messages to the file.
1515*7c478bd9Sstevel@tonic-gate 		 */
1516*7c478bd9Sstevel@tonic-gate 		if ((mp->flags & FLUSHMSG) && (f->f_prevcount > 0)) {
1517*7c478bd9Sstevel@tonic-gate 			set_flush_msg(f);
1518*7c478bd9Sstevel@tonic-gate 			writemsg(SAVED, f);
1519*7c478bd9Sstevel@tonic-gate 			goto out;
1520*7c478bd9Sstevel@tonic-gate 		}
1521*7c478bd9Sstevel@tonic-gate 
1522*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(f->f_current.msg, mp->msg, MAXLINE+1);
1523*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(f->f_current.host, mp->hlp->hl_hosts[0],
1524*7c478bd9Sstevel@tonic-gate 				SYS_NMLN);
1525*7c478bd9Sstevel@tonic-gate 		f->f_current.pri = mp->pri;
1526*7c478bd9Sstevel@tonic-gate 		f->f_current.flags = mp->flags;
1527*7c478bd9Sstevel@tonic-gate 		f->f_current.time = mp->ts;
1528*7c478bd9Sstevel@tonic-gate 		f->f_msgflag &= ~CURRENT_VALID;
1529*7c478bd9Sstevel@tonic-gate 		hlp = mp->hlp;
1530*7c478bd9Sstevel@tonic-gate 
1531*7c478bd9Sstevel@tonic-gate 		prevofst = (f->f_prevmsg.flags & ADDDATE) ? 0 : 16;
1532*7c478bd9Sstevel@tonic-gate 		currofst = (f->f_current.flags & ADDDATE) ? 0 : 16;
1533*7c478bd9Sstevel@tonic-gate 
1534*7c478bd9Sstevel@tonic-gate 		if (f->f_type == F_FORW) {
1535*7c478bd9Sstevel@tonic-gate 			/*
1536*7c478bd9Sstevel@tonic-gate 			 * Should not forward MARK messages, as they are
1537*7c478bd9Sstevel@tonic-gate 			 * not defined outside of the current system.
1538*7c478bd9Sstevel@tonic-gate 			 */
1539*7c478bd9Sstevel@tonic-gate 
1540*7c478bd9Sstevel@tonic-gate 			if (mp->flags & MARK) {
1541*7c478bd9Sstevel@tonic-gate 				DPRINT1(1, "logit(%u): cannot forward "
1542*7c478bd9Sstevel@tonic-gate 					"Mark\n", f->f_thread);
1543*7c478bd9Sstevel@tonic-gate 				goto out;
1544*7c478bd9Sstevel@tonic-gate 			}
1545*7c478bd9Sstevel@tonic-gate 
1546*7c478bd9Sstevel@tonic-gate 			/*
1547*7c478bd9Sstevel@tonic-gate 			 * can not forward message if we do
1548*7c478bd9Sstevel@tonic-gate 			 * not have a host to forward to
1549*7c478bd9Sstevel@tonic-gate 			 */
1550*7c478bd9Sstevel@tonic-gate 			if (hlp == (host_list_t *)NULL)
1551*7c478bd9Sstevel@tonic-gate 				goto out;
1552*7c478bd9Sstevel@tonic-gate 			/*
1553*7c478bd9Sstevel@tonic-gate 			 * a forwarding loop is created on machines
1554*7c478bd9Sstevel@tonic-gate 			 * with multiple interfaces because the
1555*7c478bd9Sstevel@tonic-gate 			 * network address of the sender is different
1556*7c478bd9Sstevel@tonic-gate 			 * to the receiver even though it is the
1557*7c478bd9Sstevel@tonic-gate 			 * same machine. Instead, if the
1558*7c478bd9Sstevel@tonic-gate 			 * hostname the source and target are
1559*7c478bd9Sstevel@tonic-gate 			 * the same the message if thrown away
1560*7c478bd9Sstevel@tonic-gate 			 */
1561*7c478bd9Sstevel@tonic-gate 			forwardingloop = 0;
1562*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < hlp->hl_cnt; i++) {
1563*7c478bd9Sstevel@tonic-gate 				if (strcmp(hlp->hl_hosts[i],
1564*7c478bd9Sstevel@tonic-gate 					f->f_un.f_forw.f_hname) == 0) {
1565*7c478bd9Sstevel@tonic-gate 					DPRINT3(1, errmsg, f->f_thread,
1566*7c478bd9Sstevel@tonic-gate 						f->f_un.f_forw.f_hname,
1567*7c478bd9Sstevel@tonic-gate 						hlp->hl_hosts[i]);
1568*7c478bd9Sstevel@tonic-gate 					forwardingloop = 1;
1569*7c478bd9Sstevel@tonic-gate 					break;
1570*7c478bd9Sstevel@tonic-gate 				}
1571*7c478bd9Sstevel@tonic-gate 			}
1572*7c478bd9Sstevel@tonic-gate 
1573*7c478bd9Sstevel@tonic-gate 			if (forwardingloop == 1) {
1574*7c478bd9Sstevel@tonic-gate 				f->f_stat.cantfwd++;
1575*7c478bd9Sstevel@tonic-gate 				goto out;
1576*7c478bd9Sstevel@tonic-gate 			}
1577*7c478bd9Sstevel@tonic-gate 		}
1578*7c478bd9Sstevel@tonic-gate 
1579*7c478bd9Sstevel@tonic-gate 		f->f_msgflag |= CURRENT_VALID;
1580*7c478bd9Sstevel@tonic-gate 
1581*7c478bd9Sstevel@tonic-gate 		/* check for dup message */
1582*7c478bd9Sstevel@tonic-gate 		if (f->f_type != F_FORW &&
1583*7c478bd9Sstevel@tonic-gate 			(f->f_msgflag & OLD_VALID) &&
1584*7c478bd9Sstevel@tonic-gate 			prevofst == currofst &&
1585*7c478bd9Sstevel@tonic-gate 			(strcmp(f->f_prevmsg.msg + prevofst,
1586*7c478bd9Sstevel@tonic-gate 				f->f_current.msg + currofst) == 0) &&
1587*7c478bd9Sstevel@tonic-gate 			(strcmp(f->f_prevmsg.host,
1588*7c478bd9Sstevel@tonic-gate 				f->f_current.host) == 0)) {
1589*7c478bd9Sstevel@tonic-gate 			/* a dup */
1590*7c478bd9Sstevel@tonic-gate 			DPRINT2(2, "logit(%u): msg is dup - %p\n",
1591*7c478bd9Sstevel@tonic-gate 				f->f_thread, mp);
1592*7c478bd9Sstevel@tonic-gate 			if (currofst == 16) {
1593*7c478bd9Sstevel@tonic-gate 				(void) strncpy(f->f_prevmsg.msg,
1594*7c478bd9Sstevel@tonic-gate 				f->f_current.msg, 15); /* update time */
1595*7c478bd9Sstevel@tonic-gate 			}
1596*7c478bd9Sstevel@tonic-gate 			f->f_prevcount++;
1597*7c478bd9Sstevel@tonic-gate 			f->f_stat.dups++;
1598*7c478bd9Sstevel@tonic-gate 			f->f_stat.total++;
1599*7c478bd9Sstevel@tonic-gate 			f->f_msgflag &= ~CURRENT_VALID;
1600*7c478bd9Sstevel@tonic-gate 		} else {
1601*7c478bd9Sstevel@tonic-gate 			/* new: mark or prior dups exist */
1602*7c478bd9Sstevel@tonic-gate 			if (f->f_current.flags & MARK || f->f_prevcount > 0) {
1603*7c478bd9Sstevel@tonic-gate 				if (f->f_prevcount > 0 && f->f_type != F_FORW) {
1604*7c478bd9Sstevel@tonic-gate 					set_flush_msg(f);
1605*7c478bd9Sstevel@tonic-gate 					if (f->f_msgflag & OLD_VALID) {
1606*7c478bd9Sstevel@tonic-gate 						writemsg(SAVED, f);
1607*7c478bd9Sstevel@tonic-gate 					}
1608*7c478bd9Sstevel@tonic-gate 				}
1609*7c478bd9Sstevel@tonic-gate 				if (f->f_msgflag & CURRENT_VALID)
1610*7c478bd9Sstevel@tonic-gate 					writemsg(CURRENT, f);
1611*7c478bd9Sstevel@tonic-gate 				if (!(mp->flags & NOCOPY))
1612*7c478bd9Sstevel@tonic-gate 					copy_msg(f);
1613*7c478bd9Sstevel@tonic-gate 				if (f->f_current.flags & MARK) {
1614*7c478bd9Sstevel@tonic-gate 					DPRINT2(2, "logit(%u): msg is "
1615*7c478bd9Sstevel@tonic-gate 						"mark - %p)\n",
1616*7c478bd9Sstevel@tonic-gate 						f->f_thread, mp);
1617*7c478bd9Sstevel@tonic-gate 					f->f_msgflag &= ~OLD_VALID;
1618*7c478bd9Sstevel@tonic-gate 				} else {
1619*7c478bd9Sstevel@tonic-gate 					DPRINT2(2, "logit(%u): saving "
1620*7c478bd9Sstevel@tonic-gate 						"message - %p\n",
1621*7c478bd9Sstevel@tonic-gate 						f->f_thread, mp);
1622*7c478bd9Sstevel@tonic-gate 				}
1623*7c478bd9Sstevel@tonic-gate 				f->f_stat.total++;
1624*7c478bd9Sstevel@tonic-gate 			} else { /* new message */
1625*7c478bd9Sstevel@tonic-gate 				DPRINT2(2, "logit(%u): msg is new "
1626*7c478bd9Sstevel@tonic-gate 					"- %p\n", f->f_thread, mp);
1627*7c478bd9Sstevel@tonic-gate 				writemsg(CURRENT, f);
1628*7c478bd9Sstevel@tonic-gate 				if (!(mp->flags & NOCOPY))
1629*7c478bd9Sstevel@tonic-gate 					copy_msg(f);
1630*7c478bd9Sstevel@tonic-gate 				f->f_stat.total++;
1631*7c478bd9Sstevel@tonic-gate 			}
1632*7c478bd9Sstevel@tonic-gate 		}
1633*7c478bd9Sstevel@tonic-gate 		/*
1634*7c478bd9Sstevel@tonic-gate 		 * if message refcnt goes to zero after we decrement
1635*7c478bd9Sstevel@tonic-gate 		 * it here, we are the last consumer of the message,
1636*7c478bd9Sstevel@tonic-gate 		 * and we should free it.  We need to hold the lock
1637*7c478bd9Sstevel@tonic-gate 		 * between decrementing the count and checking for
1638*7c478bd9Sstevel@tonic-gate 		 * zero so another thread doesn't beat us to it.
1639*7c478bd9Sstevel@tonic-gate 		 */
1640*7c478bd9Sstevel@tonic-gate out:
1641*7c478bd9Sstevel@tonic-gate 		pthread_mutex_lock(&mp->msg_mutex);
1642*7c478bd9Sstevel@tonic-gate 		refcnt = --mp->refcnt;
1643*7c478bd9Sstevel@tonic-gate 		pthread_mutex_unlock(&mp->msg_mutex);
1644*7c478bd9Sstevel@tonic-gate 		if (refcnt == 0)
1645*7c478bd9Sstevel@tonic-gate 			free_msg(mp);
1646*7c478bd9Sstevel@tonic-gate 	}
1647*7c478bd9Sstevel@tonic-gate 	/* register our exit */
1648*7c478bd9Sstevel@tonic-gate 
1649*7c478bd9Sstevel@tonic-gate 	/*
1650*7c478bd9Sstevel@tonic-gate 	 * Pull out all pending messages, if they exist.
1651*7c478bd9Sstevel@tonic-gate 	 */
1652*7c478bd9Sstevel@tonic-gate 
1653*7c478bd9Sstevel@tonic-gate 	pthread_mutex_lock(&f->filed_mutex);
1654*7c478bd9Sstevel@tonic-gate 
1655*7c478bd9Sstevel@tonic-gate 	while (f->f_queue_count > 0) {
1656*7c478bd9Sstevel@tonic-gate 		(void) dataq_dequeue(&f->f_queue, (void **)&mp, 0);
1657*7c478bd9Sstevel@tonic-gate 		DPRINT3(5, "logit(%u): logger dequeued msg %p from queue "
1658*7c478bd9Sstevel@tonic-gate 			"%p\n",
1659*7c478bd9Sstevel@tonic-gate 			f->f_thread, mp, &f->f_queue);
1660*7c478bd9Sstevel@tonic-gate 		pthread_mutex_lock(&mp->msg_mutex);
1661*7c478bd9Sstevel@tonic-gate 		refcnt = --mp->refcnt;
1662*7c478bd9Sstevel@tonic-gate 		pthread_mutex_unlock(&mp->msg_mutex);
1663*7c478bd9Sstevel@tonic-gate 		if (refcnt == 0)
1664*7c478bd9Sstevel@tonic-gate 			free_msg(mp);
1665*7c478bd9Sstevel@tonic-gate 		f->f_queue_count--;
1666*7c478bd9Sstevel@tonic-gate 	}
1667*7c478bd9Sstevel@tonic-gate 
1668*7c478bd9Sstevel@tonic-gate 	pthread_mutex_unlock(&f->filed_mutex);
1669*7c478bd9Sstevel@tonic-gate 
1670*7c478bd9Sstevel@tonic-gate 	if (f->f_type != F_USERS && f->f_type != F_WALL &&
1671*7c478bd9Sstevel@tonic-gate 		f->f_type != F_UNUSED) {
1672*7c478bd9Sstevel@tonic-gate 		if (f->f_type == F_FORW)
1673*7c478bd9Sstevel@tonic-gate 			(void) t_close(f->f_file);
1674*7c478bd9Sstevel@tonic-gate 		else
1675*7c478bd9Sstevel@tonic-gate 			(void) close(f->f_file);
1676*7c478bd9Sstevel@tonic-gate 	}
1677*7c478bd9Sstevel@tonic-gate 
1678*7c478bd9Sstevel@tonic-gate 	/*
1679*7c478bd9Sstevel@tonic-gate 	 * Since f_type may have been changed before this point, we need
1680*7c478bd9Sstevel@tonic-gate 	 * to test orig_type.
1681*7c478bd9Sstevel@tonic-gate 	 */
1682*7c478bd9Sstevel@tonic-gate 	if (f->f_orig_type == F_FORW) {
1683*7c478bd9Sstevel@tonic-gate 		free(f->f_un.f_forw.f_addr.buf);
1684*7c478bd9Sstevel@tonic-gate 	}
1685*7c478bd9Sstevel@tonic-gate 
1686*7c478bd9Sstevel@tonic-gate 	f->f_type = F_UNUSED;
1687*7c478bd9Sstevel@tonic-gate 	pthread_mutex_lock(&cft);
1688*7c478bd9Sstevel@tonic-gate 	--conf_threads;
1689*7c478bd9Sstevel@tonic-gate 	pthread_mutex_unlock(&cft);
1690*7c478bd9Sstevel@tonic-gate 	DPRINT1(5, "logit(%u): logging thread exited\n", f->f_thread);
1691*7c478bd9Sstevel@tonic-gate 	return (NULL);
1692*7c478bd9Sstevel@tonic-gate }
1693*7c478bd9Sstevel@tonic-gate 
1694*7c478bd9Sstevel@tonic-gate /*
1695*7c478bd9Sstevel@tonic-gate  * change the previous message to a flush message, stating how
1696*7c478bd9Sstevel@tonic-gate  * many repeats occurred since the last flush
1697*7c478bd9Sstevel@tonic-gate  */
1698*7c478bd9Sstevel@tonic-gate static void
1699*7c478bd9Sstevel@tonic-gate set_flush_msg(struct filed *f)
1700*7c478bd9Sstevel@tonic-gate {
1701*7c478bd9Sstevel@tonic-gate 	char tbuf[10];
1702*7c478bd9Sstevel@tonic-gate 	int prevofst = (f->f_prevmsg.flags & ADDDATE) ? 0 : 16;
1703*7c478bd9Sstevel@tonic-gate 
1704*7c478bd9Sstevel@tonic-gate 	if (f->f_prevcount == 1)
1705*7c478bd9Sstevel@tonic-gate 		(void) strncpy(tbuf, "time", sizeof (tbuf));
1706*7c478bd9Sstevel@tonic-gate 	else
1707*7c478bd9Sstevel@tonic-gate 		(void) strncpy(tbuf, "times", sizeof (tbuf));
1708*7c478bd9Sstevel@tonic-gate 
1709*7c478bd9Sstevel@tonic-gate 	(void) sprintf(f->f_prevmsg.msg+prevofst,
1710*7c478bd9Sstevel@tonic-gate 		"last message repeated %d %s", f->f_prevcount, tbuf);
1711*7c478bd9Sstevel@tonic-gate 	f->f_prevcount = 0;
1712*7c478bd9Sstevel@tonic-gate 	f->f_msgflag |= OLD_VALID;
1713*7c478bd9Sstevel@tonic-gate }
1714*7c478bd9Sstevel@tonic-gate 
1715*7c478bd9Sstevel@tonic-gate 
1716*7c478bd9Sstevel@tonic-gate /*
1717*7c478bd9Sstevel@tonic-gate  * the actual writing of the message is broken into a separate function
1718*7c478bd9Sstevel@tonic-gate  * because each file has a current and saved message associated with
1719*7c478bd9Sstevel@tonic-gate  * it (for duplicate message detection). It is necessary to be able
1720*7c478bd9Sstevel@tonic-gate  * to write either the saved message or the current message.
1721*7c478bd9Sstevel@tonic-gate  */
1722*7c478bd9Sstevel@tonic-gate static void
1723*7c478bd9Sstevel@tonic-gate writemsg(int selection, struct filed *f)
1724*7c478bd9Sstevel@tonic-gate {
1725*7c478bd9Sstevel@tonic-gate 	char *cp, *p;
1726*7c478bd9Sstevel@tonic-gate 	int pri;
1727*7c478bd9Sstevel@tonic-gate 	int flags;
1728*7c478bd9Sstevel@tonic-gate 	int l;
1729*7c478bd9Sstevel@tonic-gate 	time_t ts;
1730*7c478bd9Sstevel@tonic-gate 	struct t_unitdata ud;
1731*7c478bd9Sstevel@tonic-gate 	char *eomp, *eomp2, *from, *text, *msg;
1732*7c478bd9Sstevel@tonic-gate 	char line[MAXLINE*2];
1733*7c478bd9Sstevel@tonic-gate 	char head[MAXLINE+1];
1734*7c478bd9Sstevel@tonic-gate 	char tmpbuf[MAXLINE+1];
1735*7c478bd9Sstevel@tonic-gate 	char cbuf[30];
1736*7c478bd9Sstevel@tonic-gate 	char *filtered;
1737*7c478bd9Sstevel@tonic-gate 	char *msgid_start, *msgid_end;
1738*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
1739*7c478bd9Sstevel@tonic-gate 	size_t	hlen, filter_len;
1740*7c478bd9Sstevel@tonic-gate 
1741*7c478bd9Sstevel@tonic-gate 	if (Debug) {
1742*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
1743*7c478bd9Sstevel@tonic-gate 	}
1744*7c478bd9Sstevel@tonic-gate 
1745*7c478bd9Sstevel@tonic-gate 	switch (selection) {
1746*7c478bd9Sstevel@tonic-gate 	default:
1747*7c478bd9Sstevel@tonic-gate 	case CURRENT:		/* print current message */
1748*7c478bd9Sstevel@tonic-gate 		msg = f->f_current.msg;
1749*7c478bd9Sstevel@tonic-gate 		from = f->f_current.host;
1750*7c478bd9Sstevel@tonic-gate 		pri = f->f_current.pri;
1751*7c478bd9Sstevel@tonic-gate 		flags = f->f_current.flags;
1752*7c478bd9Sstevel@tonic-gate 		ts = f->f_current.time;
1753*7c478bd9Sstevel@tonic-gate 		f->f_msgflag &= ~CURRENT_VALID;
1754*7c478bd9Sstevel@tonic-gate 		break;
1755*7c478bd9Sstevel@tonic-gate 	case SAVED:		/* print saved message */
1756*7c478bd9Sstevel@tonic-gate 		msg = f->f_prevmsg.msg;
1757*7c478bd9Sstevel@tonic-gate 		from = f->f_prevmsg.host;
1758*7c478bd9Sstevel@tonic-gate 		pri = f->f_prevmsg.pri;
1759*7c478bd9Sstevel@tonic-gate 		flags = f->f_prevmsg.flags;
1760*7c478bd9Sstevel@tonic-gate 		ts = f->f_prevmsg.time;
1761*7c478bd9Sstevel@tonic-gate 		f->f_msgflag &= ~OLD_VALID;
1762*7c478bd9Sstevel@tonic-gate 		break;
1763*7c478bd9Sstevel@tonic-gate 	}
1764*7c478bd9Sstevel@tonic-gate 
1765*7c478bd9Sstevel@tonic-gate 	if (msg[0] == '\0')
1766*7c478bd9Sstevel@tonic-gate 		return;
1767*7c478bd9Sstevel@tonic-gate 
1768*7c478bd9Sstevel@tonic-gate 	cp = line;
1769*7c478bd9Sstevel@tonic-gate 
1770*7c478bd9Sstevel@tonic-gate 	if (flags & ADDDATE)
1771*7c478bd9Sstevel@tonic-gate 		(void) strncpy(cp, ctime_r(&ts, cbuf) + 4, 15);
1772*7c478bd9Sstevel@tonic-gate 	else
1773*7c478bd9Sstevel@tonic-gate 		(void) strncpy(cp, msg, 15);
1774*7c478bd9Sstevel@tonic-gate 
1775*7c478bd9Sstevel@tonic-gate 	line[15] = '\0';
1776*7c478bd9Sstevel@tonic-gate 	(void) strcat(cp, " ");
1777*7c478bd9Sstevel@tonic-gate 	(void) strcat(cp, from);
1778*7c478bd9Sstevel@tonic-gate 	(void) strcat(cp, " ");
1779*7c478bd9Sstevel@tonic-gate 	text = cp + strlen(cp);
1780*7c478bd9Sstevel@tonic-gate 
1781*7c478bd9Sstevel@tonic-gate 	if (flags & ADDDATE)
1782*7c478bd9Sstevel@tonic-gate 		(void) strcat(cp, msg);
1783*7c478bd9Sstevel@tonic-gate 	else
1784*7c478bd9Sstevel@tonic-gate 		(void) strcat(cp, msg+16);
1785*7c478bd9Sstevel@tonic-gate 	DPRINT2(5, "writemsg(%u): text = \"%s\"\n", mythreadno, text);
1786*7c478bd9Sstevel@tonic-gate 
1787*7c478bd9Sstevel@tonic-gate 	errno = 0;
1788*7c478bd9Sstevel@tonic-gate 	t_errno = 0;
1789*7c478bd9Sstevel@tonic-gate 	switch (f->f_type) {
1790*7c478bd9Sstevel@tonic-gate 	case F_UNUSED:
1791*7c478bd9Sstevel@tonic-gate 		DPRINT1(1, "writemsg(%u): UNUSED\n", mythreadno);
1792*7c478bd9Sstevel@tonic-gate 		break;
1793*7c478bd9Sstevel@tonic-gate 	case F_FORW:
1794*7c478bd9Sstevel@tonic-gate 		DPRINT4(1, "writemsg(%u): Logging msg '%s' to %s %s\n",
1795*7c478bd9Sstevel@tonic-gate 			mythreadno, msg, TypeNames[f->f_type],
1796*7c478bd9Sstevel@tonic-gate 			f->f_un.f_forw.f_hname);
1797*7c478bd9Sstevel@tonic-gate 
1798*7c478bd9Sstevel@tonic-gate 		hlen = snprintf(head, sizeof (head),
1799*7c478bd9Sstevel@tonic-gate 			"<%d>%.15s ", pri, cp);
1800*7c478bd9Sstevel@tonic-gate 
1801*7c478bd9Sstevel@tonic-gate 		DPRINT2(5, "writemsg(%u): head = \"%s\"\n", mythreadno, head);
1802*7c478bd9Sstevel@tonic-gate 		DPRINT2(5, "writemsg(%u): hlen = %d\n", mythreadno, hlen);
1803*7c478bd9Sstevel@tonic-gate 
1804*7c478bd9Sstevel@tonic-gate 		l = strlen(text);
1805*7c478bd9Sstevel@tonic-gate 		p = text;
1806*7c478bd9Sstevel@tonic-gate 
1807*7c478bd9Sstevel@tonic-gate 		DPRINT2(5, "writemsg(%u): text = \"%s\"\n", mythreadno, text);
1808*7c478bd9Sstevel@tonic-gate 		DPRINT2(5, "writemsg(%u): strlen(text) = %d\n", mythreadno, l);
1809*7c478bd9Sstevel@tonic-gate 
1810*7c478bd9Sstevel@tonic-gate 		(void) strncpy(tmpbuf, head, hlen);
1811*7c478bd9Sstevel@tonic-gate 
1812*7c478bd9Sstevel@tonic-gate 		while (l > 0) {
1813*7c478bd9Sstevel@tonic-gate 			size_t	len;
1814*7c478bd9Sstevel@tonic-gate 
1815*7c478bd9Sstevel@tonic-gate 			len = copy_frwd(tmpbuf + hlen, sizeof (tmpbuf) - hlen,
1816*7c478bd9Sstevel@tonic-gate 					p, l);
1817*7c478bd9Sstevel@tonic-gate 
1818*7c478bd9Sstevel@tonic-gate 			DPRINT2(5, "writemsg(%u): tmpbuf = \"%s\"\n",
1819*7c478bd9Sstevel@tonic-gate 				mythreadno, tmpbuf);
1820*7c478bd9Sstevel@tonic-gate 			DPRINT2(5, "writemsg(%u): len = %d\n", mythreadno,
1821*7c478bd9Sstevel@tonic-gate 				len);
1822*7c478bd9Sstevel@tonic-gate 			DPRINT2(5, "writemsg(%u): strlen(tmpbuf) = %d\n",
1823*7c478bd9Sstevel@tonic-gate 				mythreadno, strlen(tmpbuf));
1824*7c478bd9Sstevel@tonic-gate 
1825*7c478bd9Sstevel@tonic-gate 			ud.opt.buf = NULL;
1826*7c478bd9Sstevel@tonic-gate 			ud.opt.len = 0;
1827*7c478bd9Sstevel@tonic-gate 			ud.udata.buf = tmpbuf;
1828*7c478bd9Sstevel@tonic-gate 			ud.udata.len = len + hlen;
1829*7c478bd9Sstevel@tonic-gate 			ud.addr.maxlen = f->f_un.f_forw.f_addr.maxlen;
1830*7c478bd9Sstevel@tonic-gate 			ud.addr.buf = f->f_un.f_forw.f_addr.buf;
1831*7c478bd9Sstevel@tonic-gate 			ud.addr.len = f->f_un.f_forw.f_addr.len;
1832*7c478bd9Sstevel@tonic-gate 			if (t_sndudata(f->f_file, &ud) < 0) {
1833*7c478bd9Sstevel@tonic-gate 				if ((hup_state & HUP_INPROGRESS) &&
1834*7c478bd9Sstevel@tonic-gate 					f->f_type == F_UNUSED) {
1835*7c478bd9Sstevel@tonic-gate 					break;
1836*7c478bd9Sstevel@tonic-gate 				}
1837*7c478bd9Sstevel@tonic-gate 				(void) t_close(f->f_file);
1838*7c478bd9Sstevel@tonic-gate 				f->f_type = F_UNUSED;
1839*7c478bd9Sstevel@tonic-gate 				logerror("t_sndudata");
1840*7c478bd9Sstevel@tonic-gate 
1841*7c478bd9Sstevel@tonic-gate 				/*
1842*7c478bd9Sstevel@tonic-gate 				 * Since it has already failed, it's not worth
1843*7c478bd9Sstevel@tonic-gate 				 * continuing output from the middle of
1844*7c478bd9Sstevel@tonic-gate 				 * message string.
1845*7c478bd9Sstevel@tonic-gate 				 */
1846*7c478bd9Sstevel@tonic-gate 				break;
1847*7c478bd9Sstevel@tonic-gate 			}
1848*7c478bd9Sstevel@tonic-gate 			p += len;
1849*7c478bd9Sstevel@tonic-gate 			l -= len;
1850*7c478bd9Sstevel@tonic-gate 		}
1851*7c478bd9Sstevel@tonic-gate 		break;
1852*7c478bd9Sstevel@tonic-gate 	case F_CONSOLE:
1853*7c478bd9Sstevel@tonic-gate 	case F_TTY:
1854*7c478bd9Sstevel@tonic-gate 	case F_FILE:
1855*7c478bd9Sstevel@tonic-gate 	case F_USERS:
1856*7c478bd9Sstevel@tonic-gate 	case F_WALL:
1857*7c478bd9Sstevel@tonic-gate 		DPRINT4(1, "writemsg(%u): Logging msg '%s' to %s %s\n",
1858*7c478bd9Sstevel@tonic-gate 			mythreadno, msg, TypeNames[f->f_type],
1859*7c478bd9Sstevel@tonic-gate 			((f->f_type == F_USERS) || (f->f_type == F_WALL)) ?
1860*7c478bd9Sstevel@tonic-gate 			"" : f->f_un.f_fname);
1861*7c478bd9Sstevel@tonic-gate 		/*
1862*7c478bd9Sstevel@tonic-gate 		 * filter the string in preparation for writing it
1863*7c478bd9Sstevel@tonic-gate 		 * save the original for possible forwarding.
1864*7c478bd9Sstevel@tonic-gate 		 * In case every byte in cp is a control character,
1865*7c478bd9Sstevel@tonic-gate 		 * allocates large enough buffer for filtered.
1866*7c478bd9Sstevel@tonic-gate 		 */
1867*7c478bd9Sstevel@tonic-gate 
1868*7c478bd9Sstevel@tonic-gate 		filter_len = strlen(cp) * 4 + 1;
1869*7c478bd9Sstevel@tonic-gate 		filtered = (char *)malloc(filter_len);
1870*7c478bd9Sstevel@tonic-gate 		if (!filtered) {
1871*7c478bd9Sstevel@tonic-gate 			MALLOC_FAIL("dropping message");
1872*7c478bd9Sstevel@tonic-gate 			/* seems we can just return */
1873*7c478bd9Sstevel@tonic-gate 			return;
1874*7c478bd9Sstevel@tonic-gate 		}
1875*7c478bd9Sstevel@tonic-gate 		DPRINT3(5, "writemsg(%u): "
1876*7c478bd9Sstevel@tonic-gate 			"filtered allocated (%p: %d bytes)\n",
1877*7c478bd9Sstevel@tonic-gate 			mythreadno, filtered, filter_len);
1878*7c478bd9Sstevel@tonic-gate 		/* -3 : we may add "\r\n" to ecomp(filtered) later */
1879*7c478bd9Sstevel@tonic-gate 		filter_string(cp, filtered, filter_len - 3);
1880*7c478bd9Sstevel@tonic-gate 
1881*7c478bd9Sstevel@tonic-gate 		DPRINT2(5, "writemsg(%u): strlen(filtered) = %d\n",
1882*7c478bd9Sstevel@tonic-gate 			mythreadno, strlen(filtered));
1883*7c478bd9Sstevel@tonic-gate 		/*
1884*7c478bd9Sstevel@tonic-gate 		 * If we're writing to the console, strip out the message ID
1885*7c478bd9Sstevel@tonic-gate 		 * to reduce visual clutter.
1886*7c478bd9Sstevel@tonic-gate 		 */
1887*7c478bd9Sstevel@tonic-gate 		if ((msgid_start = strstr(filtered, "[ID ")) != NULL &&
1888*7c478bd9Sstevel@tonic-gate 			(msgid_end = strstr(msgid_start, "] ")) != NULL &&
1889*7c478bd9Sstevel@tonic-gate 			f->f_type == F_CONSOLE)
1890*7c478bd9Sstevel@tonic-gate 			(void) strcpy(msgid_start, msgid_end + 2);
1891*7c478bd9Sstevel@tonic-gate 
1892*7c478bd9Sstevel@tonic-gate 		eomp = filtered + strlen(filtered);
1893*7c478bd9Sstevel@tonic-gate 
1894*7c478bd9Sstevel@tonic-gate 		if ((f->f_type == F_USERS) || (f->f_type == F_WALL)) {
1895*7c478bd9Sstevel@tonic-gate 			/* CSTYLED */
1896*7c478bd9Sstevel@tonic-gate 			(void) strcat(eomp, "\r\n"); /*lint !e669*/
1897*7c478bd9Sstevel@tonic-gate 			/*
1898*7c478bd9Sstevel@tonic-gate 			 * Since wallmsg messes with utmpx we need
1899*7c478bd9Sstevel@tonic-gate 			 * to guarantee single threadedness...
1900*7c478bd9Sstevel@tonic-gate 			 */
1901*7c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_lock(&wmp);
1902*7c478bd9Sstevel@tonic-gate 			wallmsg(f, from, filtered);
1903*7c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&wmp);
1904*7c478bd9Sstevel@tonic-gate 
1905*7c478bd9Sstevel@tonic-gate 			/*
1906*7c478bd9Sstevel@tonic-gate 			 * The contents of filtered have been copied
1907*7c478bd9Sstevel@tonic-gate 			 * out to the struct walldev. We should free it here.
1908*7c478bd9Sstevel@tonic-gate 			 */
1909*7c478bd9Sstevel@tonic-gate 
1910*7c478bd9Sstevel@tonic-gate 			free(filtered);
1911*7c478bd9Sstevel@tonic-gate 
1912*7c478bd9Sstevel@tonic-gate 			/* exiting the switch */
1913*7c478bd9Sstevel@tonic-gate 			break;
1914*7c478bd9Sstevel@tonic-gate 		} else if (f->f_type != F_FILE) {
1915*7c478bd9Sstevel@tonic-gate 			/* CSTYLED */
1916*7c478bd9Sstevel@tonic-gate 			(void) strncpy(eomp, "\r\n", 3); /*lint !e669*/
1917*7c478bd9Sstevel@tonic-gate 		} else {
1918*7c478bd9Sstevel@tonic-gate 			if ((eomp2 = strchr(filtered, '\r')) != NULL) {
1919*7c478bd9Sstevel@tonic-gate 				(void) strncpy(eomp2, "\n", 2);
1920*7c478bd9Sstevel@tonic-gate 			} else {
1921*7c478bd9Sstevel@tonic-gate 				/* CSTYLED */
1922*7c478bd9Sstevel@tonic-gate 				(void) strncpy(eomp, "\n", 2); /*lint !e669*/
1923*7c478bd9Sstevel@tonic-gate 			}
1924*7c478bd9Sstevel@tonic-gate 		}
1925*7c478bd9Sstevel@tonic-gate 		if (write(f->f_file, filtered, strlen(filtered)) < 0) {
1926*7c478bd9Sstevel@tonic-gate 			int e = errno;
1927*7c478bd9Sstevel@tonic-gate 
1928*7c478bd9Sstevel@tonic-gate 			if ((hup_state & HUP_INPROGRESS) &&
1929*7c478bd9Sstevel@tonic-gate 				f->f_type == F_UNUSED) {
1930*7c478bd9Sstevel@tonic-gate 				free(filtered);
1931*7c478bd9Sstevel@tonic-gate 				break;
1932*7c478bd9Sstevel@tonic-gate 			}
1933*7c478bd9Sstevel@tonic-gate 			(void) close(f->f_file);
1934*7c478bd9Sstevel@tonic-gate 			/*
1935*7c478bd9Sstevel@tonic-gate 			 * Check for EBADF on TTY's due
1936*7c478bd9Sstevel@tonic-gate 			 * to vhangup() XXX
1937*7c478bd9Sstevel@tonic-gate 			 */
1938*7c478bd9Sstevel@tonic-gate 			if (e == EBADF && f->f_type != F_FILE) {
1939*7c478bd9Sstevel@tonic-gate 				f->f_file = open(f->f_un.f_fname,
1940*7c478bd9Sstevel@tonic-gate 					O_WRONLY|O_APPEND|O_NOCTTY);
1941*7c478bd9Sstevel@tonic-gate 				if (f->f_file < 0) {
1942*7c478bd9Sstevel@tonic-gate 					f->f_type = F_UNUSED;
1943*7c478bd9Sstevel@tonic-gate 					logerror(f->f_un.f_fname);
1944*7c478bd9Sstevel@tonic-gate 					f->f_stat.errs++;
1945*7c478bd9Sstevel@tonic-gate 				}
1946*7c478bd9Sstevel@tonic-gate 				untty();
1947*7c478bd9Sstevel@tonic-gate 			} else {
1948*7c478bd9Sstevel@tonic-gate 				f->f_type = F_UNUSED;
1949*7c478bd9Sstevel@tonic-gate 				f->f_stat.errs++;
1950*7c478bd9Sstevel@tonic-gate 				errno = e;
1951*7c478bd9Sstevel@tonic-gate 				logerror(f->f_un.f_fname);
1952*7c478bd9Sstevel@tonic-gate 			}
1953*7c478bd9Sstevel@tonic-gate 		} else if (flags & SYNC_FILE)
1954*7c478bd9Sstevel@tonic-gate 			if (((pri & LOG_FACMASK) >> 3) == LOG_KERN)
1955*7c478bd9Sstevel@tonic-gate 				(void) fsync(f->f_file);
1956*7c478bd9Sstevel@tonic-gate 
1957*7c478bd9Sstevel@tonic-gate 		DPRINT2(5, "writemsg(%u): freeing filtered (%p)\n",
1958*7c478bd9Sstevel@tonic-gate 			mythreadno, filtered);
1959*7c478bd9Sstevel@tonic-gate 
1960*7c478bd9Sstevel@tonic-gate 		free(filtered);
1961*7c478bd9Sstevel@tonic-gate 		break;
1962*7c478bd9Sstevel@tonic-gate 	}
1963*7c478bd9Sstevel@tonic-gate }
1964*7c478bd9Sstevel@tonic-gate 
1965*7c478bd9Sstevel@tonic-gate /*
1966*7c478bd9Sstevel@tonic-gate  *  WALLMSG -- Write a message to the world at large
1967*7c478bd9Sstevel@tonic-gate  *
1968*7c478bd9Sstevel@tonic-gate  *	Write the specified message to either the entire
1969*7c478bd9Sstevel@tonic-gate  *	world, or a list of approved users.
1970*7c478bd9Sstevel@tonic-gate  */
1971*7c478bd9Sstevel@tonic-gate static void
1972*7c478bd9Sstevel@tonic-gate wallmsg(struct filed *f, char *from, char *msg)
1973*7c478bd9Sstevel@tonic-gate {
1974*7c478bd9Sstevel@tonic-gate 	int i;
1975*7c478bd9Sstevel@tonic-gate 	size_t	len, clen;
1976*7c478bd9Sstevel@tonic-gate 	char *buf = NULL;
1977*7c478bd9Sstevel@tonic-gate 	struct utmpx *utxp;
1978*7c478bd9Sstevel@tonic-gate 	time_t now;
1979*7c478bd9Sstevel@tonic-gate 	char line[512], dev[100];
1980*7c478bd9Sstevel@tonic-gate 	char cp[MAXLINE+1];
1981*7c478bd9Sstevel@tonic-gate 	struct stat statbuf;
1982*7c478bd9Sstevel@tonic-gate 	walldev_t *w;
1983*7c478bd9Sstevel@tonic-gate 	char cbuf[30];
1984*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
1985*7c478bd9Sstevel@tonic-gate 
1986*7c478bd9Sstevel@tonic-gate 	if (Debug) {
1987*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
1988*7c478bd9Sstevel@tonic-gate 	}
1989*7c478bd9Sstevel@tonic-gate 
1990*7c478bd9Sstevel@tonic-gate 	if (access(UTMPX_FILE, R_OK) != 0 || stat(UTMPX_FILE, &statbuf) != 0) {
1991*7c478bd9Sstevel@tonic-gate 		logerror(UTMPX_FILE);
1992*7c478bd9Sstevel@tonic-gate 		return;
1993*7c478bd9Sstevel@tonic-gate 	} else if (statbuf.st_uid != 0 || (statbuf.st_mode & 07777) != 0644) {
1994*7c478bd9Sstevel@tonic-gate 		(void) sprintf(line, "%s %s", UTMPX_FILE,
1995*7c478bd9Sstevel@tonic-gate 			"not owned by root or not mode 644.\n"
1996*7c478bd9Sstevel@tonic-gate 			"This file must be owned by root "
1997*7c478bd9Sstevel@tonic-gate 			"and not writable by\n"
1998*7c478bd9Sstevel@tonic-gate 			"anyone other than root.  This alert is being "
1999*7c478bd9Sstevel@tonic-gate 			"dropped because of\n"
2000*7c478bd9Sstevel@tonic-gate 			"this problem.");
2001*7c478bd9Sstevel@tonic-gate 		logerror(line);
2002*7c478bd9Sstevel@tonic-gate 		return;
2003*7c478bd9Sstevel@tonic-gate 	}
2004*7c478bd9Sstevel@tonic-gate 
2005*7c478bd9Sstevel@tonic-gate 	if (f->f_type == F_WALL) {
2006*7c478bd9Sstevel@tonic-gate 		(void) time(&now);
2007*7c478bd9Sstevel@tonic-gate 		len = snprintf(line, sizeof (line),
2008*7c478bd9Sstevel@tonic-gate 			"\r\n\7Message from syslogd@%s "
2009*7c478bd9Sstevel@tonic-gate 			"at %.24s ...\r\n", from, ctime_r(&now, cbuf));
2010*7c478bd9Sstevel@tonic-gate 		len += strlen(msg + 16);
2011*7c478bd9Sstevel@tonic-gate 		buf = (char *)malloc(len + 1);
2012*7c478bd9Sstevel@tonic-gate 		if (!buf) {
2013*7c478bd9Sstevel@tonic-gate 			MALLOC_FAIL("dropping message");
2014*7c478bd9Sstevel@tonic-gate 			return;
2015*7c478bd9Sstevel@tonic-gate 		}
2016*7c478bd9Sstevel@tonic-gate 		DPRINT3(5, "wallmsg(%u): buf allocated (%p: %d bytes)\n",
2017*7c478bd9Sstevel@tonic-gate 			mythreadno, buf, len + 1);
2018*7c478bd9Sstevel@tonic-gate 		(void) strcpy(buf, line);
2019*7c478bd9Sstevel@tonic-gate 		(void) strcat(buf, msg + 16);
2020*7c478bd9Sstevel@tonic-gate 		clen = copy_frwd(cp, sizeof (cp), buf, len);
2021*7c478bd9Sstevel@tonic-gate 		DPRINT2(5, "wallmsg(%u): clen = %d\n",
2022*7c478bd9Sstevel@tonic-gate 			mythreadno, clen);
2023*7c478bd9Sstevel@tonic-gate 		DPRINT2(5, "wallmsg(%u): freeing buf (%p)\n",
2024*7c478bd9Sstevel@tonic-gate 			mythreadno, buf);
2025*7c478bd9Sstevel@tonic-gate 		free(buf);
2026*7c478bd9Sstevel@tonic-gate 	} else {
2027*7c478bd9Sstevel@tonic-gate 		clen = copy_frwd(cp, sizeof (cp), msg, strlen(msg));
2028*7c478bd9Sstevel@tonic-gate 		DPRINT2(5, "wallmsg(%u): clen = %d\n",
2029*7c478bd9Sstevel@tonic-gate 			mythreadno, clen);
2030*7c478bd9Sstevel@tonic-gate 	}
2031*7c478bd9Sstevel@tonic-gate 	/* scan the user login file */
2032*7c478bd9Sstevel@tonic-gate 	setutxent();
2033*7c478bd9Sstevel@tonic-gate 	while ((utxp = getutxent()) != NULL) {
2034*7c478bd9Sstevel@tonic-gate 		/* is this slot used? */
2035*7c478bd9Sstevel@tonic-gate 		if (utxp->ut_name[0] == '\0' ||
2036*7c478bd9Sstevel@tonic-gate 			utxp->ut_line[0] == '\0' ||
2037*7c478bd9Sstevel@tonic-gate 			utxp->ut_type != USER_PROCESS)
2038*7c478bd9Sstevel@tonic-gate 			continue;
2039*7c478bd9Sstevel@tonic-gate 		/* should we send the message to this user? */
2040*7c478bd9Sstevel@tonic-gate 		if (f->f_type == F_USERS) {
2041*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < MAXUNAMES; i++) {
2042*7c478bd9Sstevel@tonic-gate 				if (!f->f_un.f_uname[i][0]) {
2043*7c478bd9Sstevel@tonic-gate 					i = MAXUNAMES;
2044*7c478bd9Sstevel@tonic-gate 					break;
2045*7c478bd9Sstevel@tonic-gate 				}
2046*7c478bd9Sstevel@tonic-gate 				if (strncmp(f->f_un.f_uname[i],
2047*7c478bd9Sstevel@tonic-gate 					utxp->ut_name, UNAMESZ) == 0)
2048*7c478bd9Sstevel@tonic-gate 					break;
2049*7c478bd9Sstevel@tonic-gate 			}
2050*7c478bd9Sstevel@tonic-gate 			if (i >= MAXUNAMES)
2051*7c478bd9Sstevel@tonic-gate 				continue;
2052*7c478bd9Sstevel@tonic-gate 		}
2053*7c478bd9Sstevel@tonic-gate 
2054*7c478bd9Sstevel@tonic-gate 		/* compute the device name */
2055*7c478bd9Sstevel@tonic-gate 		if (utxp->ut_line[0] == '/') {
2056*7c478bd9Sstevel@tonic-gate 			(void) strncpy(dev, utxp->ut_line, UDEVSZ);
2057*7c478bd9Sstevel@tonic-gate 		} else {
2058*7c478bd9Sstevel@tonic-gate 			(void) strcpy(dev, "/dev/");
2059*7c478bd9Sstevel@tonic-gate 			(void) strncat(dev, utxp->ut_line, UDEVSZ);
2060*7c478bd9Sstevel@tonic-gate 		}
2061*7c478bd9Sstevel@tonic-gate 		DPRINT2(1, "wallmsg(%u): write to '%s'\n", mythreadno,
2062*7c478bd9Sstevel@tonic-gate 			dev);
2063*7c478bd9Sstevel@tonic-gate 
2064*7c478bd9Sstevel@tonic-gate 		if ((w = malloc(sizeof (walldev_t))) != NULL) {
2065*7c478bd9Sstevel@tonic-gate 			int rc;
2066*7c478bd9Sstevel@tonic-gate 			(void) pthread_attr_init(&w->thread_attr);
2067*7c478bd9Sstevel@tonic-gate 			(void) pthread_attr_setdetachstate(&w->thread_attr,
2068*7c478bd9Sstevel@tonic-gate 				PTHREAD_CREATE_DETACHED);
2069*7c478bd9Sstevel@tonic-gate 			(void) strncpy(w->dev, dev, PATH_MAX);
2070*7c478bd9Sstevel@tonic-gate 			(void) strncpy(w->msg, cp, MAXLINE+1);
2071*7c478bd9Sstevel@tonic-gate 			(void) strncpy(w->ut_name, utxp->ut_name,
2072*7c478bd9Sstevel@tonic-gate 			    sizeof (w->ut_name));
2073*7c478bd9Sstevel@tonic-gate 
2074*7c478bd9Sstevel@tonic-gate 			if ((rc = pthread_create(&w->thread, &w->thread_attr,
2075*7c478bd9Sstevel@tonic-gate 				writetodev, (void *) w)) != 0) {
2076*7c478bd9Sstevel@tonic-gate 				DPRINT2(5, "wallmsg(%u): wallmsg thread "
2077*7c478bd9Sstevel@tonic-gate 					"create failed rc = %d\n",
2078*7c478bd9Sstevel@tonic-gate 					mythreadno, rc);
2079*7c478bd9Sstevel@tonic-gate 				free(w);
2080*7c478bd9Sstevel@tonic-gate 				break;
2081*7c478bd9Sstevel@tonic-gate 			}
2082*7c478bd9Sstevel@tonic-gate 		} else {
2083*7c478bd9Sstevel@tonic-gate 			MALLOC_FAIL("dropping message to user");
2084*7c478bd9Sstevel@tonic-gate 		}
2085*7c478bd9Sstevel@tonic-gate 	}
2086*7c478bd9Sstevel@tonic-gate 	/* close the user login file */
2087*7c478bd9Sstevel@tonic-gate 	endutxent();
2088*7c478bd9Sstevel@tonic-gate }
2089*7c478bd9Sstevel@tonic-gate 
2090*7c478bd9Sstevel@tonic-gate /*
2091*7c478bd9Sstevel@tonic-gate  * Each time we need to write to a tty device (a potentially expensive
2092*7c478bd9Sstevel@tonic-gate  * or long-running operation) this routine gets called as a new
2093*7c478bd9Sstevel@tonic-gate  * detached, unbound thread. This allows writes to many devices
2094*7c478bd9Sstevel@tonic-gate  * to proceed nearly in parallel, without having to resort to
2095*7c478bd9Sstevel@tonic-gate  * asynchronous I/O or forking.
2096*7c478bd9Sstevel@tonic-gate  */
2097*7c478bd9Sstevel@tonic-gate static void *
2098*7c478bd9Sstevel@tonic-gate writetodev(void *ap)
2099*7c478bd9Sstevel@tonic-gate {
2100*7c478bd9Sstevel@tonic-gate 	walldev_t *w = ap;
2101*7c478bd9Sstevel@tonic-gate 	int ttyf;
2102*7c478bd9Sstevel@tonic-gate 	int len;
2103*7c478bd9Sstevel@tonic-gate 	struct stat statb;
2104*7c478bd9Sstevel@tonic-gate 	struct passwd pw, *pwp;
2105*7c478bd9Sstevel@tonic-gate 	char pwbuf[MAXLINE];
2106*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
2107*7c478bd9Sstevel@tonic-gate 
2108*7c478bd9Sstevel@tonic-gate 	if (Debug) {
2109*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
2110*7c478bd9Sstevel@tonic-gate 	}
2111*7c478bd9Sstevel@tonic-gate 
2112*7c478bd9Sstevel@tonic-gate 	DPRINT1(1, "writetodev(%u): Device writer thread started\n",
2113*7c478bd9Sstevel@tonic-gate 		mythreadno);
2114*7c478bd9Sstevel@tonic-gate 
2115*7c478bd9Sstevel@tonic-gate 	len = strlen(w->msg);
2116*7c478bd9Sstevel@tonic-gate 
2117*7c478bd9Sstevel@tonic-gate 	ttyf = open(w->dev, O_WRONLY|O_NOCTTY|O_NDELAY);
2118*7c478bd9Sstevel@tonic-gate 	if (ttyf >= 0) {
2119*7c478bd9Sstevel@tonic-gate 		if (fstat(ttyf, &statb) != 0) {
2120*7c478bd9Sstevel@tonic-gate 			DPRINT2(1, "writetodev(%u): Can't stat '%s'\n",
2121*7c478bd9Sstevel@tonic-gate 				mythreadno, w->dev);
2122*7c478bd9Sstevel@tonic-gate 			errno = 0;
2123*7c478bd9Sstevel@tonic-gate 			logerror("Can't stat '%s'", w->dev);
2124*7c478bd9Sstevel@tonic-gate 		} else if (!(statb.st_mode & S_IWRITE)) {
2125*7c478bd9Sstevel@tonic-gate 			DPRINT2(1, "writetodev(%u): Can't write to "
2126*7c478bd9Sstevel@tonic-gate 				"'%s'\n", mythreadno, w->dev);
2127*7c478bd9Sstevel@tonic-gate 		} else if (!isatty(ttyf)) {
2128*7c478bd9Sstevel@tonic-gate 			DPRINT2(1, "writetodev(%u): '%s' not a tty\n",
2129*7c478bd9Sstevel@tonic-gate 				mythreadno, w->dev);
2130*7c478bd9Sstevel@tonic-gate 			/*
2131*7c478bd9Sstevel@tonic-gate 			 * We might hit dtremote here. Don't generate
2132*7c478bd9Sstevel@tonic-gate 			 * error message.
2133*7c478bd9Sstevel@tonic-gate 			 */
2134*7c478bd9Sstevel@tonic-gate 		} else if (getpwuid_r(statb.st_uid, &pw, pwbuf,
2135*7c478bd9Sstevel@tonic-gate 				sizeof (pwbuf), &pwp) != 0) {
2136*7c478bd9Sstevel@tonic-gate 			DPRINT2(1, "writetodev(%u): Can't determine owner "
2137*7c478bd9Sstevel@tonic-gate 				"of '%s'\n", mythreadno, w->dev);
2138*7c478bd9Sstevel@tonic-gate 			errno = 0;
2139*7c478bd9Sstevel@tonic-gate 			logerror("Can't determine owner of '%s'", w->dev);
2140*7c478bd9Sstevel@tonic-gate 		} else if (strncmp(pw.pw_name, w->ut_name, UNAMESZ) != 0) {
2141*7c478bd9Sstevel@tonic-gate 			DPRINT2(1, "writetodev(%u): Bad terminal owner '%s'"
2142*7c478bd9Sstevel@tonic-gate 				"\n", mythreadno, w->dev);
2143*7c478bd9Sstevel@tonic-gate 			errno = 0;
2144*7c478bd9Sstevel@tonic-gate 			logerror("%s %s owns '%s' %s %.*s",
2145*7c478bd9Sstevel@tonic-gate 				"Bad terminal owner;", pw.pw_name, w->dev,
2146*7c478bd9Sstevel@tonic-gate 				"but utmpx says", UNAMESZ, w->ut_name);
2147*7c478bd9Sstevel@tonic-gate 		} else if (write(ttyf, w->msg, len) != len) {
2148*7c478bd9Sstevel@tonic-gate 			DPRINT2(1, "writetodev(%u): Write failed to "
2149*7c478bd9Sstevel@tonic-gate 				"'%s'\n", mythreadno, w->dev);
2150*7c478bd9Sstevel@tonic-gate 			errno = 0;
2151*7c478bd9Sstevel@tonic-gate 			logerror("Write failed to '%s'", w->dev);
2152*7c478bd9Sstevel@tonic-gate 		}
2153*7c478bd9Sstevel@tonic-gate 
2154*7c478bd9Sstevel@tonic-gate 		DPRINT2(1, "writetodev(%u): write to '%s' succeeded\n",
2155*7c478bd9Sstevel@tonic-gate 			mythreadno, w->dev);
2156*7c478bd9Sstevel@tonic-gate 
2157*7c478bd9Sstevel@tonic-gate 		(void) close(ttyf);
2158*7c478bd9Sstevel@tonic-gate 	} else {
2159*7c478bd9Sstevel@tonic-gate 		DPRINT2(1, "writetodev(%u): Can't open '%s'\n",
2160*7c478bd9Sstevel@tonic-gate 			mythreadno, w->dev);
2161*7c478bd9Sstevel@tonic-gate 	}
2162*7c478bd9Sstevel@tonic-gate 
2163*7c478bd9Sstevel@tonic-gate 	pthread_attr_destroy(&w->thread_attr);
2164*7c478bd9Sstevel@tonic-gate 	free(w);
2165*7c478bd9Sstevel@tonic-gate 
2166*7c478bd9Sstevel@tonic-gate 	DPRINT1(1, "writetodev(%u): Device writer thread exiting\n",
2167*7c478bd9Sstevel@tonic-gate 		mythreadno);
2168*7c478bd9Sstevel@tonic-gate 
2169*7c478bd9Sstevel@tonic-gate 	pthread_exit(0);
2170*7c478bd9Sstevel@tonic-gate 	return (NULL);
2171*7c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
2172*7c478bd9Sstevel@tonic-gate }
2173*7c478bd9Sstevel@tonic-gate 
2174*7c478bd9Sstevel@tonic-gate /*
2175*7c478bd9Sstevel@tonic-gate  * Return a printable representation of a host address. If unable to
2176*7c478bd9Sstevel@tonic-gate  * look up hostname, format the numeric address for display instead.
2177*7c478bd9Sstevel@tonic-gate  *
2178*7c478bd9Sstevel@tonic-gate  * First calls hnc_lookup to see if there is valid cache entry for
2179*7c478bd9Sstevel@tonic-gate  * given network address. If it failed, cvthname looks up hostname,
2180*7c478bd9Sstevel@tonic-gate  * and push the results into the hostname cache.
2181*7c478bd9Sstevel@tonic-gate  */
2182*7c478bd9Sstevel@tonic-gate static host_list_t *
2183*7c478bd9Sstevel@tonic-gate cvthname(struct netbuf *nbp, struct netconfig *ncp, char *failsafe_addr)
2184*7c478bd9Sstevel@tonic-gate {
2185*7c478bd9Sstevel@tonic-gate 	int i;
2186*7c478bd9Sstevel@tonic-gate 	host_list_t *h;
2187*7c478bd9Sstevel@tonic-gate 	struct nd_hostservlist *hsp;
2188*7c478bd9Sstevel@tonic-gate 	struct nd_hostserv *hspp;
2189*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
2190*7c478bd9Sstevel@tonic-gate 	char *uap;
2191*7c478bd9Sstevel@tonic-gate 
2192*7c478bd9Sstevel@tonic-gate 	if (Debug) {
2193*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
2194*7c478bd9Sstevel@tonic-gate 	}
2195*7c478bd9Sstevel@tonic-gate 
2196*7c478bd9Sstevel@tonic-gate 	if (Debug)
2197*7c478bd9Sstevel@tonic-gate 		uap = taddr2uaddr(ncp, nbp);
2198*7c478bd9Sstevel@tonic-gate 
2199*7c478bd9Sstevel@tonic-gate 	DPRINT2(2, "cvthname(%u): looking up hostname for %s\n",
2200*7c478bd9Sstevel@tonic-gate 			mythreadno, uap ? uap : "<unknown>");
2201*7c478bd9Sstevel@tonic-gate 
2202*7c478bd9Sstevel@tonic-gate 	if ((h = hnc_lookup(nbp, ncp)) != NULL) {
2203*7c478bd9Sstevel@tonic-gate 		DPRINT4(2, "cvthname(%u): Cache found %p for %s (%s)\n",
2204*7c478bd9Sstevel@tonic-gate 				mythreadno, h, uap ? uap : "<unknown>",
2205*7c478bd9Sstevel@tonic-gate 				h->hl_hosts[0]);
2206*7c478bd9Sstevel@tonic-gate 		return (h);
2207*7c478bd9Sstevel@tonic-gate 	}
2208*7c478bd9Sstevel@tonic-gate 	DPRINT2(2, "cvthname(%u): No cache found for %s\n",
2209*7c478bd9Sstevel@tonic-gate 			mythreadno, uap ? uap : "<unknown>");
2210*7c478bd9Sstevel@tonic-gate 
2211*7c478bd9Sstevel@tonic-gate 	if (Debug)
2212*7c478bd9Sstevel@tonic-gate 		free(uap);
2213*7c478bd9Sstevel@tonic-gate 
2214*7c478bd9Sstevel@tonic-gate 	if (ncp->nc_semantics != NC_TPI_CLTS) {
2215*7c478bd9Sstevel@tonic-gate 		return (NULL);
2216*7c478bd9Sstevel@tonic-gate 	}
2217*7c478bd9Sstevel@tonic-gate 
2218*7c478bd9Sstevel@tonic-gate 	/* memory allocation failure here is fatal */
2219*7c478bd9Sstevel@tonic-gate 	if ((h = malloc(sizeof (host_list_t))) == NULL) {
2220*7c478bd9Sstevel@tonic-gate 		MALLOC_FAIL("host name conversion");
2221*7c478bd9Sstevel@tonic-gate 		return (NULL);
2222*7c478bd9Sstevel@tonic-gate 	}
2223*7c478bd9Sstevel@tonic-gate 
2224*7c478bd9Sstevel@tonic-gate 	if (netdir_getbyaddr(ncp, &hsp, nbp) == 0) {
2225*7c478bd9Sstevel@tonic-gate 		if (hsp->h_cnt <= 0) {
2226*7c478bd9Sstevel@tonic-gate out:			netdir_free((void *)hsp, ND_HOSTSERVLIST);
2227*7c478bd9Sstevel@tonic-gate 			free(h);
2228*7c478bd9Sstevel@tonic-gate 			return (NULL);
2229*7c478bd9Sstevel@tonic-gate 		}
2230*7c478bd9Sstevel@tonic-gate 
2231*7c478bd9Sstevel@tonic-gate 		hspp = hsp->h_hostservs;
2232*7c478bd9Sstevel@tonic-gate 		h->hl_cnt = hsp->h_cnt;
2233*7c478bd9Sstevel@tonic-gate 		h->hl_hosts = (char **)malloc(sizeof (char *) * (h->hl_cnt));
2234*7c478bd9Sstevel@tonic-gate 		if (h->hl_hosts == NULL) {
2235*7c478bd9Sstevel@tonic-gate 			MALLOC_FAIL("host name conversion");
2236*7c478bd9Sstevel@tonic-gate 			goto out;
2237*7c478bd9Sstevel@tonic-gate 		}
2238*7c478bd9Sstevel@tonic-gate 
2239*7c478bd9Sstevel@tonic-gate 		DPRINT2(2, "cvthname(%u): Found %d hostnames\n",
2240*7c478bd9Sstevel@tonic-gate 					mythreadno, h->hl_cnt);
2241*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < h->hl_cnt; i++) {
2242*7c478bd9Sstevel@tonic-gate 			h->hl_hosts[i] = (char *)
2243*7c478bd9Sstevel@tonic-gate 			    malloc(sizeof (char) * (strlen(hspp->h_host) + 1));
2244*7c478bd9Sstevel@tonic-gate 			if (h->hl_hosts[i] == NULL) {
2245*7c478bd9Sstevel@tonic-gate 				int j;
2246*7c478bd9Sstevel@tonic-gate 				for (j = 0; j < i; j++) {
2247*7c478bd9Sstevel@tonic-gate 					free(h->hl_hosts[j]);
2248*7c478bd9Sstevel@tonic-gate 				}
2249*7c478bd9Sstevel@tonic-gate 				free(h->hl_hosts);
2250*7c478bd9Sstevel@tonic-gate 				MALLOC_FAIL("host name conversion");
2251*7c478bd9Sstevel@tonic-gate 				goto out;
2252*7c478bd9Sstevel@tonic-gate 			}
2253*7c478bd9Sstevel@tonic-gate 			(void) strcpy(h->hl_hosts[i], hspp->h_host);
2254*7c478bd9Sstevel@tonic-gate 			hspp++;
2255*7c478bd9Sstevel@tonic-gate 		}
2256*7c478bd9Sstevel@tonic-gate 		netdir_free((void *)hsp, ND_HOSTSERVLIST);
2257*7c478bd9Sstevel@tonic-gate 	} else { /* unknown address */
2258*7c478bd9Sstevel@tonic-gate 		h->hl_cnt = 1;
2259*7c478bd9Sstevel@tonic-gate 		h->hl_hosts = (char **)malloc(sizeof (char *));
2260*7c478bd9Sstevel@tonic-gate 		if (h->hl_hosts == NULL) {
2261*7c478bd9Sstevel@tonic-gate 			free(h);
2262*7c478bd9Sstevel@tonic-gate 			MALLOC_FAIL("host name conversion");
2263*7c478bd9Sstevel@tonic-gate 			return (NULL);
2264*7c478bd9Sstevel@tonic-gate 		}
2265*7c478bd9Sstevel@tonic-gate 		h->hl_hosts[0] = (char *)malloc(strlen(failsafe_addr) + 3);
2266*7c478bd9Sstevel@tonic-gate 		if (h->hl_hosts[0] == NULL) {
2267*7c478bd9Sstevel@tonic-gate 			free(h->hl_hosts);
2268*7c478bd9Sstevel@tonic-gate 			free(h);
2269*7c478bd9Sstevel@tonic-gate 			MALLOC_FAIL("host name conversion");
2270*7c478bd9Sstevel@tonic-gate 			return (NULL);
2271*7c478bd9Sstevel@tonic-gate 		}
2272*7c478bd9Sstevel@tonic-gate 		(void) sprintf(h->hl_hosts[0], "[%s]", failsafe_addr);
2273*7c478bd9Sstevel@tonic-gate 		DPRINT2(1, "cvthname(%u): Hostname lookup failed "
2274*7c478bd9Sstevel@tonic-gate 			"- using address %s instead\n",
2275*7c478bd9Sstevel@tonic-gate 			mythreadno, h->hl_hosts[0]);
2276*7c478bd9Sstevel@tonic-gate 	}
2277*7c478bd9Sstevel@tonic-gate 
2278*7c478bd9Sstevel@tonic-gate 	h->hl_refcnt = 1;
2279*7c478bd9Sstevel@tonic-gate 	if (pthread_mutex_init(&h->hl_mutex, NULL) != 0) {
2280*7c478bd9Sstevel@tonic-gate 		logerror("pthread_mutex_init failed");
2281*7c478bd9Sstevel@tonic-gate 		/* This host_list won't be shared by the cache. */
2282*7c478bd9Sstevel@tonic-gate 		return (h);
2283*7c478bd9Sstevel@tonic-gate 	}
2284*7c478bd9Sstevel@tonic-gate 	hnc_register(nbp, ncp, h);
2285*7c478bd9Sstevel@tonic-gate 	DPRINT3(2, "cvthname(%u): returning %p for %s\n",
2286*7c478bd9Sstevel@tonic-gate 			mythreadno, h, h->hl_hosts[0]);
2287*7c478bd9Sstevel@tonic-gate 	return (h);
2288*7c478bd9Sstevel@tonic-gate }
2289*7c478bd9Sstevel@tonic-gate 
2290*7c478bd9Sstevel@tonic-gate /*
2291*7c478bd9Sstevel@tonic-gate  * Print syslogd errors some place. Need to be careful here, because
2292*7c478bd9Sstevel@tonic-gate  * this routine is called at times when we're not initialized and
2293*7c478bd9Sstevel@tonic-gate  * ready to log messages...in this case, fall back to using the console.
2294*7c478bd9Sstevel@tonic-gate  */
2295*7c478bd9Sstevel@tonic-gate void
2296*7c478bd9Sstevel@tonic-gate logerror(const char *type, ...)
2297*7c478bd9Sstevel@tonic-gate {
2298*7c478bd9Sstevel@tonic-gate 	char buf[MAXLINE+1];
2299*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
2300*7c478bd9Sstevel@tonic-gate 	int flag;
2301*7c478bd9Sstevel@tonic-gate 	va_list ap;
2302*7c478bd9Sstevel@tonic-gate 
2303*7c478bd9Sstevel@tonic-gate 	if (Debug) {
2304*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
2305*7c478bd9Sstevel@tonic-gate 	}
2306*7c478bd9Sstevel@tonic-gate 
2307*7c478bd9Sstevel@tonic-gate 	va_start(ap, type);
2308*7c478bd9Sstevel@tonic-gate 	logerror_format(type, buf, ap);
2309*7c478bd9Sstevel@tonic-gate 	va_end(ap);
2310*7c478bd9Sstevel@tonic-gate 	DPRINT2(1, "logerror(%u): %s\n", mythreadno, buf);
2311*7c478bd9Sstevel@tonic-gate 
2312*7c478bd9Sstevel@tonic-gate 	pthread_mutex_lock(&logerror_lock);
2313*7c478bd9Sstevel@tonic-gate 	if (!interrorlog) {
2314*7c478bd9Sstevel@tonic-gate 		flag = 0;
2315*7c478bd9Sstevel@tonic-gate 		if (logerror_to_console(1, buf) == 0) {
2316*7c478bd9Sstevel@tonic-gate 			/* has written to the console */
2317*7c478bd9Sstevel@tonic-gate 			flag = IGN_CONS;
2318*7c478bd9Sstevel@tonic-gate 		}
2319*7c478bd9Sstevel@tonic-gate 		(void) logmymsg(LOG_SYSLOG|LOG_ERR, buf, ADDDATE|flag, 1);
2320*7c478bd9Sstevel@tonic-gate 	} else {
2321*7c478bd9Sstevel@tonic-gate 		if (logmymsg(LOG_SYSLOG|LOG_ERR, buf, ADDDATE, 0) == -1) {
2322*7c478bd9Sstevel@tonic-gate 			(void) logerror_to_console(1, buf);
2323*7c478bd9Sstevel@tonic-gate 		}
2324*7c478bd9Sstevel@tonic-gate 	}
2325*7c478bd9Sstevel@tonic-gate 	pthread_mutex_unlock(&logerror_lock);
2326*7c478bd9Sstevel@tonic-gate 
2327*7c478bd9Sstevel@tonic-gate 	errno = 0;
2328*7c478bd9Sstevel@tonic-gate 	t_errno = 0;
2329*7c478bd9Sstevel@tonic-gate }
2330*7c478bd9Sstevel@tonic-gate 
2331*7c478bd9Sstevel@tonic-gate static void
2332*7c478bd9Sstevel@tonic-gate logerror_format(const char *type, char *buf, va_list ap)
2333*7c478bd9Sstevel@tonic-gate {
2334*7c478bd9Sstevel@tonic-gate 	char tmpbuf[MAXLINE + 1];
2335*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
2336*7c478bd9Sstevel@tonic-gate 
2337*7c478bd9Sstevel@tonic-gate 	if (Debug) {
2338*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
2339*7c478bd9Sstevel@tonic-gate 	}
2340*7c478bd9Sstevel@tonic-gate 
2341*7c478bd9Sstevel@tonic-gate 	(void) vsnprintf(tmpbuf, MAXLINE, type, ap);
2342*7c478bd9Sstevel@tonic-gate 
2343*7c478bd9Sstevel@tonic-gate 	if (t_errno == 0 || t_errno == TSYSERR) {
2344*7c478bd9Sstevel@tonic-gate 		char *errstr;
2345*7c478bd9Sstevel@tonic-gate 
2346*7c478bd9Sstevel@tonic-gate 		if (errno == 0) {
2347*7c478bd9Sstevel@tonic-gate 			(void) snprintf(buf, MAXLINE, "syslogd: %.*s",
2348*7c478bd9Sstevel@tonic-gate 				MAXLINE, tmpbuf);
2349*7c478bd9Sstevel@tonic-gate 		} else if ((errstr = strerror(errno)) == (char *)NULL) {
2350*7c478bd9Sstevel@tonic-gate 			(void) snprintf(buf, MAXLINE, "syslogd: %s: error"
2351*7c478bd9Sstevel@tonic-gate 				" %d", tmpbuf, errno);
2352*7c478bd9Sstevel@tonic-gate 		} else {
2353*7c478bd9Sstevel@tonic-gate 			(void) snprintf(buf, MAXLINE, "syslogd: %s: %s",
2354*7c478bd9Sstevel@tonic-gate 				tmpbuf, errstr);
2355*7c478bd9Sstevel@tonic-gate 		}
2356*7c478bd9Sstevel@tonic-gate 	} else {
2357*7c478bd9Sstevel@tonic-gate 		if (t_errno > t_nerr) {
2358*7c478bd9Sstevel@tonic-gate 			(void) snprintf(buf, MAXLINE, "syslogd: %s:"
2359*7c478bd9Sstevel@tonic-gate 				" t_error %d", tmpbuf, t_errno);
2360*7c478bd9Sstevel@tonic-gate 		} else {
2361*7c478bd9Sstevel@tonic-gate 			(void) snprintf(buf, MAXLINE, "syslogd: %s: %s",
2362*7c478bd9Sstevel@tonic-gate 				tmpbuf, t_errlist[t_errno]);
2363*7c478bd9Sstevel@tonic-gate 		}
2364*7c478bd9Sstevel@tonic-gate 	}
2365*7c478bd9Sstevel@tonic-gate 
2366*7c478bd9Sstevel@tonic-gate 	DPRINT2(5, "logerror_format(%u): out %s\n", mythreadno, buf);
2367*7c478bd9Sstevel@tonic-gate }
2368*7c478bd9Sstevel@tonic-gate 
2369*7c478bd9Sstevel@tonic-gate static int
2370*7c478bd9Sstevel@tonic-gate logerror_to_console(int nonblock, const char *buf)
2371*7c478bd9Sstevel@tonic-gate {
2372*7c478bd9Sstevel@tonic-gate 	int cfd, modes;
2373*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
2374*7c478bd9Sstevel@tonic-gate 	int ret = 0, len;
2375*7c478bd9Sstevel@tonic-gate 	char tmpbuf[MAXLINE + 1];
2376*7c478bd9Sstevel@tonic-gate 
2377*7c478bd9Sstevel@tonic-gate 	if (Debug) {
2378*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
2379*7c478bd9Sstevel@tonic-gate 	}
2380*7c478bd9Sstevel@tonic-gate 
2381*7c478bd9Sstevel@tonic-gate 	DPRINT2(1, "logerror_to_console(%u): %s\n", mythreadno, buf);
2382*7c478bd9Sstevel@tonic-gate 
2383*7c478bd9Sstevel@tonic-gate 	/*
2384*7c478bd9Sstevel@tonic-gate 	 * must use open here instead of fopen, because
2385*7c478bd9Sstevel@tonic-gate 	 * we need the O_NOCTTY behavior - otherwise we
2386*7c478bd9Sstevel@tonic-gate 	 * could hang the console at boot time
2387*7c478bd9Sstevel@tonic-gate 	 */
2388*7c478bd9Sstevel@tonic-gate 
2389*7c478bd9Sstevel@tonic-gate 	modes = (nonblock) ?
2390*7c478bd9Sstevel@tonic-gate 		O_WRONLY|O_APPEND|O_NOCTTY|O_NONBLOCK :
2391*7c478bd9Sstevel@tonic-gate 		O_WRONLY|O_APPEND|O_NOCTTY;
2392*7c478bd9Sstevel@tonic-gate 
2393*7c478bd9Sstevel@tonic-gate 	if (((cfd = open(sysmsg, modes)) >= 0) ||
2394*7c478bd9Sstevel@tonic-gate 	    ((cfd = open(ctty, modes)) >= 0)) {
2395*7c478bd9Sstevel@tonic-gate 		(void) snprintf(tmpbuf, MAXLINE, "%s\n", buf);
2396*7c478bd9Sstevel@tonic-gate 		len = strlen(tmpbuf);
2397*7c478bd9Sstevel@tonic-gate 		if (write(cfd, tmpbuf, len) != len) {
2398*7c478bd9Sstevel@tonic-gate 			ret = 1;
2399*7c478bd9Sstevel@tonic-gate 		}
2400*7c478bd9Sstevel@tonic-gate 		(void) close(cfd);
2401*7c478bd9Sstevel@tonic-gate 	} else {
2402*7c478bd9Sstevel@tonic-gate 		ret = 1;
2403*7c478bd9Sstevel@tonic-gate 
2404*7c478bd9Sstevel@tonic-gate 		/* punt */
2405*7c478bd9Sstevel@tonic-gate 		DPRINT1(1, "logerror_console(%u): can't open console\n",
2406*7c478bd9Sstevel@tonic-gate 			mythreadno);
2407*7c478bd9Sstevel@tonic-gate 	}
2408*7c478bd9Sstevel@tonic-gate 	return (ret);
2409*7c478bd9Sstevel@tonic-gate }
2410*7c478bd9Sstevel@tonic-gate 
2411*7c478bd9Sstevel@tonic-gate /*
2412*7c478bd9Sstevel@tonic-gate  * copy current message to saved message in filed structure.
2413*7c478bd9Sstevel@tonic-gate  */
2414*7c478bd9Sstevel@tonic-gate static void
2415*7c478bd9Sstevel@tonic-gate copy_msg(struct filed *f)
2416*7c478bd9Sstevel@tonic-gate {
2417*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(f->f_prevmsg.msg, f->f_current.msg, MAXLINE+1);
2418*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(f->f_prevmsg.host, f->f_current.host, SYS_NMLN);
2419*7c478bd9Sstevel@tonic-gate 	f->f_prevmsg.pri = f->f_current.pri;
2420*7c478bd9Sstevel@tonic-gate 	f->f_prevmsg.flags = f->f_current.flags;
2421*7c478bd9Sstevel@tonic-gate 	f->f_prevmsg.time = f->f_current.time;
2422*7c478bd9Sstevel@tonic-gate 	f->f_msgflag |= OLD_VALID;
2423*7c478bd9Sstevel@tonic-gate }
2424*7c478bd9Sstevel@tonic-gate 
2425*7c478bd9Sstevel@tonic-gate 
2426*7c478bd9Sstevel@tonic-gate /*
2427*7c478bd9Sstevel@tonic-gate  * function to free a host_list_t struct that was allocated
2428*7c478bd9Sstevel@tonic-gate  * out of cvthname(). There is a special case where we don't
2429*7c478bd9Sstevel@tonic-gate  * free the hostname list in LocalHostName, because that's
2430*7c478bd9Sstevel@tonic-gate  * our own addresses, and we just want to have to look it
2431*7c478bd9Sstevel@tonic-gate  * up once and save it.  Also don't free it if it's
2432*7c478bd9Sstevel@tonic-gate  * NullHostName, because that's a special one we use if
2433*7c478bd9Sstevel@tonic-gate  * name service lookup fails.
2434*7c478bd9Sstevel@tonic-gate  *
2435*7c478bd9Sstevel@tonic-gate  * By having hostname cache, now host_list_t will be shared
2436*7c478bd9Sstevel@tonic-gate  * by messages and hostname cache. hl_refcnt is used for
2437*7c478bd9Sstevel@tonic-gate  * the purpose.
2438*7c478bd9Sstevel@tonic-gate  */
2439*7c478bd9Sstevel@tonic-gate static void
2440*7c478bd9Sstevel@tonic-gate freehl(host_list_t *h)
2441*7c478bd9Sstevel@tonic-gate {
2442*7c478bd9Sstevel@tonic-gate 	int i, refcnt;
2443*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
2444*7c478bd9Sstevel@tonic-gate 
2445*7c478bd9Sstevel@tonic-gate 	if (Debug) {
2446*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
2447*7c478bd9Sstevel@tonic-gate 	}
2448*7c478bd9Sstevel@tonic-gate 
2449*7c478bd9Sstevel@tonic-gate 	DPRINT2(2, "freehl(%u): releasing %p\n", mythreadno, h);
2450*7c478bd9Sstevel@tonic-gate 
2451*7c478bd9Sstevel@tonic-gate 	if (h == NULL || h == &LocalHostName || h == &NullHostName) {
2452*7c478bd9Sstevel@tonic-gate 		return;
2453*7c478bd9Sstevel@tonic-gate 	}
2454*7c478bd9Sstevel@tonic-gate 
2455*7c478bd9Sstevel@tonic-gate 	pthread_mutex_lock(&h->hl_mutex);
2456*7c478bd9Sstevel@tonic-gate 	refcnt = --h->hl_refcnt;
2457*7c478bd9Sstevel@tonic-gate 	pthread_mutex_unlock(&h->hl_mutex);
2458*7c478bd9Sstevel@tonic-gate 
2459*7c478bd9Sstevel@tonic-gate 	if (refcnt != 0) {
2460*7c478bd9Sstevel@tonic-gate 		DPRINT3(5, "freehl(%u): %p has reference %d\n",
2461*7c478bd9Sstevel@tonic-gate 				mythreadno, h, refcnt);
2462*7c478bd9Sstevel@tonic-gate 		return;
2463*7c478bd9Sstevel@tonic-gate 	}
2464*7c478bd9Sstevel@tonic-gate 
2465*7c478bd9Sstevel@tonic-gate 	pthread_mutex_destroy(&h->hl_mutex);
2466*7c478bd9Sstevel@tonic-gate 
2467*7c478bd9Sstevel@tonic-gate 	DPRINT2(5, "freehl(%u): freeing %p\n", mythreadno, h);
2468*7c478bd9Sstevel@tonic-gate 
2469*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < h->hl_cnt; i++) {
2470*7c478bd9Sstevel@tonic-gate 		free(h->hl_hosts[i]);
2471*7c478bd9Sstevel@tonic-gate 	}
2472*7c478bd9Sstevel@tonic-gate 
2473*7c478bd9Sstevel@tonic-gate 	free(h->hl_hosts);
2474*7c478bd9Sstevel@tonic-gate 	free(h);
2475*7c478bd9Sstevel@tonic-gate }
2476*7c478bd9Sstevel@tonic-gate 
2477*7c478bd9Sstevel@tonic-gate /*
2478*7c478bd9Sstevel@tonic-gate  * Create the door file and the pid file in /var/run.  If the filesystem
2479*7c478bd9Sstevel@tonic-gate  * containing /etc is writable, create symlinks /etc/.syslog_door and
2480*7c478bd9Sstevel@tonic-gate  * /etc/syslog.pid to them.  On systems that do not support /var/run, create
2481*7c478bd9Sstevel@tonic-gate  * /etc/.syslog_door and /etc/syslog.pid directly.
2482*7c478bd9Sstevel@tonic-gate  *
2483*7c478bd9Sstevel@tonic-gate  * Note: it is not considered fatal to fail to create the pid file or its
2484*7c478bd9Sstevel@tonic-gate  * symlink.  Attempts to use them in the usual way will fail, of course, but
2485*7c478bd9Sstevel@tonic-gate  * syslogd will function nicely without it (not so for the door file).
2486*7c478bd9Sstevel@tonic-gate  */
2487*7c478bd9Sstevel@tonic-gate 
2488*7c478bd9Sstevel@tonic-gate static void
2489*7c478bd9Sstevel@tonic-gate open_door(void)
2490*7c478bd9Sstevel@tonic-gate {
2491*7c478bd9Sstevel@tonic-gate 	struct stat buf;
2492*7c478bd9Sstevel@tonic-gate 	door_info_t info;
2493*7c478bd9Sstevel@tonic-gate 	char line[MAXLINE+1];
2494*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
2495*7c478bd9Sstevel@tonic-gate 	int err;
2496*7c478bd9Sstevel@tonic-gate 
2497*7c478bd9Sstevel@tonic-gate 	if (Debug) {
2498*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
2499*7c478bd9Sstevel@tonic-gate 	}
2500*7c478bd9Sstevel@tonic-gate 
2501*7c478bd9Sstevel@tonic-gate 	/*
2502*7c478bd9Sstevel@tonic-gate 	 * first see if another syslogd is running by trying
2503*7c478bd9Sstevel@tonic-gate 	 * a door call - if it succeeds, there is already
2504*7c478bd9Sstevel@tonic-gate 	 * a syslogd process active
2505*7c478bd9Sstevel@tonic-gate 	 */
2506*7c478bd9Sstevel@tonic-gate 
2507*7c478bd9Sstevel@tonic-gate 	if (!DoorCreated) {
2508*7c478bd9Sstevel@tonic-gate 		int door;
2509*7c478bd9Sstevel@tonic-gate 
2510*7c478bd9Sstevel@tonic-gate 		if ((door = open(DoorFileName, O_RDONLY)) >= 0) {
2511*7c478bd9Sstevel@tonic-gate 			DPRINT2(5, "open_door(%u): %s opened "
2512*7c478bd9Sstevel@tonic-gate 				"successfully\n", mythreadno, DoorFileName);
2513*7c478bd9Sstevel@tonic-gate 
2514*7c478bd9Sstevel@tonic-gate 			if (door_info(door, &info) >= 0) {
2515*7c478bd9Sstevel@tonic-gate 				DPRINT2(5, "open_door(%u): "
2516*7c478bd9Sstevel@tonic-gate 					"door_info:info.di_target = %ld\n",
2517*7c478bd9Sstevel@tonic-gate 					mythreadno, info.di_target);
2518*7c478bd9Sstevel@tonic-gate 
2519*7c478bd9Sstevel@tonic-gate 				if (info.di_target > 0) {
2520*7c478bd9Sstevel@tonic-gate 					(void) sprintf(line, "syslogd pid %ld"
2521*7c478bd9Sstevel@tonic-gate 						" already running. Cannot "
2522*7c478bd9Sstevel@tonic-gate 						"start another syslogd pid %ld",
2523*7c478bd9Sstevel@tonic-gate 						info.di_target, getpid());
2524*7c478bd9Sstevel@tonic-gate 					DPRINT2(5, "open_door(%u): error: "
2525*7c478bd9Sstevel@tonic-gate 						"%s\n", mythreadno, line);
2526*7c478bd9Sstevel@tonic-gate 					errno = 0;
2527*7c478bd9Sstevel@tonic-gate 					logerror(line);
2528*7c478bd9Sstevel@tonic-gate 					exit(1);
2529*7c478bd9Sstevel@tonic-gate 				}
2530*7c478bd9Sstevel@tonic-gate 			}
2531*7c478bd9Sstevel@tonic-gate 
2532*7c478bd9Sstevel@tonic-gate 			(void) close(door);
2533*7c478bd9Sstevel@tonic-gate 		} else {
2534*7c478bd9Sstevel@tonic-gate 			if (lstat(DoorFileName, &buf) < 0) {
2535*7c478bd9Sstevel@tonic-gate 				err = errno;
2536*7c478bd9Sstevel@tonic-gate 
2537*7c478bd9Sstevel@tonic-gate 				DPRINT3(5, "open_door(%u): lstat() of %s "
2538*7c478bd9Sstevel@tonic-gate 					"failed, errno=%d\n",
2539*7c478bd9Sstevel@tonic-gate 					mythreadno, DoorFileName, err);
2540*7c478bd9Sstevel@tonic-gate 
2541*7c478bd9Sstevel@tonic-gate 				if ((door = creat(DoorFileName, 0644)) < 0) {
2542*7c478bd9Sstevel@tonic-gate 					err = errno;
2543*7c478bd9Sstevel@tonic-gate 					(void) sprintf(line, "creat() of %s "
2544*7c478bd9Sstevel@tonic-gate 						"failed - fatal", DoorFileName);
2545*7c478bd9Sstevel@tonic-gate 					DPRINT3(1, "open_door(%u): error: %s, "
2546*7c478bd9Sstevel@tonic-gate 						"errno=%d\n", mythreadno, line,
2547*7c478bd9Sstevel@tonic-gate 						err);
2548*7c478bd9Sstevel@tonic-gate 					errno = err;
2549*7c478bd9Sstevel@tonic-gate 					logerror(line);
2550*7c478bd9Sstevel@tonic-gate 					delete_doorfiles();
2551*7c478bd9Sstevel@tonic-gate 					exit(1);
2552*7c478bd9Sstevel@tonic-gate 				}
2553*7c478bd9Sstevel@tonic-gate 
2554*7c478bd9Sstevel@tonic-gate 				(void) fchmod(door,
2555*7c478bd9Sstevel@tonic-gate 					S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
2556*7c478bd9Sstevel@tonic-gate 
2557*7c478bd9Sstevel@tonic-gate 				DPRINT2(5, "open_door(%u): creat() of %s "
2558*7c478bd9Sstevel@tonic-gate 					"succeeded\n", mythreadno,
2559*7c478bd9Sstevel@tonic-gate 					DoorFileName);
2560*7c478bd9Sstevel@tonic-gate 
2561*7c478bd9Sstevel@tonic-gate 				(void) close(door);
2562*7c478bd9Sstevel@tonic-gate 			}
2563*7c478bd9Sstevel@tonic-gate 		}
2564*7c478bd9Sstevel@tonic-gate 
2565*7c478bd9Sstevel@tonic-gate 		if (strcmp(DoorFileName, DOORFILE) == 0) {
2566*7c478bd9Sstevel@tonic-gate 			if (lstat(OLD_DOORFILE, &buf) == 0) {
2567*7c478bd9Sstevel@tonic-gate 				DPRINT2(5, "open_door(%u): lstat() of %s "
2568*7c478bd9Sstevel@tonic-gate 					"succeeded\n", mythreadno,
2569*7c478bd9Sstevel@tonic-gate 					OLD_DOORFILE);
2570*7c478bd9Sstevel@tonic-gate 
2571*7c478bd9Sstevel@tonic-gate 				if (S_ISDIR(buf.st_mode)) {
2572*7c478bd9Sstevel@tonic-gate 					(void) sprintf(line, "%s is a "
2573*7c478bd9Sstevel@tonic-gate 						"directory - fatal",
2574*7c478bd9Sstevel@tonic-gate 						OLD_DOORFILE);
2575*7c478bd9Sstevel@tonic-gate 					DPRINT2(1, "open_door(%u): error: "
2576*7c478bd9Sstevel@tonic-gate 						"%s\n", mythreadno, line);
2577*7c478bd9Sstevel@tonic-gate 					errno = 0;
2578*7c478bd9Sstevel@tonic-gate 					logerror(line);
2579*7c478bd9Sstevel@tonic-gate 					delete_doorfiles();
2580*7c478bd9Sstevel@tonic-gate 					exit(1);
2581*7c478bd9Sstevel@tonic-gate 				}
2582*7c478bd9Sstevel@tonic-gate 
2583*7c478bd9Sstevel@tonic-gate 				DPRINT2(5, "open_door(%u): %s is not a "
2584*7c478bd9Sstevel@tonic-gate 					"directory\n",
2585*7c478bd9Sstevel@tonic-gate 					mythreadno, OLD_DOORFILE);
2586*7c478bd9Sstevel@tonic-gate 
2587*7c478bd9Sstevel@tonic-gate 				if (unlink(OLD_DOORFILE) < 0) {
2588*7c478bd9Sstevel@tonic-gate 					err = errno;
2589*7c478bd9Sstevel@tonic-gate 					(void) sprintf(line, "unlink() of %s "
2590*7c478bd9Sstevel@tonic-gate 						"failed", OLD_DOORFILE);
2591*7c478bd9Sstevel@tonic-gate 					DPRINT2(5, "open_door(%u): %s\n",
2592*7c478bd9Sstevel@tonic-gate 						mythreadno, line);
2593*7c478bd9Sstevel@tonic-gate 
2594*7c478bd9Sstevel@tonic-gate 					if (err != EROFS) {
2595*7c478bd9Sstevel@tonic-gate 						DPRINT3(1, "open_door(%u): "
2596*7c478bd9Sstevel@tonic-gate 							"error: %s, "
2597*7c478bd9Sstevel@tonic-gate 							"errno=%d\n",
2598*7c478bd9Sstevel@tonic-gate 							mythreadno, line, err);
2599*7c478bd9Sstevel@tonic-gate 						(void) strcat(line, " - fatal");
2600*7c478bd9Sstevel@tonic-gate 						errno = err;
2601*7c478bd9Sstevel@tonic-gate 						logerror(line);
2602*7c478bd9Sstevel@tonic-gate 						delete_doorfiles();
2603*7c478bd9Sstevel@tonic-gate 						exit(1);
2604*7c478bd9Sstevel@tonic-gate 					}
2605*7c478bd9Sstevel@tonic-gate 
2606*7c478bd9Sstevel@tonic-gate 					DPRINT1(5, "open_door(%u): unlink "
2607*7c478bd9Sstevel@tonic-gate 						"failure OK on RO file "
2608*7c478bd9Sstevel@tonic-gate 						"system\n", mythreadno);
2609*7c478bd9Sstevel@tonic-gate 				}
2610*7c478bd9Sstevel@tonic-gate 			} else {
2611*7c478bd9Sstevel@tonic-gate 				DPRINT2(5, "open_door(%u): file %s doesn't "
2612*7c478bd9Sstevel@tonic-gate 					"exist\n", mythreadno, OLD_DOORFILE);
2613*7c478bd9Sstevel@tonic-gate 			}
2614*7c478bd9Sstevel@tonic-gate 
2615*7c478bd9Sstevel@tonic-gate 			if (symlink(RELATIVE_DOORFILE, OLD_DOORFILE) < 0) {
2616*7c478bd9Sstevel@tonic-gate 				err = errno;
2617*7c478bd9Sstevel@tonic-gate 				(void) sprintf(line, "symlink %s -> %s "
2618*7c478bd9Sstevel@tonic-gate 					"failed", OLD_DOORFILE,
2619*7c478bd9Sstevel@tonic-gate 					RELATIVE_DOORFILE);
2620*7c478bd9Sstevel@tonic-gate 				DPRINT2(5, "open_door(%u): %s\n", mythreadno,
2621*7c478bd9Sstevel@tonic-gate 					line);
2622*7c478bd9Sstevel@tonic-gate 
2623*7c478bd9Sstevel@tonic-gate 				if (err != EROFS) {
2624*7c478bd9Sstevel@tonic-gate 					DPRINT3(1, "open_door(%u): error: %s, "
2625*7c478bd9Sstevel@tonic-gate 						"errno=%d\n", mythreadno, line,
2626*7c478bd9Sstevel@tonic-gate 						err);
2627*7c478bd9Sstevel@tonic-gate 					errno = err;
2628*7c478bd9Sstevel@tonic-gate 					(void) strcat(line, " - fatal");
2629*7c478bd9Sstevel@tonic-gate 					logerror(line);
2630*7c478bd9Sstevel@tonic-gate 					delete_doorfiles();
2631*7c478bd9Sstevel@tonic-gate 					exit(1);
2632*7c478bd9Sstevel@tonic-gate 				}
2633*7c478bd9Sstevel@tonic-gate 
2634*7c478bd9Sstevel@tonic-gate 				DPRINT1(5, "open_door(%u): symlink failure OK "
2635*7c478bd9Sstevel@tonic-gate 					"on RO file system\n", mythreadno);
2636*7c478bd9Sstevel@tonic-gate 			} else {
2637*7c478bd9Sstevel@tonic-gate 				DPRINT3(5, "open_door(%u): symlink %s -> %s "
2638*7c478bd9Sstevel@tonic-gate 					"succeeded\n", mythreadno,
2639*7c478bd9Sstevel@tonic-gate 					OLD_DOORFILE, RELATIVE_DOORFILE);
2640*7c478bd9Sstevel@tonic-gate 			}
2641*7c478bd9Sstevel@tonic-gate 		}
2642*7c478bd9Sstevel@tonic-gate 
2643*7c478bd9Sstevel@tonic-gate 		if ((DoorFd = door_create(server, 0,
2644*7c478bd9Sstevel@tonic-gate 		    DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) < 0) {
2645*7c478bd9Sstevel@tonic-gate 			err = errno;
2646*7c478bd9Sstevel@tonic-gate 			(void) sprintf(line, "door_create() failed - fatal");
2647*7c478bd9Sstevel@tonic-gate 			DPRINT3(1, "open_door(%u): error: %s, errno=%d\n",
2648*7c478bd9Sstevel@tonic-gate 				mythreadno, line, err);
2649*7c478bd9Sstevel@tonic-gate 			errno = err;
2650*7c478bd9Sstevel@tonic-gate 			logerror(line);
2651*7c478bd9Sstevel@tonic-gate 			delete_doorfiles();
2652*7c478bd9Sstevel@tonic-gate 			exit(1);
2653*7c478bd9Sstevel@tonic-gate 		}
2654*7c478bd9Sstevel@tonic-gate 		(void) door_setparam(DoorFd, DOOR_PARAM_DATA_MAX, 0);
2655*7c478bd9Sstevel@tonic-gate 		DPRINT2(5, "open_door(%u): door_create() succeeded, "
2656*7c478bd9Sstevel@tonic-gate 			"DoorFd=%d\n", mythreadno, DoorFd);
2657*7c478bd9Sstevel@tonic-gate 
2658*7c478bd9Sstevel@tonic-gate 		DoorCreated = 1;
2659*7c478bd9Sstevel@tonic-gate 	}
2660*7c478bd9Sstevel@tonic-gate 
2661*7c478bd9Sstevel@tonic-gate 	(void) fdetach(DoorFileName);	/* just in case... */
2662*7c478bd9Sstevel@tonic-gate 
2663*7c478bd9Sstevel@tonic-gate 	if (fattach(DoorFd, DoorFileName) < 0) {
2664*7c478bd9Sstevel@tonic-gate 		err = errno;
2665*7c478bd9Sstevel@tonic-gate 		(void) sprintf(line, "fattach() of fd"
2666*7c478bd9Sstevel@tonic-gate 			" %d to %s failed - fatal",
2667*7c478bd9Sstevel@tonic-gate 			DoorFd, DoorFileName);
2668*7c478bd9Sstevel@tonic-gate 		DPRINT3(1, "open_door(%u): error: %s, errno=%d\n", mythreadno,
2669*7c478bd9Sstevel@tonic-gate 			line, err);
2670*7c478bd9Sstevel@tonic-gate 		errno = err;
2671*7c478bd9Sstevel@tonic-gate 		logerror(line);
2672*7c478bd9Sstevel@tonic-gate 		delete_doorfiles();
2673*7c478bd9Sstevel@tonic-gate 		exit(1);
2674*7c478bd9Sstevel@tonic-gate 	}
2675*7c478bd9Sstevel@tonic-gate 
2676*7c478bd9Sstevel@tonic-gate 	DPRINT2(5, "open_door(%u): attached server() to %s\n", mythreadno,
2677*7c478bd9Sstevel@tonic-gate 		DoorFileName);
2678*7c478bd9Sstevel@tonic-gate 
2679*7c478bd9Sstevel@tonic-gate 	/*
2680*7c478bd9Sstevel@tonic-gate 	 * create pidfile anyway, so those using it to control
2681*7c478bd9Sstevel@tonic-gate 	 * syslogd (with kill `cat /etc/syslog.pid` perhaps)
2682*7c478bd9Sstevel@tonic-gate 	 * don't get broken.
2683*7c478bd9Sstevel@tonic-gate 	 */
2684*7c478bd9Sstevel@tonic-gate 
2685*7c478bd9Sstevel@tonic-gate 	if (!PidfileCreated) {
2686*7c478bd9Sstevel@tonic-gate 		int pidfd;
2687*7c478bd9Sstevel@tonic-gate 
2688*7c478bd9Sstevel@tonic-gate 		PidfileCreated = 1;
2689*7c478bd9Sstevel@tonic-gate 
2690*7c478bd9Sstevel@tonic-gate 		if ((pidfd = open(PidFileName, O_RDWR|O_CREAT|O_TRUNC, 0644))
2691*7c478bd9Sstevel@tonic-gate 		    < 0) {
2692*7c478bd9Sstevel@tonic-gate 			err = errno;
2693*7c478bd9Sstevel@tonic-gate 			(void) sprintf(line, "open() of %s failed",
2694*7c478bd9Sstevel@tonic-gate 				PidFileName);
2695*7c478bd9Sstevel@tonic-gate 			DPRINT3(1, "open_door(%u): warning: %s, errno=%d\n",
2696*7c478bd9Sstevel@tonic-gate 				mythreadno, line, err);
2697*7c478bd9Sstevel@tonic-gate 			errno = err;
2698*7c478bd9Sstevel@tonic-gate 			logerror(line);
2699*7c478bd9Sstevel@tonic-gate 			return;
2700*7c478bd9Sstevel@tonic-gate 		}
2701*7c478bd9Sstevel@tonic-gate 
2702*7c478bd9Sstevel@tonic-gate 		(void) fchmod(pidfd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
2703*7c478bd9Sstevel@tonic-gate 		(void) sprintf(line, "%ld\n", getpid());
2704*7c478bd9Sstevel@tonic-gate 
2705*7c478bd9Sstevel@tonic-gate 		if (write(pidfd, line, strlen(line)) < 0) {
2706*7c478bd9Sstevel@tonic-gate 			err = errno;
2707*7c478bd9Sstevel@tonic-gate 			(void) sprintf(line, "write to %s on fd %d failed",
2708*7c478bd9Sstevel@tonic-gate 				PidFileName, pidfd);
2709*7c478bd9Sstevel@tonic-gate 			DPRINT3(1, "open_door(%u): warning: %s, errno=%d\n",
2710*7c478bd9Sstevel@tonic-gate 				mythreadno, line, err);
2711*7c478bd9Sstevel@tonic-gate 			errno = err;
2712*7c478bd9Sstevel@tonic-gate 			logerror(line);
2713*7c478bd9Sstevel@tonic-gate 			return;
2714*7c478bd9Sstevel@tonic-gate 		}
2715*7c478bd9Sstevel@tonic-gate 
2716*7c478bd9Sstevel@tonic-gate 		(void) close(pidfd);
2717*7c478bd9Sstevel@tonic-gate 
2718*7c478bd9Sstevel@tonic-gate 		DPRINT2(5, "open_door(%u): %s created\n",
2719*7c478bd9Sstevel@tonic-gate 			mythreadno, PidFileName);
2720*7c478bd9Sstevel@tonic-gate 
2721*7c478bd9Sstevel@tonic-gate 		if (strcmp(PidFileName, PIDFILE) == 0) {
2722*7c478bd9Sstevel@tonic-gate 			if (lstat(OLD_PIDFILE, &buf) == 0) {
2723*7c478bd9Sstevel@tonic-gate 				DPRINT2(5, "open_door(%u): lstat() of %s "
2724*7c478bd9Sstevel@tonic-gate 					"succeded\n", mythreadno, OLD_PIDFILE);
2725*7c478bd9Sstevel@tonic-gate 
2726*7c478bd9Sstevel@tonic-gate 				if (S_ISDIR(buf.st_mode)) {
2727*7c478bd9Sstevel@tonic-gate 					(void) sprintf(line, "file %s is a "
2728*7c478bd9Sstevel@tonic-gate 						"directory",
2729*7c478bd9Sstevel@tonic-gate 						OLD_PIDFILE);
2730*7c478bd9Sstevel@tonic-gate 					DPRINT2(1, "open_door(%u): warning: "
2731*7c478bd9Sstevel@tonic-gate 						"%s\n", mythreadno, line);
2732*7c478bd9Sstevel@tonic-gate 					errno = 0;
2733*7c478bd9Sstevel@tonic-gate 					logerror(line);
2734*7c478bd9Sstevel@tonic-gate 					return;
2735*7c478bd9Sstevel@tonic-gate 				}
2736*7c478bd9Sstevel@tonic-gate 
2737*7c478bd9Sstevel@tonic-gate 				if (unlink(OLD_PIDFILE) < 0) {
2738*7c478bd9Sstevel@tonic-gate 					err = errno;
2739*7c478bd9Sstevel@tonic-gate 					(void) sprintf(line, "unlink() "
2740*7c478bd9Sstevel@tonic-gate 						"of %s failed", OLD_PIDFILE);
2741*7c478bd9Sstevel@tonic-gate 					DPRINT2(5, "open_door(%u): %s\n",
2742*7c478bd9Sstevel@tonic-gate 						mythreadno, line);
2743*7c478bd9Sstevel@tonic-gate 
2744*7c478bd9Sstevel@tonic-gate 					if (err != EROFS) {
2745*7c478bd9Sstevel@tonic-gate 						DPRINT3(1, "open_door (%u): "
2746*7c478bd9Sstevel@tonic-gate 							"warning: %s, "
2747*7c478bd9Sstevel@tonic-gate 							"errno=%d\n",
2748*7c478bd9Sstevel@tonic-gate 							mythreadno, line, err);
2749*7c478bd9Sstevel@tonic-gate 						errno = err;
2750*7c478bd9Sstevel@tonic-gate 						logerror(line);
2751*7c478bd9Sstevel@tonic-gate 						return;
2752*7c478bd9Sstevel@tonic-gate 					}
2753*7c478bd9Sstevel@tonic-gate 
2754*7c478bd9Sstevel@tonic-gate 					DPRINT1(5, "open_door(%u): unlink "
2755*7c478bd9Sstevel@tonic-gate 						"failure OK on RO file "
2756*7c478bd9Sstevel@tonic-gate 						"system\n", mythreadno);
2757*7c478bd9Sstevel@tonic-gate 				}
2758*7c478bd9Sstevel@tonic-gate 			} else {
2759*7c478bd9Sstevel@tonic-gate 				DPRINT2(5, "open_door(%u): file %s doesn't "
2760*7c478bd9Sstevel@tonic-gate 					"exist\n", mythreadno, OLD_PIDFILE);
2761*7c478bd9Sstevel@tonic-gate 			}
2762*7c478bd9Sstevel@tonic-gate 
2763*7c478bd9Sstevel@tonic-gate 			if (symlink(RELATIVE_PIDFILE, OLD_PIDFILE) < 0) {
2764*7c478bd9Sstevel@tonic-gate 				err = errno;
2765*7c478bd9Sstevel@tonic-gate 				(void) sprintf(line, "symlink %s -> %s "
2766*7c478bd9Sstevel@tonic-gate 					"failed", OLD_PIDFILE,
2767*7c478bd9Sstevel@tonic-gate 					RELATIVE_PIDFILE);
2768*7c478bd9Sstevel@tonic-gate 				DPRINT2(5, "open_door(%u): %s\n", mythreadno,
2769*7c478bd9Sstevel@tonic-gate 					line);
2770*7c478bd9Sstevel@tonic-gate 
2771*7c478bd9Sstevel@tonic-gate 				if (err != EROFS) {
2772*7c478bd9Sstevel@tonic-gate 					DPRINT3(1, "open_door(%u): warning: "
2773*7c478bd9Sstevel@tonic-gate 						"%s, errno=%d\n", mythreadno,
2774*7c478bd9Sstevel@tonic-gate 						line, err);
2775*7c478bd9Sstevel@tonic-gate 					errno = err;
2776*7c478bd9Sstevel@tonic-gate 					logerror(line);
2777*7c478bd9Sstevel@tonic-gate 					return;
2778*7c478bd9Sstevel@tonic-gate 				}
2779*7c478bd9Sstevel@tonic-gate 
2780*7c478bd9Sstevel@tonic-gate 				DPRINT1(5, "open_door(%u): symlink failure OK "
2781*7c478bd9Sstevel@tonic-gate 					"on RO file system\n", mythreadno);
2782*7c478bd9Sstevel@tonic-gate 				return;
2783*7c478bd9Sstevel@tonic-gate 			}
2784*7c478bd9Sstevel@tonic-gate 
2785*7c478bd9Sstevel@tonic-gate 			DPRINT3(5, "open_door(%u): symlink %s -> %s "
2786*7c478bd9Sstevel@tonic-gate 				"succeeded\n", mythreadno, OLD_PIDFILE,
2787*7c478bd9Sstevel@tonic-gate 				RELATIVE_PIDFILE);
2788*7c478bd9Sstevel@tonic-gate 		}
2789*7c478bd9Sstevel@tonic-gate 	}
2790*7c478bd9Sstevel@tonic-gate }
2791*7c478bd9Sstevel@tonic-gate 
2792*7c478bd9Sstevel@tonic-gate /*
2793*7c478bd9Sstevel@tonic-gate  * the 'server' function that we export via the door. It does
2794*7c478bd9Sstevel@tonic-gate  * nothing but return.
2795*7c478bd9Sstevel@tonic-gate  */
2796*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2797*7c478bd9Sstevel@tonic-gate static void
2798*7c478bd9Sstevel@tonic-gate server(void *cookie, char *argp, size_t arg_size,
2799*7c478bd9Sstevel@tonic-gate     door_desc_t *dp, uint_t n)
2800*7c478bd9Sstevel@tonic-gate {
2801*7c478bd9Sstevel@tonic-gate 	(void) door_return(NULL, 0, NULL, 0);
2802*7c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
2803*7c478bd9Sstevel@tonic-gate }
2804*7c478bd9Sstevel@tonic-gate 
2805*7c478bd9Sstevel@tonic-gate /*
2806*7c478bd9Sstevel@tonic-gate  * checkm4 - used to verify that the external utilities that
2807*7c478bd9Sstevel@tonic-gate  * syslogd depends on are where we expect them to be.
2808*7c478bd9Sstevel@tonic-gate  * Returns 0 if all utilities are found, > 0 if any are missing.
2809*7c478bd9Sstevel@tonic-gate  * Also logs errors so user knows what's missing
2810*7c478bd9Sstevel@tonic-gate  */
2811*7c478bd9Sstevel@tonic-gate static int
2812*7c478bd9Sstevel@tonic-gate checkm4(void)
2813*7c478bd9Sstevel@tonic-gate {
2814*7c478bd9Sstevel@tonic-gate 	int notfound = 0;
2815*7c478bd9Sstevel@tonic-gate 	int saverrno;
2816*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
2817*7c478bd9Sstevel@tonic-gate 
2818*7c478bd9Sstevel@tonic-gate 	if (Debug) {
2819*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
2820*7c478bd9Sstevel@tonic-gate 	}
2821*7c478bd9Sstevel@tonic-gate 
2822*7c478bd9Sstevel@tonic-gate 	if (access("/usr/ccs/bin/m4", X_OK) < 0) {
2823*7c478bd9Sstevel@tonic-gate 		saverrno = errno;
2824*7c478bd9Sstevel@tonic-gate 		logerror("/usr/ccs/bin/m4");
2825*7c478bd9Sstevel@tonic-gate 		DPRINT2(1, "checkm4(%u): /usr/ccs/bin/m4 - access "
2826*7c478bd9Sstevel@tonic-gate 			"returned %d\n", mythreadno, saverrno);
2827*7c478bd9Sstevel@tonic-gate 		notfound++;
2828*7c478bd9Sstevel@tonic-gate 	}
2829*7c478bd9Sstevel@tonic-gate 
2830*7c478bd9Sstevel@tonic-gate 	return (notfound);
2831*7c478bd9Sstevel@tonic-gate }
2832*7c478bd9Sstevel@tonic-gate 
2833*7c478bd9Sstevel@tonic-gate /*
2834*7c478bd9Sstevel@tonic-gate  *  INIT -- Initialize syslogd from configuration table, start up
2835*7c478bd9Sstevel@tonic-gate  *  input and logger threads. This routine is called only once.
2836*7c478bd9Sstevel@tonic-gate  */
2837*7c478bd9Sstevel@tonic-gate static void
2838*7c478bd9Sstevel@tonic-gate init(void)
2839*7c478bd9Sstevel@tonic-gate {
2840*7c478bd9Sstevel@tonic-gate 	struct utsname *up;
2841*7c478bd9Sstevel@tonic-gate 	pthread_attr_t sys_attr, net_attr, log_attr, hnl_attr;
2842*7c478bd9Sstevel@tonic-gate 	int nthread;
2843*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
2844*7c478bd9Sstevel@tonic-gate 
2845*7c478bd9Sstevel@tonic-gate 	if (Debug) {
2846*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
2847*7c478bd9Sstevel@tonic-gate 	}
2848*7c478bd9Sstevel@tonic-gate 
2849*7c478bd9Sstevel@tonic-gate 	DPRINT1(2, "init(%u): initializing\n", mythreadno);
2850*7c478bd9Sstevel@tonic-gate 
2851*7c478bd9Sstevel@tonic-gate 	/* hand-craft a host_list_t entry for our local host name */
2852*7c478bd9Sstevel@tonic-gate 	if ((up = malloc(sizeof (struct utsname))) == NULL) {
2853*7c478bd9Sstevel@tonic-gate 		MALLOC_FAIL_EXIT;
2854*7c478bd9Sstevel@tonic-gate 	}
2855*7c478bd9Sstevel@tonic-gate 	(void) uname(up);
2856*7c478bd9Sstevel@tonic-gate 	LocalHostName.hl_cnt = 1;
2857*7c478bd9Sstevel@tonic-gate 	if ((LocalHostName.hl_hosts = malloc(sizeof (char *))) == NULL) {
2858*7c478bd9Sstevel@tonic-gate 		MALLOC_FAIL_EXIT;
2859*7c478bd9Sstevel@tonic-gate 	}
2860*7c478bd9Sstevel@tonic-gate 	if ((LocalHostName.hl_hosts[0] = strdup(up->nodename)) == NULL) {
2861*7c478bd9Sstevel@tonic-gate 		free(LocalHostName.hl_hosts);
2862*7c478bd9Sstevel@tonic-gate 		MALLOC_FAIL_EXIT;
2863*7c478bd9Sstevel@tonic-gate 	}
2864*7c478bd9Sstevel@tonic-gate 	free(up);
2865*7c478bd9Sstevel@tonic-gate 	/* also hand craft one for use if name resolution fails */
2866*7c478bd9Sstevel@tonic-gate 	NullHostName.hl_cnt = 1;
2867*7c478bd9Sstevel@tonic-gate 	if ((NullHostName.hl_hosts = malloc(sizeof (char *))) == NULL) {
2868*7c478bd9Sstevel@tonic-gate 		MALLOC_FAIL_EXIT;
2869*7c478bd9Sstevel@tonic-gate 	}
2870*7c478bd9Sstevel@tonic-gate 	if ((NullHostName.hl_hosts[0] = strdup("name lookup failed")) == NULL) {
2871*7c478bd9Sstevel@tonic-gate 		MALLOC_FAIL_EXIT;
2872*7c478bd9Sstevel@tonic-gate 	}
2873*7c478bd9Sstevel@tonic-gate 
2874*7c478bd9Sstevel@tonic-gate 	hnc_init(0);
2875*7c478bd9Sstevel@tonic-gate 
2876*7c478bd9Sstevel@tonic-gate 	/*
2877*7c478bd9Sstevel@tonic-gate 	 * Note that getnets will allocate network resources, but won't be
2878*7c478bd9Sstevel@tonic-gate 	 * binding UDP port. This is because, there could be a race
2879*7c478bd9Sstevel@tonic-gate 	 * condition between door. If we bind here, one syslogd could grab
2880*7c478bd9Sstevel@tonic-gate 	 * UDP port first, but later another syslogd could take over without
2881*7c478bd9Sstevel@tonic-gate 	 * getting UDP port but grab the door file. The 2nd syslogd could
2882*7c478bd9Sstevel@tonic-gate 	 * continue to run without listening network.
2883*7c478bd9Sstevel@tonic-gate 	 * bindnet() will be called after door was successfully opened.
2884*7c478bd9Sstevel@tonic-gate 	 */
2885*7c478bd9Sstevel@tonic-gate 	getnets();
2886*7c478bd9Sstevel@tonic-gate 
2887*7c478bd9Sstevel@tonic-gate 	/*
2888*7c478bd9Sstevel@tonic-gate 	 * Start up configured theads
2889*7c478bd9Sstevel@tonic-gate 	 */
2890*7c478bd9Sstevel@tonic-gate 	conf_init();
2891*7c478bd9Sstevel@tonic-gate 
2892*7c478bd9Sstevel@tonic-gate 	/*
2893*7c478bd9Sstevel@tonic-gate 	 * allocate thread stacks for the persistant threads
2894*7c478bd9Sstevel@tonic-gate 	 */
2895*7c478bd9Sstevel@tonic-gate 	nthread = (turnoff == 0) ? 4 : 2;
2896*7c478bd9Sstevel@tonic-gate 
2897*7c478bd9Sstevel@tonic-gate 	if ((stack_ptr = alloc_stacks(nthread)) == NULL) {
2898*7c478bd9Sstevel@tonic-gate 		logerror("alloc_stacks failed - fatal");
2899*7c478bd9Sstevel@tonic-gate 		exit(1);
2900*7c478bd9Sstevel@tonic-gate 	}
2901*7c478bd9Sstevel@tonic-gate 
2902*7c478bd9Sstevel@tonic-gate 	if (Debug) {
2903*7c478bd9Sstevel@tonic-gate 		dumpstats(STDOUT_FILENO);
2904*7c478bd9Sstevel@tonic-gate 	}
2905*7c478bd9Sstevel@tonic-gate 
2906*7c478bd9Sstevel@tonic-gate 	(void) dataq_init(&inputq);	/* init the input queue */
2907*7c478bd9Sstevel@tonic-gate 
2908*7c478bd9Sstevel@tonic-gate 	if (pthread_attr_init(&sys_attr) != 0 ||
2909*7c478bd9Sstevel@tonic-gate 	    pthread_attr_init(&log_attr) != 0 ||
2910*7c478bd9Sstevel@tonic-gate 	    pthread_attr_init(&net_attr) != 0 ||
2911*7c478bd9Sstevel@tonic-gate 	    pthread_attr_init(&hnl_attr) != 0) {
2912*7c478bd9Sstevel@tonic-gate 		logerror("pthread_attr_init failed - fatal");
2913*7c478bd9Sstevel@tonic-gate 		exit(1);
2914*7c478bd9Sstevel@tonic-gate 	}
2915*7c478bd9Sstevel@tonic-gate 
2916*7c478bd9Sstevel@tonic-gate 	(void) pthread_attr_setscope(&sys_attr, PTHREAD_SCOPE_PROCESS);
2917*7c478bd9Sstevel@tonic-gate 	(void) pthread_attr_setscope(&log_attr, PTHREAD_SCOPE_PROCESS);
2918*7c478bd9Sstevel@tonic-gate 	(void) pthread_attr_setscope(&net_attr, PTHREAD_SCOPE_PROCESS);
2919*7c478bd9Sstevel@tonic-gate 	(void) pthread_attr_setscope(&hnl_attr, PTHREAD_SCOPE_PROCESS);
2920*7c478bd9Sstevel@tonic-gate 
2921*7c478bd9Sstevel@tonic-gate 	/* 1: logmsg thread */
2922*7c478bd9Sstevel@tonic-gate 	(void) pthread_attr_setstacksize(&log_attr, stacksize);
2923*7c478bd9Sstevel@tonic-gate 	(void) pthread_attr_setstackaddr(&log_attr, stack_ptr);
2924*7c478bd9Sstevel@tonic-gate 	stack_ptr += stacksize + redzonesize;
2925*7c478bd9Sstevel@tonic-gate 	if (pthread_create(&log_thread, &log_attr, logmsg, NULL) != 0) {
2926*7c478bd9Sstevel@tonic-gate 		logerror("pthread_create failed - fatal");
2927*7c478bd9Sstevel@tonic-gate 		exit(1);
2928*7c478bd9Sstevel@tonic-gate 	}
2929*7c478bd9Sstevel@tonic-gate 
2930*7c478bd9Sstevel@tonic-gate 	/*
2931*7c478bd9Sstevel@tonic-gate 	 * open the log device, and pull up all pending message
2932*7c478bd9Sstevel@tonic-gate 	 * from the log driver.
2933*7c478bd9Sstevel@tonic-gate 	 */
2934*7c478bd9Sstevel@tonic-gate 	prepare_sys_poll();
2935*7c478bd9Sstevel@tonic-gate 
2936*7c478bd9Sstevel@tonic-gate 	/*
2937*7c478bd9Sstevel@tonic-gate 	 * Now we can deliver the pending internal error messages.
2938*7c478bd9Sstevel@tonic-gate 	 */
2939*7c478bd9Sstevel@tonic-gate 	enable_errorlog();
2940*7c478bd9Sstevel@tonic-gate 
2941*7c478bd9Sstevel@tonic-gate 	/* 2: sys_poll thread */
2942*7c478bd9Sstevel@tonic-gate 	(void) pthread_attr_setstacksize(&sys_attr, stacksize);
2943*7c478bd9Sstevel@tonic-gate 	(void) pthread_attr_setstackaddr(&sys_attr, stack_ptr);
2944*7c478bd9Sstevel@tonic-gate 	stack_ptr += stacksize + redzonesize;
2945*7c478bd9Sstevel@tonic-gate 	if (pthread_create(&sys_thread, &sys_attr, sys_poll, NULL) != 0) {
2946*7c478bd9Sstevel@tonic-gate 		logerror("pthread_create failed - fatal");
2947*7c478bd9Sstevel@tonic-gate 		exit(1);
2948*7c478bd9Sstevel@tonic-gate 	}
2949*7c478bd9Sstevel@tonic-gate 
2950*7c478bd9Sstevel@tonic-gate 	/*
2951*7c478bd9Sstevel@tonic-gate 	 * We've started the sys_poll() and logmsg() threads.  Now we are ready
2952*7c478bd9Sstevel@tonic-gate 	 * to open the door.  This cannot happen before spawning sys_poll(),
2953*7c478bd9Sstevel@tonic-gate 	 * because after opening the door, syslog() will no longer take care of
2954*7c478bd9Sstevel@tonic-gate 	 * LOG_CONS.  Therefor, we should pull up all pending log messages and
2955*7c478bd9Sstevel@tonic-gate 	 * activate sys_poll() before opening the door, so that log driver
2956*7c478bd9Sstevel@tonic-gate 	 * won't drop messages.
2957*7c478bd9Sstevel@tonic-gate 	 */
2958*7c478bd9Sstevel@tonic-gate 	open_door();
2959*7c478bd9Sstevel@tonic-gate 
2960*7c478bd9Sstevel@tonic-gate 	DPRINT1(1, "init(%u): accepting messages from local system\n",
2961*7c478bd9Sstevel@tonic-gate 			mythreadno);
2962*7c478bd9Sstevel@tonic-gate 
2963*7c478bd9Sstevel@tonic-gate 	if (turnoff == 0) {
2964*7c478bd9Sstevel@tonic-gate 		/* init the hostname lookup queue */
2965*7c478bd9Sstevel@tonic-gate 		(void) dataq_init(&hnlq);
2966*7c478bd9Sstevel@tonic-gate 
2967*7c478bd9Sstevel@tonic-gate 		/* 3: hostname lookup thread */
2968*7c478bd9Sstevel@tonic-gate 		(void) pthread_attr_setstacksize(&hnl_attr, stacksize);
2969*7c478bd9Sstevel@tonic-gate 		(void) pthread_attr_setstackaddr(&hnl_attr, stack_ptr);
2970*7c478bd9Sstevel@tonic-gate 		stack_ptr += stacksize + redzonesize;
2971*7c478bd9Sstevel@tonic-gate 		if (pthread_create(&hnl_thread, &hnl_attr,
2972*7c478bd9Sstevel@tonic-gate 				hostname_lookup, NULL) != 0) {
2973*7c478bd9Sstevel@tonic-gate 			logerror("pthread_create failed - fatal");
2974*7c478bd9Sstevel@tonic-gate 			exit(1);
2975*7c478bd9Sstevel@tonic-gate 		}
2976*7c478bd9Sstevel@tonic-gate 
2977*7c478bd9Sstevel@tonic-gate 		/* 4: net_poll thread */
2978*7c478bd9Sstevel@tonic-gate 		(void) pthread_attr_setstacksize(&net_attr, stacksize);
2979*7c478bd9Sstevel@tonic-gate 		(void) pthread_attr_setstackaddr(&net_attr, stack_ptr);
2980*7c478bd9Sstevel@tonic-gate 		stack_ptr += stacksize + redzonesize;
2981*7c478bd9Sstevel@tonic-gate 
2982*7c478bd9Sstevel@tonic-gate 		/* grab UDP port */
2983*7c478bd9Sstevel@tonic-gate 		bindnet();
2984*7c478bd9Sstevel@tonic-gate 
2985*7c478bd9Sstevel@tonic-gate 		if (pthread_create(&net_thread, &net_attr, net_poll,
2986*7c478bd9Sstevel@tonic-gate 					NULL) != 0) {
2987*7c478bd9Sstevel@tonic-gate 			logerror("pthread_create failed - fatal");
2988*7c478bd9Sstevel@tonic-gate 			exit(1);
2989*7c478bd9Sstevel@tonic-gate 		}
2990*7c478bd9Sstevel@tonic-gate 		DPRINT1(1, "init(%u): accepting messages from remote\n",
2991*7c478bd9Sstevel@tonic-gate 				mythreadno);
2992*7c478bd9Sstevel@tonic-gate 	}
2993*7c478bd9Sstevel@tonic-gate 
2994*7c478bd9Sstevel@tonic-gate 	(void) pthread_attr_destroy(&sys_attr);
2995*7c478bd9Sstevel@tonic-gate 	(void) pthread_attr_destroy(&net_attr);
2996*7c478bd9Sstevel@tonic-gate 	(void) pthread_attr_destroy(&log_attr);
2997*7c478bd9Sstevel@tonic-gate 	(void) pthread_attr_destroy(&hnl_attr);
2998*7c478bd9Sstevel@tonic-gate 
2999*7c478bd9Sstevel@tonic-gate 	curalarm = MarkInterval * 60 / MARKCOUNT;
3000*7c478bd9Sstevel@tonic-gate 	(void) alarm((unsigned)curalarm);
3001*7c478bd9Sstevel@tonic-gate 	DPRINT2(2, "init(%u): Next alarm in %d seconds\n",
3002*7c478bd9Sstevel@tonic-gate 		mythreadno, curalarm);
3003*7c478bd9Sstevel@tonic-gate 	DPRINT1(1, "init(%u): syslogd: started\n", mythreadno);
3004*7c478bd9Sstevel@tonic-gate }
3005*7c478bd9Sstevel@tonic-gate 
3006*7c478bd9Sstevel@tonic-gate /*
3007*7c478bd9Sstevel@tonic-gate  * will print a bunch of debugging stats on 'fd'
3008*7c478bd9Sstevel@tonic-gate  */
3009*7c478bd9Sstevel@tonic-gate static void
3010*7c478bd9Sstevel@tonic-gate dumpstats(int fd)
3011*7c478bd9Sstevel@tonic-gate {
3012*7c478bd9Sstevel@tonic-gate 	FILE *out;
3013*7c478bd9Sstevel@tonic-gate 	struct filed *f;
3014*7c478bd9Sstevel@tonic-gate 	int i;
3015*7c478bd9Sstevel@tonic-gate 	char users[1024];
3016*7c478bd9Sstevel@tonic-gate 	char cbuf[30];
3017*7c478bd9Sstevel@tonic-gate 	char *dashes = "------------------------";
3018*7c478bd9Sstevel@tonic-gate 	static int conversion_printed;
3019*7c478bd9Sstevel@tonic-gate 
3020*7c478bd9Sstevel@tonic-gate 	if ((out = fdopen(fd, "w+")) == NULL)
3021*7c478bd9Sstevel@tonic-gate 		return;
3022*7c478bd9Sstevel@tonic-gate 
3023*7c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "\n  syslogd: version %s\n", Version);
3024*7c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "  Started: %s", ctime_r(&start_time, cbuf));
3025*7c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "Input message count: system %d, network %d\n",
3026*7c478bd9Sstevel@tonic-gate 		sys_msg_count, net_msg_count);
3027*7c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "# Outputs: %d\n\n", nlogs);
3028*7c478bd9Sstevel@tonic-gate 
3029*7c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "%s priority = [file, facility] %s\n\n",
3030*7c478bd9Sstevel@tonic-gate 		dashes, dashes);
3031*7c478bd9Sstevel@tonic-gate 
3032*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < LOG_NFACILITIES + 1; i++) {
3033*7c478bd9Sstevel@tonic-gate 		(void) fprintf(out, "%d ", i / 10);
3034*7c478bd9Sstevel@tonic-gate 	}
3035*7c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "\n");
3036*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < LOG_NFACILITIES + 1; i++) {
3037*7c478bd9Sstevel@tonic-gate 		(void) fprintf(out, "%d ", i % 10);
3038*7c478bd9Sstevel@tonic-gate 	}
3039*7c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "\n");
3040*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < LOG_NFACILITIES + 1; i++) {
3041*7c478bd9Sstevel@tonic-gate 		(void) fprintf(out, "--");
3042*7c478bd9Sstevel@tonic-gate 	}
3043*7c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "\n");
3044*7c478bd9Sstevel@tonic-gate 
3045*7c478bd9Sstevel@tonic-gate 	for (f = Files; f < &Files[nlogs]; f++) {
3046*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < LOG_NFACILITIES + 1; i++) {
3047*7c478bd9Sstevel@tonic-gate 			if (f->f_pmask[i] == NOPRI)
3048*7c478bd9Sstevel@tonic-gate 				(void) fprintf(out, "X ");
3049*7c478bd9Sstevel@tonic-gate 			else
3050*7c478bd9Sstevel@tonic-gate 				(void) fprintf(out, "%d ",
3051*7c478bd9Sstevel@tonic-gate 					f->f_pmask[i]);
3052*7c478bd9Sstevel@tonic-gate 		}
3053*7c478bd9Sstevel@tonic-gate 		(void) fprintf(out, "%s: ", TypeNames[f->f_type]);
3054*7c478bd9Sstevel@tonic-gate 		switch (f->f_type) {
3055*7c478bd9Sstevel@tonic-gate 		case F_FILE:
3056*7c478bd9Sstevel@tonic-gate 		case F_TTY:
3057*7c478bd9Sstevel@tonic-gate 		case F_CONSOLE:
3058*7c478bd9Sstevel@tonic-gate 			(void) fprintf(out, "%s", f->f_un.f_fname);
3059*7c478bd9Sstevel@tonic-gate 			break;
3060*7c478bd9Sstevel@tonic-gate 		case F_FORW:
3061*7c478bd9Sstevel@tonic-gate 			(void) fprintf(out, "%s", f->f_un.f_forw.f_hname);
3062*7c478bd9Sstevel@tonic-gate 			break;
3063*7c478bd9Sstevel@tonic-gate 		case F_USERS:
3064*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < MAXUNAMES &&
3065*7c478bd9Sstevel@tonic-gate 				*f->f_un.f_uname[i]; i++) {
3066*7c478bd9Sstevel@tonic-gate 				if (!i)
3067*7c478bd9Sstevel@tonic-gate 					(void) fprintf(out, "%s",
3068*7c478bd9Sstevel@tonic-gate 						f->f_un.f_uname[i]);
3069*7c478bd9Sstevel@tonic-gate 				else
3070*7c478bd9Sstevel@tonic-gate 					(void) fprintf(out, ", %s",
3071*7c478bd9Sstevel@tonic-gate 						f->f_un.f_uname[i]);
3072*7c478bd9Sstevel@tonic-gate 			}
3073*7c478bd9Sstevel@tonic-gate 			break;
3074*7c478bd9Sstevel@tonic-gate 		}
3075*7c478bd9Sstevel@tonic-gate 		(void) fprintf(out, "\n");
3076*7c478bd9Sstevel@tonic-gate 	}
3077*7c478bd9Sstevel@tonic-gate 
3078*7c478bd9Sstevel@tonic-gate 	if (!conversion_printed) {
3079*7c478bd9Sstevel@tonic-gate 		fprintf(out, "\nFacilities:\n");
3080*7c478bd9Sstevel@tonic-gate 
3081*7c478bd9Sstevel@tonic-gate 		for (i = 0; FacNames[i].c_val != -1; i++) {
3082*7c478bd9Sstevel@tonic-gate 			fprintf(out, "  [%02d] %s: %3d\n", i,
3083*7c478bd9Sstevel@tonic-gate 				FacNames[i].c_name, FacNames[i].c_val);
3084*7c478bd9Sstevel@tonic-gate 		}
3085*7c478bd9Sstevel@tonic-gate 
3086*7c478bd9Sstevel@tonic-gate 		fprintf(out, "\nPriorities:\n");
3087*7c478bd9Sstevel@tonic-gate 
3088*7c478bd9Sstevel@tonic-gate 		for (i = 0; PriNames[i].c_val != -1; i++) {
3089*7c478bd9Sstevel@tonic-gate 			fprintf(out, "  [%02d] %s: %3d\n", i,
3090*7c478bd9Sstevel@tonic-gate 				PriNames[i].c_name, PriNames[i].c_val);
3091*7c478bd9Sstevel@tonic-gate 		}
3092*7c478bd9Sstevel@tonic-gate 
3093*7c478bd9Sstevel@tonic-gate 		conversion_printed = 1;
3094*7c478bd9Sstevel@tonic-gate 	}
3095*7c478bd9Sstevel@tonic-gate 
3096*7c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "\n\n\n\t\tPer File Statistics\n");
3097*7c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "%-24s\tTot\tDups\tNofwd\tErrs\n", "File");
3098*7c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "%-24s\t---\t----\t-----\t----\n", "----");
3099*7c478bd9Sstevel@tonic-gate 	for (f = Files; f < &Files[nlogs]; f++) {
3100*7c478bd9Sstevel@tonic-gate 		switch (f->f_type) {
3101*7c478bd9Sstevel@tonic-gate 		case F_FILE:
3102*7c478bd9Sstevel@tonic-gate 		case F_TTY:
3103*7c478bd9Sstevel@tonic-gate 		case F_CONSOLE:
3104*7c478bd9Sstevel@tonic-gate 			(void) fprintf(out, "%-24s", f->f_un.f_fname);
3105*7c478bd9Sstevel@tonic-gate 			break;
3106*7c478bd9Sstevel@tonic-gate 		case F_WALL:
3107*7c478bd9Sstevel@tonic-gate 			(void) fprintf(out, "%-24s", TypeNames[f->f_type]);
3108*7c478bd9Sstevel@tonic-gate 			break;
3109*7c478bd9Sstevel@tonic-gate 		case F_FORW:
3110*7c478bd9Sstevel@tonic-gate 			(void) fprintf(out, "%-24s", f->f_un.f_forw.f_hname);
3111*7c478bd9Sstevel@tonic-gate 			break;
3112*7c478bd9Sstevel@tonic-gate 		case F_USERS:
3113*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < MAXUNAMES &&
3114*7c478bd9Sstevel@tonic-gate 				*f->f_un.f_uname[i]; i++) {
3115*7c478bd9Sstevel@tonic-gate 				if (!i)
3116*7c478bd9Sstevel@tonic-gate 					(void) strcpy(users,
3117*7c478bd9Sstevel@tonic-gate 						f->f_un.f_uname[i]);
3118*7c478bd9Sstevel@tonic-gate 				else {
3119*7c478bd9Sstevel@tonic-gate 					(void) strcat(users, ",");
3120*7c478bd9Sstevel@tonic-gate 					(void) strcat(users,
3121*7c478bd9Sstevel@tonic-gate 						f->f_un.f_uname[i]);
3122*7c478bd9Sstevel@tonic-gate 				}
3123*7c478bd9Sstevel@tonic-gate 			}
3124*7c478bd9Sstevel@tonic-gate 			(void) fprintf(out, "%-24s", users);
3125*7c478bd9Sstevel@tonic-gate 			break;
3126*7c478bd9Sstevel@tonic-gate 		}
3127*7c478bd9Sstevel@tonic-gate 		(void) fprintf(out, "\t%d\t%d\t%d\t%d\n",
3128*7c478bd9Sstevel@tonic-gate 			f->f_stat.total, f->f_stat.dups,
3129*7c478bd9Sstevel@tonic-gate 			f->f_stat.cantfwd, f->f_stat.errs);
3130*7c478bd9Sstevel@tonic-gate 	}
3131*7c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "\n\n");
3132*7c478bd9Sstevel@tonic-gate 	if (Debug && fd == 1)
3133*7c478bd9Sstevel@tonic-gate 		return;
3134*7c478bd9Sstevel@tonic-gate 	(void) fclose(out);
3135*7c478bd9Sstevel@tonic-gate }
3136*7c478bd9Sstevel@tonic-gate 
3137*7c478bd9Sstevel@tonic-gate /*
3138*7c478bd9Sstevel@tonic-gate  * conf_init - This routine is code seperated from the
3139*7c478bd9Sstevel@tonic-gate  * init routine in order to be re-callable when we get
3140*7c478bd9Sstevel@tonic-gate  * a SIGHUP signal.
3141*7c478bd9Sstevel@tonic-gate  */
3142*7c478bd9Sstevel@tonic-gate static void
3143*7c478bd9Sstevel@tonic-gate conf_init(void)
3144*7c478bd9Sstevel@tonic-gate {
3145*7c478bd9Sstevel@tonic-gate 	char *p;
3146*7c478bd9Sstevel@tonic-gate 	int i;
3147*7c478bd9Sstevel@tonic-gate 	struct filed *f;
3148*7c478bd9Sstevel@tonic-gate 	char *m4argv[4];
3149*7c478bd9Sstevel@tonic-gate 	int m4argc = 0;
3150*7c478bd9Sstevel@tonic-gate 	conf_t cf;
3151*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
3152*7c478bd9Sstevel@tonic-gate 
3153*7c478bd9Sstevel@tonic-gate 	if (Debug) {
3154*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
3155*7c478bd9Sstevel@tonic-gate 	}
3156*7c478bd9Sstevel@tonic-gate 
3157*7c478bd9Sstevel@tonic-gate 	DPRINT1(2, "conf_init(%u): starting logger threads\n",
3158*7c478bd9Sstevel@tonic-gate 		mythreadno);
3159*7c478bd9Sstevel@tonic-gate 
3160*7c478bd9Sstevel@tonic-gate 	m4argv[m4argc++] = "m4";
3161*7c478bd9Sstevel@tonic-gate 
3162*7c478bd9Sstevel@tonic-gate 	if (amiloghost() == 1) {
3163*7c478bd9Sstevel@tonic-gate 		DPRINT1(1, "conf_init(%u): I am loghost\n", mythreadno);
3164*7c478bd9Sstevel@tonic-gate 		m4argv[m4argc++] = "-DLOGHOST=1";
3165*7c478bd9Sstevel@tonic-gate 	}
3166*7c478bd9Sstevel@tonic-gate 
3167*7c478bd9Sstevel@tonic-gate 	m4argv[m4argc++] = ConfFile;
3168*7c478bd9Sstevel@tonic-gate 	m4argv[m4argc] = NULL;
3169*7c478bd9Sstevel@tonic-gate 
3170*7c478bd9Sstevel@tonic-gate 	/*
3171*7c478bd9Sstevel@tonic-gate 	 * Make sure the configuration file and m4 exist, and then parse
3172*7c478bd9Sstevel@tonic-gate 	 * the configuration file with m4.  If any of these fail, resort
3173*7c478bd9Sstevel@tonic-gate 	 * to our hardcoded fallback configuration.
3174*7c478bd9Sstevel@tonic-gate 	 */
3175*7c478bd9Sstevel@tonic-gate 
3176*7c478bd9Sstevel@tonic-gate 	if (access(ConfFile, R_OK) == -1) {
3177*7c478bd9Sstevel@tonic-gate 		DPRINT2(1, "conf_init(%u): %s does not exist\n", mythreadno,
3178*7c478bd9Sstevel@tonic-gate 			ConfFile);
3179*7c478bd9Sstevel@tonic-gate 		logerror("can't open configuration file");
3180*7c478bd9Sstevel@tonic-gate 		/* CSTYLED */
3181*7c478bd9Sstevel@tonic-gate 		Files = (struct filed *) &fallback; /*lint !e545 */
3182*7c478bd9Sstevel@tonic-gate 		cfline("*.ERR\t/dev/sysmsg", 0, &Files[0]);
3183*7c478bd9Sstevel@tonic-gate 		cfline("*.PANIC\t*", 0, &Files[1]);
3184*7c478bd9Sstevel@tonic-gate 		nlogs = 2;
3185*7c478bd9Sstevel@tonic-gate 		goto nofile;
3186*7c478bd9Sstevel@tonic-gate 	}
3187*7c478bd9Sstevel@tonic-gate 
3188*7c478bd9Sstevel@tonic-gate 	if (checkm4() != 0 || conf_open(&cf, "/usr/ccs/bin/m4", m4argv) == -1) {
3189*7c478bd9Sstevel@tonic-gate 		DPRINT2(1, "conf_init(%u): cannot open %s\n", mythreadno,
3190*7c478bd9Sstevel@tonic-gate 			ConfFile);
3191*7c478bd9Sstevel@tonic-gate 		/* CSTYLED */
3192*7c478bd9Sstevel@tonic-gate 		Files = (struct filed *) &fallback; /*lint !e545 */
3193*7c478bd9Sstevel@tonic-gate 		cfline("*.ERR\t/dev/sysmsg", 0, &Files[0]);
3194*7c478bd9Sstevel@tonic-gate 		cfline("*.PANIC\t*", 0, &Files[1]);
3195*7c478bd9Sstevel@tonic-gate 		nlogs = 2;
3196*7c478bd9Sstevel@tonic-gate 		goto nofile;
3197*7c478bd9Sstevel@tonic-gate 	}
3198*7c478bd9Sstevel@tonic-gate 
3199*7c478bd9Sstevel@tonic-gate 	/* Count the number of lines which are not blanks or comments */
3200*7c478bd9Sstevel@tonic-gate 	nlogs = 0;
3201*7c478bd9Sstevel@tonic-gate 	while ((p = conf_read(&cf)) != NULL) {
3202*7c478bd9Sstevel@tonic-gate 		if (p[0] != '\0' && p[0] != '#')
3203*7c478bd9Sstevel@tonic-gate 			nlogs++;
3204*7c478bd9Sstevel@tonic-gate 	}
3205*7c478bd9Sstevel@tonic-gate 
3206*7c478bd9Sstevel@tonic-gate 	Files = (struct filed *)malloc(sizeof (struct filed) * nlogs);
3207*7c478bd9Sstevel@tonic-gate 
3208*7c478bd9Sstevel@tonic-gate 	if (!Files) {
3209*7c478bd9Sstevel@tonic-gate 		DPRINT1(1, "conf_init(%u): malloc failed - can't "
3210*7c478bd9Sstevel@tonic-gate 			"allocate 'Files' array\n", mythreadno);
3211*7c478bd9Sstevel@tonic-gate 		MALLOC_FAIL("loading minimum configuration");
3212*7c478bd9Sstevel@tonic-gate 		/* CSTYLED */
3213*7c478bd9Sstevel@tonic-gate 		Files = (struct filed *) &fallback; /*lint !e545 */
3214*7c478bd9Sstevel@tonic-gate 		cfline("*.ERR\t/dev/sysmsg", 0, &Files[0]);
3215*7c478bd9Sstevel@tonic-gate 		cfline("*.PANIC\t*", 0, &Files[1]);
3216*7c478bd9Sstevel@tonic-gate 		nlogs = 2;
3217*7c478bd9Sstevel@tonic-gate 		conf_close(&cf);
3218*7c478bd9Sstevel@tonic-gate 		goto nofile;
3219*7c478bd9Sstevel@tonic-gate 	}
3220*7c478bd9Sstevel@tonic-gate 
3221*7c478bd9Sstevel@tonic-gate 	/*
3222*7c478bd9Sstevel@tonic-gate 	 *  Foreach line in the conf table, open that file.
3223*7c478bd9Sstevel@tonic-gate 	 */
3224*7c478bd9Sstevel@tonic-gate 	conf_rewind(&cf);
3225*7c478bd9Sstevel@tonic-gate 	f = Files;
3226*7c478bd9Sstevel@tonic-gate 	i = 0;
3227*7c478bd9Sstevel@tonic-gate 	while (((p = conf_read(&cf)) != NULL) && (f < &Files[nlogs])) {
3228*7c478bd9Sstevel@tonic-gate 		i++;
3229*7c478bd9Sstevel@tonic-gate 		/* check for end-of-section */
3230*7c478bd9Sstevel@tonic-gate 		if (p[0] == '\0' || p[0] == '#')
3231*7c478bd9Sstevel@tonic-gate 			continue;
3232*7c478bd9Sstevel@tonic-gate 
3233*7c478bd9Sstevel@tonic-gate 		cfline(p, i, f);
3234*7c478bd9Sstevel@tonic-gate 		if (f->f_type == F_UNUSED)
3235*7c478bd9Sstevel@tonic-gate 			nlogs--;
3236*7c478bd9Sstevel@tonic-gate 		else
3237*7c478bd9Sstevel@tonic-gate 			f++;
3238*7c478bd9Sstevel@tonic-gate 	}
3239*7c478bd9Sstevel@tonic-gate 
3240*7c478bd9Sstevel@tonic-gate 	conf_close(&cf);
3241*7c478bd9Sstevel@tonic-gate 
3242*7c478bd9Sstevel@tonic-gate 	/*
3243*7c478bd9Sstevel@tonic-gate 	 * See if marks are to be written to any files.  If so, set up a
3244*7c478bd9Sstevel@tonic-gate 	 * timeout for marks.
3245*7c478bd9Sstevel@tonic-gate 	 */
3246*7c478bd9Sstevel@tonic-gate nofile:
3247*7c478bd9Sstevel@tonic-gate 	Marking = 0;
3248*7c478bd9Sstevel@tonic-gate 
3249*7c478bd9Sstevel@tonic-gate 	/*
3250*7c478bd9Sstevel@tonic-gate 	 * allocate thread stacks - one for each logger thread.
3251*7c478bd9Sstevel@tonic-gate 	 */
3252*7c478bd9Sstevel@tonic-gate 	if ((cstack_ptr = alloc_stacks(nlogs)) == NULL) {
3253*7c478bd9Sstevel@tonic-gate 		logerror("alloc_stacks failed - fatal");
3254*7c478bd9Sstevel@tonic-gate 		exit(1);
3255*7c478bd9Sstevel@tonic-gate 	}
3256*7c478bd9Sstevel@tonic-gate 
3257*7c478bd9Sstevel@tonic-gate 	/* And now one thread for each configured file */
3258*7c478bd9Sstevel@tonic-gate 	for (f = Files; f < &Files[nlogs]; f++) {
3259*7c478bd9Sstevel@tonic-gate 		if (filed_init(f) != 0) {
3260*7c478bd9Sstevel@tonic-gate 			logerror("pthread_create failed - fatal");
3261*7c478bd9Sstevel@tonic-gate 			exit(1);
3262*7c478bd9Sstevel@tonic-gate 		}
3263*7c478bd9Sstevel@tonic-gate 
3264*7c478bd9Sstevel@tonic-gate 		pthread_mutex_lock(&cft);
3265*7c478bd9Sstevel@tonic-gate 		++conf_threads;
3266*7c478bd9Sstevel@tonic-gate 		pthread_mutex_unlock(&cft);
3267*7c478bd9Sstevel@tonic-gate 
3268*7c478bd9Sstevel@tonic-gate 		if (f->f_type != F_UNUSED &&
3269*7c478bd9Sstevel@tonic-gate 			f->f_pmask[LOG_NFACILITIES] != NOPRI)
3270*7c478bd9Sstevel@tonic-gate 			Marking = 1;
3271*7c478bd9Sstevel@tonic-gate 	}
3272*7c478bd9Sstevel@tonic-gate }
3273*7c478bd9Sstevel@tonic-gate 
3274*7c478bd9Sstevel@tonic-gate /*
3275*7c478bd9Sstevel@tonic-gate  * filed init - initialize fields in a file descriptor struct
3276*7c478bd9Sstevel@tonic-gate  * this is called before multiple threads are running, so no mutex
3277*7c478bd9Sstevel@tonic-gate  * needs to be held at this time.
3278*7c478bd9Sstevel@tonic-gate  */
3279*7c478bd9Sstevel@tonic-gate static
3280*7c478bd9Sstevel@tonic-gate filed_init(struct filed *f)
3281*7c478bd9Sstevel@tonic-gate {
3282*7c478bd9Sstevel@tonic-gate 	pthread_attr_t stack_attr;
3283*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
3284*7c478bd9Sstevel@tonic-gate 
3285*7c478bd9Sstevel@tonic-gate 	if (Debug) {
3286*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
3287*7c478bd9Sstevel@tonic-gate 	}
3288*7c478bd9Sstevel@tonic-gate 
3289*7c478bd9Sstevel@tonic-gate 	if (pthread_mutex_init(&f->filed_mutex, NULL) != 0) {
3290*7c478bd9Sstevel@tonic-gate 		logerror("pthread_mutex_init failed");
3291*7c478bd9Sstevel@tonic-gate 		return (-1);
3292*7c478bd9Sstevel@tonic-gate 	}
3293*7c478bd9Sstevel@tonic-gate 
3294*7c478bd9Sstevel@tonic-gate 	DPRINT2(5, "filed_init(%u): dataq_init for queue %p\n",
3295*7c478bd9Sstevel@tonic-gate 		mythreadno, &f->f_queue);
3296*7c478bd9Sstevel@tonic-gate 	(void) dataq_init(&f->f_queue);
3297*7c478bd9Sstevel@tonic-gate 
3298*7c478bd9Sstevel@tonic-gate 	if (pthread_attr_init(&stack_attr) != 0) {
3299*7c478bd9Sstevel@tonic-gate 		logerror("pthread_attr_init failed");
3300*7c478bd9Sstevel@tonic-gate 		return (-1);
3301*7c478bd9Sstevel@tonic-gate 	}
3302*7c478bd9Sstevel@tonic-gate 
3303*7c478bd9Sstevel@tonic-gate 	(void) pthread_attr_setstacksize(&stack_attr, stacksize);
3304*7c478bd9Sstevel@tonic-gate 	(void) pthread_attr_setstackaddr(&stack_attr, cstack_ptr);
3305*7c478bd9Sstevel@tonic-gate 	cstack_ptr += stacksize + redzonesize;
3306*7c478bd9Sstevel@tonic-gate 
3307*7c478bd9Sstevel@tonic-gate 	f->f_msgflag = 0;
3308*7c478bd9Sstevel@tonic-gate 	f->f_prevmsg.msg[0] = '\0';
3309*7c478bd9Sstevel@tonic-gate 	f->f_prevmsg.flags = 0;
3310*7c478bd9Sstevel@tonic-gate 	f->f_prevmsg.pri = 0;
3311*7c478bd9Sstevel@tonic-gate 	f->f_prevmsg.host[0] = '\0';
3312*7c478bd9Sstevel@tonic-gate 
3313*7c478bd9Sstevel@tonic-gate 	f->f_current.msg[0] = '\0';
3314*7c478bd9Sstevel@tonic-gate 	f->f_current.flags = 0;
3315*7c478bd9Sstevel@tonic-gate 	f->f_current.pri = 0;
3316*7c478bd9Sstevel@tonic-gate 	f->f_current.host[0] = '\0';
3317*7c478bd9Sstevel@tonic-gate 
3318*7c478bd9Sstevel@tonic-gate 	f->f_prevcount = 0;
3319*7c478bd9Sstevel@tonic-gate 
3320*7c478bd9Sstevel@tonic-gate 	f->f_stat.flag = 0;
3321*7c478bd9Sstevel@tonic-gate 	f->f_stat.total = 0;
3322*7c478bd9Sstevel@tonic-gate 	f->f_stat.dups = 0;
3323*7c478bd9Sstevel@tonic-gate 	f->f_stat.cantfwd = 0;
3324*7c478bd9Sstevel@tonic-gate 	f->f_stat.errs = 0;
3325*7c478bd9Sstevel@tonic-gate 
3326*7c478bd9Sstevel@tonic-gate 	if (pthread_create(&f->f_thread, NULL, logit, (void *)f) != 0) {
3327*7c478bd9Sstevel@tonic-gate 		logerror("pthread_create failed");
3328*7c478bd9Sstevel@tonic-gate 		pthread_attr_destroy(&stack_attr);
3329*7c478bd9Sstevel@tonic-gate 		return (-1);
3330*7c478bd9Sstevel@tonic-gate 	}
3331*7c478bd9Sstevel@tonic-gate 
3332*7c478bd9Sstevel@tonic-gate 	pthread_attr_destroy(&stack_attr);
3333*7c478bd9Sstevel@tonic-gate 	return (0);
3334*7c478bd9Sstevel@tonic-gate }
3335*7c478bd9Sstevel@tonic-gate 
3336*7c478bd9Sstevel@tonic-gate 
3337*7c478bd9Sstevel@tonic-gate /*
3338*7c478bd9Sstevel@tonic-gate  * Crack a configuration file line
3339*7c478bd9Sstevel@tonic-gate  */
3340*7c478bd9Sstevel@tonic-gate static void
3341*7c478bd9Sstevel@tonic-gate cfline(char *line, int lineno, struct filed *f)
3342*7c478bd9Sstevel@tonic-gate {
3343*7c478bd9Sstevel@tonic-gate 	char *p;
3344*7c478bd9Sstevel@tonic-gate 	char *q;
3345*7c478bd9Sstevel@tonic-gate 	int i;
3346*7c478bd9Sstevel@tonic-gate 	char *bp;
3347*7c478bd9Sstevel@tonic-gate 	int pri;
3348*7c478bd9Sstevel@tonic-gate 	char buf[MAXLINE];
3349*7c478bd9Sstevel@tonic-gate 	char ebuf[SYS_NMLN+1+40];
3350*7c478bd9Sstevel@tonic-gate 	mode_t fmode, omode = O_WRONLY|O_APPEND|O_NOCTTY;
3351*7c478bd9Sstevel@tonic-gate 	struct stat64 sbuf;
3352*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
3353*7c478bd9Sstevel@tonic-gate 
3354*7c478bd9Sstevel@tonic-gate 	if (Debug) {
3355*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
3356*7c478bd9Sstevel@tonic-gate 	}
3357*7c478bd9Sstevel@tonic-gate 
3358*7c478bd9Sstevel@tonic-gate 	DPRINT2(1, "cfline(%u): (%s)\n", mythreadno, line);
3359*7c478bd9Sstevel@tonic-gate 
3360*7c478bd9Sstevel@tonic-gate 	errno = 0;	/* keep sys_errlist stuff out of logerror messages */
3361*7c478bd9Sstevel@tonic-gate 
3362*7c478bd9Sstevel@tonic-gate 	/* clear out file entry */
3363*7c478bd9Sstevel@tonic-gate 	bzero((char *)f, sizeof (*f));
3364*7c478bd9Sstevel@tonic-gate 	for (i = 0; i <= LOG_NFACILITIES; i++)
3365*7c478bd9Sstevel@tonic-gate 		f->f_pmask[i] = NOPRI;
3366*7c478bd9Sstevel@tonic-gate 
3367*7c478bd9Sstevel@tonic-gate 	/* scan through the list of selectors */
3368*7c478bd9Sstevel@tonic-gate 	for (p = line; *p && *p != '\t'; ) {
3369*7c478bd9Sstevel@tonic-gate 
3370*7c478bd9Sstevel@tonic-gate 		/* find the end of this facility name list */
3371*7c478bd9Sstevel@tonic-gate 		for (q = p; *q && *q != '\t' && *q++ != '.'; )
3372*7c478bd9Sstevel@tonic-gate 			continue;
3373*7c478bd9Sstevel@tonic-gate 
3374*7c478bd9Sstevel@tonic-gate 		/* collect priority name */
3375*7c478bd9Sstevel@tonic-gate 		for (bp = buf; *q && !strchr("\t,;", *q); )
3376*7c478bd9Sstevel@tonic-gate 			*bp++ = *q++;
3377*7c478bd9Sstevel@tonic-gate 		*bp = '\0';
3378*7c478bd9Sstevel@tonic-gate 
3379*7c478bd9Sstevel@tonic-gate 		/* skip cruft */
3380*7c478bd9Sstevel@tonic-gate 		while (strchr(", ;", *q))
3381*7c478bd9Sstevel@tonic-gate 			q++;
3382*7c478bd9Sstevel@tonic-gate 
3383*7c478bd9Sstevel@tonic-gate 		/* decode priority name */
3384*7c478bd9Sstevel@tonic-gate 		pri = decode(buf, PriNames);
3385*7c478bd9Sstevel@tonic-gate 		if (pri < 0) {
3386*7c478bd9Sstevel@tonic-gate 			logerror("line %d: unknown priority name \"%s\"",
3387*7c478bd9Sstevel@tonic-gate 					lineno, buf);
3388*7c478bd9Sstevel@tonic-gate 			return;
3389*7c478bd9Sstevel@tonic-gate 		}
3390*7c478bd9Sstevel@tonic-gate 
3391*7c478bd9Sstevel@tonic-gate 		/* scan facilities */
3392*7c478bd9Sstevel@tonic-gate 		while (*p && !strchr("\t.;", *p)) {
3393*7c478bd9Sstevel@tonic-gate 			for (bp = buf; *p && !strchr("\t,;.", *p); )
3394*7c478bd9Sstevel@tonic-gate 				*bp++ = *p++;
3395*7c478bd9Sstevel@tonic-gate 			*bp = '\0';
3396*7c478bd9Sstevel@tonic-gate 			if (*buf == '*')
3397*7c478bd9Sstevel@tonic-gate 				for (i = 0; i < LOG_NFACILITIES; i++)
3398*7c478bd9Sstevel@tonic-gate 					f->f_pmask[i] = (uchar_t)pri;
3399*7c478bd9Sstevel@tonic-gate 			else {
3400*7c478bd9Sstevel@tonic-gate 				i = decode(buf, FacNames);
3401*7c478bd9Sstevel@tonic-gate 				if (i < 0) {
3402*7c478bd9Sstevel@tonic-gate 					logerror("line %d: unknown facility"
3403*7c478bd9Sstevel@tonic-gate 						" name \"%s\"", lineno, buf);
3404*7c478bd9Sstevel@tonic-gate 					return;
3405*7c478bd9Sstevel@tonic-gate 				}
3406*7c478bd9Sstevel@tonic-gate 				f->f_pmask[i >> 3] = (uchar_t)pri;
3407*7c478bd9Sstevel@tonic-gate 			}
3408*7c478bd9Sstevel@tonic-gate 			while (*p == ',' || *p == ' ')
3409*7c478bd9Sstevel@tonic-gate 				p++;
3410*7c478bd9Sstevel@tonic-gate 		}
3411*7c478bd9Sstevel@tonic-gate 
3412*7c478bd9Sstevel@tonic-gate 		p = q;
3413*7c478bd9Sstevel@tonic-gate 	}
3414*7c478bd9Sstevel@tonic-gate 
3415*7c478bd9Sstevel@tonic-gate 	/* skip to action part */
3416*7c478bd9Sstevel@tonic-gate 	while (*p == '\t' || *p == ' ')
3417*7c478bd9Sstevel@tonic-gate 		p++;
3418*7c478bd9Sstevel@tonic-gate 
3419*7c478bd9Sstevel@tonic-gate 	switch (*p) {
3420*7c478bd9Sstevel@tonic-gate 	case '\0':
3421*7c478bd9Sstevel@tonic-gate 		errno = 0;
3422*7c478bd9Sstevel@tonic-gate 		logerror("line %d: no action part", lineno);
3423*7c478bd9Sstevel@tonic-gate 		break;
3424*7c478bd9Sstevel@tonic-gate 
3425*7c478bd9Sstevel@tonic-gate 	case '@':
3426*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(f->f_un.f_forw.f_hname, ++p, SYS_NMLN);
3427*7c478bd9Sstevel@tonic-gate 		if (logforward(f, ebuf) != 0) {
3428*7c478bd9Sstevel@tonic-gate 			logerror("line %d: %s", lineno, ebuf);
3429*7c478bd9Sstevel@tonic-gate 			break;
3430*7c478bd9Sstevel@tonic-gate 		}
3431*7c478bd9Sstevel@tonic-gate 		f->f_type = F_FORW;
3432*7c478bd9Sstevel@tonic-gate 		break;
3433*7c478bd9Sstevel@tonic-gate 
3434*7c478bd9Sstevel@tonic-gate 	case '/':
3435*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(f->f_un.f_fname, p, MAXPATHLEN);
3436*7c478bd9Sstevel@tonic-gate 		if (stat64(p, &sbuf) < 0) {
3437*7c478bd9Sstevel@tonic-gate 			logerror(p);
3438*7c478bd9Sstevel@tonic-gate 			break;
3439*7c478bd9Sstevel@tonic-gate 		}
3440*7c478bd9Sstevel@tonic-gate 		/*
3441*7c478bd9Sstevel@tonic-gate 		 * don't block trying to open a pipe
3442*7c478bd9Sstevel@tonic-gate 		 * with no reader on the other end
3443*7c478bd9Sstevel@tonic-gate 		 */
3444*7c478bd9Sstevel@tonic-gate 		fmode = 0; 	/* reset each pass */
3445*7c478bd9Sstevel@tonic-gate 		if (S_ISFIFO(sbuf.st_mode))
3446*7c478bd9Sstevel@tonic-gate 			fmode = O_NONBLOCK;
3447*7c478bd9Sstevel@tonic-gate 
3448*7c478bd9Sstevel@tonic-gate 		f->f_file = open64(p, omode|fmode);
3449*7c478bd9Sstevel@tonic-gate 		if (f->f_file < 0) {
3450*7c478bd9Sstevel@tonic-gate 			if (fmode && errno == ENXIO) {
3451*7c478bd9Sstevel@tonic-gate 				errno = 0;
3452*7c478bd9Sstevel@tonic-gate 				logerror("%s - no reader", p);
3453*7c478bd9Sstevel@tonic-gate 			} else
3454*7c478bd9Sstevel@tonic-gate 				logerror(p);
3455*7c478bd9Sstevel@tonic-gate 			break;
3456*7c478bd9Sstevel@tonic-gate 		}
3457*7c478bd9Sstevel@tonic-gate 
3458*7c478bd9Sstevel@tonic-gate 		/*
3459*7c478bd9Sstevel@tonic-gate 		 * Fifos are initially opened NONBLOCK
3460*7c478bd9Sstevel@tonic-gate 		 * to insure we don't hang, but once
3461*7c478bd9Sstevel@tonic-gate 		 * we are open, we need to change the
3462*7c478bd9Sstevel@tonic-gate 		 * behavior back to blocking, otherwise
3463*7c478bd9Sstevel@tonic-gate 		 * we may get write errors, and the log
3464*7c478bd9Sstevel@tonic-gate 		 * will get closed down the line.
3465*7c478bd9Sstevel@tonic-gate 		 */
3466*7c478bd9Sstevel@tonic-gate 		if (S_ISFIFO(sbuf.st_mode))
3467*7c478bd9Sstevel@tonic-gate 			(void) fcntl(f->f_file, F_SETFL, omode);
3468*7c478bd9Sstevel@tonic-gate 
3469*7c478bd9Sstevel@tonic-gate 		if (isatty(f->f_file)) {
3470*7c478bd9Sstevel@tonic-gate 			f->f_type = F_TTY;
3471*7c478bd9Sstevel@tonic-gate 			untty();
3472*7c478bd9Sstevel@tonic-gate 		} else
3473*7c478bd9Sstevel@tonic-gate 			f->f_type = F_FILE;
3474*7c478bd9Sstevel@tonic-gate 
3475*7c478bd9Sstevel@tonic-gate 		if ((strcmp(p, ctty) == 0) || (strcmp(p, sysmsg) == 0))
3476*7c478bd9Sstevel@tonic-gate 			f->f_type = F_CONSOLE;
3477*7c478bd9Sstevel@tonic-gate 		break;
3478*7c478bd9Sstevel@tonic-gate 
3479*7c478bd9Sstevel@tonic-gate 	case '*':
3480*7c478bd9Sstevel@tonic-gate 		f->f_type = F_WALL;
3481*7c478bd9Sstevel@tonic-gate 		break;
3482*7c478bd9Sstevel@tonic-gate 
3483*7c478bd9Sstevel@tonic-gate 	default:
3484*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < MAXUNAMES && *p; i++) {
3485*7c478bd9Sstevel@tonic-gate 			for (q = p; *q && *q != ','; )
3486*7c478bd9Sstevel@tonic-gate 				q++;
3487*7c478bd9Sstevel@tonic-gate 			(void) strlcpy(f->f_un.f_uname[i], p, UNAMESZ);
3488*7c478bd9Sstevel@tonic-gate 			if ((q - p) > UNAMESZ)
3489*7c478bd9Sstevel@tonic-gate 				f->f_un.f_uname[i][UNAMESZ] = '\0';
3490*7c478bd9Sstevel@tonic-gate 			else
3491*7c478bd9Sstevel@tonic-gate 				f->f_un.f_uname[i][q - p] = '\0';
3492*7c478bd9Sstevel@tonic-gate 			while (*q == ',' || *q == ' ')
3493*7c478bd9Sstevel@tonic-gate 				q++;
3494*7c478bd9Sstevel@tonic-gate 			p = q;
3495*7c478bd9Sstevel@tonic-gate 		}
3496*7c478bd9Sstevel@tonic-gate 		f->f_type = F_USERS;
3497*7c478bd9Sstevel@tonic-gate 		break;
3498*7c478bd9Sstevel@tonic-gate 	}
3499*7c478bd9Sstevel@tonic-gate 	f->f_orig_type = f->f_type;
3500*7c478bd9Sstevel@tonic-gate }
3501*7c478bd9Sstevel@tonic-gate 
3502*7c478bd9Sstevel@tonic-gate 
3503*7c478bd9Sstevel@tonic-gate /*
3504*7c478bd9Sstevel@tonic-gate  *  Decode a symbolic name to a numeric value
3505*7c478bd9Sstevel@tonic-gate  */
3506*7c478bd9Sstevel@tonic-gate static int
3507*7c478bd9Sstevel@tonic-gate decode(char *name, struct code *codetab)
3508*7c478bd9Sstevel@tonic-gate {
3509*7c478bd9Sstevel@tonic-gate 	struct code *c;
3510*7c478bd9Sstevel@tonic-gate 	char *p;
3511*7c478bd9Sstevel@tonic-gate 	char buf[40];
3512*7c478bd9Sstevel@tonic-gate 
3513*7c478bd9Sstevel@tonic-gate 	if (isdigit(*name))
3514*7c478bd9Sstevel@tonic-gate 		return (atoi(name));
3515*7c478bd9Sstevel@tonic-gate 
3516*7c478bd9Sstevel@tonic-gate 	(void) strncpy(buf, name, sizeof (buf) - 1);
3517*7c478bd9Sstevel@tonic-gate 	for (p = buf; *p; p++)
3518*7c478bd9Sstevel@tonic-gate 		if (isupper(*p))
3519*7c478bd9Sstevel@tonic-gate 			*p = tolower(*p);
3520*7c478bd9Sstevel@tonic-gate 	for (c = codetab; c->c_name; c++)
3521*7c478bd9Sstevel@tonic-gate 		if (!(strcmp(buf, c->c_name)))
3522*7c478bd9Sstevel@tonic-gate 			return (c->c_val);
3523*7c478bd9Sstevel@tonic-gate 
3524*7c478bd9Sstevel@tonic-gate 	return (-1);
3525*7c478bd9Sstevel@tonic-gate }
3526*7c478bd9Sstevel@tonic-gate 
3527*7c478bd9Sstevel@tonic-gate static int
3528*7c478bd9Sstevel@tonic-gate ismyaddr(struct netbuf *nbp)
3529*7c478bd9Sstevel@tonic-gate {
3530*7c478bd9Sstevel@tonic-gate 	int i;
3531*7c478bd9Sstevel@tonic-gate 
3532*7c478bd9Sstevel@tonic-gate 	if (nbp == NULL)
3533*7c478bd9Sstevel@tonic-gate 		return (0);
3534*7c478bd9Sstevel@tonic-gate 
3535*7c478bd9Sstevel@tonic-gate 	for (i = 1; i < Ninputs; i++) {
3536*7c478bd9Sstevel@tonic-gate 		if (same_addr(nbp, Myaddrs[i]))
3537*7c478bd9Sstevel@tonic-gate 			return (1);
3538*7c478bd9Sstevel@tonic-gate 	}
3539*7c478bd9Sstevel@tonic-gate 	return (0);
3540*7c478bd9Sstevel@tonic-gate }
3541*7c478bd9Sstevel@tonic-gate 
3542*7c478bd9Sstevel@tonic-gate static void
3543*7c478bd9Sstevel@tonic-gate getnets(void)
3544*7c478bd9Sstevel@tonic-gate {
3545*7c478bd9Sstevel@tonic-gate 	struct nd_hostserv hs;
3546*7c478bd9Sstevel@tonic-gate 	struct netconfig *ncp;
3547*7c478bd9Sstevel@tonic-gate 	struct nd_addrlist *nap;
3548*7c478bd9Sstevel@tonic-gate 	struct netbuf *nbp;
3549*7c478bd9Sstevel@tonic-gate 	int i, inputs;
3550*7c478bd9Sstevel@tonic-gate 	void *handle;
3551*7c478bd9Sstevel@tonic-gate 	char *uap;
3552*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
3553*7c478bd9Sstevel@tonic-gate 
3554*7c478bd9Sstevel@tonic-gate 	if (Debug) {
3555*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
3556*7c478bd9Sstevel@tonic-gate 	}
3557*7c478bd9Sstevel@tonic-gate 
3558*7c478bd9Sstevel@tonic-gate 	if (turnoff) {
3559*7c478bd9Sstevel@tonic-gate 		DPRINT1(1, "getnets(%u): network is being turned off\n",
3560*7c478bd9Sstevel@tonic-gate 				mythreadno);
3561*7c478bd9Sstevel@tonic-gate 		return;
3562*7c478bd9Sstevel@tonic-gate 	}
3563*7c478bd9Sstevel@tonic-gate 
3564*7c478bd9Sstevel@tonic-gate 	hs.h_host = HOST_SELF;
3565*7c478bd9Sstevel@tonic-gate 	hs.h_serv = "syslog";
3566*7c478bd9Sstevel@tonic-gate 
3567*7c478bd9Sstevel@tonic-gate 	if ((handle = setnetconfig()) == NULL) {
3568*7c478bd9Sstevel@tonic-gate 		return;
3569*7c478bd9Sstevel@tonic-gate 	}
3570*7c478bd9Sstevel@tonic-gate 
3571*7c478bd9Sstevel@tonic-gate 	while ((ncp = getnetconfig(handle)) != NULL) {
3572*7c478bd9Sstevel@tonic-gate 		if (ncp->nc_semantics != NC_TPI_CLTS) {
3573*7c478bd9Sstevel@tonic-gate 			continue;
3574*7c478bd9Sstevel@tonic-gate 		}
3575*7c478bd9Sstevel@tonic-gate 
3576*7c478bd9Sstevel@tonic-gate 		if (netdir_getbyname(ncp, &hs, &nap) != 0) {
3577*7c478bd9Sstevel@tonic-gate 			continue;
3578*7c478bd9Sstevel@tonic-gate 		}
3579*7c478bd9Sstevel@tonic-gate 
3580*7c478bd9Sstevel@tonic-gate 		if (nap == NULL || nap->n_cnt <= 0) {
3581*7c478bd9Sstevel@tonic-gate 			DPRINT1(1, "getnets(%u): found no address\n",
3582*7c478bd9Sstevel@tonic-gate 					mythreadno);
3583*7c478bd9Sstevel@tonic-gate 			netdir_free((void *)nap, ND_ADDRLIST);
3584*7c478bd9Sstevel@tonic-gate 			continue;
3585*7c478bd9Sstevel@tonic-gate 		}
3586*7c478bd9Sstevel@tonic-gate 
3587*7c478bd9Sstevel@tonic-gate 		if (Debug) {
3588*7c478bd9Sstevel@tonic-gate 			DPRINT2(1, "getnets(%u): found %d addresses",
3589*7c478bd9Sstevel@tonic-gate 				mythreadno, nap->n_cnt);
3590*7c478bd9Sstevel@tonic-gate 			DPRINT0(1, ", they are: ");
3591*7c478bd9Sstevel@tonic-gate 			nbp = nap->n_addrs;
3592*7c478bd9Sstevel@tonic-gate 
3593*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < nap->n_cnt; i++) {
3594*7c478bd9Sstevel@tonic-gate 				if ((uap = taddr2uaddr(ncp, nbp)) != NULL) {
3595*7c478bd9Sstevel@tonic-gate 					DPRINT1(1, "%s ", uap);
3596*7c478bd9Sstevel@tonic-gate 					free(uap);
3597*7c478bd9Sstevel@tonic-gate 				}
3598*7c478bd9Sstevel@tonic-gate 				nbp++;
3599*7c478bd9Sstevel@tonic-gate 			}
3600*7c478bd9Sstevel@tonic-gate 
3601*7c478bd9Sstevel@tonic-gate 			DPRINT0(1, "\n");
3602*7c478bd9Sstevel@tonic-gate 		}
3603*7c478bd9Sstevel@tonic-gate 
3604*7c478bd9Sstevel@tonic-gate 		inputs = Ninputs + nap->n_cnt;
3605*7c478bd9Sstevel@tonic-gate 
3606*7c478bd9Sstevel@tonic-gate 		Nfd = realloc(Nfd, inputs * sizeof (struct pollfd));
3607*7c478bd9Sstevel@tonic-gate 		Ncf = realloc(Ncf, inputs * sizeof (struct netconfig));
3608*7c478bd9Sstevel@tonic-gate 		Myaddrs = realloc(Myaddrs, inputs * sizeof (struct netbuf *));
3609*7c478bd9Sstevel@tonic-gate 		Udp = realloc(Udp, inputs * sizeof (struct t_unitdata *));
3610*7c478bd9Sstevel@tonic-gate 		Errp = realloc(Errp, inputs * sizeof (struct t_uderr *));
3611*7c478bd9Sstevel@tonic-gate 
3612*7c478bd9Sstevel@tonic-gate 		/*
3613*7c478bd9Sstevel@tonic-gate 		 * all malloc failures here are fatal
3614*7c478bd9Sstevel@tonic-gate 		 */
3615*7c478bd9Sstevel@tonic-gate 		if (Nfd == NULL || Ncf == NULL || Myaddrs == NULL ||
3616*7c478bd9Sstevel@tonic-gate 			Udp == NULL || Errp == NULL) {
3617*7c478bd9Sstevel@tonic-gate 			MALLOC_FAIL_EXIT;
3618*7c478bd9Sstevel@tonic-gate 		}
3619*7c478bd9Sstevel@tonic-gate 
3620*7c478bd9Sstevel@tonic-gate 		nbp = nap->n_addrs;
3621*7c478bd9Sstevel@tonic-gate 
3622*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < nap->n_cnt; i++, nbp++) {
3623*7c478bd9Sstevel@tonic-gate 			char ebuf[128];
3624*7c478bd9Sstevel@tonic-gate 
3625*7c478bd9Sstevel@tonic-gate 			if (addnet(ncp, nbp) == 0) {
3626*7c478bd9Sstevel@tonic-gate 				/* no error */
3627*7c478bd9Sstevel@tonic-gate 				continue;
3628*7c478bd9Sstevel@tonic-gate 			}
3629*7c478bd9Sstevel@tonic-gate 
3630*7c478bd9Sstevel@tonic-gate 			(void) strcpy(ebuf, "Unable to configure syslog port");
3631*7c478bd9Sstevel@tonic-gate 
3632*7c478bd9Sstevel@tonic-gate 			if ((uap = taddr2uaddr(ncp, nbp)) != NULL) {
3633*7c478bd9Sstevel@tonic-gate 				size_t l = strlen(ebuf);
3634*7c478bd9Sstevel@tonic-gate 				(void) snprintf(ebuf + l, sizeof (ebuf) - l,
3635*7c478bd9Sstevel@tonic-gate 					" for %s", uap);
3636*7c478bd9Sstevel@tonic-gate 			}
3637*7c478bd9Sstevel@tonic-gate 
3638*7c478bd9Sstevel@tonic-gate 			DPRINT2(1, "getnets(%u): %s",
3639*7c478bd9Sstevel@tonic-gate 				mythreadno, ebuf);
3640*7c478bd9Sstevel@tonic-gate 
3641*7c478bd9Sstevel@tonic-gate 			if (uap) {
3642*7c478bd9Sstevel@tonic-gate 				free(uap);
3643*7c478bd9Sstevel@tonic-gate 			}
3644*7c478bd9Sstevel@tonic-gate 
3645*7c478bd9Sstevel@tonic-gate 			logerror(ebuf);
3646*7c478bd9Sstevel@tonic-gate 			/*
3647*7c478bd9Sstevel@tonic-gate 			 * Here maybe syslogd can quit. However, syslogd
3648*7c478bd9Sstevel@tonic-gate 			 * has been ignoring this error and keep running.
3649*7c478bd9Sstevel@tonic-gate 			 * So we won't break it.
3650*7c478bd9Sstevel@tonic-gate 			 */
3651*7c478bd9Sstevel@tonic-gate 		}
3652*7c478bd9Sstevel@tonic-gate 
3653*7c478bd9Sstevel@tonic-gate 		netdir_free((void *)nap, ND_ADDRLIST);
3654*7c478bd9Sstevel@tonic-gate 	}
3655*7c478bd9Sstevel@tonic-gate 
3656*7c478bd9Sstevel@tonic-gate 	(void) endnetconfig(handle);
3657*7c478bd9Sstevel@tonic-gate }
3658*7c478bd9Sstevel@tonic-gate 
3659*7c478bd9Sstevel@tonic-gate /*
3660*7c478bd9Sstevel@tonic-gate  * Open the network device, and allocate necessary resources.
3661*7c478bd9Sstevel@tonic-gate  * Myaddrs will also be filled, so that we can call ismyaddr() before
3662*7c478bd9Sstevel@tonic-gate  * being bound to the network.
3663*7c478bd9Sstevel@tonic-gate  */
3664*7c478bd9Sstevel@tonic-gate static int
3665*7c478bd9Sstevel@tonic-gate addnet(struct netconfig *ncp, struct netbuf *nbp)
3666*7c478bd9Sstevel@tonic-gate {
3667*7c478bd9Sstevel@tonic-gate 	int fd;
3668*7c478bd9Sstevel@tonic-gate 	struct netbuf *bp;
3669*7c478bd9Sstevel@tonic-gate 
3670*7c478bd9Sstevel@tonic-gate 	fd = t_open(ncp->nc_device, O_RDWR, NULL);
3671*7c478bd9Sstevel@tonic-gate 
3672*7c478bd9Sstevel@tonic-gate 	if (fd < 0) {
3673*7c478bd9Sstevel@tonic-gate 		return (1);
3674*7c478bd9Sstevel@tonic-gate 	}
3675*7c478bd9Sstevel@tonic-gate 
3676*7c478bd9Sstevel@tonic-gate 	(void) memcpy(&Ncf[Ninputs], ncp, sizeof (struct netconfig));
3677*7c478bd9Sstevel@tonic-gate 
3678*7c478bd9Sstevel@tonic-gate 	/*LINTED*/
3679*7c478bd9Sstevel@tonic-gate 	Udp[Ninputs] = (struct t_unitdata *)t_alloc(fd, T_UNITDATA, T_ADDR);
3680*7c478bd9Sstevel@tonic-gate 
3681*7c478bd9Sstevel@tonic-gate 	if (Udp[Ninputs] == NULL) {
3682*7c478bd9Sstevel@tonic-gate 		t_close(fd);
3683*7c478bd9Sstevel@tonic-gate 		return (1);
3684*7c478bd9Sstevel@tonic-gate 	}
3685*7c478bd9Sstevel@tonic-gate 
3686*7c478bd9Sstevel@tonic-gate 	/*LINTED*/
3687*7c478bd9Sstevel@tonic-gate 	Errp[Ninputs] = (struct t_uderr *)t_alloc(fd, T_UDERROR, T_ADDR);
3688*7c478bd9Sstevel@tonic-gate 
3689*7c478bd9Sstevel@tonic-gate 	if (Errp[Ninputs] == NULL) {
3690*7c478bd9Sstevel@tonic-gate 		t_close(fd);
3691*7c478bd9Sstevel@tonic-gate 		t_free((char *)Udp[Ninputs], T_UNITDATA);
3692*7c478bd9Sstevel@tonic-gate 		return (1);
3693*7c478bd9Sstevel@tonic-gate 	}
3694*7c478bd9Sstevel@tonic-gate 
3695*7c478bd9Sstevel@tonic-gate 	if ((bp = malloc(sizeof (struct netbuf))) == NULL ||
3696*7c478bd9Sstevel@tonic-gate 		(bp->buf = malloc(nbp->len)) == NULL) {
3697*7c478bd9Sstevel@tonic-gate 		MALLOC_FAIL("allocating address buffer");
3698*7c478bd9Sstevel@tonic-gate 		t_close(fd);
3699*7c478bd9Sstevel@tonic-gate 		t_free((char *)Udp[Ninputs], T_UNITDATA);
3700*7c478bd9Sstevel@tonic-gate 		t_free((char *)Errp[Ninputs], T_UDERROR);
3701*7c478bd9Sstevel@tonic-gate 
3702*7c478bd9Sstevel@tonic-gate 		if (bp) {
3703*7c478bd9Sstevel@tonic-gate 			free(bp);
3704*7c478bd9Sstevel@tonic-gate 		}
3705*7c478bd9Sstevel@tonic-gate 
3706*7c478bd9Sstevel@tonic-gate 		return (1);
3707*7c478bd9Sstevel@tonic-gate 	}
3708*7c478bd9Sstevel@tonic-gate 
3709*7c478bd9Sstevel@tonic-gate 	bp->len = nbp->len;
3710*7c478bd9Sstevel@tonic-gate 	(void) memcpy(bp->buf, nbp->buf, nbp->len);
3711*7c478bd9Sstevel@tonic-gate 	Myaddrs[Ninputs] = bp;
3712*7c478bd9Sstevel@tonic-gate 
3713*7c478bd9Sstevel@tonic-gate 	Nfd[Ninputs].fd = fd;
3714*7c478bd9Sstevel@tonic-gate 	Nfd[Ninputs].events = POLLIN;
3715*7c478bd9Sstevel@tonic-gate 	Ninputs++;
3716*7c478bd9Sstevel@tonic-gate 	return (0);
3717*7c478bd9Sstevel@tonic-gate }
3718*7c478bd9Sstevel@tonic-gate 
3719*7c478bd9Sstevel@tonic-gate /*
3720*7c478bd9Sstevel@tonic-gate  * Allocate UDP buffer to minimize packet loss.
3721*7c478bd9Sstevel@tonic-gate  */
3722*7c478bd9Sstevel@tonic-gate static void
3723*7c478bd9Sstevel@tonic-gate set_udp_buffer(int fd)
3724*7c478bd9Sstevel@tonic-gate {
3725*7c478bd9Sstevel@tonic-gate 	struct t_optmgmt req, resp;
3726*7c478bd9Sstevel@tonic-gate 	struct opthdr *opt;
3727*7c478bd9Sstevel@tonic-gate 	size_t optsize, bsize = 256 * 1024;
3728*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
3729*7c478bd9Sstevel@tonic-gate 
3730*7c478bd9Sstevel@tonic-gate 	if (Debug) {
3731*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
3732*7c478bd9Sstevel@tonic-gate 	}
3733*7c478bd9Sstevel@tonic-gate 
3734*7c478bd9Sstevel@tonic-gate 	optsize = sizeof (struct opthdr) + sizeof (int);
3735*7c478bd9Sstevel@tonic-gate 	if ((opt = malloc(optsize)) == NULL) {
3736*7c478bd9Sstevel@tonic-gate 		MALLOC_FAIL("will have no udp buffer");
3737*7c478bd9Sstevel@tonic-gate 		return;
3738*7c478bd9Sstevel@tonic-gate 	}
3739*7c478bd9Sstevel@tonic-gate 	opt->level = SOL_SOCKET;
3740*7c478bd9Sstevel@tonic-gate 	opt->name = SO_RCVBUF;
3741*7c478bd9Sstevel@tonic-gate 	opt->len = sizeof (int);
3742*7c478bd9Sstevel@tonic-gate 	*(int *)(opt + 1) = bsize;
3743*7c478bd9Sstevel@tonic-gate 
3744*7c478bd9Sstevel@tonic-gate 	req.flags = T_NEGOTIATE;
3745*7c478bd9Sstevel@tonic-gate 	req.opt.len = optsize;
3746*7c478bd9Sstevel@tonic-gate 	req.opt.buf = (char *)opt;
3747*7c478bd9Sstevel@tonic-gate 
3748*7c478bd9Sstevel@tonic-gate 	resp.flags = 0;
3749*7c478bd9Sstevel@tonic-gate 	resp.opt.maxlen = optsize;
3750*7c478bd9Sstevel@tonic-gate 	resp.opt.buf = (char *)opt;
3751*7c478bd9Sstevel@tonic-gate 
3752*7c478bd9Sstevel@tonic-gate 	while (t_optmgmt(fd, &req, &resp) == -1 || resp.flags != T_SUCCESS) {
3753*7c478bd9Sstevel@tonic-gate 		if (t_errno != TSYSERR || errno != ENOBUFS) {
3754*7c478bd9Sstevel@tonic-gate 			bsize = 0;
3755*7c478bd9Sstevel@tonic-gate 			break;
3756*7c478bd9Sstevel@tonic-gate 		}
3757*7c478bd9Sstevel@tonic-gate 		bsize >>= 1;
3758*7c478bd9Sstevel@tonic-gate 		if (bsize < 8192) {
3759*7c478bd9Sstevel@tonic-gate 			break;
3760*7c478bd9Sstevel@tonic-gate 		}
3761*7c478bd9Sstevel@tonic-gate 		*(int *)(opt + 1) = bsize;
3762*7c478bd9Sstevel@tonic-gate 	}
3763*7c478bd9Sstevel@tonic-gate 	if (bsize == 0) {
3764*7c478bd9Sstevel@tonic-gate 		logerror("failed to allocate UDP buffer");
3765*7c478bd9Sstevel@tonic-gate 	}
3766*7c478bd9Sstevel@tonic-gate 	DPRINT3(1, "set_udp_buffer(%u): allocate %d for fd %d\n",
3767*7c478bd9Sstevel@tonic-gate 		mythreadno, bsize, fd);
3768*7c478bd9Sstevel@tonic-gate 	free(opt);
3769*7c478bd9Sstevel@tonic-gate }
3770*7c478bd9Sstevel@tonic-gate 
3771*7c478bd9Sstevel@tonic-gate /*
3772*7c478bd9Sstevel@tonic-gate  * Attach the network, and allocate UDP buffer for the interface.
3773*7c478bd9Sstevel@tonic-gate  */
3774*7c478bd9Sstevel@tonic-gate static void
3775*7c478bd9Sstevel@tonic-gate bindnet(void)
3776*7c478bd9Sstevel@tonic-gate {
3777*7c478bd9Sstevel@tonic-gate 	struct t_bind bind, *bound;
3778*7c478bd9Sstevel@tonic-gate 	int cnt, i;
3779*7c478bd9Sstevel@tonic-gate 	char *uap;
3780*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
3781*7c478bd9Sstevel@tonic-gate 
3782*7c478bd9Sstevel@tonic-gate 	if (Debug) {
3783*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
3784*7c478bd9Sstevel@tonic-gate 	}
3785*7c478bd9Sstevel@tonic-gate 
3786*7c478bd9Sstevel@tonic-gate 	cnt = 0;
3787*7c478bd9Sstevel@tonic-gate 
3788*7c478bd9Sstevel@tonic-gate 	while (cnt < Ninputs) {
3789*7c478bd9Sstevel@tonic-gate 		char ebuf[128];
3790*7c478bd9Sstevel@tonic-gate 
3791*7c478bd9Sstevel@tonic-gate 		/*LINTED*/
3792*7c478bd9Sstevel@tonic-gate 		bound  = (struct t_bind *)t_alloc(Nfd[cnt].fd, T_BIND, T_ADDR);
3793*7c478bd9Sstevel@tonic-gate 		bind.addr = *Myaddrs[cnt];
3794*7c478bd9Sstevel@tonic-gate 		bind.qlen = 0;
3795*7c478bd9Sstevel@tonic-gate 
3796*7c478bd9Sstevel@tonic-gate 		if (t_bind(Nfd[cnt].fd, &bind, bound) == 0) {
3797*7c478bd9Sstevel@tonic-gate 			if (same_addr(&bind.addr, &bound->addr)) {
3798*7c478bd9Sstevel@tonic-gate 				t_free((char *)bound, T_BIND);
3799*7c478bd9Sstevel@tonic-gate 				set_udp_buffer(Nfd[cnt].fd);
3800*7c478bd9Sstevel@tonic-gate 				cnt++;
3801*7c478bd9Sstevel@tonic-gate 				continue;
3802*7c478bd9Sstevel@tonic-gate 			}
3803*7c478bd9Sstevel@tonic-gate 		}
3804*7c478bd9Sstevel@tonic-gate 
3805*7c478bd9Sstevel@tonic-gate 		/* failed to bind port */
3806*7c478bd9Sstevel@tonic-gate 		t_free((char *)bound, T_BIND);
3807*7c478bd9Sstevel@tonic-gate 
3808*7c478bd9Sstevel@tonic-gate 		(void) strcpy(ebuf, "Unable to bind syslog port");
3809*7c478bd9Sstevel@tonic-gate 
3810*7c478bd9Sstevel@tonic-gate 		uap = taddr2uaddr(&Ncf[cnt], Myaddrs[cnt]);
3811*7c478bd9Sstevel@tonic-gate 		if (uap) {
3812*7c478bd9Sstevel@tonic-gate 			i = strlen(ebuf);
3813*7c478bd9Sstevel@tonic-gate 			(void) snprintf(ebuf + i, sizeof (ebuf) - i,
3814*7c478bd9Sstevel@tonic-gate 				" for %s", uap);
3815*7c478bd9Sstevel@tonic-gate 		}
3816*7c478bd9Sstevel@tonic-gate 
3817*7c478bd9Sstevel@tonic-gate 		DPRINT2(1, "bindnet(%u): failed to bind port (%s)\n",
3818*7c478bd9Sstevel@tonic-gate 			mythreadno, uap ? uap : "<unknown>");
3819*7c478bd9Sstevel@tonic-gate 
3820*7c478bd9Sstevel@tonic-gate 		if (uap) {
3821*7c478bd9Sstevel@tonic-gate 			free(uap);
3822*7c478bd9Sstevel@tonic-gate 		}
3823*7c478bd9Sstevel@tonic-gate 
3824*7c478bd9Sstevel@tonic-gate 		errno = 0;
3825*7c478bd9Sstevel@tonic-gate 		logerror(ebuf);
3826*7c478bd9Sstevel@tonic-gate 
3827*7c478bd9Sstevel@tonic-gate 		t_close(Nfd[cnt].fd);
3828*7c478bd9Sstevel@tonic-gate 		free(Myaddrs[cnt]->buf);
3829*7c478bd9Sstevel@tonic-gate 		free(Myaddrs[cnt]);
3830*7c478bd9Sstevel@tonic-gate 		t_free((char *)Udp[cnt], T_UNITDATA);
3831*7c478bd9Sstevel@tonic-gate 		t_free((char *)Errp[cnt], T_UDERROR);
3832*7c478bd9Sstevel@tonic-gate 
3833*7c478bd9Sstevel@tonic-gate 		for (i = cnt; i < (Ninputs-1); i++) {
3834*7c478bd9Sstevel@tonic-gate 			Nfd[i] = Nfd[i + 1];
3835*7c478bd9Sstevel@tonic-gate 			Ncf[i] = Ncf[i + 1];
3836*7c478bd9Sstevel@tonic-gate 			Myaddrs[i] = Myaddrs[i + 1];
3837*7c478bd9Sstevel@tonic-gate 			Udp[i] = Udp[i + 1];
3838*7c478bd9Sstevel@tonic-gate 			Errp[i] = Errp[i + 1];
3839*7c478bd9Sstevel@tonic-gate 		}
3840*7c478bd9Sstevel@tonic-gate 
3841*7c478bd9Sstevel@tonic-gate 		Ninputs--;
3842*7c478bd9Sstevel@tonic-gate 	}
3843*7c478bd9Sstevel@tonic-gate }
3844*7c478bd9Sstevel@tonic-gate 
3845*7c478bd9Sstevel@tonic-gate static int
3846*7c478bd9Sstevel@tonic-gate logforward(struct filed *f, char *ebuf)
3847*7c478bd9Sstevel@tonic-gate {
3848*7c478bd9Sstevel@tonic-gate 	struct nd_hostserv hs;
3849*7c478bd9Sstevel@tonic-gate 	struct netbuf *nbp;
3850*7c478bd9Sstevel@tonic-gate 	struct netconfig *ncp;
3851*7c478bd9Sstevel@tonic-gate 	struct nd_addrlist *nap;
3852*7c478bd9Sstevel@tonic-gate 	void *handle;
3853*7c478bd9Sstevel@tonic-gate 	char *hp;
3854*7c478bd9Sstevel@tonic-gate 
3855*7c478bd9Sstevel@tonic-gate 	hp = f->f_un.f_forw.f_hname;
3856*7c478bd9Sstevel@tonic-gate 	hs.h_host = hp;
3857*7c478bd9Sstevel@tonic-gate 	hs.h_serv = "syslog";
3858*7c478bd9Sstevel@tonic-gate 
3859*7c478bd9Sstevel@tonic-gate 	if ((handle = setnetconfig()) == NULL) {
3860*7c478bd9Sstevel@tonic-gate 		(void) strcpy(ebuf,
3861*7c478bd9Sstevel@tonic-gate 			"unable to rewind the netconfig database");
3862*7c478bd9Sstevel@tonic-gate 		errno = 0;
3863*7c478bd9Sstevel@tonic-gate 		return (-1);
3864*7c478bd9Sstevel@tonic-gate 	}
3865*7c478bd9Sstevel@tonic-gate 	nap = (struct nd_addrlist *)NULL;
3866*7c478bd9Sstevel@tonic-gate 	while ((ncp = getnetconfig(handle)) != NULL) {
3867*7c478bd9Sstevel@tonic-gate 		if (ncp->nc_semantics == NC_TPI_CLTS) {
3868*7c478bd9Sstevel@tonic-gate 			if (netdir_getbyname(ncp, &hs, &nap) == 0) {
3869*7c478bd9Sstevel@tonic-gate 				if (!nap)
3870*7c478bd9Sstevel@tonic-gate 					continue;
3871*7c478bd9Sstevel@tonic-gate 				nbp = nap->n_addrs;
3872*7c478bd9Sstevel@tonic-gate 				break;
3873*7c478bd9Sstevel@tonic-gate 			}
3874*7c478bd9Sstevel@tonic-gate 		}
3875*7c478bd9Sstevel@tonic-gate 	}
3876*7c478bd9Sstevel@tonic-gate 	if (ncp == NULL) {
3877*7c478bd9Sstevel@tonic-gate 		endnetconfig(handle);
3878*7c478bd9Sstevel@tonic-gate 		(void) sprintf(ebuf, "WARNING: %s could not be resolved", hp);
3879*7c478bd9Sstevel@tonic-gate 		errno = 0;
3880*7c478bd9Sstevel@tonic-gate 		return (-1);
3881*7c478bd9Sstevel@tonic-gate 	}
3882*7c478bd9Sstevel@tonic-gate 	if (nap == (struct nd_addrlist *)NULL) {
3883*7c478bd9Sstevel@tonic-gate 		endnetconfig(handle);
3884*7c478bd9Sstevel@tonic-gate 		(void) sprintf(ebuf, "unknown host %s", hp);
3885*7c478bd9Sstevel@tonic-gate 		errno = 0;
3886*7c478bd9Sstevel@tonic-gate 		return (-1);
3887*7c478bd9Sstevel@tonic-gate 	}
3888*7c478bd9Sstevel@tonic-gate 	/* CSTYLED */
3889*7c478bd9Sstevel@tonic-gate 	if (ismyaddr(nbp)) { /*lint !e644 */
3890*7c478bd9Sstevel@tonic-gate 		netdir_free((void *)nap, ND_ADDRLIST);
3891*7c478bd9Sstevel@tonic-gate 		endnetconfig(handle);
3892*7c478bd9Sstevel@tonic-gate 		(void) sprintf(ebuf, "host %s is this host - logging loop",
3893*7c478bd9Sstevel@tonic-gate 			hp);
3894*7c478bd9Sstevel@tonic-gate 		errno = 0;
3895*7c478bd9Sstevel@tonic-gate 		return (-1);
3896*7c478bd9Sstevel@tonic-gate 	}
3897*7c478bd9Sstevel@tonic-gate 	f->f_un.f_forw.f_addr.buf = malloc(nbp->len);
3898*7c478bd9Sstevel@tonic-gate 	if (f->f_un.f_forw.f_addr.buf == NULL) {
3899*7c478bd9Sstevel@tonic-gate 		netdir_free((void *)nap, ND_ADDRLIST);
3900*7c478bd9Sstevel@tonic-gate 		endnetconfig(handle);
3901*7c478bd9Sstevel@tonic-gate 		(void) strcpy(ebuf, "malloc failed");
3902*7c478bd9Sstevel@tonic-gate 		return (-1);
3903*7c478bd9Sstevel@tonic-gate 	}
3904*7c478bd9Sstevel@tonic-gate 	bcopy(nbp->buf, f->f_un.f_forw.f_addr.buf, nbp->len);
3905*7c478bd9Sstevel@tonic-gate 	f->f_un.f_forw.f_addr.len = nbp->len;
3906*7c478bd9Sstevel@tonic-gate 	f->f_file = t_open(ncp->nc_device, O_RDWR, NULL);
3907*7c478bd9Sstevel@tonic-gate 	if (f->f_file < 0) {
3908*7c478bd9Sstevel@tonic-gate 		netdir_free((void *)nap, ND_ADDRLIST);
3909*7c478bd9Sstevel@tonic-gate 		endnetconfig(handle);
3910*7c478bd9Sstevel@tonic-gate 		free(f->f_un.f_forw.f_addr.buf);
3911*7c478bd9Sstevel@tonic-gate 		(void) strcpy(ebuf, "t_open");
3912*7c478bd9Sstevel@tonic-gate 		return (-1);
3913*7c478bd9Sstevel@tonic-gate 	}
3914*7c478bd9Sstevel@tonic-gate 	netdir_free((void *)nap, ND_ADDRLIST);
3915*7c478bd9Sstevel@tonic-gate 	endnetconfig(handle);
3916*7c478bd9Sstevel@tonic-gate 	if (t_bind(f->f_file, NULL, NULL) < 0) {
3917*7c478bd9Sstevel@tonic-gate 		(void) strcpy(ebuf, "t_bind");
3918*7c478bd9Sstevel@tonic-gate 		free(f->f_un.f_forw.f_addr.buf);
3919*7c478bd9Sstevel@tonic-gate 		t_close(f->f_file);
3920*7c478bd9Sstevel@tonic-gate 		return (-1);
3921*7c478bd9Sstevel@tonic-gate 	}
3922*7c478bd9Sstevel@tonic-gate 	return (0);
3923*7c478bd9Sstevel@tonic-gate }
3924*7c478bd9Sstevel@tonic-gate 
3925*7c478bd9Sstevel@tonic-gate static int
3926*7c478bd9Sstevel@tonic-gate amiloghost(void)
3927*7c478bd9Sstevel@tonic-gate {
3928*7c478bd9Sstevel@tonic-gate 	struct nd_hostserv hs;
3929*7c478bd9Sstevel@tonic-gate 	struct netconfig *ncp;
3930*7c478bd9Sstevel@tonic-gate 	struct nd_addrlist *nap;
3931*7c478bd9Sstevel@tonic-gate 	struct netbuf *nbp;
3932*7c478bd9Sstevel@tonic-gate 	int i, fd;
3933*7c478bd9Sstevel@tonic-gate 	void *handle;
3934*7c478bd9Sstevel@tonic-gate 	char *uap;
3935*7c478bd9Sstevel@tonic-gate 	struct t_bind bind, *bound;
3936*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
3937*7c478bd9Sstevel@tonic-gate 
3938*7c478bd9Sstevel@tonic-gate 	if (Debug) {
3939*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
3940*7c478bd9Sstevel@tonic-gate 	}
3941*7c478bd9Sstevel@tonic-gate 
3942*7c478bd9Sstevel@tonic-gate 	/*
3943*7c478bd9Sstevel@tonic-gate 	 * we need to know if we are running on the loghost. This is
3944*7c478bd9Sstevel@tonic-gate 	 * checked by binding to the address associated with "loghost"
3945*7c478bd9Sstevel@tonic-gate 	 * and "syslogd" service over the connectionless transport
3946*7c478bd9Sstevel@tonic-gate 	 */
3947*7c478bd9Sstevel@tonic-gate 	hs.h_host = "loghost";
3948*7c478bd9Sstevel@tonic-gate 	hs.h_serv = "syslog";
3949*7c478bd9Sstevel@tonic-gate 
3950*7c478bd9Sstevel@tonic-gate 	if ((handle = setnetconfig()) == NULL) {
3951*7c478bd9Sstevel@tonic-gate 		return (0);
3952*7c478bd9Sstevel@tonic-gate 	}
3953*7c478bd9Sstevel@tonic-gate 
3954*7c478bd9Sstevel@tonic-gate 	while ((ncp = getnetconfig(handle)) != NULL) {
3955*7c478bd9Sstevel@tonic-gate 		if (ncp->nc_semantics != NC_TPI_CLTS) {
3956*7c478bd9Sstevel@tonic-gate 			continue;
3957*7c478bd9Sstevel@tonic-gate 		}
3958*7c478bd9Sstevel@tonic-gate 
3959*7c478bd9Sstevel@tonic-gate 		if (netdir_getbyname(ncp, &hs, &nap) != 0) {
3960*7c478bd9Sstevel@tonic-gate 			continue;
3961*7c478bd9Sstevel@tonic-gate 		}
3962*7c478bd9Sstevel@tonic-gate 
3963*7c478bd9Sstevel@tonic-gate 		if (nap == NULL) {
3964*7c478bd9Sstevel@tonic-gate 			continue;
3965*7c478bd9Sstevel@tonic-gate 		}
3966*7c478bd9Sstevel@tonic-gate 
3967*7c478bd9Sstevel@tonic-gate 		nbp = nap->n_addrs;
3968*7c478bd9Sstevel@tonic-gate 
3969*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < nap->n_cnt; i++) {
3970*7c478bd9Sstevel@tonic-gate 			if ((uap = taddr2uaddr(ncp, nbp)) != (char *)NULL) {
3971*7c478bd9Sstevel@tonic-gate 				DPRINT2(1, "amiloghost(%u): testing %s\n",
3972*7c478bd9Sstevel@tonic-gate 					mythreadno, uap);
3973*7c478bd9Sstevel@tonic-gate 			}
3974*7c478bd9Sstevel@tonic-gate 
3975*7c478bd9Sstevel@tonic-gate 			free(uap);
3976*7c478bd9Sstevel@tonic-gate 
3977*7c478bd9Sstevel@tonic-gate 			fd = t_open(ncp->nc_device, O_RDWR, NULL);
3978*7c478bd9Sstevel@tonic-gate 
3979*7c478bd9Sstevel@tonic-gate 			if (fd < 0) {
3980*7c478bd9Sstevel@tonic-gate 				netdir_free((void *)nap, ND_ADDRLIST);
3981*7c478bd9Sstevel@tonic-gate 				endnetconfig(handle);
3982*7c478bd9Sstevel@tonic-gate 				return (0);
3983*7c478bd9Sstevel@tonic-gate 			}
3984*7c478bd9Sstevel@tonic-gate 
3985*7c478bd9Sstevel@tonic-gate 			/*LINTED*/
3986*7c478bd9Sstevel@tonic-gate 			bound = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR);
3987*7c478bd9Sstevel@tonic-gate 			bind.addr = *nbp;
3988*7c478bd9Sstevel@tonic-gate 			bind.qlen = 0;
3989*7c478bd9Sstevel@tonic-gate 
3990*7c478bd9Sstevel@tonic-gate 			if (t_bind(fd, &bind, bound) == 0) {
3991*7c478bd9Sstevel@tonic-gate 				t_close(fd);
3992*7c478bd9Sstevel@tonic-gate 				t_free((char *)bound, T_BIND);
3993*7c478bd9Sstevel@tonic-gate 				netdir_free((void *)nap, ND_ADDRLIST);
3994*7c478bd9Sstevel@tonic-gate 				endnetconfig(handle);
3995*7c478bd9Sstevel@tonic-gate 				return (1);
3996*7c478bd9Sstevel@tonic-gate 			} else {
3997*7c478bd9Sstevel@tonic-gate 				t_close(fd);
3998*7c478bd9Sstevel@tonic-gate 				t_free((char *)bound, T_BIND);
3999*7c478bd9Sstevel@tonic-gate 			}
4000*7c478bd9Sstevel@tonic-gate 
4001*7c478bd9Sstevel@tonic-gate 			nbp++;
4002*7c478bd9Sstevel@tonic-gate 		}
4003*7c478bd9Sstevel@tonic-gate 
4004*7c478bd9Sstevel@tonic-gate 		netdir_free((void *)nap, ND_ADDRLIST);
4005*7c478bd9Sstevel@tonic-gate 	}
4006*7c478bd9Sstevel@tonic-gate 
4007*7c478bd9Sstevel@tonic-gate 	endnetconfig(handle);
4008*7c478bd9Sstevel@tonic-gate 	return (0);
4009*7c478bd9Sstevel@tonic-gate }
4010*7c478bd9Sstevel@tonic-gate 
4011*7c478bd9Sstevel@tonic-gate int
4012*7c478bd9Sstevel@tonic-gate same_addr(struct netbuf *na, struct netbuf *nb)
4013*7c478bd9Sstevel@tonic-gate {
4014*7c478bd9Sstevel@tonic-gate 	char *a, *b;
4015*7c478bd9Sstevel@tonic-gate 	size_t n;
4016*7c478bd9Sstevel@tonic-gate 
4017*7c478bd9Sstevel@tonic-gate 	assert(a != NULL && b != NULL);
4018*7c478bd9Sstevel@tonic-gate 
4019*7c478bd9Sstevel@tonic-gate 	if (na->len != nb->len) {
4020*7c478bd9Sstevel@tonic-gate 		return (0);
4021*7c478bd9Sstevel@tonic-gate 	}
4022*7c478bd9Sstevel@tonic-gate 
4023*7c478bd9Sstevel@tonic-gate 	a = na->buf;
4024*7c478bd9Sstevel@tonic-gate 	b = nb->buf;
4025*7c478bd9Sstevel@tonic-gate 	n = nb->len;
4026*7c478bd9Sstevel@tonic-gate 
4027*7c478bd9Sstevel@tonic-gate 	while (n-- > 0) {
4028*7c478bd9Sstevel@tonic-gate 		if (*a++ != *b++) {
4029*7c478bd9Sstevel@tonic-gate 			return (0);
4030*7c478bd9Sstevel@tonic-gate 		}
4031*7c478bd9Sstevel@tonic-gate 	}
4032*7c478bd9Sstevel@tonic-gate 
4033*7c478bd9Sstevel@tonic-gate 	return (1);
4034*7c478bd9Sstevel@tonic-gate }
4035*7c478bd9Sstevel@tonic-gate 
4036*7c478bd9Sstevel@tonic-gate /*
4037*7c478bd9Sstevel@tonic-gate  * allocates a new message structure, initializes it
4038*7c478bd9Sstevel@tonic-gate  * and returns a pointer to it
4039*7c478bd9Sstevel@tonic-gate  */
4040*7c478bd9Sstevel@tonic-gate static log_message_t *
4041*7c478bd9Sstevel@tonic-gate new_msg(void)
4042*7c478bd9Sstevel@tonic-gate {
4043*7c478bd9Sstevel@tonic-gate 	log_message_t *lm;
4044*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
4045*7c478bd9Sstevel@tonic-gate 
4046*7c478bd9Sstevel@tonic-gate 	if (Debug) {
4047*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
4048*7c478bd9Sstevel@tonic-gate 	}
4049*7c478bd9Sstevel@tonic-gate 
4050*7c478bd9Sstevel@tonic-gate 	if ((lm = malloc(sizeof (log_message_t))) == NULL)
4051*7c478bd9Sstevel@tonic-gate 		return ((log_message_t *)NULL);
4052*7c478bd9Sstevel@tonic-gate 
4053*7c478bd9Sstevel@tonic-gate 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lm))
4054*7c478bd9Sstevel@tonic-gate 
4055*7c478bd9Sstevel@tonic-gate 	if (pthread_mutex_init(&lm->msg_mutex, NULL) != 0)
4056*7c478bd9Sstevel@tonic-gate 		return ((log_message_t *)NULL);
4057*7c478bd9Sstevel@tonic-gate 	lm->refcnt = 0;
4058*7c478bd9Sstevel@tonic-gate 	lm->pri = 0;
4059*7c478bd9Sstevel@tonic-gate 	lm->flags = 0;
4060*7c478bd9Sstevel@tonic-gate 	lm->hlp = NULL;
4061*7c478bd9Sstevel@tonic-gate 	lm->msg[0] = '\0';
4062*7c478bd9Sstevel@tonic-gate 	lm->ptr = NULL;
4063*7c478bd9Sstevel@tonic-gate 
4064*7c478bd9Sstevel@tonic-gate 	DPRINT2(3, "new_msg(%u): creating msg %p\n", mythreadno, lm);
4065*7c478bd9Sstevel@tonic-gate 	return (lm);
4066*7c478bd9Sstevel@tonic-gate }
4067*7c478bd9Sstevel@tonic-gate 
4068*7c478bd9Sstevel@tonic-gate /*
4069*7c478bd9Sstevel@tonic-gate  * frees a message structure - should only be called if
4070*7c478bd9Sstevel@tonic-gate  * the refcount is 0
4071*7c478bd9Sstevel@tonic-gate  */
4072*7c478bd9Sstevel@tonic-gate static void
4073*7c478bd9Sstevel@tonic-gate free_msg(log_message_t *lm)
4074*7c478bd9Sstevel@tonic-gate {
4075*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
4076*7c478bd9Sstevel@tonic-gate 
4077*7c478bd9Sstevel@tonic-gate 	if (Debug) {
4078*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
4079*7c478bd9Sstevel@tonic-gate 	}
4080*7c478bd9Sstevel@tonic-gate 
4081*7c478bd9Sstevel@tonic-gate 	assert(lm != NULL && lm->refcnt == 0);
4082*7c478bd9Sstevel@tonic-gate 	if (lm->hlp != NULL)
4083*7c478bd9Sstevel@tonic-gate 		freehl(lm->hlp);
4084*7c478bd9Sstevel@tonic-gate 	DPRINT2(3, "free_msg(%u): freeing msg %p\n", mythreadno, lm);
4085*7c478bd9Sstevel@tonic-gate 	free(lm);
4086*7c478bd9Sstevel@tonic-gate }
4087*7c478bd9Sstevel@tonic-gate 
4088*7c478bd9Sstevel@tonic-gate /*
4089*7c478bd9Sstevel@tonic-gate  *  Make sure that the message makes sense in the current locale, and
4090*7c478bd9Sstevel@tonic-gate  *  does not contain stray control characters.
4091*7c478bd9Sstevel@tonic-gate  */
4092*7c478bd9Sstevel@tonic-gate static void
4093*7c478bd9Sstevel@tonic-gate filter_string(char *mbstr, char *filtered, size_t max)
4094*7c478bd9Sstevel@tonic-gate {
4095*7c478bd9Sstevel@tonic-gate 	size_t	cs = 0;
4096*7c478bd9Sstevel@tonic-gate 	size_t	mb_cur_max;
4097*7c478bd9Sstevel@tonic-gate 	unsigned char	*p = (unsigned char *)mbstr;
4098*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno = 0;
4099*7c478bd9Sstevel@tonic-gate 
4100*7c478bd9Sstevel@tonic-gate 	if (Debug) {
4101*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
4102*7c478bd9Sstevel@tonic-gate 	}
4103*7c478bd9Sstevel@tonic-gate 
4104*7c478bd9Sstevel@tonic-gate 	assert(mbstr != NULL && filtered != NULL);
4105*7c478bd9Sstevel@tonic-gate 
4106*7c478bd9Sstevel@tonic-gate 	/*
4107*7c478bd9Sstevel@tonic-gate 	 * Since the access to MB_CUR_MAX is expensive (because
4108*7c478bd9Sstevel@tonic-gate 	 * MB_CUR_MAX lives in a global area), it should be
4109*7c478bd9Sstevel@tonic-gate 	 * restrained for the better performance.
4110*7c478bd9Sstevel@tonic-gate 	 */
4111*7c478bd9Sstevel@tonic-gate 	mb_cur_max = (size_t)MB_CUR_MAX;
4112*7c478bd9Sstevel@tonic-gate 	if (mb_cur_max > 1) {
4113*7c478bd9Sstevel@tonic-gate 		/* multibyte locale */
4114*7c478bd9Sstevel@tonic-gate 		int	mlen;
4115*7c478bd9Sstevel@tonic-gate 		wchar_t	wc;
4116*7c478bd9Sstevel@tonic-gate 
4117*7c478bd9Sstevel@tonic-gate 		while (*p != '\0') {
4118*7c478bd9Sstevel@tonic-gate 			if ((mlen = mbtowc(&wc, (char *)p,
4119*7c478bd9Sstevel@tonic-gate 				mb_cur_max)) == -1) {
4120*7c478bd9Sstevel@tonic-gate 				/*
4121*7c478bd9Sstevel@tonic-gate 				 * Invalid byte sequence found.
4122*7c478bd9Sstevel@tonic-gate 				 *
4123*7c478bd9Sstevel@tonic-gate 				 * try to print one byte
4124*7c478bd9Sstevel@tonic-gate 				 * in ASCII format.
4125*7c478bd9Sstevel@tonic-gate 				 */
4126*7c478bd9Sstevel@tonic-gate 				DPRINT2(9, "filter_string(%u): Invalid "
4127*7c478bd9Sstevel@tonic-gate 					"MB sequence: %d\n", mythreadno,
4128*7c478bd9Sstevel@tonic-gate 					wc);
4129*7c478bd9Sstevel@tonic-gate 
4130*7c478bd9Sstevel@tonic-gate 				if (!putctrlc(*p++, &filtered, &cs, max)) {
4131*7c478bd9Sstevel@tonic-gate 					/* not enough buffer */
4132*7c478bd9Sstevel@tonic-gate 					goto end;
4133*7c478bd9Sstevel@tonic-gate 				} else {
4134*7c478bd9Sstevel@tonic-gate 					continue;
4135*7c478bd9Sstevel@tonic-gate 				}
4136*7c478bd9Sstevel@tonic-gate 			} else {
4137*7c478bd9Sstevel@tonic-gate 				/*
4138*7c478bd9Sstevel@tonic-gate 				 * Since *p is not a null byte here,
4139*7c478bd9Sstevel@tonic-gate 				 * mbtowc should have never returned 0.
4140*7c478bd9Sstevel@tonic-gate 				 *
4141*7c478bd9Sstevel@tonic-gate 				 * A valid wide character found.
4142*7c478bd9Sstevel@tonic-gate 				 */
4143*7c478bd9Sstevel@tonic-gate 
4144*7c478bd9Sstevel@tonic-gate 				if (wc != L'\t' && iswcntrl(wc)) {
4145*7c478bd9Sstevel@tonic-gate 					/*
4146*7c478bd9Sstevel@tonic-gate 					 * non-tab, non-newline, and
4147*7c478bd9Sstevel@tonic-gate 					 * control character found.
4148*7c478bd9Sstevel@tonic-gate 					 *
4149*7c478bd9Sstevel@tonic-gate 					 * try to print this wide character
4150*7c478bd9Sstevel@tonic-gate 					 * in ASCII-format.
4151*7c478bd9Sstevel@tonic-gate 					 */
4152*7c478bd9Sstevel@tonic-gate 					char	*q = filtered;
4153*7c478bd9Sstevel@tonic-gate 
4154*7c478bd9Sstevel@tonic-gate 					DPRINT2(9, "filter_string(%u): MB"
4155*7c478bd9Sstevel@tonic-gate 						" control character: %d\n",
4156*7c478bd9Sstevel@tonic-gate 						mythreadno, wc);
4157*7c478bd9Sstevel@tonic-gate 
4158*7c478bd9Sstevel@tonic-gate 					while (mlen--) {
4159*7c478bd9Sstevel@tonic-gate 						if (!putctrlc(*p++, &filtered,
4160*7c478bd9Sstevel@tonic-gate 							&cs, max)) {
4161*7c478bd9Sstevel@tonic-gate 							/*
4162*7c478bd9Sstevel@tonic-gate 							 * not enough buffer in
4163*7c478bd9Sstevel@tonic-gate 							 * filtered
4164*7c478bd9Sstevel@tonic-gate 							 *
4165*7c478bd9Sstevel@tonic-gate 							 * cancel already
4166*7c478bd9Sstevel@tonic-gate 							 * stored bytes in
4167*7c478bd9Sstevel@tonic-gate 							 * filtered for this
4168*7c478bd9Sstevel@tonic-gate 							 * wide character.
4169*7c478bd9Sstevel@tonic-gate 							 */
4170*7c478bd9Sstevel@tonic-gate 							filtered = q;
4171*7c478bd9Sstevel@tonic-gate 							goto end;
4172*7c478bd9Sstevel@tonic-gate 						}
4173*7c478bd9Sstevel@tonic-gate 					}
4174*7c478bd9Sstevel@tonic-gate 					continue;
4175*7c478bd9Sstevel@tonic-gate 				} else {
4176*7c478bd9Sstevel@tonic-gate 					/*
4177*7c478bd9Sstevel@tonic-gate 					 * tab, newline, or non-control
4178*7c478bd9Sstevel@tonic-gate 					 * character found.
4179*7c478bd9Sstevel@tonic-gate 					 */
4180*7c478bd9Sstevel@tonic-gate 					if (cs + mlen < max) {
4181*7c478bd9Sstevel@tonic-gate 						/* enough buffer */
4182*7c478bd9Sstevel@tonic-gate 						cs += mlen;
4183*7c478bd9Sstevel@tonic-gate 						while (mlen--) {
4184*7c478bd9Sstevel@tonic-gate 							*filtered++ = *p++;
4185*7c478bd9Sstevel@tonic-gate 						}
4186*7c478bd9Sstevel@tonic-gate 						continue;
4187*7c478bd9Sstevel@tonic-gate 					} else {
4188*7c478bd9Sstevel@tonic-gate 						/* not enough buffer */
4189*7c478bd9Sstevel@tonic-gate 						goto end;
4190*7c478bd9Sstevel@tonic-gate 					}
4191*7c478bd9Sstevel@tonic-gate 				}
4192*7c478bd9Sstevel@tonic-gate 			}
4193*7c478bd9Sstevel@tonic-gate 		}
4194*7c478bd9Sstevel@tonic-gate 	} else {
4195*7c478bd9Sstevel@tonic-gate 		/* singlebyte locale */
4196*7c478bd9Sstevel@tonic-gate 
4197*7c478bd9Sstevel@tonic-gate 		while (*p != '\0') {
4198*7c478bd9Sstevel@tonic-gate 			if (*p != '\t' && iscntrl(*p)) {
4199*7c478bd9Sstevel@tonic-gate 				/*
4200*7c478bd9Sstevel@tonic-gate 				 * non-tab, non-newline,
4201*7c478bd9Sstevel@tonic-gate 				 * and control character found.
4202*7c478bd9Sstevel@tonic-gate 				 *
4203*7c478bd9Sstevel@tonic-gate 				 * try to print this singlebyte character
4204*7c478bd9Sstevel@tonic-gate 				 * in ASCII format.
4205*7c478bd9Sstevel@tonic-gate 				 */
4206*7c478bd9Sstevel@tonic-gate 				DPRINT2(9, "filter_string(%u): control "
4207*7c478bd9Sstevel@tonic-gate 					"character: %d\n", mythreadno, *p);
4208*7c478bd9Sstevel@tonic-gate 
4209*7c478bd9Sstevel@tonic-gate 				if (!putctrlc(*p++, &filtered, &cs, max)) {
4210*7c478bd9Sstevel@tonic-gate 					/* not enough buffer */
4211*7c478bd9Sstevel@tonic-gate 					goto end;
4212*7c478bd9Sstevel@tonic-gate 				} else {
4213*7c478bd9Sstevel@tonic-gate 					continue;
4214*7c478bd9Sstevel@tonic-gate 				}
4215*7c478bd9Sstevel@tonic-gate 			} else if (*p != '\t' && !isprint(*p)) {
4216*7c478bd9Sstevel@tonic-gate 				/*
4217*7c478bd9Sstevel@tonic-gate 				 * non-tab and non printable character found
4218*7c478bd9Sstevel@tonic-gate 				 * this check is required for the C locale
4219*7c478bd9Sstevel@tonic-gate 				 */
4220*7c478bd9Sstevel@tonic-gate 				DPRINT2(9, "filter_string(%u): non-printable "
4221*7c478bd9Sstevel@tonic-gate 					"character: %d\n", mythreadno, *p);
4222*7c478bd9Sstevel@tonic-gate 				if (!putctrlc(*p++, &filtered, &cs, max)) {
4223*7c478bd9Sstevel@tonic-gate 					/* not enough buffer */
4224*7c478bd9Sstevel@tonic-gate 					goto end;
4225*7c478bd9Sstevel@tonic-gate 				} else {
4226*7c478bd9Sstevel@tonic-gate 					continue;
4227*7c478bd9Sstevel@tonic-gate 				}
4228*7c478bd9Sstevel@tonic-gate 			} else {
4229*7c478bd9Sstevel@tonic-gate 				/*
4230*7c478bd9Sstevel@tonic-gate 				 * tab, newline, non-control character, or
4231*7c478bd9Sstevel@tonic-gate 				 * printable found.
4232*7c478bd9Sstevel@tonic-gate 				 */
4233*7c478bd9Sstevel@tonic-gate 				if (cs + 1 < max) {
4234*7c478bd9Sstevel@tonic-gate 					*filtered++ = *p++;
4235*7c478bd9Sstevel@tonic-gate 					cs++;
4236*7c478bd9Sstevel@tonic-gate 					continue;
4237*7c478bd9Sstevel@tonic-gate 				} else {
4238*7c478bd9Sstevel@tonic-gate 					/* not enough buffer */
4239*7c478bd9Sstevel@tonic-gate 					goto end;
4240*7c478bd9Sstevel@tonic-gate 				}
4241*7c478bd9Sstevel@tonic-gate 			}
4242*7c478bd9Sstevel@tonic-gate 		}
4243*7c478bd9Sstevel@tonic-gate 	}
4244*7c478bd9Sstevel@tonic-gate 
4245*7c478bd9Sstevel@tonic-gate end:
4246*7c478bd9Sstevel@tonic-gate 	*filtered = '\0';
4247*7c478bd9Sstevel@tonic-gate 
4248*7c478bd9Sstevel@tonic-gate 	if (cs >= 2 &&
4249*7c478bd9Sstevel@tonic-gate 		filtered[-2] == '\\' && filtered[-1] == 'n') {
4250*7c478bd9Sstevel@tonic-gate 		filtered[-2] = '\0';
4251*7c478bd9Sstevel@tonic-gate 	}
4252*7c478bd9Sstevel@tonic-gate }
4253*7c478bd9Sstevel@tonic-gate 
4254*7c478bd9Sstevel@tonic-gate static char *
4255*7c478bd9Sstevel@tonic-gate alloc_stacks(int numstacks)
4256*7c478bd9Sstevel@tonic-gate {
4257*7c478bd9Sstevel@tonic-gate 	size_t pagesize, mapsize;
4258*7c478bd9Sstevel@tonic-gate 	char *stack_top;
4259*7c478bd9Sstevel@tonic-gate 	char *addr;
4260*7c478bd9Sstevel@tonic-gate 	int i;
4261*7c478bd9Sstevel@tonic-gate 
4262*7c478bd9Sstevel@tonic-gate 	pagesize = (size_t)sysconf(_SC_PAGESIZE);
4263*7c478bd9Sstevel@tonic-gate 	/*
4264*7c478bd9Sstevel@tonic-gate 	 * stacksize and redzonesize are global so threads
4265*7c478bd9Sstevel@tonic-gate 	 * can be created elsewhere and refer to the sizes
4266*7c478bd9Sstevel@tonic-gate 	 */
4267*7c478bd9Sstevel@tonic-gate 	stacksize = (size_t)roundup(sysconf(_SC_THREAD_STACK_MIN) +
4268*7c478bd9Sstevel@tonic-gate 		DEFAULT_STACKSIZE, pagesize);
4269*7c478bd9Sstevel@tonic-gate 	redzonesize = (size_t)roundup(DEFAULT_REDZONESIZE, pagesize);
4270*7c478bd9Sstevel@tonic-gate 
4271*7c478bd9Sstevel@tonic-gate 	/*
4272*7c478bd9Sstevel@tonic-gate 	 * allocate an additional "redzonesize" chunk in addition
4273*7c478bd9Sstevel@tonic-gate 	 * to what we require, so we can create a redzone at the
4274*7c478bd9Sstevel@tonic-gate 	 * bottom of the last stack as well.
4275*7c478bd9Sstevel@tonic-gate 	 */
4276*7c478bd9Sstevel@tonic-gate 	mapsize = redzonesize + numstacks * (stacksize + redzonesize);
4277*7c478bd9Sstevel@tonic-gate 	stack_top = mmap(NULL, mapsize, PROT_READ|PROT_WRITE,
4278*7c478bd9Sstevel@tonic-gate 		MAP_PRIVATE|MAP_ANON, -1, 0);
4279*7c478bd9Sstevel@tonic-gate 	if (stack_top == MAP_FAILED)
4280*7c478bd9Sstevel@tonic-gate 		return (NULL);
4281*7c478bd9Sstevel@tonic-gate 
4282*7c478bd9Sstevel@tonic-gate 	addr = stack_top;
4283*7c478bd9Sstevel@tonic-gate 	/*
4284*7c478bd9Sstevel@tonic-gate 	 * this loop is intentionally <= instead of <, so we can
4285*7c478bd9Sstevel@tonic-gate 	 * protect the redzone at the bottom of the last stack
4286*7c478bd9Sstevel@tonic-gate 	 */
4287*7c478bd9Sstevel@tonic-gate 	for (i = 0; i <= numstacks; i++) {
4288*7c478bd9Sstevel@tonic-gate 		(void) mprotect(addr, redzonesize, PROT_NONE);
4289*7c478bd9Sstevel@tonic-gate 		addr += stacksize + redzonesize;
4290*7c478bd9Sstevel@tonic-gate 	}
4291*7c478bd9Sstevel@tonic-gate 	return ((char *)(stack_top + redzonesize));
4292*7c478bd9Sstevel@tonic-gate }
4293*7c478bd9Sstevel@tonic-gate 
4294*7c478bd9Sstevel@tonic-gate static void
4295*7c478bd9Sstevel@tonic-gate dealloc_stacks(int numstacks)
4296*7c478bd9Sstevel@tonic-gate {
4297*7c478bd9Sstevel@tonic-gate 	size_t pagesize, mapsize;
4298*7c478bd9Sstevel@tonic-gate 
4299*7c478bd9Sstevel@tonic-gate 	pagesize = (size_t)sysconf(_SC_PAGESIZE);
4300*7c478bd9Sstevel@tonic-gate 
4301*7c478bd9Sstevel@tonic-gate 	stacksize = (size_t)roundup(sysconf(_SC_THREAD_STACK_MIN) +
4302*7c478bd9Sstevel@tonic-gate 	    DEFAULT_STACKSIZE, pagesize);
4303*7c478bd9Sstevel@tonic-gate 
4304*7c478bd9Sstevel@tonic-gate 	redzonesize = (size_t)roundup(DEFAULT_REDZONESIZE, pagesize);
4305*7c478bd9Sstevel@tonic-gate 
4306*7c478bd9Sstevel@tonic-gate 	mapsize = redzonesize + numstacks * (stacksize + redzonesize);
4307*7c478bd9Sstevel@tonic-gate 	(void) munmap(cstack_ptr - mapsize, mapsize);
4308*7c478bd9Sstevel@tonic-gate }
4309*7c478bd9Sstevel@tonic-gate 
4310*7c478bd9Sstevel@tonic-gate static void
4311*7c478bd9Sstevel@tonic-gate filed_destroy(struct filed *f)
4312*7c478bd9Sstevel@tonic-gate {
4313*7c478bd9Sstevel@tonic-gate 	(void) dataq_destroy(&f->f_queue);
4314*7c478bd9Sstevel@tonic-gate 	pthread_mutex_destroy(&f->filed_mutex);
4315*7c478bd9Sstevel@tonic-gate }
4316*7c478bd9Sstevel@tonic-gate 
4317*7c478bd9Sstevel@tonic-gate static void
4318*7c478bd9Sstevel@tonic-gate close_door(void)
4319*7c478bd9Sstevel@tonic-gate {
4320*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
4321*7c478bd9Sstevel@tonic-gate 
4322*7c478bd9Sstevel@tonic-gate 	if (Debug) {
4323*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
4324*7c478bd9Sstevel@tonic-gate 	}
4325*7c478bd9Sstevel@tonic-gate 
4326*7c478bd9Sstevel@tonic-gate 	(void) fdetach(DoorFileName);
4327*7c478bd9Sstevel@tonic-gate 
4328*7c478bd9Sstevel@tonic-gate 	DPRINT2(5, "close_door(%u): detached server() from %s\n",
4329*7c478bd9Sstevel@tonic-gate 		mythreadno, DoorFileName);
4330*7c478bd9Sstevel@tonic-gate }
4331*7c478bd9Sstevel@tonic-gate 
4332*7c478bd9Sstevel@tonic-gate static void
4333*7c478bd9Sstevel@tonic-gate delete_doorfiles(void)
4334*7c478bd9Sstevel@tonic-gate {
4335*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
4336*7c478bd9Sstevel@tonic-gate 	struct stat sb;
4337*7c478bd9Sstevel@tonic-gate 	int err;
4338*7c478bd9Sstevel@tonic-gate 	char line[MAXLINE+1];
4339*7c478bd9Sstevel@tonic-gate 
4340*7c478bd9Sstevel@tonic-gate 	if (Debug) {
4341*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
4342*7c478bd9Sstevel@tonic-gate 	}
4343*7c478bd9Sstevel@tonic-gate 
4344*7c478bd9Sstevel@tonic-gate 
4345*7c478bd9Sstevel@tonic-gate 	if (lstat(DoorFileName, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
4346*7c478bd9Sstevel@tonic-gate 		if (unlink(DoorFileName) < 0) {
4347*7c478bd9Sstevel@tonic-gate 			err = errno;
4348*7c478bd9Sstevel@tonic-gate 			(void) sprintf(line, "unlink() of %s failed - fatal",
4349*7c478bd9Sstevel@tonic-gate 				DoorFileName);
4350*7c478bd9Sstevel@tonic-gate 			errno = err;
4351*7c478bd9Sstevel@tonic-gate 			logerror(line);
4352*7c478bd9Sstevel@tonic-gate 			DPRINT3(1, "delete_doorfiles(%u): error: %s, "
4353*7c478bd9Sstevel@tonic-gate 				"errno=%d\n", mythreadno, line, err);
4354*7c478bd9Sstevel@tonic-gate 			exit(1);
4355*7c478bd9Sstevel@tonic-gate 		}
4356*7c478bd9Sstevel@tonic-gate 
4357*7c478bd9Sstevel@tonic-gate 		DPRINT2(5, "delete_doorfiles(%u): deleted %s\n",
4358*7c478bd9Sstevel@tonic-gate 			mythreadno, DoorFileName);
4359*7c478bd9Sstevel@tonic-gate 	}
4360*7c478bd9Sstevel@tonic-gate 
4361*7c478bd9Sstevel@tonic-gate 	if (strcmp(DoorFileName, DOORFILE) == 0) {
4362*7c478bd9Sstevel@tonic-gate 		if (lstat(OLD_DOORFILE, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
4363*7c478bd9Sstevel@tonic-gate 			if (unlink(OLD_DOORFILE) < 0) {
4364*7c478bd9Sstevel@tonic-gate 				err = errno;
4365*7c478bd9Sstevel@tonic-gate 				(void) sprintf(line, "unlink() of %s "
4366*7c478bd9Sstevel@tonic-gate 					"failed", OLD_DOORFILE);
4367*7c478bd9Sstevel@tonic-gate 				DPRINT2(5, "delete_doorfiles(%u): %s\n",
4368*7c478bd9Sstevel@tonic-gate 					mythreadno, line);
4369*7c478bd9Sstevel@tonic-gate 
4370*7c478bd9Sstevel@tonic-gate 				if (err != EROFS) {
4371*7c478bd9Sstevel@tonic-gate 					errno = err;
4372*7c478bd9Sstevel@tonic-gate 					(void) strcat(line, " - fatal");
4373*7c478bd9Sstevel@tonic-gate 					logerror(line);
4374*7c478bd9Sstevel@tonic-gate 					DPRINT3(1, "delete_doorfiles(%u): "
4375*7c478bd9Sstevel@tonic-gate 						"error: %s, errno=%d\n",
4376*7c478bd9Sstevel@tonic-gate 						mythreadno, line, err);
4377*7c478bd9Sstevel@tonic-gate 					exit(1);
4378*7c478bd9Sstevel@tonic-gate 				}
4379*7c478bd9Sstevel@tonic-gate 
4380*7c478bd9Sstevel@tonic-gate 				DPRINT1(5, "delete_doorfiles(%u): unlink() "
4381*7c478bd9Sstevel@tonic-gate 					"failure OK on RO file system\n",
4382*7c478bd9Sstevel@tonic-gate 					mythreadno);
4383*7c478bd9Sstevel@tonic-gate 			}
4384*7c478bd9Sstevel@tonic-gate 
4385*7c478bd9Sstevel@tonic-gate 			DPRINT2(5, "delete_doorfiles(%u): deleted %s\n",
4386*7c478bd9Sstevel@tonic-gate 				mythreadno, OLD_DOORFILE);
4387*7c478bd9Sstevel@tonic-gate 		}
4388*7c478bd9Sstevel@tonic-gate 	}
4389*7c478bd9Sstevel@tonic-gate 
4390*7c478bd9Sstevel@tonic-gate 	if (lstat(PidFileName, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
4391*7c478bd9Sstevel@tonic-gate 		if (unlink(PidFileName) < 0) {
4392*7c478bd9Sstevel@tonic-gate 			err = errno;
4393*7c478bd9Sstevel@tonic-gate 			(void) sprintf(line, "unlink() of %s failed"
4394*7c478bd9Sstevel@tonic-gate 				" - fatal", PidFileName);
4395*7c478bd9Sstevel@tonic-gate 			errno = err;
4396*7c478bd9Sstevel@tonic-gate 			logerror(line);
4397*7c478bd9Sstevel@tonic-gate 			DPRINT3(1, "delete_doorfiles(%u): error: %s, "
4398*7c478bd9Sstevel@tonic-gate 				"errno=%d\n", mythreadno, line, err);
4399*7c478bd9Sstevel@tonic-gate 			exit(1);
4400*7c478bd9Sstevel@tonic-gate 		}
4401*7c478bd9Sstevel@tonic-gate 
4402*7c478bd9Sstevel@tonic-gate 		DPRINT2(5, "delete_doorfiles(%u): deleted %s\n", mythreadno,
4403*7c478bd9Sstevel@tonic-gate 			PidFileName);
4404*7c478bd9Sstevel@tonic-gate 	}
4405*7c478bd9Sstevel@tonic-gate 
4406*7c478bd9Sstevel@tonic-gate 	if (strcmp(PidFileName, PIDFILE) == 0) {
4407*7c478bd9Sstevel@tonic-gate 		if (lstat(OLD_PIDFILE, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
4408*7c478bd9Sstevel@tonic-gate 			if (unlink(OLD_PIDFILE) < 0) {
4409*7c478bd9Sstevel@tonic-gate 				err = errno;
4410*7c478bd9Sstevel@tonic-gate 				(void) sprintf(line, "unlink() of %s failed",
4411*7c478bd9Sstevel@tonic-gate 					OLD_PIDFILE);
4412*7c478bd9Sstevel@tonic-gate 				DPRINT2(5, "delete_doorfiles(%u): %s, \n",
4413*7c478bd9Sstevel@tonic-gate 					mythreadno, line);
4414*7c478bd9Sstevel@tonic-gate 
4415*7c478bd9Sstevel@tonic-gate 				if (err != EROFS) {
4416*7c478bd9Sstevel@tonic-gate 					errno = err;
4417*7c478bd9Sstevel@tonic-gate 					(void) strcat(line, " - fatal");
4418*7c478bd9Sstevel@tonic-gate 					logerror(line);
4419*7c478bd9Sstevel@tonic-gate 					DPRINT3(1, "delete_doorfiles(%u): "
4420*7c478bd9Sstevel@tonic-gate 						"error: %s, errno=%d\n",
4421*7c478bd9Sstevel@tonic-gate 						mythreadno, line, err);
4422*7c478bd9Sstevel@tonic-gate 					exit(1);
4423*7c478bd9Sstevel@tonic-gate 				}
4424*7c478bd9Sstevel@tonic-gate 
4425*7c478bd9Sstevel@tonic-gate 				DPRINT1(5, "delete_doorfiles(%u): unlink "
4426*7c478bd9Sstevel@tonic-gate 					"failure OK on RO file system\n",
4427*7c478bd9Sstevel@tonic-gate 					mythreadno);
4428*7c478bd9Sstevel@tonic-gate 			}
4429*7c478bd9Sstevel@tonic-gate 
4430*7c478bd9Sstevel@tonic-gate 			DPRINT2(5, "delete_doorfiles(%u): deleted %s\n",
4431*7c478bd9Sstevel@tonic-gate 				mythreadno, OLD_PIDFILE);
4432*7c478bd9Sstevel@tonic-gate 		}
4433*7c478bd9Sstevel@tonic-gate 	}
4434*7c478bd9Sstevel@tonic-gate 
4435*7c478bd9Sstevel@tonic-gate 	if (DoorFd != -1) {
4436*7c478bd9Sstevel@tonic-gate 		(void) door_revoke(DoorFd);
4437*7c478bd9Sstevel@tonic-gate 	}
4438*7c478bd9Sstevel@tonic-gate 
4439*7c478bd9Sstevel@tonic-gate 	DPRINT2(1, "delete_doorfiles(%u): revoked door: DoorFd=%d\n",
4440*7c478bd9Sstevel@tonic-gate 		mythreadno, DoorFd);
4441*7c478bd9Sstevel@tonic-gate }
4442*7c478bd9Sstevel@tonic-gate 
4443*7c478bd9Sstevel@tonic-gate 
4444*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4445*7c478bd9Sstevel@tonic-gate static void
4446*7c478bd9Sstevel@tonic-gate signull(int sig, siginfo_t *sip, void *utp)
4447*7c478bd9Sstevel@tonic-gate {
4448*7c478bd9Sstevel@tonic-gate 	DPRINT1(1, "signull(%u): THIS CALL SHOULD NEVER HAPPEN\n",
4449*7c478bd9Sstevel@tonic-gate 		pthread_self());
4450*7c478bd9Sstevel@tonic-gate 	/*
4451*7c478bd9Sstevel@tonic-gate 	 * Do nothing, as this is a place-holder used in conjunction with
4452*7c478bd9Sstevel@tonic-gate 	 * sigaction()/sigwait() to ensure that the proper disposition is
4453*7c478bd9Sstevel@tonic-gate 	 * given to the signals we handle in main().
4454*7c478bd9Sstevel@tonic-gate 	 */
4455*7c478bd9Sstevel@tonic-gate }
4456*7c478bd9Sstevel@tonic-gate 
4457*7c478bd9Sstevel@tonic-gate /*
4458*7c478bd9Sstevel@tonic-gate  * putctrlc returns zero, if failed due to not enough buffer.
4459*7c478bd9Sstevel@tonic-gate  * Otherwise, putctrlc returns non-zero.
4460*7c478bd9Sstevel@tonic-gate  *
4461*7c478bd9Sstevel@tonic-gate  * c:     a byte to print in ASCII format
4462*7c478bd9Sstevel@tonic-gate  * **buf: a pointer to the pointer to the output buffer.
4463*7c478bd9Sstevel@tonic-gate  * *cl:   current length of characters in the output buffer
4464*7c478bd9Sstevel@tonic-gate  * max:   maximum length of the buffer
4465*7c478bd9Sstevel@tonic-gate  */
4466*7c478bd9Sstevel@tonic-gate 
4467*7c478bd9Sstevel@tonic-gate static int
4468*7c478bd9Sstevel@tonic-gate putctrlc(int c, char **buf, size_t *cl, size_t max)
4469*7c478bd9Sstevel@tonic-gate {
4470*7c478bd9Sstevel@tonic-gate 	char	*p = *buf;
4471*7c478bd9Sstevel@tonic-gate 
4472*7c478bd9Sstevel@tonic-gate 	if (c == '\n') {
4473*7c478bd9Sstevel@tonic-gate 		if (*cl + 2 < max) {
4474*7c478bd9Sstevel@tonic-gate 			*p++ = '\\';
4475*7c478bd9Sstevel@tonic-gate 			*p++ = 'n';
4476*7c478bd9Sstevel@tonic-gate 			*cl += 2;
4477*7c478bd9Sstevel@tonic-gate 			*buf = p;
4478*7c478bd9Sstevel@tonic-gate 			return (2);
4479*7c478bd9Sstevel@tonic-gate 		} else {
4480*7c478bd9Sstevel@tonic-gate 			return (0);
4481*7c478bd9Sstevel@tonic-gate 		}
4482*7c478bd9Sstevel@tonic-gate 	} else if (c < 0200) {
4483*7c478bd9Sstevel@tonic-gate 		/* ascii control character */
4484*7c478bd9Sstevel@tonic-gate 		if (*cl + 2 < max) {
4485*7c478bd9Sstevel@tonic-gate 			*p++ = '^';
4486*7c478bd9Sstevel@tonic-gate 			*p++ = c ^ 0100;
4487*7c478bd9Sstevel@tonic-gate 			*cl += 2;
4488*7c478bd9Sstevel@tonic-gate 			*buf = p;
4489*7c478bd9Sstevel@tonic-gate 			return (2);
4490*7c478bd9Sstevel@tonic-gate 		} else {
4491*7c478bd9Sstevel@tonic-gate 			return (0);
4492*7c478bd9Sstevel@tonic-gate 		}
4493*7c478bd9Sstevel@tonic-gate 	} else {
4494*7c478bd9Sstevel@tonic-gate 		if (*cl + 4 < max) {
4495*7c478bd9Sstevel@tonic-gate 			*p++ = '\\';
4496*7c478bd9Sstevel@tonic-gate 			*p++ = ((c >> 6) & 07) + '0';
4497*7c478bd9Sstevel@tonic-gate 			*p++ = ((c >> 3) & 07) + '0';
4498*7c478bd9Sstevel@tonic-gate 			*p++ = (c & 07) + '0';
4499*7c478bd9Sstevel@tonic-gate 			*cl += 4;
4500*7c478bd9Sstevel@tonic-gate 			*buf = p;
4501*7c478bd9Sstevel@tonic-gate 			return (4);
4502*7c478bd9Sstevel@tonic-gate 		} else {
4503*7c478bd9Sstevel@tonic-gate 			return (0);
4504*7c478bd9Sstevel@tonic-gate 		}
4505*7c478bd9Sstevel@tonic-gate 	}
4506*7c478bd9Sstevel@tonic-gate }
4507*7c478bd9Sstevel@tonic-gate 
4508*7c478bd9Sstevel@tonic-gate /*
4509*7c478bd9Sstevel@tonic-gate  * findnl_bkwd:
4510*7c478bd9Sstevel@tonic-gate  *	Scans each character in buf until it finds the last newline in buf,
4511*7c478bd9Sstevel@tonic-gate  *	or the scanned character becomes the last COMPLETE character in buf.
4512*7c478bd9Sstevel@tonic-gate  *	Returns the number of scanned bytes.
4513*7c478bd9Sstevel@tonic-gate  *
4514*7c478bd9Sstevel@tonic-gate  *	buf - pointer to a buffer containing the message string
4515*7c478bd9Sstevel@tonic-gate  *	len - the length of the buffer
4516*7c478bd9Sstevel@tonic-gate  */
4517*7c478bd9Sstevel@tonic-gate size_t
4518*7c478bd9Sstevel@tonic-gate findnl_bkwd(const char *buf, const size_t len)
4519*7c478bd9Sstevel@tonic-gate {
4520*7c478bd9Sstevel@tonic-gate 	const char *p;
4521*7c478bd9Sstevel@tonic-gate 	size_t	mb_cur_max;
4522*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
4523*7c478bd9Sstevel@tonic-gate 
4524*7c478bd9Sstevel@tonic-gate 	if (Debug) {
4525*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
4526*7c478bd9Sstevel@tonic-gate 	}
4527*7c478bd9Sstevel@tonic-gate 
4528*7c478bd9Sstevel@tonic-gate 	if (len == 0) {
4529*7c478bd9Sstevel@tonic-gate 		return (0);
4530*7c478bd9Sstevel@tonic-gate 	}
4531*7c478bd9Sstevel@tonic-gate 
4532*7c478bd9Sstevel@tonic-gate 	mb_cur_max = MB_CUR_MAX;
4533*7c478bd9Sstevel@tonic-gate 
4534*7c478bd9Sstevel@tonic-gate 	if (mb_cur_max == 1) {
4535*7c478bd9Sstevel@tonic-gate 		/* single-byte locale */
4536*7c478bd9Sstevel@tonic-gate 		for (p = buf + len - 1; p != buf; p--) {
4537*7c478bd9Sstevel@tonic-gate 			if (*p == '\n') {
4538*7c478bd9Sstevel@tonic-gate 				return ((size_t)(p - buf));
4539*7c478bd9Sstevel@tonic-gate 			}
4540*7c478bd9Sstevel@tonic-gate 		}
4541*7c478bd9Sstevel@tonic-gate 		return ((size_t)len);
4542*7c478bd9Sstevel@tonic-gate 	} else {
4543*7c478bd9Sstevel@tonic-gate 		/* multi-byte locale */
4544*7c478bd9Sstevel@tonic-gate 		int mlen;
4545*7c478bd9Sstevel@tonic-gate 		const char *nl;
4546*7c478bd9Sstevel@tonic-gate 		size_t	rem;
4547*7c478bd9Sstevel@tonic-gate 
4548*7c478bd9Sstevel@tonic-gate 		p = buf;
4549*7c478bd9Sstevel@tonic-gate 		nl = NULL;
4550*7c478bd9Sstevel@tonic-gate 		for (rem = len; rem >= mb_cur_max; ) {
4551*7c478bd9Sstevel@tonic-gate 			mlen = mblen(p, mb_cur_max);
4552*7c478bd9Sstevel@tonic-gate 			if (mlen == -1) {
4553*7c478bd9Sstevel@tonic-gate 				/*
4554*7c478bd9Sstevel@tonic-gate 				 * Invalid character found.
4555*7c478bd9Sstevel@tonic-gate 				 */
4556*7c478bd9Sstevel@tonic-gate 				DPRINT1(9, "findnl_bkwd(%u): Invalid MB "
4557*7c478bd9Sstevel@tonic-gate 					"sequence\n", mythreadno);
4558*7c478bd9Sstevel@tonic-gate 				/*
4559*7c478bd9Sstevel@tonic-gate 				 * handle as a single byte character.
4560*7c478bd9Sstevel@tonic-gate 				 */
4561*7c478bd9Sstevel@tonic-gate 				p++;
4562*7c478bd9Sstevel@tonic-gate 				rem--;
4563*7c478bd9Sstevel@tonic-gate 			} else {
4564*7c478bd9Sstevel@tonic-gate 				/*
4565*7c478bd9Sstevel@tonic-gate 				 * It's guaranteed that *p points to
4566*7c478bd9Sstevel@tonic-gate 				 * the 1st byte of a multibyte character.
4567*7c478bd9Sstevel@tonic-gate 				 */
4568*7c478bd9Sstevel@tonic-gate 				if (*p == '\n') {
4569*7c478bd9Sstevel@tonic-gate 					nl = p;
4570*7c478bd9Sstevel@tonic-gate 				}
4571*7c478bd9Sstevel@tonic-gate 				p += mlen;
4572*7c478bd9Sstevel@tonic-gate 				rem -= mlen;
4573*7c478bd9Sstevel@tonic-gate 			}
4574*7c478bd9Sstevel@tonic-gate 		}
4575*7c478bd9Sstevel@tonic-gate 		if (nl) {
4576*7c478bd9Sstevel@tonic-gate 			return ((size_t)(nl - buf));
4577*7c478bd9Sstevel@tonic-gate 		}
4578*7c478bd9Sstevel@tonic-gate 		/*
4579*7c478bd9Sstevel@tonic-gate 		 * no newline nor null byte found.
4580*7c478bd9Sstevel@tonic-gate 		 * Also it's guaranteed that *p points to
4581*7c478bd9Sstevel@tonic-gate 		 * the 1st byte of a (multibyte) character
4582*7c478bd9Sstevel@tonic-gate 		 * at this point.
4583*7c478bd9Sstevel@tonic-gate 		 */
4584*7c478bd9Sstevel@tonic-gate 		return (len - rem);
4585*7c478bd9Sstevel@tonic-gate 	}
4586*7c478bd9Sstevel@tonic-gate }
4587*7c478bd9Sstevel@tonic-gate 
4588*7c478bd9Sstevel@tonic-gate /*
4589*7c478bd9Sstevel@tonic-gate  * copynl_frwd:
4590*7c478bd9Sstevel@tonic-gate  *	Scans each character in buf and copies the scanned character to obuf
4591*7c478bd9Sstevel@tonic-gate  *	until it finds a null byte or a newline, or
4592*7c478bd9Sstevel@tonic-gate  *	the number of the remaining bytes in obuf gets to exceed obuflen
4593*7c478bd9Sstevel@tonic-gate  *	if copying the scanned character to obuf.
4594*7c478bd9Sstevel@tonic-gate  *	Returns the number of scanned bytes.
4595*7c478bd9Sstevel@tonic-gate  *
4596*7c478bd9Sstevel@tonic-gate  *	obuf - buffer to be copied the scanned character
4597*7c478bd9Sstevel@tonic-gate  *	obuflen - the size of obuf
4598*7c478bd9Sstevel@tonic-gate  *	buf - pointer to a buffer containing the message string
4599*7c478bd9Sstevel@tonic-gate  *	len - the length of the buffer
4600*7c478bd9Sstevel@tonic-gate  */
4601*7c478bd9Sstevel@tonic-gate size_t
4602*7c478bd9Sstevel@tonic-gate copynl_frwd(char *obuf, const size_t obuflen,
4603*7c478bd9Sstevel@tonic-gate 	    const char *buf, const size_t len)
4604*7c478bd9Sstevel@tonic-gate {
4605*7c478bd9Sstevel@tonic-gate 	const char *p;
4606*7c478bd9Sstevel@tonic-gate 	char	*q = obuf;
4607*7c478bd9Sstevel@tonic-gate 	size_t	olen = 0;
4608*7c478bd9Sstevel@tonic-gate 	size_t	mb_cur_max;
4609*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
4610*7c478bd9Sstevel@tonic-gate 
4611*7c478bd9Sstevel@tonic-gate 	if (Debug) {
4612*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
4613*7c478bd9Sstevel@tonic-gate 	}
4614*7c478bd9Sstevel@tonic-gate 
4615*7c478bd9Sstevel@tonic-gate 	if (len == 0) {
4616*7c478bd9Sstevel@tonic-gate 		return (0);
4617*7c478bd9Sstevel@tonic-gate 	}
4618*7c478bd9Sstevel@tonic-gate 
4619*7c478bd9Sstevel@tonic-gate 	mb_cur_max = MB_CUR_MAX;
4620*7c478bd9Sstevel@tonic-gate 
4621*7c478bd9Sstevel@tonic-gate 	if (mb_cur_max == 1) {
4622*7c478bd9Sstevel@tonic-gate 		/* single-byte locale */
4623*7c478bd9Sstevel@tonic-gate 		for (p = buf; *p; ) {
4624*7c478bd9Sstevel@tonic-gate 			if (obuflen > olen + 1) {
4625*7c478bd9Sstevel@tonic-gate 				if (*p != '\n') {
4626*7c478bd9Sstevel@tonic-gate 					*q++ = *p++;
4627*7c478bd9Sstevel@tonic-gate 					olen++;
4628*7c478bd9Sstevel@tonic-gate 				} else {
4629*7c478bd9Sstevel@tonic-gate 					*q = '\0';
4630*7c478bd9Sstevel@tonic-gate 					return ((size_t)(p - buf));
4631*7c478bd9Sstevel@tonic-gate 				}
4632*7c478bd9Sstevel@tonic-gate 			} else {
4633*7c478bd9Sstevel@tonic-gate 				*q = '\0';
4634*7c478bd9Sstevel@tonic-gate 				return ((size_t)(p - buf));
4635*7c478bd9Sstevel@tonic-gate 			}
4636*7c478bd9Sstevel@tonic-gate 		}
4637*7c478bd9Sstevel@tonic-gate 		*q = '\0';
4638*7c478bd9Sstevel@tonic-gate 		return ((size_t)(p - buf));
4639*7c478bd9Sstevel@tonic-gate 	} else {
4640*7c478bd9Sstevel@tonic-gate 		/* multi-byte locale */
4641*7c478bd9Sstevel@tonic-gate 		int mlen;
4642*7c478bd9Sstevel@tonic-gate 
4643*7c478bd9Sstevel@tonic-gate 		for (p = buf; *p; ) {
4644*7c478bd9Sstevel@tonic-gate 			mlen = mblen(p, mb_cur_max);
4645*7c478bd9Sstevel@tonic-gate 			if (mlen == -1) {
4646*7c478bd9Sstevel@tonic-gate 				/*
4647*7c478bd9Sstevel@tonic-gate 				 * Invalid character found.
4648*7c478bd9Sstevel@tonic-gate 				 */
4649*7c478bd9Sstevel@tonic-gate 				DPRINT1(9, "copynl_frwd(%u): Invalid MB "
4650*7c478bd9Sstevel@tonic-gate 					"sequence\n", mythreadno);
4651*7c478bd9Sstevel@tonic-gate 				/*
4652*7c478bd9Sstevel@tonic-gate 				 * handle as a single byte character.
4653*7c478bd9Sstevel@tonic-gate 				 */
4654*7c478bd9Sstevel@tonic-gate 				if (obuflen > olen + 1) {
4655*7c478bd9Sstevel@tonic-gate 					*q++ = *p++;
4656*7c478bd9Sstevel@tonic-gate 					olen++;
4657*7c478bd9Sstevel@tonic-gate 				} else {
4658*7c478bd9Sstevel@tonic-gate 					*q = '\0';
4659*7c478bd9Sstevel@tonic-gate 					return ((size_t)(p - buf));
4660*7c478bd9Sstevel@tonic-gate 				}
4661*7c478bd9Sstevel@tonic-gate 			} else {
4662*7c478bd9Sstevel@tonic-gate 				/*
4663*7c478bd9Sstevel@tonic-gate 				 * It's guaranteed that *p points to
4664*7c478bd9Sstevel@tonic-gate 				 * the 1st byte of a multibyte character.
4665*7c478bd9Sstevel@tonic-gate 				 */
4666*7c478bd9Sstevel@tonic-gate 				if (*p == '\n') {
4667*7c478bd9Sstevel@tonic-gate 					*q = '\0';
4668*7c478bd9Sstevel@tonic-gate 					return ((size_t)(p - buf));
4669*7c478bd9Sstevel@tonic-gate 				}
4670*7c478bd9Sstevel@tonic-gate 				if (obuflen > olen + mlen) {
4671*7c478bd9Sstevel@tonic-gate 					int	n;
4672*7c478bd9Sstevel@tonic-gate 					for (n = 0; n < mlen; n++) {
4673*7c478bd9Sstevel@tonic-gate 						*q++ = *p++;
4674*7c478bd9Sstevel@tonic-gate 					}
4675*7c478bd9Sstevel@tonic-gate 					olen += mlen;
4676*7c478bd9Sstevel@tonic-gate 				} else {
4677*7c478bd9Sstevel@tonic-gate 					*q = '\0';
4678*7c478bd9Sstevel@tonic-gate 					return ((size_t)(p - buf));
4679*7c478bd9Sstevel@tonic-gate 				}
4680*7c478bd9Sstevel@tonic-gate 			}
4681*7c478bd9Sstevel@tonic-gate 		}
4682*7c478bd9Sstevel@tonic-gate 		/*
4683*7c478bd9Sstevel@tonic-gate 		 * no newline nor null byte found.
4684*7c478bd9Sstevel@tonic-gate 		 * Also it's guaranteed that *p points to
4685*7c478bd9Sstevel@tonic-gate 		 * the 1st byte of a (multibyte) character
4686*7c478bd9Sstevel@tonic-gate 		 * at this point.
4687*7c478bd9Sstevel@tonic-gate 		 */
4688*7c478bd9Sstevel@tonic-gate 		*q = '\0';
4689*7c478bd9Sstevel@tonic-gate 		return ((size_t)(p - buf));
4690*7c478bd9Sstevel@tonic-gate 	}
4691*7c478bd9Sstevel@tonic-gate }
4692*7c478bd9Sstevel@tonic-gate 
4693*7c478bd9Sstevel@tonic-gate /*
4694*7c478bd9Sstevel@tonic-gate  * copy_frwd:
4695*7c478bd9Sstevel@tonic-gate  *	Scans each character in buf and copies the scanned character to obuf
4696*7c478bd9Sstevel@tonic-gate  *	until the number of the remaining bytes in obuf gets to exceed obuflen
4697*7c478bd9Sstevel@tonic-gate  *	if copying the scanned character to obuf.
4698*7c478bd9Sstevel@tonic-gate  *	Returns the number of scanned (copied) bytes.
4699*7c478bd9Sstevel@tonic-gate  *
4700*7c478bd9Sstevel@tonic-gate  *	obuf - buffer to be copied the scanned character
4701*7c478bd9Sstevel@tonic-gate  *	obuflen - the size of obuf
4702*7c478bd9Sstevel@tonic-gate  *	buf - pointer to a buffer containing the message string
4703*7c478bd9Sstevel@tonic-gate  *	len - the length of the buffer
4704*7c478bd9Sstevel@tonic-gate  */
4705*7c478bd9Sstevel@tonic-gate size_t
4706*7c478bd9Sstevel@tonic-gate copy_frwd(char *obuf, const size_t obuflen,
4707*7c478bd9Sstevel@tonic-gate 	const char *buf, const size_t len)
4708*7c478bd9Sstevel@tonic-gate {
4709*7c478bd9Sstevel@tonic-gate 	const char *p;
4710*7c478bd9Sstevel@tonic-gate 	char	*q = obuf;
4711*7c478bd9Sstevel@tonic-gate 	size_t	olen = 0;
4712*7c478bd9Sstevel@tonic-gate 	size_t	mb_cur_max;
4713*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
4714*7c478bd9Sstevel@tonic-gate 
4715*7c478bd9Sstevel@tonic-gate 	if (Debug) {
4716*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
4717*7c478bd9Sstevel@tonic-gate 	}
4718*7c478bd9Sstevel@tonic-gate 
4719*7c478bd9Sstevel@tonic-gate 	if (len == 0) {
4720*7c478bd9Sstevel@tonic-gate 		return (0);
4721*7c478bd9Sstevel@tonic-gate 	}
4722*7c478bd9Sstevel@tonic-gate 
4723*7c478bd9Sstevel@tonic-gate 	mb_cur_max = MB_CUR_MAX;
4724*7c478bd9Sstevel@tonic-gate 
4725*7c478bd9Sstevel@tonic-gate 	if (mb_cur_max == 1) {
4726*7c478bd9Sstevel@tonic-gate 		/* single-byte locale */
4727*7c478bd9Sstevel@tonic-gate 		if (obuflen > len) {
4728*7c478bd9Sstevel@tonic-gate 			(void) memcpy(obuf, buf, len);
4729*7c478bd9Sstevel@tonic-gate 			obuf[len] = '\0';
4730*7c478bd9Sstevel@tonic-gate 			return ((size_t)len);
4731*7c478bd9Sstevel@tonic-gate 		} else {
4732*7c478bd9Sstevel@tonic-gate 			(void) memcpy(obuf, buf, obuflen - 1);
4733*7c478bd9Sstevel@tonic-gate 			obuf[obuflen - 1] = '\0';
4734*7c478bd9Sstevel@tonic-gate 			return (obuflen - 1);
4735*7c478bd9Sstevel@tonic-gate 		}
4736*7c478bd9Sstevel@tonic-gate 	} else {
4737*7c478bd9Sstevel@tonic-gate 		/* multi-byte locale */
4738*7c478bd9Sstevel@tonic-gate 		int mlen;
4739*7c478bd9Sstevel@tonic-gate 
4740*7c478bd9Sstevel@tonic-gate 		for (p = buf; *p; ) {
4741*7c478bd9Sstevel@tonic-gate 			mlen = mblen(p, mb_cur_max);
4742*7c478bd9Sstevel@tonic-gate 			if (mlen == -1) {
4743*7c478bd9Sstevel@tonic-gate 				/*
4744*7c478bd9Sstevel@tonic-gate 				 * Invalid character found.
4745*7c478bd9Sstevel@tonic-gate 				 */
4746*7c478bd9Sstevel@tonic-gate 				DPRINT1(9, "copy_frwd(%u): Invalid MB "
4747*7c478bd9Sstevel@tonic-gate 					"sequence\n", mythreadno);
4748*7c478bd9Sstevel@tonic-gate 				/*
4749*7c478bd9Sstevel@tonic-gate 				 * handle as a single byte character.
4750*7c478bd9Sstevel@tonic-gate 				 */
4751*7c478bd9Sstevel@tonic-gate 				if (obuflen > olen + 1) {
4752*7c478bd9Sstevel@tonic-gate 					*q++ = *p++;
4753*7c478bd9Sstevel@tonic-gate 					olen++;
4754*7c478bd9Sstevel@tonic-gate 				} else {
4755*7c478bd9Sstevel@tonic-gate 					*q = '\0';
4756*7c478bd9Sstevel@tonic-gate 					return ((size_t)(p - buf));
4757*7c478bd9Sstevel@tonic-gate 				}
4758*7c478bd9Sstevel@tonic-gate 			} else {
4759*7c478bd9Sstevel@tonic-gate 				if (obuflen > olen + mlen) {
4760*7c478bd9Sstevel@tonic-gate 					int	n;
4761*7c478bd9Sstevel@tonic-gate 					for (n = 0; n < mlen; n++) {
4762*7c478bd9Sstevel@tonic-gate 						*q++ = *p++;
4763*7c478bd9Sstevel@tonic-gate 					}
4764*7c478bd9Sstevel@tonic-gate 					olen += mlen;
4765*7c478bd9Sstevel@tonic-gate 				} else {
4766*7c478bd9Sstevel@tonic-gate 					*q = '\0';
4767*7c478bd9Sstevel@tonic-gate 					return ((size_t)(p - buf));
4768*7c478bd9Sstevel@tonic-gate 				}
4769*7c478bd9Sstevel@tonic-gate 			}
4770*7c478bd9Sstevel@tonic-gate 		}
4771*7c478bd9Sstevel@tonic-gate 		*q = '\0';
4772*7c478bd9Sstevel@tonic-gate 		return ((size_t)(p - buf));
4773*7c478bd9Sstevel@tonic-gate 	}
4774*7c478bd9Sstevel@tonic-gate }
4775*7c478bd9Sstevel@tonic-gate 
4776*7c478bd9Sstevel@tonic-gate /*
4777*7c478bd9Sstevel@tonic-gate  * defaults:
4778*7c478bd9Sstevel@tonic-gate  *	Read defaults from file.
4779*7c478bd9Sstevel@tonic-gate  */
4780*7c478bd9Sstevel@tonic-gate static void
4781*7c478bd9Sstevel@tonic-gate defaults(void)
4782*7c478bd9Sstevel@tonic-gate {
4783*7c478bd9Sstevel@tonic-gate 	int  flags;
4784*7c478bd9Sstevel@tonic-gate 	char *ptr;
4785*7c478bd9Sstevel@tonic-gate 
4786*7c478bd9Sstevel@tonic-gate 	if (defopen(DflFile) == 0) {
4787*7c478bd9Sstevel@tonic-gate 		/*
4788*7c478bd9Sstevel@tonic-gate 		 * ignore case
4789*7c478bd9Sstevel@tonic-gate 		 */
4790*7c478bd9Sstevel@tonic-gate 		flags = defcntl(DC_GETFLAGS, 0);
4791*7c478bd9Sstevel@tonic-gate 		TURNOFF(flags, DC_CASE);
4792*7c478bd9Sstevel@tonic-gate 		defcntl(DC_SETFLAGS, flags);
4793*7c478bd9Sstevel@tonic-gate 
4794*7c478bd9Sstevel@tonic-gate 		if ((ptr = defread("LOG_FROM_REMOTE=")) != NULL) {
4795*7c478bd9Sstevel@tonic-gate 			turnoff = strcasecmp(ptr, "NO") == 0;
4796*7c478bd9Sstevel@tonic-gate 		}
4797*7c478bd9Sstevel@tonic-gate 
4798*7c478bd9Sstevel@tonic-gate 		(void) defopen((char *)NULL);
4799*7c478bd9Sstevel@tonic-gate 	}
4800*7c478bd9Sstevel@tonic-gate }
4801*7c478bd9Sstevel@tonic-gate 
4802*7c478bd9Sstevel@tonic-gate /*
4803*7c478bd9Sstevel@tonic-gate  * close all the input devices.
4804*7c478bd9Sstevel@tonic-gate  */
4805*7c478bd9Sstevel@tonic-gate static void
4806*7c478bd9Sstevel@tonic-gate shutdown_input(void)
4807*7c478bd9Sstevel@tonic-gate {
4808*7c478bd9Sstevel@tonic-gate 	int cnt;
4809*7c478bd9Sstevel@tonic-gate 
4810*7c478bd9Sstevel@tonic-gate 	shutting_down = 1;
4811*7c478bd9Sstevel@tonic-gate 
4812*7c478bd9Sstevel@tonic-gate 	for (cnt = 0; cnt < Ninputs; cnt++) {
4813*7c478bd9Sstevel@tonic-gate 		(void) t_close(Nfd[cnt].fd);
4814*7c478bd9Sstevel@tonic-gate 	}
4815*7c478bd9Sstevel@tonic-gate 
4816*7c478bd9Sstevel@tonic-gate 	(void) close(Pfd.fd);
4817*7c478bd9Sstevel@tonic-gate }
4818*7c478bd9Sstevel@tonic-gate 
4819*7c478bd9Sstevel@tonic-gate /*
4820*7c478bd9Sstevel@tonic-gate  * This is for the one thread that dedicates to resolve the
4821*7c478bd9Sstevel@tonic-gate  * hostname. This will get the messages from net_poll() through
4822*7c478bd9Sstevel@tonic-gate  * hnlq, and resolve the hostname, and push the messages back
4823*7c478bd9Sstevel@tonic-gate  * into the inputq.
4824*7c478bd9Sstevel@tonic-gate  */
4825*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4826*7c478bd9Sstevel@tonic-gate static void *
4827*7c478bd9Sstevel@tonic-gate hostname_lookup(void *ap)
4828*7c478bd9Sstevel@tonic-gate {
4829*7c478bd9Sstevel@tonic-gate 	char *uap;
4830*7c478bd9Sstevel@tonic-gate 	log_message_t *mp;
4831*7c478bd9Sstevel@tonic-gate 	host_info_t *hip;
4832*7c478bd9Sstevel@tonic-gate 	char failsafe_addr[SYS_NMLN + 1];
4833*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
4834*7c478bd9Sstevel@tonic-gate 
4835*7c478bd9Sstevel@tonic-gate 	if (Debug) {
4836*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
4837*7c478bd9Sstevel@tonic-gate 	}
4838*7c478bd9Sstevel@tonic-gate 
4839*7c478bd9Sstevel@tonic-gate 	DPRINT1(1, "hostname_lookup(%u): hostname_lookup started\n",
4840*7c478bd9Sstevel@tonic-gate 		mythreadno);
4841*7c478bd9Sstevel@tonic-gate 
4842*7c478bd9Sstevel@tonic-gate 	for (;;) {
4843*7c478bd9Sstevel@tonic-gate 		(void) dataq_dequeue(&hnlq, (void **)&mp, 0);
4844*7c478bd9Sstevel@tonic-gate 
4845*7c478bd9Sstevel@tonic-gate 		DPRINT3(5, "hostname_lookup(%u): dequeued msg %p"
4846*7c478bd9Sstevel@tonic-gate 				" from queue %p\n", mythreadno, mp, &hnlq);
4847*7c478bd9Sstevel@tonic-gate 
4848*7c478bd9Sstevel@tonic-gate 		hip = (host_info_t *)mp->ptr;
4849*7c478bd9Sstevel@tonic-gate 		if ((uap = taddr2uaddr(hip->ncp, &hip->addr)) != NULL) {
4850*7c478bd9Sstevel@tonic-gate 			(void) strlcpy(failsafe_addr, uap, SYS_NMLN);
4851*7c478bd9Sstevel@tonic-gate 			free(uap);
4852*7c478bd9Sstevel@tonic-gate 		} else {
4853*7c478bd9Sstevel@tonic-gate 			(void) strlcpy(failsafe_addr, "<unknown>", SYS_NMLN);
4854*7c478bd9Sstevel@tonic-gate 		}
4855*7c478bd9Sstevel@tonic-gate 
4856*7c478bd9Sstevel@tonic-gate 		mp->hlp = cvthname(&hip->addr, hip->ncp, failsafe_addr);
4857*7c478bd9Sstevel@tonic-gate 
4858*7c478bd9Sstevel@tonic-gate 		if (mp->hlp == NULL) {
4859*7c478bd9Sstevel@tonic-gate 			mp->hlp = &NullHostName;
4860*7c478bd9Sstevel@tonic-gate 		}
4861*7c478bd9Sstevel@tonic-gate 
4862*7c478bd9Sstevel@tonic-gate 		free(hip->addr.buf);
4863*7c478bd9Sstevel@tonic-gate 		free(hip);
4864*7c478bd9Sstevel@tonic-gate 		mp->ptr = NULL;
4865*7c478bd9Sstevel@tonic-gate 
4866*7c478bd9Sstevel@tonic-gate 		if (dataq_enqueue(&inputq, (void *)mp) == -1) {
4867*7c478bd9Sstevel@tonic-gate 			MALLOC_FAIL("dropping message from remote");
4868*7c478bd9Sstevel@tonic-gate 			free_msg(mp);
4869*7c478bd9Sstevel@tonic-gate 			continue;
4870*7c478bd9Sstevel@tonic-gate 		}
4871*7c478bd9Sstevel@tonic-gate 
4872*7c478bd9Sstevel@tonic-gate 		DPRINT3(5, "hostname_lookup(%u): enqueued msg %p on queue %p\n",
4873*7c478bd9Sstevel@tonic-gate 			mythreadno, mp, &inputq);
4874*7c478bd9Sstevel@tonic-gate 	}
4875*7c478bd9Sstevel@tonic-gate 
4876*7c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
4877*7c478bd9Sstevel@tonic-gate 	return (NULL);
4878*7c478bd9Sstevel@tonic-gate }
4879*7c478bd9Sstevel@tonic-gate 
4880*7c478bd9Sstevel@tonic-gate /*
4881*7c478bd9Sstevel@tonic-gate  * Does all HUP(re-configuration) process.
4882*7c478bd9Sstevel@tonic-gate  */
4883*7c478bd9Sstevel@tonic-gate static void
4884*7c478bd9Sstevel@tonic-gate reconfigure()
4885*7c478bd9Sstevel@tonic-gate {
4886*7c478bd9Sstevel@tonic-gate 	int cnt, loop, drops;
4887*7c478bd9Sstevel@tonic-gate 	int really_stuck;
4888*7c478bd9Sstevel@tonic-gate 	int console_stuck = 0;
4889*7c478bd9Sstevel@tonic-gate 	struct filed *f;
4890*7c478bd9Sstevel@tonic-gate 	char buf[LINE_MAX];
4891*7c478bd9Sstevel@tonic-gate 	struct utsname up;
4892*7c478bd9Sstevel@tonic-gate 	char cbuf[30];
4893*7c478bd9Sstevel@tonic-gate 	time_t tim;
4894*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
4895*7c478bd9Sstevel@tonic-gate 
4896*7c478bd9Sstevel@tonic-gate 	if (Debug) {
4897*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
4898*7c478bd9Sstevel@tonic-gate 	}
4899*7c478bd9Sstevel@tonic-gate 
4900*7c478bd9Sstevel@tonic-gate 	/* If we get here then we must need to regen */
4901*7c478bd9Sstevel@tonic-gate 	flushmsg(0);
4902*7c478bd9Sstevel@tonic-gate 
4903*7c478bd9Sstevel@tonic-gate 	if (logmymsg(LOG_SYSLOG|LOG_INFO, "syslogd: configuration restart",
4904*7c478bd9Sstevel@tonic-gate 		ADDDATE, 0) == -1) {
4905*7c478bd9Sstevel@tonic-gate 		MALLOC_FAIL("dropping message");
4906*7c478bd9Sstevel@tonic-gate 	}
4907*7c478bd9Sstevel@tonic-gate 
4908*7c478bd9Sstevel@tonic-gate 	/*
4909*7c478bd9Sstevel@tonic-gate 	 * make sure the logmsg thread is not in the waiting state.
4910*7c478bd9Sstevel@tonic-gate 	 * Otherwise, changing hup_state will prevent the logmsg thread
4911*7c478bd9Sstevel@tonic-gate 	 * getting out from the waiting loop.
4912*7c478bd9Sstevel@tonic-gate 	 */
4913*7c478bd9Sstevel@tonic-gate 
4914*7c478bd9Sstevel@tonic-gate 	if (Debug) {
4915*7c478bd9Sstevel@tonic-gate 		tim = time(NULL);
4916*7c478bd9Sstevel@tonic-gate 		DPRINT2(3, "reconfigure(%u): %.15s: awaiting logmsg()"
4917*7c478bd9Sstevel@tonic-gate 			" moving to the safe place\n",
4918*7c478bd9Sstevel@tonic-gate 			mythreadno, ctime_r(&tim, cbuf)+4);
4919*7c478bd9Sstevel@tonic-gate 	}
4920*7c478bd9Sstevel@tonic-gate 
4921*7c478bd9Sstevel@tonic-gate 	for (loop = 0; loop < LOOP_MAX; loop++) {
4922*7c478bd9Sstevel@tonic-gate 		/* we don't need the mutex to read */
4923*7c478bd9Sstevel@tonic-gate 		if (hup_state == HUP_ACCEPTABLE)
4924*7c478bd9Sstevel@tonic-gate 			break;
4925*7c478bd9Sstevel@tonic-gate 		(void) sleep(1);
4926*7c478bd9Sstevel@tonic-gate 	}
4927*7c478bd9Sstevel@tonic-gate 	if (hup_state != HUP_ACCEPTABLE) {
4928*7c478bd9Sstevel@tonic-gate 		goto thread_stuck;
4929*7c478bd9Sstevel@tonic-gate 	}
4930*7c478bd9Sstevel@tonic-gate 
4931*7c478bd9Sstevel@tonic-gate 	if (Debug) {
4932*7c478bd9Sstevel@tonic-gate 		tim = time(NULL);
4933*7c478bd9Sstevel@tonic-gate 		DPRINT2(3, "reconfigure(%u): %.15s: logmsg() will accept HUP\n",
4934*7c478bd9Sstevel@tonic-gate 			mythreadno, ctime_r(&tim, cbuf)+4);
4935*7c478bd9Sstevel@tonic-gate 	}
4936*7c478bd9Sstevel@tonic-gate 
4937*7c478bd9Sstevel@tonic-gate 	/*
4938*7c478bd9Sstevel@tonic-gate 	 * Prevent logging until we are truly done processing the HUP
4939*7c478bd9Sstevel@tonic-gate 	 */
4940*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&hup_lock);
4941*7c478bd9Sstevel@tonic-gate 	hup_state = HUP_INPROGRESS;
4942*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&hup_lock);
4943*7c478bd9Sstevel@tonic-gate 
4944*7c478bd9Sstevel@tonic-gate 	/*
4945*7c478bd9Sstevel@tonic-gate 	 * We will be going into a critical state. Any error message
4946*7c478bd9Sstevel@tonic-gate 	 * from syslogd needs to be dumped to the console by default
4947*7c478bd9Sstevel@tonic-gate 	 * immediately. Also, those error messages are quened in a temporary
4948*7c478bd9Sstevel@tonic-gate 	 * queue to be able to post into the regular stream later.
4949*7c478bd9Sstevel@tonic-gate 	 */
4950*7c478bd9Sstevel@tonic-gate 	disable_errorlog();
4951*7c478bd9Sstevel@tonic-gate 
4952*7c478bd9Sstevel@tonic-gate 	if (Debug) {
4953*7c478bd9Sstevel@tonic-gate 		tim = time(NULL);
4954*7c478bd9Sstevel@tonic-gate 		DPRINT2(3, "reconfigure(%u): %.15s: sending SHUTDOWN\n",
4955*7c478bd9Sstevel@tonic-gate 			mythreadno, ctime_r(&tim, cbuf)+4);
4956*7c478bd9Sstevel@tonic-gate 	}
4957*7c478bd9Sstevel@tonic-gate 
4958*7c478bd9Sstevel@tonic-gate 	/* stop configured threads */
4959*7c478bd9Sstevel@tonic-gate 	if (shutdown_msg() == -1) {
4960*7c478bd9Sstevel@tonic-gate 		/*
4961*7c478bd9Sstevel@tonic-gate 		 * No memory, message will be dumped to the console.
4962*7c478bd9Sstevel@tonic-gate 		 */
4963*7c478bd9Sstevel@tonic-gate 		MALLOC_FAIL("unable to restart syslogd");
4964*7c478bd9Sstevel@tonic-gate 		goto out;
4965*7c478bd9Sstevel@tonic-gate 	}
4966*7c478bd9Sstevel@tonic-gate 
4967*7c478bd9Sstevel@tonic-gate 	/* make sure logmsg() is in suspended state */
4968*7c478bd9Sstevel@tonic-gate 	for (loop = 0; loop < LOOP_INTERVAL; loop++) {
4969*7c478bd9Sstevel@tonic-gate 		if (hup_state & HUP_LOGMSG_SUSPENDED)
4970*7c478bd9Sstevel@tonic-gate 			break;
4971*7c478bd9Sstevel@tonic-gate 		(void) sleep(1);
4972*7c478bd9Sstevel@tonic-gate 	}
4973*7c478bd9Sstevel@tonic-gate 
4974*7c478bd9Sstevel@tonic-gate 	if ((hup_state & HUP_LOGMSG_SUSPENDED) == 0) {
4975*7c478bd9Sstevel@tonic-gate 		if (Debug) {
4976*7c478bd9Sstevel@tonic-gate 			tim = time(NULL);
4977*7c478bd9Sstevel@tonic-gate 			DPRINT2(3, "reconfigure(%u): %.15s: logmsg() does not "
4978*7c478bd9Sstevel@tonic-gate 				"stop. enforcing\n",
4979*7c478bd9Sstevel@tonic-gate 				mythreadno, ctime_r(&tim, cbuf)+4);
4980*7c478bd9Sstevel@tonic-gate 		}
4981*7c478bd9Sstevel@tonic-gate 
4982*7c478bd9Sstevel@tonic-gate 		/* probably we have too long input queue, or really stuck */
4983*7c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&hup_lock);
4984*7c478bd9Sstevel@tonic-gate 		hup_state |= HUP_SUSP_LOGMSG_REQD;
4985*7c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&hup_lock);
4986*7c478bd9Sstevel@tonic-gate 
4987*7c478bd9Sstevel@tonic-gate 		for (loop = 0; loop < LOOP_MAX; loop++) {
4988*7c478bd9Sstevel@tonic-gate 			if (hup_state & HUP_LOGMSG_SUSPENDED)
4989*7c478bd9Sstevel@tonic-gate 				break;
4990*7c478bd9Sstevel@tonic-gate 			(void) sleep(1);
4991*7c478bd9Sstevel@tonic-gate 		}
4992*7c478bd9Sstevel@tonic-gate 		if ((hup_state & HUP_LOGMSG_SUSPENDED) == 0) {
4993*7c478bd9Sstevel@tonic-gate 			if (Debug) {
4994*7c478bd9Sstevel@tonic-gate 				tim = time(NULL);
4995*7c478bd9Sstevel@tonic-gate 				DPRINT2(3, "reconfigure(%u): %.15s: logmsg()"
4996*7c478bd9Sstevel@tonic-gate 					" does not stop. give up\n",
4997*7c478bd9Sstevel@tonic-gate 					mythreadno, ctime_r(&tim, cbuf)+4);
4998*7c478bd9Sstevel@tonic-gate 			}
4999*7c478bd9Sstevel@tonic-gate 			logerror("could not suspend logmsg - fatal");
5000*7c478bd9Sstevel@tonic-gate 			goto thread_stuck;
5001*7c478bd9Sstevel@tonic-gate 		}
5002*7c478bd9Sstevel@tonic-gate 	}
5003*7c478bd9Sstevel@tonic-gate 
5004*7c478bd9Sstevel@tonic-gate 	if (Debug) {
5005*7c478bd9Sstevel@tonic-gate 		tim = time(NULL);
5006*7c478bd9Sstevel@tonic-gate 		DPRINT2(3, "reconfigure(%u): %.15s: logmsg() suspended\n",
5007*7c478bd9Sstevel@tonic-gate 			mythreadno, ctime_r(&tim, cbuf)+4);
5008*7c478bd9Sstevel@tonic-gate 	}
5009*7c478bd9Sstevel@tonic-gate 
5010*7c478bd9Sstevel@tonic-gate 	/*
5011*7c478bd9Sstevel@tonic-gate 	 * Will wait for LOOP_MAX secs with watching queue lengths for the
5012*7c478bd9Sstevel@tonic-gate 	 * each logger threads. If they have backlogs, and no change in the
5013*7c478bd9Sstevel@tonic-gate 	 * length of queue found in 30 seconds, those will be counted as
5014*7c478bd9Sstevel@tonic-gate 	 * "really stuck".
5015*7c478bd9Sstevel@tonic-gate 	 * If all running logger threads become "really stuck" state, there
5016*7c478bd9Sstevel@tonic-gate 	 * should be no worth waiting for them to quit.
5017*7c478bd9Sstevel@tonic-gate 	 * In that case, we will go ahead and close out file descriptors to
5018*7c478bd9Sstevel@tonic-gate 	 * have them pull out from hanging system call, and give them a last
5019*7c478bd9Sstevel@tonic-gate 	 * chance(LOOP_INTERVAL sec) to quit.
5020*7c478bd9Sstevel@tonic-gate 	 */
5021*7c478bd9Sstevel@tonic-gate 
5022*7c478bd9Sstevel@tonic-gate 	if (Debug) {
5023*7c478bd9Sstevel@tonic-gate 		tim = time(NULL);
5024*7c478bd9Sstevel@tonic-gate 		DPRINT2(3, "reconfigure(%u): %.15s: awaiting logit() to be"
5025*7c478bd9Sstevel@tonic-gate 			" shutdown\n", mythreadno, ctime_r(&tim, cbuf)+4);
5026*7c478bd9Sstevel@tonic-gate 	}
5027*7c478bd9Sstevel@tonic-gate 
5028*7c478bd9Sstevel@tonic-gate 	cnt = 0;
5029*7c478bd9Sstevel@tonic-gate 	really_stuck = 0;
5030*7c478bd9Sstevel@tonic-gate 	while (cnt < (LOOP_MAX/LOOP_INTERVAL) &&
5031*7c478bd9Sstevel@tonic-gate 		conf_threads > really_stuck) {
5032*7c478bd9Sstevel@tonic-gate 
5033*7c478bd9Sstevel@tonic-gate 		/* save initial queue count */
5034*7c478bd9Sstevel@tonic-gate 		for (f = Files; f < &Files[nlogs]; f++) {
5035*7c478bd9Sstevel@tonic-gate 			f->f_prev_queue_count = (f->f_type == F_UNUSED) ?
5036*7c478bd9Sstevel@tonic-gate 				-1 : f->f_queue_count;
5037*7c478bd9Sstevel@tonic-gate 		}
5038*7c478bd9Sstevel@tonic-gate 
5039*7c478bd9Sstevel@tonic-gate 		for (loop = 0; loop < LOOP_INTERVAL; loop++) {
5040*7c478bd9Sstevel@tonic-gate 			if (conf_threads == 0)
5041*7c478bd9Sstevel@tonic-gate 				break;
5042*7c478bd9Sstevel@tonic-gate 			(void) sleep(1);
5043*7c478bd9Sstevel@tonic-gate 		}
5044*7c478bd9Sstevel@tonic-gate 
5045*7c478bd9Sstevel@tonic-gate 		if (conf_threads == 0)
5046*7c478bd9Sstevel@tonic-gate 			break;
5047*7c478bd9Sstevel@tonic-gate 
5048*7c478bd9Sstevel@tonic-gate 		if (Debug) {
5049*7c478bd9Sstevel@tonic-gate 			tim = time(NULL);
5050*7c478bd9Sstevel@tonic-gate 			DPRINT3(3, "reconfigure(%u): %.15s: "
5051*7c478bd9Sstevel@tonic-gate 				"%d threads are still alive.\n",
5052*7c478bd9Sstevel@tonic-gate 				mythreadno, ctime_r(&tim, cbuf)+4,
5053*7c478bd9Sstevel@tonic-gate 				conf_threads);
5054*7c478bd9Sstevel@tonic-gate 		}
5055*7c478bd9Sstevel@tonic-gate 
5056*7c478bd9Sstevel@tonic-gate 		really_stuck = 0;
5057*7c478bd9Sstevel@tonic-gate 		for (f = Files; f < &Files[nlogs]; f++) {
5058*7c478bd9Sstevel@tonic-gate 			if (f->f_type == F_UNUSED) {
5059*7c478bd9Sstevel@tonic-gate 				f->f_prev_queue_count = -1;
5060*7c478bd9Sstevel@tonic-gate 				continue;
5061*7c478bd9Sstevel@tonic-gate 			}
5062*7c478bd9Sstevel@tonic-gate 			if (f->f_prev_queue_count == f->f_queue_count) {
5063*7c478bd9Sstevel@tonic-gate 				really_stuck++;
5064*7c478bd9Sstevel@tonic-gate 				f->f_prev_queue_count = 1;
5065*7c478bd9Sstevel@tonic-gate 				DPRINT2(3, "reconfigure(%u): "
5066*7c478bd9Sstevel@tonic-gate 					"tid=%d is really stuck.\n",
5067*7c478bd9Sstevel@tonic-gate 					mythreadno, f->f_thread);
5068*7c478bd9Sstevel@tonic-gate 			} else {
5069*7c478bd9Sstevel@tonic-gate 				f->f_prev_queue_count = 0;
5070*7c478bd9Sstevel@tonic-gate 				DPRINT2(3, "reconfigure(%u): "
5071*7c478bd9Sstevel@tonic-gate 					"tid=%d is still active.\n",
5072*7c478bd9Sstevel@tonic-gate 					mythreadno, f->f_thread);
5073*7c478bd9Sstevel@tonic-gate 			}
5074*7c478bd9Sstevel@tonic-gate 		}
5075*7c478bd9Sstevel@tonic-gate 		/*
5076*7c478bd9Sstevel@tonic-gate 		 * Here we have one of following values in the
5077*7c478bd9Sstevel@tonic-gate 		 * f_prev_queue_count:
5078*7c478bd9Sstevel@tonic-gate 		 *  0: logger thread is still actively working.
5079*7c478bd9Sstevel@tonic-gate 		 *  1: logger thread is really stuck.
5080*7c478bd9Sstevel@tonic-gate 		 * -1: logger thread has already died.
5081*7c478bd9Sstevel@tonic-gate 		 */
5082*7c478bd9Sstevel@tonic-gate 
5083*7c478bd9Sstevel@tonic-gate 		cnt++;
5084*7c478bd9Sstevel@tonic-gate 	}
5085*7c478bd9Sstevel@tonic-gate 
5086*7c478bd9Sstevel@tonic-gate 	if (Debug) {
5087*7c478bd9Sstevel@tonic-gate 		tim = time(NULL);
5088*7c478bd9Sstevel@tonic-gate 		DPRINT2(3, "reconfigure(%u): %.15s:"
5089*7c478bd9Sstevel@tonic-gate 			" complete awaiting logit()\n",
5090*7c478bd9Sstevel@tonic-gate 			mythreadno, ctime_r(&tim, cbuf)+4);
5091*7c478bd9Sstevel@tonic-gate 		DPRINT3(3, "reconfigure(%u): %d threads alive."
5092*7c478bd9Sstevel@tonic-gate 			" %d threads stuck\n",
5093*7c478bd9Sstevel@tonic-gate 			mythreadno, conf_threads, really_stuck);
5094*7c478bd9Sstevel@tonic-gate 	}
5095*7c478bd9Sstevel@tonic-gate 
5096*7c478bd9Sstevel@tonic-gate 	/*
5097*7c478bd9Sstevel@tonic-gate 	 * Still running? If so, mark it as UNUSED, and close
5098*7c478bd9Sstevel@tonic-gate 	 * the fd so that logger threads can bail out from the loop.
5099*7c478bd9Sstevel@tonic-gate 	 */
5100*7c478bd9Sstevel@tonic-gate 	drops = 0;
5101*7c478bd9Sstevel@tonic-gate 	if (conf_threads) {
5102*7c478bd9Sstevel@tonic-gate 		for (f = Files; f < &Files[nlogs]; f++) {
5103*7c478bd9Sstevel@tonic-gate 			if (f->f_type == F_CONSOLE &&
5104*7c478bd9Sstevel@tonic-gate 				f->f_prev_queue_count == 1) {
5105*7c478bd9Sstevel@tonic-gate 				/* console is really stuck */
5106*7c478bd9Sstevel@tonic-gate 				console_stuck = 1;
5107*7c478bd9Sstevel@tonic-gate 			}
5108*7c478bd9Sstevel@tonic-gate 			if (f->f_type == F_USERS || f->f_type == F_WALL ||
5109*7c478bd9Sstevel@tonic-gate 				f->f_type == F_UNUSED)
5110*7c478bd9Sstevel@tonic-gate 				continue;
5111*7c478bd9Sstevel@tonic-gate 			cnt = f->f_queue_count;
5112*7c478bd9Sstevel@tonic-gate 			drops += (cnt > 0) ? cnt - 1: 0;
5113*7c478bd9Sstevel@tonic-gate 			f->f_type = F_UNUSED;
5114*7c478bd9Sstevel@tonic-gate 
5115*7c478bd9Sstevel@tonic-gate 			if (f->f_orig_type == F_FORW)
5116*7c478bd9Sstevel@tonic-gate 				t_close(f->f_file);
5117*7c478bd9Sstevel@tonic-gate 			else
5118*7c478bd9Sstevel@tonic-gate 				close(f->f_file);
5119*7c478bd9Sstevel@tonic-gate 		}
5120*7c478bd9Sstevel@tonic-gate 
5121*7c478bd9Sstevel@tonic-gate 		if (Debug) {
5122*7c478bd9Sstevel@tonic-gate 			tim = time(NULL);
5123*7c478bd9Sstevel@tonic-gate 			DPRINT1(3, "reconfigure(%u): terminating logit()\n",
5124*7c478bd9Sstevel@tonic-gate 				mythreadno);
5125*7c478bd9Sstevel@tonic-gate 		}
5126*7c478bd9Sstevel@tonic-gate 
5127*7c478bd9Sstevel@tonic-gate 		/* last chance to exit */
5128*7c478bd9Sstevel@tonic-gate 		for (loop = 0; loop < LOOP_MAX; loop++) {
5129*7c478bd9Sstevel@tonic-gate 			if (conf_threads == 0)
5130*7c478bd9Sstevel@tonic-gate 				break;
5131*7c478bd9Sstevel@tonic-gate 			(void) sleep(1);
5132*7c478bd9Sstevel@tonic-gate 		}
5133*7c478bd9Sstevel@tonic-gate 
5134*7c478bd9Sstevel@tonic-gate 		if (Debug) {
5135*7c478bd9Sstevel@tonic-gate 			tim = time(NULL);
5136*7c478bd9Sstevel@tonic-gate 			DPRINT3(3, "reconfigure(%u): %.15s: %d alive\n",
5137*7c478bd9Sstevel@tonic-gate 				mythreadno, ctime_r(&tim, cbuf)+4,
5138*7c478bd9Sstevel@tonic-gate 				conf_threads);
5139*7c478bd9Sstevel@tonic-gate 		}
5140*7c478bd9Sstevel@tonic-gate 	}
5141*7c478bd9Sstevel@tonic-gate 
5142*7c478bd9Sstevel@tonic-gate 	if (conf_threads == 0 && drops) {
5143*7c478bd9Sstevel@tonic-gate 		errno = 0;
5144*7c478bd9Sstevel@tonic-gate 		logerror("Could not completely output pending messages"
5145*7c478bd9Sstevel@tonic-gate 			" while preparing re-configuration");
5146*7c478bd9Sstevel@tonic-gate 		logerror("discarded %d messages and restart configuration.",
5147*7c478bd9Sstevel@tonic-gate 			drops);
5148*7c478bd9Sstevel@tonic-gate 		if (Debug) {
5149*7c478bd9Sstevel@tonic-gate 			tim = time(NULL);
5150*7c478bd9Sstevel@tonic-gate 			DPRINT3(3, "reconfigure(%u): %.15s: "
5151*7c478bd9Sstevel@tonic-gate 				"discarded %d messages\n",
5152*7c478bd9Sstevel@tonic-gate 				mythreadno, ctime_r(&tim, cbuf)+4, drops);
5153*7c478bd9Sstevel@tonic-gate 		}
5154*7c478bd9Sstevel@tonic-gate 	}
5155*7c478bd9Sstevel@tonic-gate 
5156*7c478bd9Sstevel@tonic-gate 	/*
5157*7c478bd9Sstevel@tonic-gate 	 * If all threads still haven't exited
5158*7c478bd9Sstevel@tonic-gate 	 * something is stuck or hosed. We just
5159*7c478bd9Sstevel@tonic-gate 	 * have no option but to exit.
5160*7c478bd9Sstevel@tonic-gate 	 */
5161*7c478bd9Sstevel@tonic-gate 	if (conf_threads) {
5162*7c478bd9Sstevel@tonic-gate thread_stuck:
5163*7c478bd9Sstevel@tonic-gate 		if (Debug) {
5164*7c478bd9Sstevel@tonic-gate 			tim = time(NULL);
5165*7c478bd9Sstevel@tonic-gate 			DPRINT2(3, "reconfigure(%u): %.15s: really stuck\n",
5166*7c478bd9Sstevel@tonic-gate 				mythreadno, ctime_r(&tim, cbuf)+4);
5167*7c478bd9Sstevel@tonic-gate 		}
5168*7c478bd9Sstevel@tonic-gate 
5169*7c478bd9Sstevel@tonic-gate 		shutdown_input();
5170*7c478bd9Sstevel@tonic-gate 		delete_doorfiles();
5171*7c478bd9Sstevel@tonic-gate 		uname(&up);
5172*7c478bd9Sstevel@tonic-gate 
5173*7c478bd9Sstevel@tonic-gate 		(void) sprintf(buf,
5174*7c478bd9Sstevel@tonic-gate 			"syslogd(%s): some logger thread(s) "
5175*7c478bd9Sstevel@tonic-gate 			"are stuck%s; syslogd is shutting down.",
5176*7c478bd9Sstevel@tonic-gate 			up.nodename,
5177*7c478bd9Sstevel@tonic-gate 			console_stuck ? " (including the console)" : "");
5178*7c478bd9Sstevel@tonic-gate 
5179*7c478bd9Sstevel@tonic-gate 		if (console_stuck) {
5180*7c478bd9Sstevel@tonic-gate 			FILE *m = popen(MAILCMD, "w");
5181*7c478bd9Sstevel@tonic-gate 
5182*7c478bd9Sstevel@tonic-gate 			if (m != NULL) {
5183*7c478bd9Sstevel@tonic-gate 				fprintf(m, "%s\n", buf);
5184*7c478bd9Sstevel@tonic-gate 				pclose(m);
5185*7c478bd9Sstevel@tonic-gate 			}
5186*7c478bd9Sstevel@tonic-gate 		}
5187*7c478bd9Sstevel@tonic-gate 
5188*7c478bd9Sstevel@tonic-gate 		disable_errorlog();
5189*7c478bd9Sstevel@tonic-gate 		logerror(buf);
5190*7c478bd9Sstevel@tonic-gate 		exit(1);
5191*7c478bd9Sstevel@tonic-gate 	}
5192*7c478bd9Sstevel@tonic-gate 
5193*7c478bd9Sstevel@tonic-gate 	/* Free up some resources */
5194*7c478bd9Sstevel@tonic-gate 	if (Files != (struct filed *)&fallback) {
5195*7c478bd9Sstevel@tonic-gate 		for (f = Files; f < &Files[nlogs]; f++) {
5196*7c478bd9Sstevel@tonic-gate 			(void) pthread_join(f->f_thread, NULL);
5197*7c478bd9Sstevel@tonic-gate 			filed_destroy(f);
5198*7c478bd9Sstevel@tonic-gate 		}
5199*7c478bd9Sstevel@tonic-gate 		free(Files);
5200*7c478bd9Sstevel@tonic-gate 	}
5201*7c478bd9Sstevel@tonic-gate 
5202*7c478bd9Sstevel@tonic-gate 	dealloc_stacks(nlogs);
5203*7c478bd9Sstevel@tonic-gate 
5204*7c478bd9Sstevel@tonic-gate 	if (Debug) {
5205*7c478bd9Sstevel@tonic-gate 		tim = time(NULL);
5206*7c478bd9Sstevel@tonic-gate 		DPRINT2(3, "reconfigure(%u): %.15s: cleanup complete\n",
5207*7c478bd9Sstevel@tonic-gate 			mythreadno, ctime_r(&tim, cbuf)+4);
5208*7c478bd9Sstevel@tonic-gate 	}
5209*7c478bd9Sstevel@tonic-gate 
5210*7c478bd9Sstevel@tonic-gate 	hnc_init(1);	/* purge hostname cache */
5211*7c478bd9Sstevel@tonic-gate 	conf_init();	/* start reconfigure */
5212*7c478bd9Sstevel@tonic-gate 
5213*7c478bd9Sstevel@tonic-gate out:;
5214*7c478bd9Sstevel@tonic-gate 	/* Now should be ready to dispatch error messages from syslogd. */
5215*7c478bd9Sstevel@tonic-gate 	enable_errorlog();
5216*7c478bd9Sstevel@tonic-gate 
5217*7c478bd9Sstevel@tonic-gate 	/* Wake up the log thread */
5218*7c478bd9Sstevel@tonic-gate 
5219*7c478bd9Sstevel@tonic-gate 	if (Debug) {
5220*7c478bd9Sstevel@tonic-gate 		tim = time(NULL);
5221*7c478bd9Sstevel@tonic-gate 		DPRINT2(3, "reconfigure(%u): %.15s: resuming logmsg()\n",
5222*7c478bd9Sstevel@tonic-gate 			mythreadno, ctime_r(&tim, cbuf)+4);
5223*7c478bd9Sstevel@tonic-gate 	}
5224*7c478bd9Sstevel@tonic-gate 
5225*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&hup_lock);
5226*7c478bd9Sstevel@tonic-gate 	hup_state = HUP_COMPLETED;
5227*7c478bd9Sstevel@tonic-gate 	(void) pthread_cond_signal(&hup_done);
5228*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&hup_lock);
5229*7c478bd9Sstevel@tonic-gate }
5230*7c478bd9Sstevel@tonic-gate 
5231*7c478bd9Sstevel@tonic-gate /*
5232*7c478bd9Sstevel@tonic-gate  * The following function implements simple hostname cache mechanism.
5233*7c478bd9Sstevel@tonic-gate  * Host name cache consists of single linked list structure which contains
5234*7c478bd9Sstevel@tonic-gate  * host_list_t and netbuf pair. All cache entries(hnc_size) are allocated
5235*7c478bd9Sstevel@tonic-gate  * initially and linked to "hnc_freeq". If cache register request comes,
5236*7c478bd9Sstevel@tonic-gate  * then one element will be pulled from freeq, and will be linked to
5237*7c478bd9Sstevel@tonic-gate  * "hnc_active" with given netbuf, host_list_t and expiration time. All valid
5238*7c478bd9Sstevel@tonic-gate  * cahces are linked from hnc_active. If the cache element has run
5239*7c478bd9Sstevel@tonic-gate  * out, most unused element will be re-used for the new request.
5240*7c478bd9Sstevel@tonic-gate  *
5241*7c478bd9Sstevel@tonic-gate  * hnc_init():
5242*7c478bd9Sstevel@tonic-gate  * 	allocate and initialize the cache. If reinit is set,
5243*7c478bd9Sstevel@tonic-gate  *	invalidate all cache entries.
5244*7c478bd9Sstevel@tonic-gate  * hnc_look():
5245*7c478bd9Sstevel@tonic-gate  *	lookup the cache entries by following single linked list
5246*7c478bd9Sstevel@tonic-gate  *	from hnc_active. If cached entry was found, it will be
5247*7c478bd9Sstevel@tonic-gate  *	put in the head of the list, and return. While going through
5248*7c478bd9Sstevel@tonic-gate  *	the entries, an entry which has already expired will be invalidated.
5249*7c478bd9Sstevel@tonic-gate  * hnc_register():
5250*7c478bd9Sstevel@tonic-gate  *	take one element from freeq, and put the new entry at the top
5251*7c478bd9Sstevel@tonic-gate  *	of hnc_active.
5252*7c478bd9Sstevel@tonic-gate  * hnc_unreg():
5253*7c478bd9Sstevel@tonic-gate  *	invalidate the cache. i.e unlink from hnc_active, and linked the
5254*7c478bd9Sstevel@tonic-gate  *	element to freeq.
5255*7c478bd9Sstevel@tonic-gate  */
5256*7c478bd9Sstevel@tonic-gate 
5257*7c478bd9Sstevel@tonic-gate static void
5258*7c478bd9Sstevel@tonic-gate hnc_init(int reinit)
5259*7c478bd9Sstevel@tonic-gate {
5260*7c478bd9Sstevel@tonic-gate 	struct hostname_cache **hpp;
5261*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
5262*7c478bd9Sstevel@tonic-gate 
5263*7c478bd9Sstevel@tonic-gate 	if (Debug) {
5264*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
5265*7c478bd9Sstevel@tonic-gate 	}
5266*7c478bd9Sstevel@tonic-gate 
5267*7c478bd9Sstevel@tonic-gate 	if (reinit) {
5268*7c478bd9Sstevel@tonic-gate 		pthread_mutex_lock(&hnc_mutex);
5269*7c478bd9Sstevel@tonic-gate 
5270*7c478bd9Sstevel@tonic-gate 		for (hpp = &hnc_active; *hpp != NULL; ) {
5271*7c478bd9Sstevel@tonic-gate 			hnc_unreg(hpp);
5272*7c478bd9Sstevel@tonic-gate 		}
5273*7c478bd9Sstevel@tonic-gate 
5274*7c478bd9Sstevel@tonic-gate 		pthread_mutex_unlock(&hnc_mutex);
5275*7c478bd9Sstevel@tonic-gate 		DPRINT1(2, "hnc_init(%u): hostname cache re-configured\n",
5276*7c478bd9Sstevel@tonic-gate 			mythreadno);
5277*7c478bd9Sstevel@tonic-gate 	} else {
5278*7c478bd9Sstevel@tonic-gate 		int i;
5279*7c478bd9Sstevel@tonic-gate 
5280*7c478bd9Sstevel@tonic-gate 		hnc_cache = malloc(hnc_size * sizeof (struct hostname_cache));
5281*7c478bd9Sstevel@tonic-gate 
5282*7c478bd9Sstevel@tonic-gate 		if (hnc_cache == NULL) {
5283*7c478bd9Sstevel@tonic-gate 			MALLOC_FAIL("hostname cache");
5284*7c478bd9Sstevel@tonic-gate 			logerror("hostname cache disabled");
5285*7c478bd9Sstevel@tonic-gate 			return;
5286*7c478bd9Sstevel@tonic-gate 		}
5287*7c478bd9Sstevel@tonic-gate 
5288*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < hnc_size; i++) {
5289*7c478bd9Sstevel@tonic-gate 			hnc_cache[i].h = NULL;
5290*7c478bd9Sstevel@tonic-gate 			hnc_cache[i].next = hnc_cache + i + 1;
5291*7c478bd9Sstevel@tonic-gate 		}
5292*7c478bd9Sstevel@tonic-gate 
5293*7c478bd9Sstevel@tonic-gate 		hnc_cache[hnc_size - 1].next = NULL;
5294*7c478bd9Sstevel@tonic-gate 		hnc_freeq = hnc_cache;
5295*7c478bd9Sstevel@tonic-gate 		hnc_active = NULL;
5296*7c478bd9Sstevel@tonic-gate 
5297*7c478bd9Sstevel@tonic-gate 		DPRINT3(1, "hnc_init(%u): hostname cache configured %d entry"
5298*7c478bd9Sstevel@tonic-gate 			" ttl:%d\n", mythreadno, hnc_size, hnc_ttl);
5299*7c478bd9Sstevel@tonic-gate 	}
5300*7c478bd9Sstevel@tonic-gate }
5301*7c478bd9Sstevel@tonic-gate 
5302*7c478bd9Sstevel@tonic-gate static host_list_t *
5303*7c478bd9Sstevel@tonic-gate hnc_lookup(struct netbuf *nbp, struct netconfig *ncp)
5304*7c478bd9Sstevel@tonic-gate {
5305*7c478bd9Sstevel@tonic-gate 	struct hostname_cache **hpp, *hp;
5306*7c478bd9Sstevel@tonic-gate 	time_t now;
5307*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
5308*7c478bd9Sstevel@tonic-gate 
5309*7c478bd9Sstevel@tonic-gate 	if (Debug) {
5310*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
5311*7c478bd9Sstevel@tonic-gate 	}
5312*7c478bd9Sstevel@tonic-gate 
5313*7c478bd9Sstevel@tonic-gate 	if (hnc_cache == NULL) {
5314*7c478bd9Sstevel@tonic-gate 		return (NULL);
5315*7c478bd9Sstevel@tonic-gate 	}
5316*7c478bd9Sstevel@tonic-gate 
5317*7c478bd9Sstevel@tonic-gate 	pthread_mutex_lock(&hnc_mutex);
5318*7c478bd9Sstevel@tonic-gate 	now = time(0);
5319*7c478bd9Sstevel@tonic-gate 
5320*7c478bd9Sstevel@tonic-gate 	for (hpp = &hnc_active; (hp = *hpp) != NULL; ) {
5321*7c478bd9Sstevel@tonic-gate 		DPRINT4(10, "hnc_lookup(%u): check %p on %p for %s\n",
5322*7c478bd9Sstevel@tonic-gate 			mythreadno, hp->h, hp, hp->h->hl_hosts[0]);
5323*7c478bd9Sstevel@tonic-gate 
5324*7c478bd9Sstevel@tonic-gate 		if (hp->expire < now) {
5325*7c478bd9Sstevel@tonic-gate 			DPRINT2(9, "hnc_lookup(%u): purge %p\n",
5326*7c478bd9Sstevel@tonic-gate 				mythreadno, hp);
5327*7c478bd9Sstevel@tonic-gate 			/* Note: hnc_unreg changes *hpp */
5328*7c478bd9Sstevel@tonic-gate 			hnc_unreg(hpp);
5329*7c478bd9Sstevel@tonic-gate 			continue;
5330*7c478bd9Sstevel@tonic-gate 		}
5331*7c478bd9Sstevel@tonic-gate 
5332*7c478bd9Sstevel@tonic-gate 		if (ncp == hp->ncp && same_addr(&hp->addr, nbp)) {
5333*7c478bd9Sstevel@tonic-gate 			/*
5334*7c478bd9Sstevel@tonic-gate 			 * found!
5335*7c478bd9Sstevel@tonic-gate 			 * Put the entry at the top.
5336*7c478bd9Sstevel@tonic-gate 			 */
5337*7c478bd9Sstevel@tonic-gate 
5338*7c478bd9Sstevel@tonic-gate 			if (hp != hnc_active) {
5339*7c478bd9Sstevel@tonic-gate 				/* unlink from active list */
5340*7c478bd9Sstevel@tonic-gate 				*hpp = (*hpp)->next;
5341*7c478bd9Sstevel@tonic-gate 				/* push it onto the top */
5342*7c478bd9Sstevel@tonic-gate 				hp->next = hnc_active;
5343*7c478bd9Sstevel@tonic-gate 				hnc_active = hp;
5344*7c478bd9Sstevel@tonic-gate 			}
5345*7c478bd9Sstevel@tonic-gate 
5346*7c478bd9Sstevel@tonic-gate 			pthread_mutex_lock(&hp->h->hl_mutex);
5347*7c478bd9Sstevel@tonic-gate 			hp->h->hl_refcnt++;
5348*7c478bd9Sstevel@tonic-gate 			pthread_mutex_unlock(&hp->h->hl_mutex);
5349*7c478bd9Sstevel@tonic-gate 
5350*7c478bd9Sstevel@tonic-gate 			DPRINT4(9, "hnc_lookup(%u): found %p on %p for %s\n",
5351*7c478bd9Sstevel@tonic-gate 				mythreadno, hp->h, hp, hp->h->hl_hosts[0]);
5352*7c478bd9Sstevel@tonic-gate 
5353*7c478bd9Sstevel@tonic-gate 			pthread_mutex_unlock(&hnc_mutex);
5354*7c478bd9Sstevel@tonic-gate 			return (hp->h);
5355*7c478bd9Sstevel@tonic-gate 		}
5356*7c478bd9Sstevel@tonic-gate 
5357*7c478bd9Sstevel@tonic-gate 		hpp = &hp->next;
5358*7c478bd9Sstevel@tonic-gate 	}
5359*7c478bd9Sstevel@tonic-gate 
5360*7c478bd9Sstevel@tonic-gate 	pthread_mutex_unlock(&hnc_mutex);
5361*7c478bd9Sstevel@tonic-gate 	return (NULL);
5362*7c478bd9Sstevel@tonic-gate }
5363*7c478bd9Sstevel@tonic-gate 
5364*7c478bd9Sstevel@tonic-gate static void
5365*7c478bd9Sstevel@tonic-gate hnc_register(struct netbuf *nbp, struct netconfig *ncp, host_list_t *h)
5366*7c478bd9Sstevel@tonic-gate {
5367*7c478bd9Sstevel@tonic-gate 	struct hostname_cache **hpp, **tailp, *hp;
5368*7c478bd9Sstevel@tonic-gate 	void *addrbuf;
5369*7c478bd9Sstevel@tonic-gate 	time_t now;
5370*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
5371*7c478bd9Sstevel@tonic-gate 
5372*7c478bd9Sstevel@tonic-gate 	if (Debug) {
5373*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
5374*7c478bd9Sstevel@tonic-gate 	}
5375*7c478bd9Sstevel@tonic-gate 
5376*7c478bd9Sstevel@tonic-gate 	if (hnc_cache == NULL) {
5377*7c478bd9Sstevel@tonic-gate 		return;
5378*7c478bd9Sstevel@tonic-gate 	}
5379*7c478bd9Sstevel@tonic-gate 
5380*7c478bd9Sstevel@tonic-gate 	if ((addrbuf = malloc(nbp->len)) == NULL) {
5381*7c478bd9Sstevel@tonic-gate 		MALLOC_FAIL("pushing hostname cache");
5382*7c478bd9Sstevel@tonic-gate 		return;
5383*7c478bd9Sstevel@tonic-gate 	}
5384*7c478bd9Sstevel@tonic-gate 
5385*7c478bd9Sstevel@tonic-gate 	pthread_mutex_lock(&hnc_mutex);
5386*7c478bd9Sstevel@tonic-gate 
5387*7c478bd9Sstevel@tonic-gate 	if (hnc_freeq == NULL) {
5388*7c478bd9Sstevel@tonic-gate 		DPRINT1(9, "hnc_register(%u): freeq empty\n", mythreadno);
5389*7c478bd9Sstevel@tonic-gate 		now = time(NULL);
5390*7c478bd9Sstevel@tonic-gate 		/*
5391*7c478bd9Sstevel@tonic-gate 		 * first go through active list, and discard the
5392*7c478bd9Sstevel@tonic-gate 		 * caches which has been invalid.
5393*7c478bd9Sstevel@tonic-gate 		 */
5394*7c478bd9Sstevel@tonic-gate 		for (hpp = &hnc_active; (hp = *hpp) != NULL; ) {
5395*7c478bd9Sstevel@tonic-gate 			tailp = hpp;
5396*7c478bd9Sstevel@tonic-gate 
5397*7c478bd9Sstevel@tonic-gate 			if (hp->expire < now) {
5398*7c478bd9Sstevel@tonic-gate 				DPRINT2(9, "hnc_register(%u): discard %p\n",
5399*7c478bd9Sstevel@tonic-gate 					mythreadno, hp);
5400*7c478bd9Sstevel@tonic-gate 				hnc_unreg(hpp);
5401*7c478bd9Sstevel@tonic-gate 			} else {
5402*7c478bd9Sstevel@tonic-gate 				hpp = &hp->next;
5403*7c478bd9Sstevel@tonic-gate 			}
5404*7c478bd9Sstevel@tonic-gate 		}
5405*7c478bd9Sstevel@tonic-gate 
5406*7c478bd9Sstevel@tonic-gate 		if (hnc_freeq == NULL) {
5407*7c478bd9Sstevel@tonic-gate 			DPRINT2(9, "hnc_register(%u): stealing %p\n",
5408*7c478bd9Sstevel@tonic-gate 					mythreadno, *tailp);
5409*7c478bd9Sstevel@tonic-gate 			/*
5410*7c478bd9Sstevel@tonic-gate 			 * If still no inactive cache, then steal the least
5411*7c478bd9Sstevel@tonic-gate 			 * active element.
5412*7c478bd9Sstevel@tonic-gate 			 */
5413*7c478bd9Sstevel@tonic-gate 			hnc_unreg(tailp);
5414*7c478bd9Sstevel@tonic-gate 		}
5415*7c478bd9Sstevel@tonic-gate 	}
5416*7c478bd9Sstevel@tonic-gate 
5417*7c478bd9Sstevel@tonic-gate 	hp = hnc_freeq;
5418*7c478bd9Sstevel@tonic-gate 	hnc_freeq = hnc_freeq->next;
5419*7c478bd9Sstevel@tonic-gate 
5420*7c478bd9Sstevel@tonic-gate 	/* push it on the top */
5421*7c478bd9Sstevel@tonic-gate 	hp->next = hnc_active;
5422*7c478bd9Sstevel@tonic-gate 	hnc_active = hp;
5423*7c478bd9Sstevel@tonic-gate 
5424*7c478bd9Sstevel@tonic-gate 	(void) memcpy(addrbuf, nbp->buf, nbp->len);
5425*7c478bd9Sstevel@tonic-gate 	hp->addr.len = nbp->len;
5426*7c478bd9Sstevel@tonic-gate 	hp->addr.buf = addrbuf;
5427*7c478bd9Sstevel@tonic-gate 	hp->ncp = ncp;
5428*7c478bd9Sstevel@tonic-gate 	hp->h = h;
5429*7c478bd9Sstevel@tonic-gate 	hp->expire = time(NULL) + hnc_ttl;
5430*7c478bd9Sstevel@tonic-gate 
5431*7c478bd9Sstevel@tonic-gate 	/*
5432*7c478bd9Sstevel@tonic-gate 	 * As far as cache is valid, corresponding host_list must
5433*7c478bd9Sstevel@tonic-gate 	 * also be valid. Increments the refcnt to avoid freeing
5434*7c478bd9Sstevel@tonic-gate 	 * host_list.
5435*7c478bd9Sstevel@tonic-gate 	 */
5436*7c478bd9Sstevel@tonic-gate 	h->hl_refcnt++;
5437*7c478bd9Sstevel@tonic-gate 	DPRINT4(9, "hnc_register(%u): reg %p onto %p for %s\n",
5438*7c478bd9Sstevel@tonic-gate 			mythreadno, h, hp, hp->h->hl_hosts[0]);
5439*7c478bd9Sstevel@tonic-gate 	pthread_mutex_unlock(&hnc_mutex);
5440*7c478bd9Sstevel@tonic-gate }
5441*7c478bd9Sstevel@tonic-gate 
5442*7c478bd9Sstevel@tonic-gate static void
5443*7c478bd9Sstevel@tonic-gate hnc_unreg(struct hostname_cache **hpp)
5444*7c478bd9Sstevel@tonic-gate {
5445*7c478bd9Sstevel@tonic-gate 	struct hostname_cache *hp = *hpp;
5446*7c478bd9Sstevel@tonic-gate 	pthread_t mythreadno;
5447*7c478bd9Sstevel@tonic-gate 
5448*7c478bd9Sstevel@tonic-gate 	if (Debug) {
5449*7c478bd9Sstevel@tonic-gate 		mythreadno = pthread_self();
5450*7c478bd9Sstevel@tonic-gate 	}
5451*7c478bd9Sstevel@tonic-gate 
5452*7c478bd9Sstevel@tonic-gate 	DPRINT4(9, "hnc_unreg(%u): unreg %p on %p for %s\n",
5453*7c478bd9Sstevel@tonic-gate 			mythreadno, hp->h, hp, hp->h->hl_hosts[0]);
5454*7c478bd9Sstevel@tonic-gate 	free(hp->addr.buf);
5455*7c478bd9Sstevel@tonic-gate 	freehl(hp->h);
5456*7c478bd9Sstevel@tonic-gate 
5457*7c478bd9Sstevel@tonic-gate 	/* unlink from active list */
5458*7c478bd9Sstevel@tonic-gate 	*hpp = (*hpp)->next;
5459*7c478bd9Sstevel@tonic-gate 
5460*7c478bd9Sstevel@tonic-gate 	/* put in freeq */
5461*7c478bd9Sstevel@tonic-gate 	hp->next = hnc_freeq;
5462*7c478bd9Sstevel@tonic-gate 	hnc_freeq = hp;
5463*7c478bd9Sstevel@tonic-gate }
5464*7c478bd9Sstevel@tonic-gate 
5465*7c478bd9Sstevel@tonic-gate /*
5466*7c478bd9Sstevel@tonic-gate  * Once this is called, error messages through logerror() will go to
5467*7c478bd9Sstevel@tonic-gate  * the console immediately. Also, messages are queued into the tmpq
5468*7c478bd9Sstevel@tonic-gate  * to be able to later put them into inputq.
5469*7c478bd9Sstevel@tonic-gate  */
5470*7c478bd9Sstevel@tonic-gate static void
5471*7c478bd9Sstevel@tonic-gate disable_errorlog()
5472*7c478bd9Sstevel@tonic-gate {
5473*7c478bd9Sstevel@tonic-gate 	dataq_init(&tmpq);
5474*7c478bd9Sstevel@tonic-gate 
5475*7c478bd9Sstevel@tonic-gate 	pthread_mutex_lock(&logerror_lock);
5476*7c478bd9Sstevel@tonic-gate 	interrorlog = 0;
5477*7c478bd9Sstevel@tonic-gate 	pthread_mutex_unlock(&logerror_lock);
5478*7c478bd9Sstevel@tonic-gate }
5479*7c478bd9Sstevel@tonic-gate 
5480*7c478bd9Sstevel@tonic-gate /*
5481*7c478bd9Sstevel@tonic-gate  * Turn internal error messages to regular input stream.
5482*7c478bd9Sstevel@tonic-gate  * All pending messages are pulled and pushed into the regular
5483*7c478bd9Sstevel@tonic-gate  * input queue.
5484*7c478bd9Sstevel@tonic-gate  */
5485*7c478bd9Sstevel@tonic-gate static void
5486*7c478bd9Sstevel@tonic-gate enable_errorlog()
5487*7c478bd9Sstevel@tonic-gate {
5488*7c478bd9Sstevel@tonic-gate 	log_message_t *mp;
5489*7c478bd9Sstevel@tonic-gate 
5490*7c478bd9Sstevel@tonic-gate 	pthread_mutex_lock(&logerror_lock);
5491*7c478bd9Sstevel@tonic-gate 	interrorlog = 1;
5492*7c478bd9Sstevel@tonic-gate 	pthread_mutex_unlock(&logerror_lock);
5493*7c478bd9Sstevel@tonic-gate 
5494*7c478bd9Sstevel@tonic-gate 	/*
5495*7c478bd9Sstevel@tonic-gate 	 * push all the pending messages into inputq.
5496*7c478bd9Sstevel@tonic-gate 	 */
5497*7c478bd9Sstevel@tonic-gate 	while (dataq_dequeue(&tmpq, (void **)&mp, 1) == 0) {
5498*7c478bd9Sstevel@tonic-gate 		(void) dataq_enqueue(&inputq, mp);
5499*7c478bd9Sstevel@tonic-gate 	}
5500*7c478bd9Sstevel@tonic-gate 	dataq_destroy(&tmpq);
5501*7c478bd9Sstevel@tonic-gate }
5502