xref: /titanic_51/usr/src/cmd/consadm/consadm.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 2004 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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include "utils.h"
30*7c478bd9Sstevel@tonic-gate #include <locale.h>
31*7c478bd9Sstevel@tonic-gate #include <poll.h>
32*7c478bd9Sstevel@tonic-gate #include <setjmp.h>
33*7c478bd9Sstevel@tonic-gate #include <signal.h>
34*7c478bd9Sstevel@tonic-gate #include <strings.h>
35*7c478bd9Sstevel@tonic-gate #include <stropts.h>
36*7c478bd9Sstevel@tonic-gate #include <syslog.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/sysmsg_impl.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/termios.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate #define	CONSADM			"/usr/sbin/consadm"
45*7c478bd9Sstevel@tonic-gate #define	CONSADMD		"/usr/sbin/consadmd"
46*7c478bd9Sstevel@tonic-gate #define	CONSADMLOCK		"/tmp/CoNsAdM.lck"
47*7c478bd9Sstevel@tonic-gate #define	CONSDAEMON		"consadmd"
48*7c478bd9Sstevel@tonic-gate #define	MSGLOG			"/dev/msglog"
49*7c478bd9Sstevel@tonic-gate #define	CONSOLE			"/dev/console"
50*7c478bd9Sstevel@tonic-gate #define	WSCONS			"/dev/wscons"
51*7c478bd9Sstevel@tonic-gate #define	CONSCONFIG		"/etc/consadm.conf"
52*7c478bd9Sstevel@tonic-gate #define	SETCONSOLEPID		"/etc/consadm.pid"
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate #define	CONFIG			0
55*7c478bd9Sstevel@tonic-gate #define	UNCONFIG		1
56*7c478bd9Sstevel@tonic-gate #define	COMMENT			'#'
57*7c478bd9Sstevel@tonic-gate #define	NEWLINE			'\n'
58*7c478bd9Sstevel@tonic-gate #define	SPACE			' '
59*7c478bd9Sstevel@tonic-gate #define	TAB			'	'
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate #define	E_SUCCESS	0		/* Exit status for success */
62*7c478bd9Sstevel@tonic-gate #define	E_ERROR		1		/* Exit status for error */
63*7c478bd9Sstevel@tonic-gate #define	E_USAGE		2		/* Exit status for usage error */
64*7c478bd9Sstevel@tonic-gate #define	E_NO_CARRIER	3		/* Exit status for no carrier */
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate /* useful data structures for lock function */
67*7c478bd9Sstevel@tonic-gate static struct flock fl;
68*7c478bd9Sstevel@tonic-gate #define	LOCK_EX F_WRLCK
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate static char usage[] =
71*7c478bd9Sstevel@tonic-gate 	"Usage:	\n"
72*7c478bd9Sstevel@tonic-gate 	"\tconsadm [ -p ] [ -a device ... ]\n"
73*7c478bd9Sstevel@tonic-gate 	"\tconsadm [ -p ] [ -d device ... ]\n"
74*7c478bd9Sstevel@tonic-gate 	"\tconsadm [ -p ]\n";
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate /* data structures ... */
77*7c478bd9Sstevel@tonic-gate static char conshdr[] =
78*7c478bd9Sstevel@tonic-gate 	"#\n# consadm.conf\n#"
79*7c478bd9Sstevel@tonic-gate 	"# Configuration parameters for console message redirection.\n"
80*7c478bd9Sstevel@tonic-gate 	"# Do NOT edit this file by hand -- use consadm(1m) instead.\n"
81*7c478bd9Sstevel@tonic-gate 	"#\n";
82*7c478bd9Sstevel@tonic-gate const char *pname;		/* program name */
83*7c478bd9Sstevel@tonic-gate static sigjmp_buf deadline;
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate /* command line arguments */
86*7c478bd9Sstevel@tonic-gate static int display;
87*7c478bd9Sstevel@tonic-gate static int persist;
88*7c478bd9Sstevel@tonic-gate static int addflag;
89*7c478bd9Sstevel@tonic-gate static int deleteflag;
90*7c478bd9Sstevel@tonic-gate 
91*7c478bd9Sstevel@tonic-gate /* function headers */
92*7c478bd9Sstevel@tonic-gate static void setaux(char *);
93*7c478bd9Sstevel@tonic-gate static void unsetaux(char *);
94*7c478bd9Sstevel@tonic-gate static void getconsole(void);
95*7c478bd9Sstevel@tonic-gate static boolean_t has_carrier(int fd);
96*7c478bd9Sstevel@tonic-gate static boolean_t modem_support(int fd);
97*7c478bd9Sstevel@tonic-gate static void setfallback(char *argv[]);
98*7c478bd9Sstevel@tonic-gate static void removefallback(void);
99*7c478bd9Sstevel@tonic-gate static void fallbackdaemon(void);
100*7c478bd9Sstevel@tonic-gate static void persistlist(void);
101*7c478bd9Sstevel@tonic-gate static int verifyarg(char *, int);
102*7c478bd9Sstevel@tonic-gate static int safeopen(char *);
103*7c478bd9Sstevel@tonic-gate static void catch_term(void);
104*7c478bd9Sstevel@tonic-gate static void catch_alarm(void);
105*7c478bd9Sstevel@tonic-gate static void catch_hup(void);
106*7c478bd9Sstevel@tonic-gate static void cleanup_on_exit(void);
107*7c478bd9Sstevel@tonic-gate static void addtolist(char *);
108*7c478bd9Sstevel@tonic-gate static void removefromlist(char *);
109*7c478bd9Sstevel@tonic-gate static int pathcmp(char *, char *);
110*7c478bd9Sstevel@tonic-gate static int lckfunc(int, int);
111*7c478bd9Sstevel@tonic-gate typedef void (*sig_handler_t)();
112*7c478bd9Sstevel@tonic-gate static int getlock(void);
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate /*
115*7c478bd9Sstevel@tonic-gate  * In main, return codes carry the following meaning:
116*7c478bd9Sstevel@tonic-gate  * 0 - successful
117*7c478bd9Sstevel@tonic-gate  * 1 - error during the command execution
118*7c478bd9Sstevel@tonic-gate  */
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate int
121*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
122*7c478bd9Sstevel@tonic-gate {
123*7c478bd9Sstevel@tonic-gate 	int	index;
124*7c478bd9Sstevel@tonic-gate 	struct	sigaction sa;
125*7c478bd9Sstevel@tonic-gate 	int	c;
126*7c478bd9Sstevel@tonic-gate 	char	*p = strrchr(argv[0], '/');
127*7c478bd9Sstevel@tonic-gate 
128*7c478bd9Sstevel@tonic-gate 	if (p == NULL)
129*7c478bd9Sstevel@tonic-gate 		p = argv[0];
130*7c478bd9Sstevel@tonic-gate 	else
131*7c478bd9Sstevel@tonic-gate 		p++;
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate 	pname = p;
134*7c478bd9Sstevel@tonic-gate 
135*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
136*7c478bd9Sstevel@tonic-gate #if	!defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
137*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
138*7c478bd9Sstevel@tonic-gate #endif
139*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate 	if (getuid() != 0)
142*7c478bd9Sstevel@tonic-gate 		die(gettext("must be root to run this program\n"));
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate 	/*
145*7c478bd9Sstevel@tonic-gate 	 * Handle normal termination signals that may be received.
146*7c478bd9Sstevel@tonic-gate 	 */
147*7c478bd9Sstevel@tonic-gate 	sa.sa_handler = SIG_IGN;
148*7c478bd9Sstevel@tonic-gate 	sa.sa_flags = 0;
149*7c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&sa.sa_mask);
150*7c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGHUP, &sa, NULL);
151*7c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGINT, &sa, NULL);
152*7c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGQUIT, &sa, NULL);
153*7c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGTERM, &sa, NULL);
154*7c478bd9Sstevel@tonic-gate 
155*7c478bd9Sstevel@tonic-gate 	/*
156*7c478bd9Sstevel@tonic-gate 	 * To make sure persistent state gets removed.
157*7c478bd9Sstevel@tonic-gate 	 */
158*7c478bd9Sstevel@tonic-gate 	sa.sa_handler = cleanup_on_exit;
159*7c478bd9Sstevel@tonic-gate 	sa.sa_flags = 0;
160*7c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&sa.sa_mask);
161*7c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGSEGV, &sa, NULL);
162*7c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGILL, &sa, NULL);
163*7c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGABRT, &sa, NULL);
164*7c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGBUS, &sa, NULL);
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate 	if (strcmp(pname, CONSDAEMON) == 0) {
167*7c478bd9Sstevel@tonic-gate 		fallbackdaemon();
168*7c478bd9Sstevel@tonic-gate 		return (E_SUCCESS);
169*7c478bd9Sstevel@tonic-gate 	}
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate 	if (argc == 1)
172*7c478bd9Sstevel@tonic-gate 		display++;
173*7c478bd9Sstevel@tonic-gate 	else {
174*7c478bd9Sstevel@tonic-gate 		while ((c = getopt(argc, argv, "adp")) != EOF)  {
175*7c478bd9Sstevel@tonic-gate 			switch (c) {
176*7c478bd9Sstevel@tonic-gate 			case 'a':
177*7c478bd9Sstevel@tonic-gate 				addflag++;
178*7c478bd9Sstevel@tonic-gate 				break;
179*7c478bd9Sstevel@tonic-gate 			case 'd':
180*7c478bd9Sstevel@tonic-gate 				deleteflag++;
181*7c478bd9Sstevel@tonic-gate 				break;
182*7c478bd9Sstevel@tonic-gate 			case 'p':
183*7c478bd9Sstevel@tonic-gate 				persist++;
184*7c478bd9Sstevel@tonic-gate 				break;
185*7c478bd9Sstevel@tonic-gate 			default:
186*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(usage));
187*7c478bd9Sstevel@tonic-gate 				exit(E_USAGE);
188*7c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
189*7c478bd9Sstevel@tonic-gate 			}
190*7c478bd9Sstevel@tonic-gate 		}
191*7c478bd9Sstevel@tonic-gate 	}
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate 	if (display) {
194*7c478bd9Sstevel@tonic-gate 		getconsole();
195*7c478bd9Sstevel@tonic-gate 		return (E_SUCCESS);
196*7c478bd9Sstevel@tonic-gate 	}
197*7c478bd9Sstevel@tonic-gate 	if (addflag && deleteflag) {
198*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(usage));
199*7c478bd9Sstevel@tonic-gate 		return (E_ERROR);
200*7c478bd9Sstevel@tonic-gate 	}
201*7c478bd9Sstevel@tonic-gate 	if (addflag) {
202*7c478bd9Sstevel@tonic-gate 		if (optind == argc) {
203*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(usage));
204*7c478bd9Sstevel@tonic-gate 			return (E_ERROR);
205*7c478bd9Sstevel@tonic-gate 		}
206*7c478bd9Sstevel@tonic-gate 		/* separately check every device path specified */
207*7c478bd9Sstevel@tonic-gate 		for (index = optind; index < argc; index++) {
208*7c478bd9Sstevel@tonic-gate 			if (verifyarg(argv[index], addflag))
209*7c478bd9Sstevel@tonic-gate 				return (E_ERROR);
210*7c478bd9Sstevel@tonic-gate 		}
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate 		for (index = optind; index < argc; index++) {
213*7c478bd9Sstevel@tonic-gate 			setaux(argv[index]);
214*7c478bd9Sstevel@tonic-gate 			if (persist)
215*7c478bd9Sstevel@tonic-gate 				addtolist(argv[index]);
216*7c478bd9Sstevel@tonic-gate 		}
217*7c478bd9Sstevel@tonic-gate 
218*7c478bd9Sstevel@tonic-gate 		/*
219*7c478bd9Sstevel@tonic-gate 		 * start/restart daemon based on the auxilary
220*7c478bd9Sstevel@tonic-gate 		 * consoles at this time.
221*7c478bd9Sstevel@tonic-gate 		 */
222*7c478bd9Sstevel@tonic-gate 		setfallback(argv);
223*7c478bd9Sstevel@tonic-gate 		return (E_SUCCESS);
224*7c478bd9Sstevel@tonic-gate 	} else if (deleteflag) {
225*7c478bd9Sstevel@tonic-gate 		if (optind == argc) {
226*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(usage));
227*7c478bd9Sstevel@tonic-gate 			return (E_ERROR);
228*7c478bd9Sstevel@tonic-gate 		}
229*7c478bd9Sstevel@tonic-gate 		/* separately check every device path specified */
230*7c478bd9Sstevel@tonic-gate 		for (index = optind; index < argc; index++) {
231*7c478bd9Sstevel@tonic-gate 			if (verifyarg(argv[index], 0))
232*7c478bd9Sstevel@tonic-gate 				return (E_ERROR);
233*7c478bd9Sstevel@tonic-gate 		}
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 		for (index = optind; index < argc; index++) {
236*7c478bd9Sstevel@tonic-gate 			unsetaux(argv[index]);
237*7c478bd9Sstevel@tonic-gate 			if (persist && deleteflag)
238*7c478bd9Sstevel@tonic-gate 				removefromlist(argv[index]);
239*7c478bd9Sstevel@tonic-gate 		}
240*7c478bd9Sstevel@tonic-gate 
241*7c478bd9Sstevel@tonic-gate 		/*
242*7c478bd9Sstevel@tonic-gate 		 * kill off daemon and restart with
243*7c478bd9Sstevel@tonic-gate 		 * new list of auxiliary consoles
244*7c478bd9Sstevel@tonic-gate 		 */
245*7c478bd9Sstevel@tonic-gate 		setfallback(argv);
246*7c478bd9Sstevel@tonic-gate 		return (E_SUCCESS);
247*7c478bd9Sstevel@tonic-gate 	} else if (persist) {
248*7c478bd9Sstevel@tonic-gate 		if (optind < argc) {
249*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(usage));
250*7c478bd9Sstevel@tonic-gate 			return (E_ERROR);
251*7c478bd9Sstevel@tonic-gate 		}
252*7c478bd9Sstevel@tonic-gate 
253*7c478bd9Sstevel@tonic-gate 		persistlist();
254*7c478bd9Sstevel@tonic-gate 		return (E_SUCCESS);
255*7c478bd9Sstevel@tonic-gate 	} else {
256*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(usage));
257*7c478bd9Sstevel@tonic-gate 		return (E_ERROR);
258*7c478bd9Sstevel@tonic-gate 	}
259*7c478bd9Sstevel@tonic-gate } /* main */
260*7c478bd9Sstevel@tonic-gate 
261*7c478bd9Sstevel@tonic-gate /* for daemon to handle termination from user command */
262*7c478bd9Sstevel@tonic-gate static void
263*7c478bd9Sstevel@tonic-gate catch_term()
264*7c478bd9Sstevel@tonic-gate {
265*7c478bd9Sstevel@tonic-gate 	exit(E_SUCCESS);
266*7c478bd9Sstevel@tonic-gate }
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate /* handle lack of carrier on open */
269*7c478bd9Sstevel@tonic-gate static void
270*7c478bd9Sstevel@tonic-gate catch_alarm()
271*7c478bd9Sstevel@tonic-gate {
272*7c478bd9Sstevel@tonic-gate 	siglongjmp(deadline, 1);
273*7c478bd9Sstevel@tonic-gate }
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate /* caught a sighup */
276*7c478bd9Sstevel@tonic-gate static void
277*7c478bd9Sstevel@tonic-gate catch_hup()
278*7c478bd9Sstevel@tonic-gate {
279*7c478bd9Sstevel@tonic-gate 	/*
280*7c478bd9Sstevel@tonic-gate 	 * ttymon sends sighup to consadmd because it has the serial
281*7c478bd9Sstevel@tonic-gate 	 * port open.  We catch the signal here, but process it
282*7c478bd9Sstevel@tonic-gate 	 * within fallbackdaemon().  We ignore the signal if the
283*7c478bd9Sstevel@tonic-gate 	 * errno returned was EINTR.
284*7c478bd9Sstevel@tonic-gate 	 */
285*7c478bd9Sstevel@tonic-gate }
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate /* Remove persistent state on receiving signal. */
288*7c478bd9Sstevel@tonic-gate static void
289*7c478bd9Sstevel@tonic-gate cleanup_on_exit()
290*7c478bd9Sstevel@tonic-gate {
291*7c478bd9Sstevel@tonic-gate 	(void) unlink(CONSADMLOCK);
292*7c478bd9Sstevel@tonic-gate 	exit(E_ERROR);
293*7c478bd9Sstevel@tonic-gate }
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate /*
296*7c478bd9Sstevel@tonic-gate  * send ioctl to /dev/sysmsg to route msgs of the device specified.
297*7c478bd9Sstevel@tonic-gate  */
298*7c478bd9Sstevel@tonic-gate static void
299*7c478bd9Sstevel@tonic-gate setaux(char *dev)
300*7c478bd9Sstevel@tonic-gate {
301*7c478bd9Sstevel@tonic-gate 	int	fd;
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 	if ((fd = safeopen(SYSMSG)) < 0)
304*7c478bd9Sstevel@tonic-gate 		die(gettext("%s is missing or not a valid device\n"), SYSMSG);
305*7c478bd9Sstevel@tonic-gate 
306*7c478bd9Sstevel@tonic-gate 	if (ioctl(fd, CIOCSETCONSOLE, dev) != 0) {
307*7c478bd9Sstevel@tonic-gate 		/*
308*7c478bd9Sstevel@tonic-gate 		 * Let setting duplicate device be warning, consadm
309*7c478bd9Sstevel@tonic-gate 		 * must proceed to set persistence if requested.
310*7c478bd9Sstevel@tonic-gate 		 */
311*7c478bd9Sstevel@tonic-gate 		if (errno == EBUSY)
312*7c478bd9Sstevel@tonic-gate 			die(gettext("%s is already the default console\n"),
313*7c478bd9Sstevel@tonic-gate 			    dev);
314*7c478bd9Sstevel@tonic-gate 		else if (errno != EEXIST)
315*7c478bd9Sstevel@tonic-gate 			die(gettext("cannot get table entry"));
316*7c478bd9Sstevel@tonic-gate 	}
317*7c478bd9Sstevel@tonic-gate 	syslog(LOG_WARNING, "%s: Added auxiliary device %s", CONSADM, dev);
318*7c478bd9Sstevel@tonic-gate 
319*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
320*7c478bd9Sstevel@tonic-gate }
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate /*
323*7c478bd9Sstevel@tonic-gate  * Send ioctl to device specified and
324*7c478bd9Sstevel@tonic-gate  * Remove the entry from the list of auxiliary devices.
325*7c478bd9Sstevel@tonic-gate  */
326*7c478bd9Sstevel@tonic-gate static void
327*7c478bd9Sstevel@tonic-gate unsetaux(char *dev)
328*7c478bd9Sstevel@tonic-gate {
329*7c478bd9Sstevel@tonic-gate 	int	fd;
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate 	if ((fd = safeopen(SYSMSG)) < 0)
332*7c478bd9Sstevel@tonic-gate 		die(gettext("%s is missing or not a valid device\n"), SYSMSG);
333*7c478bd9Sstevel@tonic-gate 
334*7c478bd9Sstevel@tonic-gate 	if (ioctl(fd, CIOCRMCONSOLE, dev) != 0) {
335*7c478bd9Sstevel@tonic-gate 		if (errno == EBUSY)
336*7c478bd9Sstevel@tonic-gate 			die(gettext("cannot unset the default console\n"));
337*7c478bd9Sstevel@tonic-gate 	} else
338*7c478bd9Sstevel@tonic-gate 		syslog(LOG_WARNING, "%s: Removed auxiliary device %s",
339*7c478bd9Sstevel@tonic-gate 		    CONSADM, dev);
340*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
341*7c478bd9Sstevel@tonic-gate }
342*7c478bd9Sstevel@tonic-gate 
343*7c478bd9Sstevel@tonic-gate static int
344*7c478bd9Sstevel@tonic-gate getlock(void)
345*7c478bd9Sstevel@tonic-gate {
346*7c478bd9Sstevel@tonic-gate 	int lckfd;
347*7c478bd9Sstevel@tonic-gate 
348*7c478bd9Sstevel@tonic-gate 	if ((lckfd = open(CONSADMLOCK, O_CREAT | O_EXCL | O_WRONLY,
349*7c478bd9Sstevel@tonic-gate 	    S_IRUSR | S_IWUSR)) < 0) {
350*7c478bd9Sstevel@tonic-gate 		if (errno == EEXIST)
351*7c478bd9Sstevel@tonic-gate 			die(gettext("currently busy, try again later.\n"));
352*7c478bd9Sstevel@tonic-gate 		else
353*7c478bd9Sstevel@tonic-gate 			die(gettext("cannot open %s"), CONSADMLOCK);
354*7c478bd9Sstevel@tonic-gate 	}
355*7c478bd9Sstevel@tonic-gate 	if (lckfunc(lckfd, LOCK_EX) == -1) {
356*7c478bd9Sstevel@tonic-gate 		(void) close(lckfd);
357*7c478bd9Sstevel@tonic-gate 		(void) unlink(CONSADMLOCK);
358*7c478bd9Sstevel@tonic-gate 		die(gettext("fcntl operation failed"));
359*7c478bd9Sstevel@tonic-gate 	}
360*7c478bd9Sstevel@tonic-gate 	return (lckfd);
361*7c478bd9Sstevel@tonic-gate }
362*7c478bd9Sstevel@tonic-gate 
363*7c478bd9Sstevel@tonic-gate static void
364*7c478bd9Sstevel@tonic-gate addtolist(char *dev)
365*7c478bd9Sstevel@tonic-gate {
366*7c478bd9Sstevel@tonic-gate 	int	lckfd, fd;
367*7c478bd9Sstevel@tonic-gate 	FILE	*fp, *nfp;
368*7c478bd9Sstevel@tonic-gate 	char	newfile[MAXPATHLEN];
369*7c478bd9Sstevel@tonic-gate 	char	buf[MAXPATHLEN];
370*7c478bd9Sstevel@tonic-gate 	int	len;
371*7c478bd9Sstevel@tonic-gate 	boolean_t	found = B_FALSE;
372*7c478bd9Sstevel@tonic-gate 
373*7c478bd9Sstevel@tonic-gate 	/* update file of devices configured to get console msgs. */
374*7c478bd9Sstevel@tonic-gate 
375*7c478bd9Sstevel@tonic-gate 	lckfd = getlock();
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate 	/* Open new file */
378*7c478bd9Sstevel@tonic-gate 	(void) snprintf(newfile, sizeof (newfile), "%s%d",
379*7c478bd9Sstevel@tonic-gate 	    CONSCONFIG, (int)getpid());
380*7c478bd9Sstevel@tonic-gate 	if (((fd = creat(newfile, 0644)) < 0) ||
381*7c478bd9Sstevel@tonic-gate 	    ((nfp = fdopen(fd, "w")) == NULL)) {
382*7c478bd9Sstevel@tonic-gate 		(void) close(lckfd);
383*7c478bd9Sstevel@tonic-gate 		(void) unlink(CONSADMLOCK);
384*7c478bd9Sstevel@tonic-gate 		die(gettext("could not create new %s file"), CONSCONFIG);
385*7c478bd9Sstevel@tonic-gate 	}
386*7c478bd9Sstevel@tonic-gate 
387*7c478bd9Sstevel@tonic-gate 	/* Add header to new file */
388*7c478bd9Sstevel@tonic-gate 	(void) fprintf(nfp, "%s", conshdr);
389*7c478bd9Sstevel@tonic-gate 
390*7c478bd9Sstevel@tonic-gate 	/* Check that the file doesn't already exist */
391*7c478bd9Sstevel@tonic-gate 	if ((fp = fopen(CONSCONFIG, "r")) != NULL) {
392*7c478bd9Sstevel@tonic-gate 		while (fgets(buf, MAXPATHLEN, fp) != NULL) {
393*7c478bd9Sstevel@tonic-gate 			if (buf[0] == COMMENT || buf[0] == NEWLINE ||
394*7c478bd9Sstevel@tonic-gate 			    buf[0] == SPACE || buf[0] == TAB)
395*7c478bd9Sstevel@tonic-gate 				continue;
396*7c478bd9Sstevel@tonic-gate 			len = strlen(buf);
397*7c478bd9Sstevel@tonic-gate 			buf[len - 1] = NULL; /* Clear carriage return */
398*7c478bd9Sstevel@tonic-gate 			if (pathcmp(dev, buf) == 0) {
399*7c478bd9Sstevel@tonic-gate 				/* they match so use name passed in. */
400*7c478bd9Sstevel@tonic-gate 				(void) fprintf(nfp, "%s\n", dev);
401*7c478bd9Sstevel@tonic-gate 				found = B_TRUE;
402*7c478bd9Sstevel@tonic-gate 			} else
403*7c478bd9Sstevel@tonic-gate 				(void) fprintf(nfp, "%s\n", buf);
404*7c478bd9Sstevel@tonic-gate 		}
405*7c478bd9Sstevel@tonic-gate 	}
406*7c478bd9Sstevel@tonic-gate 	/* User specified persistent settings */
407*7c478bd9Sstevel@tonic-gate 	if (found == B_FALSE)
408*7c478bd9Sstevel@tonic-gate 		(void) fprintf(nfp, "%s\n", dev);
409*7c478bd9Sstevel@tonic-gate 
410*7c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
411*7c478bd9Sstevel@tonic-gate 	(void) fclose(nfp);
412*7c478bd9Sstevel@tonic-gate 	(void) rename(newfile, CONSCONFIG);
413*7c478bd9Sstevel@tonic-gate 	(void) close(lckfd);
414*7c478bd9Sstevel@tonic-gate 	(void) unlink(CONSADMLOCK);
415*7c478bd9Sstevel@tonic-gate }
416*7c478bd9Sstevel@tonic-gate 
417*7c478bd9Sstevel@tonic-gate /* The list in CONSCONFIG gives the persistence capability in the proto */
418*7c478bd9Sstevel@tonic-gate static void
419*7c478bd9Sstevel@tonic-gate removefromlist(char *dev)
420*7c478bd9Sstevel@tonic-gate {
421*7c478bd9Sstevel@tonic-gate 	int	lckfd;
422*7c478bd9Sstevel@tonic-gate 	FILE	*fp, *nfp;
423*7c478bd9Sstevel@tonic-gate 	char	newfile[MAXPATHLEN + 1];
424*7c478bd9Sstevel@tonic-gate 	char	len;
425*7c478bd9Sstevel@tonic-gate 	char	value[MAXPATHLEN + 1];
426*7c478bd9Sstevel@tonic-gate 	boolean_t	newcontents = B_FALSE;
427*7c478bd9Sstevel@tonic-gate 
428*7c478bd9Sstevel@tonic-gate 	/* update file of devices configured to get console msgs. */
429*7c478bd9Sstevel@tonic-gate 
430*7c478bd9Sstevel@tonic-gate 	lckfd = getlock();
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate 	if ((fp = fopen(CONSCONFIG, "r")) == NULL) {
433*7c478bd9Sstevel@tonic-gate 		(void) close(lckfd);
434*7c478bd9Sstevel@tonic-gate 		(void) unlink(CONSADMLOCK);
435*7c478bd9Sstevel@tonic-gate 		return;
436*7c478bd9Sstevel@tonic-gate 	}
437*7c478bd9Sstevel@tonic-gate 
438*7c478bd9Sstevel@tonic-gate 	/* Open new file */
439*7c478bd9Sstevel@tonic-gate 	(void) snprintf(newfile, sizeof (newfile), "%s%d",
440*7c478bd9Sstevel@tonic-gate 	    CONSCONFIG, (int)getpid());
441*7c478bd9Sstevel@tonic-gate 	if ((nfp = fopen(newfile, "w")) == NULL) {
442*7c478bd9Sstevel@tonic-gate 		(void) close(lckfd);
443*7c478bd9Sstevel@tonic-gate 		(void) unlink(CONSADMLOCK);
444*7c478bd9Sstevel@tonic-gate 		die(gettext("cannot create new %s file"), CONSCONFIG);
445*7c478bd9Sstevel@tonic-gate 	}
446*7c478bd9Sstevel@tonic-gate 
447*7c478bd9Sstevel@tonic-gate 	/* Add header to new file */
448*7c478bd9Sstevel@tonic-gate 	(void) fprintf(nfp, "%s", conshdr);
449*7c478bd9Sstevel@tonic-gate 
450*7c478bd9Sstevel@tonic-gate 	/*
451*7c478bd9Sstevel@tonic-gate 	 * Check whether the path duplicates what is already in the
452*7c478bd9Sstevel@tonic-gate 	 * file.
453*7c478bd9Sstevel@tonic-gate 	 */
454*7c478bd9Sstevel@tonic-gate 	while (fgets(value, MAXPATHLEN, fp) != NULL) {
455*7c478bd9Sstevel@tonic-gate 		/* skip comments */
456*7c478bd9Sstevel@tonic-gate 		if (value[0] == COMMENT || value[0] == NEWLINE ||
457*7c478bd9Sstevel@tonic-gate 		    value[0] == SPACE || value[0] == TAB)
458*7c478bd9Sstevel@tonic-gate 			continue;
459*7c478bd9Sstevel@tonic-gate 		len = strlen(value);
460*7c478bd9Sstevel@tonic-gate 		value[len - 1] = NULL; /* Clear carriage return */
461*7c478bd9Sstevel@tonic-gate 		if (pathcmp(dev, value) == 0) {
462*7c478bd9Sstevel@tonic-gate 			/* they match so don't write it */
463*7c478bd9Sstevel@tonic-gate 			continue;
464*7c478bd9Sstevel@tonic-gate 		}
465*7c478bd9Sstevel@tonic-gate 		(void) fprintf(nfp, "%s\n", value);
466*7c478bd9Sstevel@tonic-gate 		newcontents = B_TRUE;
467*7c478bd9Sstevel@tonic-gate 	}
468*7c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
469*7c478bd9Sstevel@tonic-gate 	(void) fclose(nfp);
470*7c478bd9Sstevel@tonic-gate 	/* Remove the file if there aren't any auxiliary consoles */
471*7c478bd9Sstevel@tonic-gate 	if (newcontents)
472*7c478bd9Sstevel@tonic-gate 		(void) rename(newfile, CONSCONFIG);
473*7c478bd9Sstevel@tonic-gate 	else {
474*7c478bd9Sstevel@tonic-gate 		(void) unlink(CONSCONFIG);
475*7c478bd9Sstevel@tonic-gate 		(void) unlink(newfile);
476*7c478bd9Sstevel@tonic-gate 	}
477*7c478bd9Sstevel@tonic-gate 	(void) close(lckfd);
478*7c478bd9Sstevel@tonic-gate 	(void) unlink(CONSADMLOCK);
479*7c478bd9Sstevel@tonic-gate }
480*7c478bd9Sstevel@tonic-gate 
481*7c478bd9Sstevel@tonic-gate static int
482*7c478bd9Sstevel@tonic-gate pathcmp(char *adev, char *bdev)
483*7c478bd9Sstevel@tonic-gate {
484*7c478bd9Sstevel@tonic-gate 	struct stat	st1;
485*7c478bd9Sstevel@tonic-gate 	struct stat	st2;
486*7c478bd9Sstevel@tonic-gate 
487*7c478bd9Sstevel@tonic-gate 	if (strcmp(adev, bdev) == 0)
488*7c478bd9Sstevel@tonic-gate 		return (0);
489*7c478bd9Sstevel@tonic-gate 
490*7c478bd9Sstevel@tonic-gate 	if (stat(adev, &st1) || (st1.st_mode & S_IFCHR) == 0)
491*7c478bd9Sstevel@tonic-gate 		die(gettext("invalid device %s\n"), adev);
492*7c478bd9Sstevel@tonic-gate 
493*7c478bd9Sstevel@tonic-gate 	if (stat(bdev, &st2) || (st2.st_mode & S_IFCHR) == 0)
494*7c478bd9Sstevel@tonic-gate 		die(gettext("invalid device %s\n"), bdev);
495*7c478bd9Sstevel@tonic-gate 
496*7c478bd9Sstevel@tonic-gate 	if (st1.st_rdev == st2.st_rdev)
497*7c478bd9Sstevel@tonic-gate 		return (0);
498*7c478bd9Sstevel@tonic-gate 
499*7c478bd9Sstevel@tonic-gate 	return (1);
500*7c478bd9Sstevel@tonic-gate }
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate /*
503*7c478bd9Sstevel@tonic-gate  * Display configured consoles.
504*7c478bd9Sstevel@tonic-gate  */
505*7c478bd9Sstevel@tonic-gate static void
506*7c478bd9Sstevel@tonic-gate getconsole(void)
507*7c478bd9Sstevel@tonic-gate {
508*7c478bd9Sstevel@tonic-gate 	int	fd;
509*7c478bd9Sstevel@tonic-gate 	int	bufsize = 0;		/* size of device cache */
510*7c478bd9Sstevel@tonic-gate 	char	*infop, *ptr, *p;	/* info structure for ioctl's */
511*7c478bd9Sstevel@tonic-gate 
512*7c478bd9Sstevel@tonic-gate 	if ((fd = safeopen(SYSMSG)) < 0)
513*7c478bd9Sstevel@tonic-gate 		die(gettext("%s is missing or not a valid device\n"), SYSMSG);
514*7c478bd9Sstevel@tonic-gate 
515*7c478bd9Sstevel@tonic-gate 	if ((bufsize = ioctl(fd, CIOCGETCONSOLE, NULL)) < 0)
516*7c478bd9Sstevel@tonic-gate 		die(gettext("cannot get table entry\n"));
517*7c478bd9Sstevel@tonic-gate 	if (bufsize == 0)
518*7c478bd9Sstevel@tonic-gate 		return;
519*7c478bd9Sstevel@tonic-gate 
520*7c478bd9Sstevel@tonic-gate 	if ((infop = calloc(bufsize, sizeof (char))) == NULL)
521*7c478bd9Sstevel@tonic-gate 		die(gettext("cannot allocate buffer"));
522*7c478bd9Sstevel@tonic-gate 
523*7c478bd9Sstevel@tonic-gate 	if (ioctl(fd, CIOCGETCONSOLE, infop) < 0)
524*7c478bd9Sstevel@tonic-gate 		die(gettext("cannot get table entry\n"));
525*7c478bd9Sstevel@tonic-gate 
526*7c478bd9Sstevel@tonic-gate 	ptr = infop;
527*7c478bd9Sstevel@tonic-gate 	while (ptr != NULL) {
528*7c478bd9Sstevel@tonic-gate 		p = strchr(ptr, ' ');
529*7c478bd9Sstevel@tonic-gate 		if (p == NULL) {
530*7c478bd9Sstevel@tonic-gate 			(void) printf("%s\n", ptr);
531*7c478bd9Sstevel@tonic-gate 			break;
532*7c478bd9Sstevel@tonic-gate 		}
533*7c478bd9Sstevel@tonic-gate 		*p++ = '\0';
534*7c478bd9Sstevel@tonic-gate 		(void) printf("%s\n", ptr);
535*7c478bd9Sstevel@tonic-gate 		ptr = p;
536*7c478bd9Sstevel@tonic-gate 	}
537*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
538*7c478bd9Sstevel@tonic-gate }
539*7c478bd9Sstevel@tonic-gate 
540*7c478bd9Sstevel@tonic-gate /*
541*7c478bd9Sstevel@tonic-gate  * It is supposed that if the device supports TIOCMGET then it
542*7c478bd9Sstevel@tonic-gate  * might be a serial device.
543*7c478bd9Sstevel@tonic-gate  */
544*7c478bd9Sstevel@tonic-gate static boolean_t
545*7c478bd9Sstevel@tonic-gate modem_support(int fd)
546*7c478bd9Sstevel@tonic-gate {
547*7c478bd9Sstevel@tonic-gate 	int	modem_state;
548*7c478bd9Sstevel@tonic-gate 
549*7c478bd9Sstevel@tonic-gate 	if (ioctl(fd, TIOCMGET, &modem_state) == 0)
550*7c478bd9Sstevel@tonic-gate 		return (B_TRUE);
551*7c478bd9Sstevel@tonic-gate 	else
552*7c478bd9Sstevel@tonic-gate 		return (B_FALSE);
553*7c478bd9Sstevel@tonic-gate }
554*7c478bd9Sstevel@tonic-gate 
555*7c478bd9Sstevel@tonic-gate static boolean_t
556*7c478bd9Sstevel@tonic-gate has_carrier(int fd)
557*7c478bd9Sstevel@tonic-gate {
558*7c478bd9Sstevel@tonic-gate 	int	modem_state;
559*7c478bd9Sstevel@tonic-gate 
560*7c478bd9Sstevel@tonic-gate 	if (ioctl(fd, TIOCMGET, &modem_state) == 0)
561*7c478bd9Sstevel@tonic-gate 		return ((modem_state & TIOCM_CAR) != 0);
562*7c478bd9Sstevel@tonic-gate 	else {
563*7c478bd9Sstevel@tonic-gate 		return (B_FALSE);
564*7c478bd9Sstevel@tonic-gate 	}
565*7c478bd9Sstevel@tonic-gate }
566*7c478bd9Sstevel@tonic-gate 
567*7c478bd9Sstevel@tonic-gate static void
568*7c478bd9Sstevel@tonic-gate setfallback(char *argv[])
569*7c478bd9Sstevel@tonic-gate {
570*7c478bd9Sstevel@tonic-gate 	pid_t	pid;
571*7c478bd9Sstevel@tonic-gate 	FILE	*fp;
572*7c478bd9Sstevel@tonic-gate 	char	*cmd = CONSADMD;
573*7c478bd9Sstevel@tonic-gate 	int	lckfd, fd;
574*7c478bd9Sstevel@tonic-gate 
575*7c478bd9Sstevel@tonic-gate 	lckfd = getlock();
576*7c478bd9Sstevel@tonic-gate 
577*7c478bd9Sstevel@tonic-gate 	/*
578*7c478bd9Sstevel@tonic-gate 	 * kill off any existing daemon
579*7c478bd9Sstevel@tonic-gate 	 * remove /etc/consadm.pid
580*7c478bd9Sstevel@tonic-gate 	 */
581*7c478bd9Sstevel@tonic-gate 	removefallback();
582*7c478bd9Sstevel@tonic-gate 
583*7c478bd9Sstevel@tonic-gate 	/* kick off a daemon */
584*7c478bd9Sstevel@tonic-gate 	if ((pid = fork()) == (pid_t)0) {
585*7c478bd9Sstevel@tonic-gate 		/* always fallback to /dev/console */
586*7c478bd9Sstevel@tonic-gate 		argv[0] = cmd;
587*7c478bd9Sstevel@tonic-gate 		argv[1] = NULL;
588*7c478bd9Sstevel@tonic-gate 		(void) close(0);
589*7c478bd9Sstevel@tonic-gate 		(void) close(1);
590*7c478bd9Sstevel@tonic-gate 		(void) close(2);
591*7c478bd9Sstevel@tonic-gate 		(void) close(lckfd);
592*7c478bd9Sstevel@tonic-gate 		if ((fd = open(MSGLOG, O_RDWR)) < 0)
593*7c478bd9Sstevel@tonic-gate 			die(gettext("cannot open %s"), MSGLOG);
594*7c478bd9Sstevel@tonic-gate 		(void) dup2(fd, 1);
595*7c478bd9Sstevel@tonic-gate 		(void) dup2(fd, 2);
596*7c478bd9Sstevel@tonic-gate 		(void) execv(cmd, argv);
597*7c478bd9Sstevel@tonic-gate 		exit(E_SUCCESS);
598*7c478bd9Sstevel@tonic-gate 	} else if (pid == -1)
599*7c478bd9Sstevel@tonic-gate 		die(gettext("%s not started"), CONSADMD);
600*7c478bd9Sstevel@tonic-gate 
601*7c478bd9Sstevel@tonic-gate 	if ((fp = fopen(SETCONSOLEPID, "w")) == NULL)
602*7c478bd9Sstevel@tonic-gate 		die(gettext("cannot open %s"), SETCONSOLEPID);
603*7c478bd9Sstevel@tonic-gate 	/* write daemon pid to file */
604*7c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "%d\n", (int)pid);
605*7c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
606*7c478bd9Sstevel@tonic-gate 	(void) close(lckfd);
607*7c478bd9Sstevel@tonic-gate 	(void) unlink(CONSADMLOCK);
608*7c478bd9Sstevel@tonic-gate }
609*7c478bd9Sstevel@tonic-gate 
610*7c478bd9Sstevel@tonic-gate /*
611*7c478bd9Sstevel@tonic-gate  * Remove the daemon that would have implemented the automatic
612*7c478bd9Sstevel@tonic-gate  * fallback in event of carrier loss on the serial console.
613*7c478bd9Sstevel@tonic-gate  */
614*7c478bd9Sstevel@tonic-gate static void
615*7c478bd9Sstevel@tonic-gate removefallback(void)
616*7c478bd9Sstevel@tonic-gate {
617*7c478bd9Sstevel@tonic-gate 	FILE	*fp;
618*7c478bd9Sstevel@tonic-gate 	int	pid;
619*7c478bd9Sstevel@tonic-gate 
620*7c478bd9Sstevel@tonic-gate 	if ((fp = fopen(SETCONSOLEPID, "r+")) == NULL)
621*7c478bd9Sstevel@tonic-gate 		/* file doesn't exist, so no work to do */
622*7c478bd9Sstevel@tonic-gate 		return;
623*7c478bd9Sstevel@tonic-gate 
624*7c478bd9Sstevel@tonic-gate 	if (fscanf(fp, "%d\n", &pid) <= 0) {
625*7c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
626*7c478bd9Sstevel@tonic-gate 		(void) unlink(SETCONSOLEPID);
627*7c478bd9Sstevel@tonic-gate 		return;
628*7c478bd9Sstevel@tonic-gate 	}
629*7c478bd9Sstevel@tonic-gate 
630*7c478bd9Sstevel@tonic-gate 	/*
631*7c478bd9Sstevel@tonic-gate 	 * Don't shoot ourselves in the foot by killing init,
632*7c478bd9Sstevel@tonic-gate 	 * sched, pageout, or fsflush.
633*7c478bd9Sstevel@tonic-gate 	 */
634*7c478bd9Sstevel@tonic-gate 	if (pid == 0 || pid == 1 || pid == 2 || pid == 3) {
635*7c478bd9Sstevel@tonic-gate 		(void) unlink(SETCONSOLEPID);
636*7c478bd9Sstevel@tonic-gate 		return;
637*7c478bd9Sstevel@tonic-gate 	}
638*7c478bd9Sstevel@tonic-gate 	/*
639*7c478bd9Sstevel@tonic-gate 	 * kill off the existing daemon listed in
640*7c478bd9Sstevel@tonic-gate 	 * /etc/consadm.pid
641*7c478bd9Sstevel@tonic-gate 	 */
642*7c478bd9Sstevel@tonic-gate 	(void) kill((pid_t)pid, SIGTERM);
643*7c478bd9Sstevel@tonic-gate 
644*7c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
645*7c478bd9Sstevel@tonic-gate 	(void) unlink(SETCONSOLEPID);
646*7c478bd9Sstevel@tonic-gate }
647*7c478bd9Sstevel@tonic-gate 
648*7c478bd9Sstevel@tonic-gate /*
649*7c478bd9Sstevel@tonic-gate  * Assume we always fall back to /dev/console.
650*7c478bd9Sstevel@tonic-gate  * parameter passed in will always be the auxiliary device.
651*7c478bd9Sstevel@tonic-gate  * The daemon will not start after the last device has been removed.
652*7c478bd9Sstevel@tonic-gate  */
653*7c478bd9Sstevel@tonic-gate static void
654*7c478bd9Sstevel@tonic-gate fallbackdaemon(void)
655*7c478bd9Sstevel@tonic-gate {
656*7c478bd9Sstevel@tonic-gate 	int	fd, sysmfd, ret = 0;
657*7c478bd9Sstevel@tonic-gate 	char	**devpaths;
658*7c478bd9Sstevel@tonic-gate 	pollfd_t	*fds;
659*7c478bd9Sstevel@tonic-gate 	nfds_t	nfds = 0;
660*7c478bd9Sstevel@tonic-gate 	int	index;
661*7c478bd9Sstevel@tonic-gate 	int	pollagain;
662*7c478bd9Sstevel@tonic-gate 	struct	sigaction sa;
663*7c478bd9Sstevel@tonic-gate 	int	bufsize = 0;		/* length of device cache paths */
664*7c478bd9Sstevel@tonic-gate 	int	cachesize = 0;		/* size of device cache */
665*7c478bd9Sstevel@tonic-gate 	char	*infop, *ptr, *p;	/* info structure for ioctl's */
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate 	/*
668*7c478bd9Sstevel@tonic-gate 	 * catch SIGTERM cause it might be coming from user via consadm
669*7c478bd9Sstevel@tonic-gate 	 */
670*7c478bd9Sstevel@tonic-gate 	sa.sa_handler = catch_term;
671*7c478bd9Sstevel@tonic-gate 	sa.sa_flags = 0;
672*7c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&sa.sa_mask);
673*7c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGTERM, &sa, NULL);
674*7c478bd9Sstevel@tonic-gate 
675*7c478bd9Sstevel@tonic-gate 	/*
676*7c478bd9Sstevel@tonic-gate 	 * catch SIGHUP cause it might be coming from a disconnect
677*7c478bd9Sstevel@tonic-gate 	 */
678*7c478bd9Sstevel@tonic-gate 	sa.sa_handler = catch_hup;
679*7c478bd9Sstevel@tonic-gate 	sa.sa_flags = 0;
680*7c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&sa.sa_mask);
681*7c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGHUP, &sa, NULL);
682*7c478bd9Sstevel@tonic-gate 
683*7c478bd9Sstevel@tonic-gate 	if ((sysmfd = safeopen(SYSMSG)) < 0)
684*7c478bd9Sstevel@tonic-gate 		die(gettext("%s is missing or not a valid device\n"), SYSMSG);
685*7c478bd9Sstevel@tonic-gate 
686*7c478bd9Sstevel@tonic-gate 	if ((bufsize = ioctl(sysmfd, CIOCGETCONSOLE, NULL)) < 0)
687*7c478bd9Sstevel@tonic-gate 		die(gettext("cannot get table entry\n"));
688*7c478bd9Sstevel@tonic-gate 	if (bufsize == 0)
689*7c478bd9Sstevel@tonic-gate 		return;
690*7c478bd9Sstevel@tonic-gate 
691*7c478bd9Sstevel@tonic-gate 	if ((infop = calloc(bufsize, sizeof (char))) == NULL)
692*7c478bd9Sstevel@tonic-gate 		die(gettext("cannot allocate buffer"));
693*7c478bd9Sstevel@tonic-gate 
694*7c478bd9Sstevel@tonic-gate 	if (ioctl(sysmfd, CIOCGETCONSOLE, infop) < 0)
695*7c478bd9Sstevel@tonic-gate 		die(gettext("cannot get table entry\n"));
696*7c478bd9Sstevel@tonic-gate 
697*7c478bd9Sstevel@tonic-gate 	ptr = infop;
698*7c478bd9Sstevel@tonic-gate 	while (ptr != NULL) {
699*7c478bd9Sstevel@tonic-gate 		p = strchr(ptr, ' ');
700*7c478bd9Sstevel@tonic-gate 		if (p == NULL) {
701*7c478bd9Sstevel@tonic-gate 			cachesize++;
702*7c478bd9Sstevel@tonic-gate 			break;
703*7c478bd9Sstevel@tonic-gate 		}
704*7c478bd9Sstevel@tonic-gate 		p++;
705*7c478bd9Sstevel@tonic-gate 		cachesize++;
706*7c478bd9Sstevel@tonic-gate 		ptr = p;
707*7c478bd9Sstevel@tonic-gate 	}
708*7c478bd9Sstevel@tonic-gate 
709*7c478bd9Sstevel@tonic-gate 	if ((fds = calloc(cachesize, sizeof (struct pollfd))) == NULL)
710*7c478bd9Sstevel@tonic-gate 		die(gettext("cannot allocate buffer"));
711*7c478bd9Sstevel@tonic-gate 
712*7c478bd9Sstevel@tonic-gate 	if ((devpaths = calloc(cachesize, sizeof (char *))) == NULL)
713*7c478bd9Sstevel@tonic-gate 		die(gettext("cannot allocate buffer"));
714*7c478bd9Sstevel@tonic-gate 
715*7c478bd9Sstevel@tonic-gate 	ptr = infop;
716*7c478bd9Sstevel@tonic-gate 	while (ptr != NULL) {
717*7c478bd9Sstevel@tonic-gate 		p = strchr(ptr, ' ');
718*7c478bd9Sstevel@tonic-gate 		if (p == NULL) {
719*7c478bd9Sstevel@tonic-gate 			if ((fd = safeopen(ptr)) < 0) {
720*7c478bd9Sstevel@tonic-gate 				warn(gettext("cannot open %s, continuing"),
721*7c478bd9Sstevel@tonic-gate 				    ptr);
722*7c478bd9Sstevel@tonic-gate 				break;
723*7c478bd9Sstevel@tonic-gate 			}
724*7c478bd9Sstevel@tonic-gate 			if (!has_carrier(fd)) {
725*7c478bd9Sstevel@tonic-gate 				(void) close(fd);
726*7c478bd9Sstevel@tonic-gate 				warn(gettext(
727*7c478bd9Sstevel@tonic-gate 		    "no carrier on %s, device will not be monitored.\n"),
728*7c478bd9Sstevel@tonic-gate 				    ptr);
729*7c478bd9Sstevel@tonic-gate 				break;
730*7c478bd9Sstevel@tonic-gate 			} else {
731*7c478bd9Sstevel@tonic-gate 				fds[nfds].fd = fd;
732*7c478bd9Sstevel@tonic-gate 				fds[nfds].events = 0;
733*7c478bd9Sstevel@tonic-gate 
734*7c478bd9Sstevel@tonic-gate 				if ((devpaths[nfds] =
735*7c478bd9Sstevel@tonic-gate 				    malloc(strlen(ptr) + 1)) == NULL)
736*7c478bd9Sstevel@tonic-gate 					die(gettext("cannot allocate buffer"));
737*7c478bd9Sstevel@tonic-gate 
738*7c478bd9Sstevel@tonic-gate 				(void) strcpy(devpaths[nfds], ptr);
739*7c478bd9Sstevel@tonic-gate 				nfds++;
740*7c478bd9Sstevel@tonic-gate 				if (nfds >= cachesize)
741*7c478bd9Sstevel@tonic-gate 					break;
742*7c478bd9Sstevel@tonic-gate 			}
743*7c478bd9Sstevel@tonic-gate 			break;
744*7c478bd9Sstevel@tonic-gate 		}
745*7c478bd9Sstevel@tonic-gate 		*p++ = '\0';
746*7c478bd9Sstevel@tonic-gate 
747*7c478bd9Sstevel@tonic-gate 		if ((fd = safeopen(ptr)) < 0) {
748*7c478bd9Sstevel@tonic-gate 			warn(gettext("cannot open %s, continuing"), ptr);
749*7c478bd9Sstevel@tonic-gate 			ptr = p;
750*7c478bd9Sstevel@tonic-gate 			continue;
751*7c478bd9Sstevel@tonic-gate 		}
752*7c478bd9Sstevel@tonic-gate 		if (!has_carrier(fd)) {
753*7c478bd9Sstevel@tonic-gate 			(void) close(fd);
754*7c478bd9Sstevel@tonic-gate 			warn(gettext(
755*7c478bd9Sstevel@tonic-gate 		    "no carrier on %s, device will not be monitored.\n"),
756*7c478bd9Sstevel@tonic-gate 			    ptr);
757*7c478bd9Sstevel@tonic-gate 			ptr = p;
758*7c478bd9Sstevel@tonic-gate 			continue;
759*7c478bd9Sstevel@tonic-gate 		} else {
760*7c478bd9Sstevel@tonic-gate 			fds[nfds].fd = fd;
761*7c478bd9Sstevel@tonic-gate 			fds[nfds].events = 0;
762*7c478bd9Sstevel@tonic-gate 
763*7c478bd9Sstevel@tonic-gate 			if ((devpaths[nfds] = malloc(strlen(ptr) + 1)) == NULL)
764*7c478bd9Sstevel@tonic-gate 				die(gettext("cannot allocate buffer"));
765*7c478bd9Sstevel@tonic-gate 
766*7c478bd9Sstevel@tonic-gate 			(void) strcpy(devpaths[nfds], ptr);
767*7c478bd9Sstevel@tonic-gate 			nfds++;
768*7c478bd9Sstevel@tonic-gate 			if (nfds >= cachesize)
769*7c478bd9Sstevel@tonic-gate 				break;
770*7c478bd9Sstevel@tonic-gate 		}
771*7c478bd9Sstevel@tonic-gate 		ptr = p;
772*7c478bd9Sstevel@tonic-gate 	}
773*7c478bd9Sstevel@tonic-gate 	(void) close(sysmfd);
774*7c478bd9Sstevel@tonic-gate 
775*7c478bd9Sstevel@tonic-gate 	/* no point polling if no devices with carrier */
776*7c478bd9Sstevel@tonic-gate 	if (nfds == 0)
777*7c478bd9Sstevel@tonic-gate 		return;
778*7c478bd9Sstevel@tonic-gate 
779*7c478bd9Sstevel@tonic-gate 	for (;;) {
780*7c478bd9Sstevel@tonic-gate 		/* daemon sleeps waiting for a hangup on the console */
781*7c478bd9Sstevel@tonic-gate 		ret = poll(fds, nfds, INFTIM);
782*7c478bd9Sstevel@tonic-gate 		if (ret == -1) {
783*7c478bd9Sstevel@tonic-gate 			/* Check if ttymon is trying to get rid of us */
784*7c478bd9Sstevel@tonic-gate 			if (errno == EINTR)
785*7c478bd9Sstevel@tonic-gate 				continue;
786*7c478bd9Sstevel@tonic-gate 			warn(gettext("cannot poll device"));
787*7c478bd9Sstevel@tonic-gate 			return;
788*7c478bd9Sstevel@tonic-gate 		} else if (ret == 0) {
789*7c478bd9Sstevel@tonic-gate 			warn(gettext("timeout (%d milleseconds) occured\n"),
790*7c478bd9Sstevel@tonic-gate 			    INFTIM);
791*7c478bd9Sstevel@tonic-gate 			return;
792*7c478bd9Sstevel@tonic-gate 		} else {
793*7c478bd9Sstevel@tonic-gate 			/* Go through poll list looking for events. */
794*7c478bd9Sstevel@tonic-gate 			for (index = 0; index < nfds; index++) {
795*7c478bd9Sstevel@tonic-gate 				/* expected result */
796*7c478bd9Sstevel@tonic-gate 				if ((fds[index].revents & POLLHUP) ==
797*7c478bd9Sstevel@tonic-gate 				    POLLHUP) {
798*7c478bd9Sstevel@tonic-gate 					/*
799*7c478bd9Sstevel@tonic-gate 					 * unsetaux console.  Take out of list
800*7c478bd9Sstevel@tonic-gate 					 * of current auxiliary consoles.
801*7c478bd9Sstevel@tonic-gate 					 */
802*7c478bd9Sstevel@tonic-gate 					unsetaux((char *)devpaths[index]);
803*7c478bd9Sstevel@tonic-gate 					warn(gettext(
804*7c478bd9Sstevel@tonic-gate 				    "lost carrier, unsetting console %s\n"),
805*7c478bd9Sstevel@tonic-gate 					    devpaths[index]);
806*7c478bd9Sstevel@tonic-gate 					syslog(LOG_WARNING,
807*7c478bd9Sstevel@tonic-gate 			    "%s: lost carrier, unsetting auxiliary device %s",
808*7c478bd9Sstevel@tonic-gate 					    CONSADM, devpaths[index]);
809*7c478bd9Sstevel@tonic-gate 					free(devpaths[index]);
810*7c478bd9Sstevel@tonic-gate 					devpaths[index] = NULL;
811*7c478bd9Sstevel@tonic-gate 					(void) close(fds[index].fd);
812*7c478bd9Sstevel@tonic-gate 					fds[index].fd = -1;
813*7c478bd9Sstevel@tonic-gate 					fds[index].revents = 0;
814*7c478bd9Sstevel@tonic-gate 					continue;
815*7c478bd9Sstevel@tonic-gate 				}
816*7c478bd9Sstevel@tonic-gate 				if ((fds[index].revents & POLLERR) ==
817*7c478bd9Sstevel@tonic-gate 				    POLLERR) {
818*7c478bd9Sstevel@tonic-gate 					warn(gettext("poll error\n"));
819*7c478bd9Sstevel@tonic-gate 					continue;
820*7c478bd9Sstevel@tonic-gate 				} else if (fds[index].revents != 0) {
821*7c478bd9Sstevel@tonic-gate 					warn(gettext(
822*7c478bd9Sstevel@tonic-gate 					    "unexpected poll result 0x%x\n"),
823*7c478bd9Sstevel@tonic-gate 					    fds[index].revents);
824*7c478bd9Sstevel@tonic-gate 					continue;
825*7c478bd9Sstevel@tonic-gate 				}
826*7c478bd9Sstevel@tonic-gate 			}
827*7c478bd9Sstevel@tonic-gate 			/* check whether any left to poll */
828*7c478bd9Sstevel@tonic-gate 			pollagain = B_FALSE;
829*7c478bd9Sstevel@tonic-gate 			for (index = 0; index < nfds; index++)
830*7c478bd9Sstevel@tonic-gate 				if (fds[index].fd != -1)
831*7c478bd9Sstevel@tonic-gate 					pollagain = B_TRUE;
832*7c478bd9Sstevel@tonic-gate 			if (pollagain == B_TRUE)
833*7c478bd9Sstevel@tonic-gate 				continue;
834*7c478bd9Sstevel@tonic-gate 			else
835*7c478bd9Sstevel@tonic-gate 				return;
836*7c478bd9Sstevel@tonic-gate 		}
837*7c478bd9Sstevel@tonic-gate 	}
838*7c478bd9Sstevel@tonic-gate }
839*7c478bd9Sstevel@tonic-gate 
840*7c478bd9Sstevel@tonic-gate static void
841*7c478bd9Sstevel@tonic-gate persistlist(void)
842*7c478bd9Sstevel@tonic-gate {
843*7c478bd9Sstevel@tonic-gate 	FILE	*fp;
844*7c478bd9Sstevel@tonic-gate 	char	value[MAXPATHLEN + 1];
845*7c478bd9Sstevel@tonic-gate 	int	lckfd;
846*7c478bd9Sstevel@tonic-gate 
847*7c478bd9Sstevel@tonic-gate 	lckfd = getlock();
848*7c478bd9Sstevel@tonic-gate 
849*7c478bd9Sstevel@tonic-gate 	if ((fp = fopen(CONSCONFIG, "r")) != NULL) {
850*7c478bd9Sstevel@tonic-gate 		while (fgets(value, MAXPATHLEN, fp) != NULL) {
851*7c478bd9Sstevel@tonic-gate 			/* skip comments */
852*7c478bd9Sstevel@tonic-gate 			if (value[0] == COMMENT ||
853*7c478bd9Sstevel@tonic-gate 			    value[0] == NEWLINE ||
854*7c478bd9Sstevel@tonic-gate 			    value[0] == SPACE || value[0] == TAB)
855*7c478bd9Sstevel@tonic-gate 				continue;
856*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stdout, "%s", value);
857*7c478bd9Sstevel@tonic-gate 		}
858*7c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
859*7c478bd9Sstevel@tonic-gate 	}
860*7c478bd9Sstevel@tonic-gate 	(void) close(lckfd);
861*7c478bd9Sstevel@tonic-gate 	(void) unlink(CONSADMLOCK);
862*7c478bd9Sstevel@tonic-gate }
863*7c478bd9Sstevel@tonic-gate 
864*7c478bd9Sstevel@tonic-gate static int
865*7c478bd9Sstevel@tonic-gate verifyarg(char *dev, int flag)
866*7c478bd9Sstevel@tonic-gate {
867*7c478bd9Sstevel@tonic-gate 	struct stat	st;
868*7c478bd9Sstevel@tonic-gate 	int	fd;
869*7c478bd9Sstevel@tonic-gate 	int	ret = 0;
870*7c478bd9Sstevel@tonic-gate 
871*7c478bd9Sstevel@tonic-gate 	if (dev == NULL) {
872*7c478bd9Sstevel@tonic-gate 		warn(gettext("specify device(s)\n"));
873*7c478bd9Sstevel@tonic-gate 		ret = 1;
874*7c478bd9Sstevel@tonic-gate 		goto err_exit;
875*7c478bd9Sstevel@tonic-gate 	}
876*7c478bd9Sstevel@tonic-gate 
877*7c478bd9Sstevel@tonic-gate 	if (dev[0] != '/') {
878*7c478bd9Sstevel@tonic-gate 		warn(gettext("device name must begin with a '/'\n"));
879*7c478bd9Sstevel@tonic-gate 		ret = 1;
880*7c478bd9Sstevel@tonic-gate 		goto err_exit;
881*7c478bd9Sstevel@tonic-gate 	}
882*7c478bd9Sstevel@tonic-gate 
883*7c478bd9Sstevel@tonic-gate 	if ((pathcmp(dev, SYSMSG) == 0) ||
884*7c478bd9Sstevel@tonic-gate 	    (pathcmp(dev, WSCONS) == 0) ||
885*7c478bd9Sstevel@tonic-gate 	    (pathcmp(dev, CONSOLE) == 0)) {
886*7c478bd9Sstevel@tonic-gate 		/* they match */
887*7c478bd9Sstevel@tonic-gate 		warn(gettext("invalid device %s\n"), dev);
888*7c478bd9Sstevel@tonic-gate 		ret = 1;
889*7c478bd9Sstevel@tonic-gate 		goto err_exit;
890*7c478bd9Sstevel@tonic-gate 	}
891*7c478bd9Sstevel@tonic-gate 
892*7c478bd9Sstevel@tonic-gate 	if (stat(dev, &st) || ! S_ISCHR(st.st_mode)) {
893*7c478bd9Sstevel@tonic-gate 		warn(gettext("invalid device %s\n"), dev);
894*7c478bd9Sstevel@tonic-gate 		ret = 1;
895*7c478bd9Sstevel@tonic-gate 		goto err_exit;
896*7c478bd9Sstevel@tonic-gate 	}
897*7c478bd9Sstevel@tonic-gate 
898*7c478bd9Sstevel@tonic-gate 	/* Delete operation doesn't require this checking */
899*7c478bd9Sstevel@tonic-gate 	if ((fd = safeopen(dev)) < 0) {
900*7c478bd9Sstevel@tonic-gate 		if (flag) {
901*7c478bd9Sstevel@tonic-gate 			warn(gettext("invalid device %s\n"), dev);
902*7c478bd9Sstevel@tonic-gate 			ret = 1;
903*7c478bd9Sstevel@tonic-gate 		}
904*7c478bd9Sstevel@tonic-gate 		goto err_exit;
905*7c478bd9Sstevel@tonic-gate 	}
906*7c478bd9Sstevel@tonic-gate 	if (!modem_support(fd)) {
907*7c478bd9Sstevel@tonic-gate 		warn(gettext("invalid device %s\n"), dev);
908*7c478bd9Sstevel@tonic-gate 		(void) close(fd);
909*7c478bd9Sstevel@tonic-gate 		ret = 1;
910*7c478bd9Sstevel@tonic-gate 		goto err_exit;
911*7c478bd9Sstevel@tonic-gate 	}
912*7c478bd9Sstevel@tonic-gate 
913*7c478bd9Sstevel@tonic-gate 	/* Only verify carrier if it's an add operation */
914*7c478bd9Sstevel@tonic-gate 	if (flag) {
915*7c478bd9Sstevel@tonic-gate 		if (!has_carrier(fd)) {
916*7c478bd9Sstevel@tonic-gate 			warn(gettext("failure, no carrier on %s\n"), dev);
917*7c478bd9Sstevel@tonic-gate 			ret = 1;
918*7c478bd9Sstevel@tonic-gate 			goto err_exit;
919*7c478bd9Sstevel@tonic-gate 		}
920*7c478bd9Sstevel@tonic-gate 	}
921*7c478bd9Sstevel@tonic-gate err_exit:
922*7c478bd9Sstevel@tonic-gate 	return (ret);
923*7c478bd9Sstevel@tonic-gate }
924*7c478bd9Sstevel@tonic-gate 
925*7c478bd9Sstevel@tonic-gate /*
926*7c478bd9Sstevel@tonic-gate  * Open the pseudo device, but be prepared to catch sigalarm if we block
927*7c478bd9Sstevel@tonic-gate  * cause there isn't any carrier present.
928*7c478bd9Sstevel@tonic-gate  */
929*7c478bd9Sstevel@tonic-gate static int
930*7c478bd9Sstevel@tonic-gate safeopen(char *devp)
931*7c478bd9Sstevel@tonic-gate {
932*7c478bd9Sstevel@tonic-gate 	int	fd;
933*7c478bd9Sstevel@tonic-gate 	struct	sigaction sigact;
934*7c478bd9Sstevel@tonic-gate 
935*7c478bd9Sstevel@tonic-gate 	sigact.sa_flags = SA_RESETHAND | SA_NODEFER;
936*7c478bd9Sstevel@tonic-gate 	sigact.sa_handler = catch_alarm;
937*7c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&sigact.sa_mask);
938*7c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGALRM, &sigact, NULL);
939*7c478bd9Sstevel@tonic-gate 	if (sigsetjmp(deadline, 1) != 0)
940*7c478bd9Sstevel@tonic-gate 		return (-1);
941*7c478bd9Sstevel@tonic-gate 	(void) alarm(5);
942*7c478bd9Sstevel@tonic-gate 	/* The sysmsg driver sets NONBLOCK and NDELAY, but what the hell */
943*7c478bd9Sstevel@tonic-gate 	if ((fd = open(devp, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY)) < 0)
944*7c478bd9Sstevel@tonic-gate 		return (-1);
945*7c478bd9Sstevel@tonic-gate 	(void) alarm(0);
946*7c478bd9Sstevel@tonic-gate 	sigact.sa_flags = 0;
947*7c478bd9Sstevel@tonic-gate 	sigact.sa_handler = SIG_DFL;
948*7c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&sigact.sa_mask);
949*7c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGALRM, &sigact, NULL);
950*7c478bd9Sstevel@tonic-gate 	return (fd);
951*7c478bd9Sstevel@tonic-gate }
952*7c478bd9Sstevel@tonic-gate 
953*7c478bd9Sstevel@tonic-gate static int
954*7c478bd9Sstevel@tonic-gate lckfunc(int fd, int flag)
955*7c478bd9Sstevel@tonic-gate {
956*7c478bd9Sstevel@tonic-gate 	fl.l_type = flag;
957*7c478bd9Sstevel@tonic-gate 	return (fcntl(fd, F_SETLKW, &fl));
958*7c478bd9Sstevel@tonic-gate }
959