xref: /titanic_52/usr/src/uts/common/io/sysmsg.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 /*
30*7c478bd9Sstevel@tonic-gate  * System message redirection driver for Sun.
31*7c478bd9Sstevel@tonic-gate  *
32*7c478bd9Sstevel@tonic-gate  * Redirects system message output to the device designated as the underlying
33*7c478bd9Sstevel@tonic-gate  * "hardware" console, as given by the value of sysmvp.  The implementation
34*7c478bd9Sstevel@tonic-gate  * assumes that sysmvp denotes a STREAMS device; the assumption is justified
35*7c478bd9Sstevel@tonic-gate  * since consoles must be capable of effecting tty semantics.
36*7c478bd9Sstevel@tonic-gate  */
37*7c478bd9Sstevel@tonic-gate 
38*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/open.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/signal.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/cred.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/user.h>
46*7c478bd9Sstevel@tonic-gate #include <sys/proc.h>
47*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/uio.h>
49*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
50*7c478bd9Sstevel@tonic-gate #include <sys/file.h>
51*7c478bd9Sstevel@tonic-gate #include <sys/stream.h>
52*7c478bd9Sstevel@tonic-gate #include <sys/strsubr.h>
53*7c478bd9Sstevel@tonic-gate #include <sys/poll.h>
54*7c478bd9Sstevel@tonic-gate #include <sys/debug.h>
55*7c478bd9Sstevel@tonic-gate #include <sys/sysmsg_impl.h>
56*7c478bd9Sstevel@tonic-gate #include <sys/conf.h>
57*7c478bd9Sstevel@tonic-gate #include <sys/termios.h>
58*7c478bd9Sstevel@tonic-gate #include <sys/errno.h>
59*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
60*7c478bd9Sstevel@tonic-gate #include <sys/pathname.h>
61*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
62*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
63*7c478bd9Sstevel@tonic-gate #include <sys/consdev.h>
64*7c478bd9Sstevel@tonic-gate #include <sys/policy.h>
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate /*
67*7c478bd9Sstevel@tonic-gate  * internal functions
68*7c478bd9Sstevel@tonic-gate  */
69*7c478bd9Sstevel@tonic-gate static int sysmopen(dev_t *, int, int, cred_t *);
70*7c478bd9Sstevel@tonic-gate static int sysmclose(dev_t, int, int, cred_t *);
71*7c478bd9Sstevel@tonic-gate static int sysmread(dev_t, struct uio *, cred_t *);
72*7c478bd9Sstevel@tonic-gate static int sysmwrite(dev_t, struct uio *, cred_t *);
73*7c478bd9Sstevel@tonic-gate static int sysmioctl(dev_t, int, intptr_t, int, cred_t *, int *);
74*7c478bd9Sstevel@tonic-gate static int sysmpoll(dev_t, short, int, short *, struct pollhead **);
75*7c478bd9Sstevel@tonic-gate static int sysm_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
76*7c478bd9Sstevel@tonic-gate static int sysm_attach(dev_info_t *, ddi_attach_cmd_t);
77*7c478bd9Sstevel@tonic-gate static int sysm_detach(dev_info_t *, ddi_detach_cmd_t);
78*7c478bd9Sstevel@tonic-gate static void bind_consadm_conf(char *);
79*7c478bd9Sstevel@tonic-gate static int checkarg(dev_t);
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate static dev_info_t *sysm_dip;		/* private copy of devinfo pointer */
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate static struct cb_ops sysm_cb_ops = {
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate 	sysmopen,		/* open */
86*7c478bd9Sstevel@tonic-gate 	sysmclose,		/* close */
87*7c478bd9Sstevel@tonic-gate 	nodev,			/* strategy */
88*7c478bd9Sstevel@tonic-gate 	nodev,			/* print */
89*7c478bd9Sstevel@tonic-gate 	nodev,			/* dump */
90*7c478bd9Sstevel@tonic-gate 	sysmread,		/* read */
91*7c478bd9Sstevel@tonic-gate 	sysmwrite,		/* write */
92*7c478bd9Sstevel@tonic-gate 	sysmioctl,		/* ioctl */
93*7c478bd9Sstevel@tonic-gate 	nodev,			/* devmap */
94*7c478bd9Sstevel@tonic-gate 	nodev,			/* mmap */
95*7c478bd9Sstevel@tonic-gate 	nodev, 			/* segmap */
96*7c478bd9Sstevel@tonic-gate 	sysmpoll,		/* poll */
97*7c478bd9Sstevel@tonic-gate 	ddi_prop_op,		/* cb_prop_op */
98*7c478bd9Sstevel@tonic-gate 	NULL,			/* streamtab  */
99*7c478bd9Sstevel@tonic-gate 	D_NEW | D_MP,		/* Driver compatibility flag */
100*7c478bd9Sstevel@tonic-gate 	CB_REV,			/* cb_rev */
101*7c478bd9Sstevel@tonic-gate 	nodev,			/* aread */
102*7c478bd9Sstevel@tonic-gate 	nodev			/* awrite */
103*7c478bd9Sstevel@tonic-gate };
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate static struct dev_ops sysm_ops = {
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate 	DEVO_REV,		/* devo_rev, */
108*7c478bd9Sstevel@tonic-gate 	0,			/* refcnt  */
109*7c478bd9Sstevel@tonic-gate 	sysm_info,		/* info */
110*7c478bd9Sstevel@tonic-gate 	nulldev,		/* identify */
111*7c478bd9Sstevel@tonic-gate 	nulldev,		/* probe */
112*7c478bd9Sstevel@tonic-gate 	sysm_attach,		/* attach */
113*7c478bd9Sstevel@tonic-gate 	sysm_detach,		/* detach */
114*7c478bd9Sstevel@tonic-gate 	nodev,			/* reset */
115*7c478bd9Sstevel@tonic-gate 	&sysm_cb_ops,		/* driver operations */
116*7c478bd9Sstevel@tonic-gate 	(struct bus_ops *)0,	/* bus operations */
117*7c478bd9Sstevel@tonic-gate 	nulldev			/* power */
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate };
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate /*
122*7c478bd9Sstevel@tonic-gate  * Global variables associated with the console device:
123*7c478bd9Sstevel@tonic-gate  */
124*7c478bd9Sstevel@tonic-gate 
125*7c478bd9Sstevel@tonic-gate #define	SYS_SYSMIN	0	/* sysmsg minor number */
126*7c478bd9Sstevel@tonic-gate #define	SYS_MSGMIN	1	/* msglog minor number */
127*7c478bd9Sstevel@tonic-gate #define	SYSPATHLEN	255	/* length of device path */
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate /*
130*7c478bd9Sstevel@tonic-gate  * Private driver state:
131*7c478bd9Sstevel@tonic-gate  */
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate #define	MAXDEVS 5
134*7c478bd9Sstevel@tonic-gate 
135*7c478bd9Sstevel@tonic-gate typedef struct {
136*7c478bd9Sstevel@tonic-gate 	dev_t	dca_devt;
137*7c478bd9Sstevel@tonic-gate 	int	dca_flags;
138*7c478bd9Sstevel@tonic-gate 	vnode_t	*dca_vp;
139*7c478bd9Sstevel@tonic-gate 	krwlock_t	dca_lock;
140*7c478bd9Sstevel@tonic-gate 	char	dca_name[SYSPATHLEN];
141*7c478bd9Sstevel@tonic-gate } devicecache_t;
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate /* list of dyn. + persist. config'ed dev's */
144*7c478bd9Sstevel@tonic-gate static devicecache_t sysmcache[MAXDEVS];
145*7c478bd9Sstevel@tonic-gate static kmutex_t	dcvp_mutex;
146*7c478bd9Sstevel@tonic-gate static vnode_t	*dcvp = NULL;
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate /* flags for device cache */
149*7c478bd9Sstevel@tonic-gate #define	SYSM_DISABLED	0x0
150*7c478bd9Sstevel@tonic-gate #define	SYSM_ENABLED	0x1
151*7c478bd9Sstevel@tonic-gate 
152*7c478bd9Sstevel@tonic-gate /*
153*7c478bd9Sstevel@tonic-gate  * Module linkage information for the kernel.
154*7c478bd9Sstevel@tonic-gate  */
155*7c478bd9Sstevel@tonic-gate 
156*7c478bd9Sstevel@tonic-gate static struct modldrv modldrv = {
157*7c478bd9Sstevel@tonic-gate 	&mod_driverops, /* Type of module.  This one is a pseudo driver */
158*7c478bd9Sstevel@tonic-gate 	"System message redirection (fanout) driver %I%",
159*7c478bd9Sstevel@tonic-gate 	&sysm_ops,	/* driver ops */
160*7c478bd9Sstevel@tonic-gate };
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
163*7c478bd9Sstevel@tonic-gate 	MODREV_1,
164*7c478bd9Sstevel@tonic-gate 	&modldrv,
165*7c478bd9Sstevel@tonic-gate 	NULL
166*7c478bd9Sstevel@tonic-gate };
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate int
169*7c478bd9Sstevel@tonic-gate _init(void)
170*7c478bd9Sstevel@tonic-gate {
171*7c478bd9Sstevel@tonic-gate 	return (mod_install(&modlinkage));
172*7c478bd9Sstevel@tonic-gate }
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate int
175*7c478bd9Sstevel@tonic-gate _fini(void)
176*7c478bd9Sstevel@tonic-gate {
177*7c478bd9Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
178*7c478bd9Sstevel@tonic-gate }
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate int
181*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
182*7c478bd9Sstevel@tonic-gate {
183*7c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
184*7c478bd9Sstevel@tonic-gate }
185*7c478bd9Sstevel@tonic-gate 
186*7c478bd9Sstevel@tonic-gate /*
187*7c478bd9Sstevel@tonic-gate  * DDI glue routines
188*7c478bd9Sstevel@tonic-gate  */
189*7c478bd9Sstevel@tonic-gate static int
190*7c478bd9Sstevel@tonic-gate sysm_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
191*7c478bd9Sstevel@tonic-gate {
192*7c478bd9Sstevel@tonic-gate 	int i;
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
195*7c478bd9Sstevel@tonic-gate 	case DDI_ATTACH:
196*7c478bd9Sstevel@tonic-gate 		ASSERT(sysm_dip == NULL);
197*7c478bd9Sstevel@tonic-gate 
198*7c478bd9Sstevel@tonic-gate 		if (ddi_create_minor_node(devi, "sysmsg", S_IFCHR,
199*7c478bd9Sstevel@tonic-gate 		    SYS_SYSMIN, DDI_PSEUDO, NULL) == DDI_FAILURE ||
200*7c478bd9Sstevel@tonic-gate 		    ddi_create_minor_node(devi, "msglog", S_IFCHR,
201*7c478bd9Sstevel@tonic-gate 		    SYS_MSGMIN, DDI_PSEUDO, NULL) == DDI_FAILURE) {
202*7c478bd9Sstevel@tonic-gate 			ddi_remove_minor_node(devi, NULL);
203*7c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
204*7c478bd9Sstevel@tonic-gate 		}
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < MAXDEVS; i++) {
207*7c478bd9Sstevel@tonic-gate 			rw_init(&sysmcache[i].dca_lock, NULL, RW_DRIVER, NULL);
208*7c478bd9Sstevel@tonic-gate 		}
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate 		/* set everything up .. */
211*7c478bd9Sstevel@tonic-gate 		bind_consadm_conf("/etc/consadm.conf");
212*7c478bd9Sstevel@tonic-gate 		sysm_dip = devi;
213*7c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
214*7c478bd9Sstevel@tonic-gate 	case DDI_SUSPEND:
215*7c478bd9Sstevel@tonic-gate 	case DDI_PM_SUSPEND:
216*7c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
217*7c478bd9Sstevel@tonic-gate 	default:
218*7c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
219*7c478bd9Sstevel@tonic-gate 	}
220*7c478bd9Sstevel@tonic-gate }
221*7c478bd9Sstevel@tonic-gate 
222*7c478bd9Sstevel@tonic-gate static int
223*7c478bd9Sstevel@tonic-gate sysm_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
224*7c478bd9Sstevel@tonic-gate {
225*7c478bd9Sstevel@tonic-gate 	int i;
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
228*7c478bd9Sstevel@tonic-gate 	case DDI_DETACH:
229*7c478bd9Sstevel@tonic-gate 		ASSERT(sysm_dip == devi);
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate 		if (dcvp) {
232*7c478bd9Sstevel@tonic-gate 			(void) VOP_CLOSE(dcvp, FWRITE, 1, (offset_t)0, kcred);
233*7c478bd9Sstevel@tonic-gate 			VN_RELE(dcvp);
234*7c478bd9Sstevel@tonic-gate 			dcvp = NULL;
235*7c478bd9Sstevel@tonic-gate 		}
236*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < MAXDEVS; i++) {
237*7c478bd9Sstevel@tonic-gate 			if (sysmcache[i].dca_vp != NULL) {
238*7c478bd9Sstevel@tonic-gate 				(void) VOP_CLOSE(sysmcache[i].dca_vp, 0,
239*7c478bd9Sstevel@tonic-gate 				    1, (offset_t)0, 0);
240*7c478bd9Sstevel@tonic-gate 				VN_RELE(sysmcache[i].dca_vp);
241*7c478bd9Sstevel@tonic-gate 			}
242*7c478bd9Sstevel@tonic-gate 			sysmcache[i].dca_vp = NULL;
243*7c478bd9Sstevel@tonic-gate 			rw_destroy(&sysmcache[i].dca_lock);
244*7c478bd9Sstevel@tonic-gate 		}
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 		ddi_remove_minor_node(devi, NULL);
247*7c478bd9Sstevel@tonic-gate 		sysm_dip = NULL;
248*7c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate 	case DDI_SUSPEND:
251*7c478bd9Sstevel@tonic-gate 	case DDI_PM_SUSPEND:
252*7c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
253*7c478bd9Sstevel@tonic-gate 	default:
254*7c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
255*7c478bd9Sstevel@tonic-gate 	}
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate }
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
260*7c478bd9Sstevel@tonic-gate static int
261*7c478bd9Sstevel@tonic-gate sysm_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
262*7c478bd9Sstevel@tonic-gate {
263*7c478bd9Sstevel@tonic-gate 	int rval = DDI_FAILURE;
264*7c478bd9Sstevel@tonic-gate 	minor_t instance;
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate 	instance = getminor((dev_t)arg);
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate 	switch (infocmd) {
269*7c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2DEVINFO:
270*7c478bd9Sstevel@tonic-gate 		if (sysm_dip != NULL &&
271*7c478bd9Sstevel@tonic-gate 		    (instance == SYS_SYSMIN || instance == SYS_MSGMIN)) {
272*7c478bd9Sstevel@tonic-gate 			*result = sysm_dip;
273*7c478bd9Sstevel@tonic-gate 			rval = DDI_SUCCESS;
274*7c478bd9Sstevel@tonic-gate 		}
275*7c478bd9Sstevel@tonic-gate 		break;
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2INSTANCE:
278*7c478bd9Sstevel@tonic-gate 		if (instance == SYS_SYSMIN || instance == SYS_MSGMIN) {
279*7c478bd9Sstevel@tonic-gate 			*result = NULL;
280*7c478bd9Sstevel@tonic-gate 			rval = DDI_SUCCESS;
281*7c478bd9Sstevel@tonic-gate 		}
282*7c478bd9Sstevel@tonic-gate 		break;
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate 	default:
285*7c478bd9Sstevel@tonic-gate 		break;
286*7c478bd9Sstevel@tonic-gate 	}
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate 	return (rval);
289*7c478bd9Sstevel@tonic-gate }
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate /*
292*7c478bd9Sstevel@tonic-gate  * Parse the contents of the buffer, and bind the named
293*7c478bd9Sstevel@tonic-gate  * devices as auxiliary consoles using our own ioctl routine.
294*7c478bd9Sstevel@tonic-gate  *
295*7c478bd9Sstevel@tonic-gate  * Comments begin with '#' and are terminated only by a newline
296*7c478bd9Sstevel@tonic-gate  * Device names begin with a '/', and are terminated by a newline,
297*7c478bd9Sstevel@tonic-gate  * space, '#' or tab.
298*7c478bd9Sstevel@tonic-gate  */
299*7c478bd9Sstevel@tonic-gate static void
300*7c478bd9Sstevel@tonic-gate parse_buffer(char *buf, ssize_t fsize)
301*7c478bd9Sstevel@tonic-gate {
302*7c478bd9Sstevel@tonic-gate 	char *ebuf = buf + fsize;
303*7c478bd9Sstevel@tonic-gate 	char *devname = NULL;
304*7c478bd9Sstevel@tonic-gate 	int eatcomments = 0;
305*7c478bd9Sstevel@tonic-gate 
306*7c478bd9Sstevel@tonic-gate 	while (buf < ebuf) {
307*7c478bd9Sstevel@tonic-gate 		if (eatcomments) {
308*7c478bd9Sstevel@tonic-gate 			if (*buf++ == '\n')
309*7c478bd9Sstevel@tonic-gate 				eatcomments = 0;
310*7c478bd9Sstevel@tonic-gate 			continue;
311*7c478bd9Sstevel@tonic-gate 		}
312*7c478bd9Sstevel@tonic-gate 		switch (*buf) {
313*7c478bd9Sstevel@tonic-gate 		case '/':
314*7c478bd9Sstevel@tonic-gate 			if (devname == NULL)
315*7c478bd9Sstevel@tonic-gate 				devname = buf;
316*7c478bd9Sstevel@tonic-gate 			break;
317*7c478bd9Sstevel@tonic-gate 		case '#':
318*7c478bd9Sstevel@tonic-gate 			eatcomments = 1;
319*7c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
320*7c478bd9Sstevel@tonic-gate 		case ' ':
321*7c478bd9Sstevel@tonic-gate 		case '\t':
322*7c478bd9Sstevel@tonic-gate 		case '\n':
323*7c478bd9Sstevel@tonic-gate 			*buf = '\0';
324*7c478bd9Sstevel@tonic-gate 			if (devname == NULL)
325*7c478bd9Sstevel@tonic-gate 				break;
326*7c478bd9Sstevel@tonic-gate 			(void) sysmioctl(NODEV, CIOCSETCONSOLE,
327*7c478bd9Sstevel@tonic-gate 			    (intptr_t)devname, FNATIVE|FKIOCTL|FREAD|FWRITE,
328*7c478bd9Sstevel@tonic-gate 			    kcred, NULL);
329*7c478bd9Sstevel@tonic-gate 			devname = NULL;
330*7c478bd9Sstevel@tonic-gate 			break;
331*7c478bd9Sstevel@tonic-gate 		default:
332*7c478bd9Sstevel@tonic-gate 			break;
333*7c478bd9Sstevel@tonic-gate 		}
334*7c478bd9Sstevel@tonic-gate 		buf++;
335*7c478bd9Sstevel@tonic-gate 	}
336*7c478bd9Sstevel@tonic-gate }
337*7c478bd9Sstevel@tonic-gate 
338*7c478bd9Sstevel@tonic-gate #define	CNSADM_BYTES_MAX	2000	/* XXX  nasty fixed size */
339*7c478bd9Sstevel@tonic-gate 
340*7c478bd9Sstevel@tonic-gate static void
341*7c478bd9Sstevel@tonic-gate bind_consadm_conf(char *path)
342*7c478bd9Sstevel@tonic-gate {
343*7c478bd9Sstevel@tonic-gate 	struct vattr vattr;
344*7c478bd9Sstevel@tonic-gate 	vnode_t *vp;
345*7c478bd9Sstevel@tonic-gate 	void *buf;
346*7c478bd9Sstevel@tonic-gate 	size_t size;
347*7c478bd9Sstevel@tonic-gate 	ssize_t resid;
348*7c478bd9Sstevel@tonic-gate 	int err = 0;
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate 	if (vn_open(path, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0) != 0)
351*7c478bd9Sstevel@tonic-gate 		return;
352*7c478bd9Sstevel@tonic-gate 	vattr.va_mask = AT_SIZE;
353*7c478bd9Sstevel@tonic-gate 	if ((err = VOP_GETATTR(vp, &vattr, 0, kcred)) != 0) {
354*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "sysmsg: getattr: '%s': error %d",
355*7c478bd9Sstevel@tonic-gate 		    path, err);
356*7c478bd9Sstevel@tonic-gate 		goto closevp;
357*7c478bd9Sstevel@tonic-gate 	}
358*7c478bd9Sstevel@tonic-gate 
359*7c478bd9Sstevel@tonic-gate 	size = vattr.va_size > CNSADM_BYTES_MAX ?
360*7c478bd9Sstevel@tonic-gate 	    CNSADM_BYTES_MAX : (ssize_t)vattr.va_size;
361*7c478bd9Sstevel@tonic-gate 	buf = kmem_alloc(size, KM_SLEEP);
362*7c478bd9Sstevel@tonic-gate 
363*7c478bd9Sstevel@tonic-gate 	if ((err = vn_rdwr(UIO_READ, vp, buf, size, (offset_t)0,
364*7c478bd9Sstevel@tonic-gate 	    UIO_SYSSPACE, 0, (rlim64_t)0, kcred, &resid)) != 0)
365*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "sysmsg: vn_rdwr: '%s': error %d",
366*7c478bd9Sstevel@tonic-gate 		    path, err);
367*7c478bd9Sstevel@tonic-gate 	else
368*7c478bd9Sstevel@tonic-gate 		parse_buffer(buf, size - resid);
369*7c478bd9Sstevel@tonic-gate 
370*7c478bd9Sstevel@tonic-gate 	kmem_free(buf, size);
371*7c478bd9Sstevel@tonic-gate closevp:
372*7c478bd9Sstevel@tonic-gate 	(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, kcred);
373*7c478bd9Sstevel@tonic-gate 	VN_RELE(vp);
374*7c478bd9Sstevel@tonic-gate }
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
377*7c478bd9Sstevel@tonic-gate static int
378*7c478bd9Sstevel@tonic-gate sysmopen(dev_t *dev, int flag, int state, cred_t *cred)
379*7c478bd9Sstevel@tonic-gate {
380*7c478bd9Sstevel@tonic-gate 	int	i;
381*7c478bd9Sstevel@tonic-gate 	vnode_t	*vp;
382*7c478bd9Sstevel@tonic-gate 	minor_t instance;
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 	instance = getminor(*dev);
385*7c478bd9Sstevel@tonic-gate 
386*7c478bd9Sstevel@tonic-gate 	if (state != OTYP_CHR || (instance != 0 && instance != 1))
387*7c478bd9Sstevel@tonic-gate 		return (ENXIO);
388*7c478bd9Sstevel@tonic-gate 
389*7c478bd9Sstevel@tonic-gate 	mutex_enter(&dcvp_mutex);
390*7c478bd9Sstevel@tonic-gate 	if ((dcvp == NULL) && (vn_open("/dev/console",
391*7c478bd9Sstevel@tonic-gate 	    UIO_SYSSPACE, FWRITE, 0, &dcvp, 0, 0) != 0)) {
392*7c478bd9Sstevel@tonic-gate 		mutex_exit(&dcvp_mutex);
393*7c478bd9Sstevel@tonic-gate 		return (ENXIO);
394*7c478bd9Sstevel@tonic-gate 	}
395*7c478bd9Sstevel@tonic-gate 	mutex_exit(&dcvp_mutex);
396*7c478bd9Sstevel@tonic-gate 
397*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < MAXDEVS; i++) {
398*7c478bd9Sstevel@tonic-gate 		rw_enter(&sysmcache[i].dca_lock, RW_WRITER);
399*7c478bd9Sstevel@tonic-gate 		if ((sysmcache[i].dca_flags & SYSM_ENABLED) &&
400*7c478bd9Sstevel@tonic-gate 		    sysmcache[i].dca_vp == NULL) {
401*7c478bd9Sstevel@tonic-gate 			/*
402*7c478bd9Sstevel@tonic-gate 			 * 4196476 - FTRUNC was causing E10K to return EINVAL
403*7c478bd9Sstevel@tonic-gate 			 * on open
404*7c478bd9Sstevel@tonic-gate 			 */
405*7c478bd9Sstevel@tonic-gate 			flag = flag & ~FTRUNC;
406*7c478bd9Sstevel@tonic-gate 			/*
407*7c478bd9Sstevel@tonic-gate 			 * Open failures on the auxiliary consoles are
408*7c478bd9Sstevel@tonic-gate 			 * not returned because we don't care if some
409*7c478bd9Sstevel@tonic-gate 			 * subset get an error. We know the default console
410*7c478bd9Sstevel@tonic-gate 			 * is okay, and preserve the semantics of the
411*7c478bd9Sstevel@tonic-gate 			 * open for the default console.
412*7c478bd9Sstevel@tonic-gate 			 * Set NONBLOCK|NDELAY in case there's no carrier.
413*7c478bd9Sstevel@tonic-gate 			 */
414*7c478bd9Sstevel@tonic-gate 			if (vn_open(sysmcache[i].dca_name, UIO_SYSSPACE,
415*7c478bd9Sstevel@tonic-gate 			    flag | FNONBLOCK | FNDELAY, 0, &vp, 0, 0) == 0)
416*7c478bd9Sstevel@tonic-gate 				sysmcache[i].dca_vp = vp;
417*7c478bd9Sstevel@tonic-gate 		}
418*7c478bd9Sstevel@tonic-gate 		rw_exit(&sysmcache[i].dca_lock);
419*7c478bd9Sstevel@tonic-gate 	}
420*7c478bd9Sstevel@tonic-gate 
421*7c478bd9Sstevel@tonic-gate 	return (0);
422*7c478bd9Sstevel@tonic-gate }
423*7c478bd9Sstevel@tonic-gate 
424*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
425*7c478bd9Sstevel@tonic-gate static int
426*7c478bd9Sstevel@tonic-gate sysmclose(dev_t dev, int flag, int state, cred_t *cred)
427*7c478bd9Sstevel@tonic-gate {
428*7c478bd9Sstevel@tonic-gate 	int	i;
429*7c478bd9Sstevel@tonic-gate 
430*7c478bd9Sstevel@tonic-gate 	if (state != OTYP_CHR)
431*7c478bd9Sstevel@tonic-gate 		return (ENXIO);
432*7c478bd9Sstevel@tonic-gate 
433*7c478bd9Sstevel@tonic-gate 	/*
434*7c478bd9Sstevel@tonic-gate 	 * Close the auxiliary consoles, we're not concerned with
435*7c478bd9Sstevel@tonic-gate 	 * passing up the errors.
436*7c478bd9Sstevel@tonic-gate 	 */
437*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < MAXDEVS; i++) {
438*7c478bd9Sstevel@tonic-gate 		rw_enter(&sysmcache[i].dca_lock, RW_WRITER);
439*7c478bd9Sstevel@tonic-gate 		if (sysmcache[i].dca_vp != NULL) {
440*7c478bd9Sstevel@tonic-gate 			(void) VOP_CLOSE(sysmcache[i].dca_vp, flag,
441*7c478bd9Sstevel@tonic-gate 			    1, (offset_t)0, cred);
442*7c478bd9Sstevel@tonic-gate 			VN_RELE(sysmcache[i].dca_vp);
443*7c478bd9Sstevel@tonic-gate 			sysmcache[i].dca_vp = NULL;
444*7c478bd9Sstevel@tonic-gate 		}
445*7c478bd9Sstevel@tonic-gate 		rw_exit(&sysmcache[i].dca_lock);
446*7c478bd9Sstevel@tonic-gate 	}
447*7c478bd9Sstevel@tonic-gate 
448*7c478bd9Sstevel@tonic-gate 	return (0);
449*7c478bd9Sstevel@tonic-gate }
450*7c478bd9Sstevel@tonic-gate 
451*7c478bd9Sstevel@tonic-gate /* Reads occur only on the default console */
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
454*7c478bd9Sstevel@tonic-gate static int
455*7c478bd9Sstevel@tonic-gate sysmread(dev_t dev, struct uio *uio, cred_t *cred)
456*7c478bd9Sstevel@tonic-gate {
457*7c478bd9Sstevel@tonic-gate 	ASSERT(dcvp != NULL);
458*7c478bd9Sstevel@tonic-gate 	return (VOP_READ(dcvp, uio, 0, cred, NULL));
459*7c478bd9Sstevel@tonic-gate }
460*7c478bd9Sstevel@tonic-gate 
461*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
462*7c478bd9Sstevel@tonic-gate static int
463*7c478bd9Sstevel@tonic-gate sysmwrite(dev_t dev, struct uio *uio, cred_t *cred)
464*7c478bd9Sstevel@tonic-gate {
465*7c478bd9Sstevel@tonic-gate 	int	i = 0;
466*7c478bd9Sstevel@tonic-gate 	iovec_t	uio_iov;
467*7c478bd9Sstevel@tonic-gate 	struct uio	tuio;
468*7c478bd9Sstevel@tonic-gate 
469*7c478bd9Sstevel@tonic-gate 	ASSERT(dcvp != NULL);
470*7c478bd9Sstevel@tonic-gate 	ASSERT(uio != NULL);
471*7c478bd9Sstevel@tonic-gate 
472*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < MAXDEVS; i++) {
473*7c478bd9Sstevel@tonic-gate 		rw_enter(&sysmcache[i].dca_lock, RW_READER);
474*7c478bd9Sstevel@tonic-gate 		if (sysmcache[i].dca_vp != NULL &&
475*7c478bd9Sstevel@tonic-gate 		    (sysmcache[i].dca_flags & SYSM_ENABLED)) {
476*7c478bd9Sstevel@tonic-gate 			tuio = *uio;
477*7c478bd9Sstevel@tonic-gate 			uio_iov = *(uio->uio_iov);
478*7c478bd9Sstevel@tonic-gate 			tuio.uio_iov = &uio_iov;
479*7c478bd9Sstevel@tonic-gate 			(void) VOP_WRITE(sysmcache[i].dca_vp, &tuio, 0, cred,
480*7c478bd9Sstevel@tonic-gate 				NULL);
481*7c478bd9Sstevel@tonic-gate 		}
482*7c478bd9Sstevel@tonic-gate 		rw_exit(&sysmcache[i].dca_lock);
483*7c478bd9Sstevel@tonic-gate 	}
484*7c478bd9Sstevel@tonic-gate 	return (VOP_WRITE(dcvp, uio, 0, cred, NULL));
485*7c478bd9Sstevel@tonic-gate }
486*7c478bd9Sstevel@tonic-gate 
487*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
488*7c478bd9Sstevel@tonic-gate static int
489*7c478bd9Sstevel@tonic-gate sysmioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cred, int *rvalp)
490*7c478bd9Sstevel@tonic-gate {
491*7c478bd9Sstevel@tonic-gate 	int	rval = 0;
492*7c478bd9Sstevel@tonic-gate 	int	error = 0;
493*7c478bd9Sstevel@tonic-gate 	size_t	size = 0;
494*7c478bd9Sstevel@tonic-gate 	int	i;
495*7c478bd9Sstevel@tonic-gate 	char	*infop;
496*7c478bd9Sstevel@tonic-gate 	char	found = 0;
497*7c478bd9Sstevel@tonic-gate 	dev_t	newdevt = (dev_t)NODEV;	/* because 0 == /dev/console */
498*7c478bd9Sstevel@tonic-gate 	vnode_t	*vp;
499*7c478bd9Sstevel@tonic-gate 
500*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
501*7c478bd9Sstevel@tonic-gate 	case CIOCGETCONSOLE:
502*7c478bd9Sstevel@tonic-gate 		/* Sum over the number of enabled devices */
503*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < MAXDEVS; i++) {
504*7c478bd9Sstevel@tonic-gate 			if (sysmcache[i].dca_flags & SYSM_ENABLED)
505*7c478bd9Sstevel@tonic-gate 				/* list is space separated, followed by NULL */
506*7c478bd9Sstevel@tonic-gate 				size += strlen(sysmcache[i].dca_name) + 1;
507*7c478bd9Sstevel@tonic-gate 		}
508*7c478bd9Sstevel@tonic-gate 		if (size == 0)
509*7c478bd9Sstevel@tonic-gate 			return (0);
510*7c478bd9Sstevel@tonic-gate 		break;
511*7c478bd9Sstevel@tonic-gate 	case CIOCSETCONSOLE:
512*7c478bd9Sstevel@tonic-gate 	case CIOCRMCONSOLE:
513*7c478bd9Sstevel@tonic-gate 		size = sizeof (sysmcache[0].dca_name);
514*7c478bd9Sstevel@tonic-gate 		break;
515*7c478bd9Sstevel@tonic-gate 	case CIOCTTYCONSOLE:
516*7c478bd9Sstevel@tonic-gate 	{
517*7c478bd9Sstevel@tonic-gate 		dev_t	d;
518*7c478bd9Sstevel@tonic-gate 		dev32_t	d32;
519*7c478bd9Sstevel@tonic-gate 		extern dev_t rwsconsdev, rconsdev, uconsdev;
520*7c478bd9Sstevel@tonic-gate 		proc_t	*p;
521*7c478bd9Sstevel@tonic-gate 
522*7c478bd9Sstevel@tonic-gate 		if (drv_getparm(UPROCP, &p) != 0)
523*7c478bd9Sstevel@tonic-gate 			return (ENODEV);
524*7c478bd9Sstevel@tonic-gate 		else
525*7c478bd9Sstevel@tonic-gate 			d = cttydev(p);
526*7c478bd9Sstevel@tonic-gate 		/*
527*7c478bd9Sstevel@tonic-gate 		 * If the controlling terminal is the real
528*7c478bd9Sstevel@tonic-gate 		 * or workstation console device, map to what the
529*7c478bd9Sstevel@tonic-gate 		 * user thinks is the console device.
530*7c478bd9Sstevel@tonic-gate 		 */
531*7c478bd9Sstevel@tonic-gate 		if (d == rwsconsdev || d == rconsdev)
532*7c478bd9Sstevel@tonic-gate 			d = uconsdev;
533*7c478bd9Sstevel@tonic-gate 		if ((flag & FMODELS) != FNATIVE) {
534*7c478bd9Sstevel@tonic-gate 			if (!cmpldev(&d32, d))
535*7c478bd9Sstevel@tonic-gate 				return (EOVERFLOW);
536*7c478bd9Sstevel@tonic-gate 			if (ddi_copyout(&d32, (caddr_t)arg, sizeof (d32),
537*7c478bd9Sstevel@tonic-gate 			    flag))
538*7c478bd9Sstevel@tonic-gate 				return (EFAULT);
539*7c478bd9Sstevel@tonic-gate 		} else {
540*7c478bd9Sstevel@tonic-gate 			if (ddi_copyout(&d, (caddr_t)arg, sizeof (d), flag))
541*7c478bd9Sstevel@tonic-gate 				return (EFAULT);
542*7c478bd9Sstevel@tonic-gate 		}
543*7c478bd9Sstevel@tonic-gate 		return (0);
544*7c478bd9Sstevel@tonic-gate 	}
545*7c478bd9Sstevel@tonic-gate 	default:
546*7c478bd9Sstevel@tonic-gate 		/* everything else is sent to the console device */
547*7c478bd9Sstevel@tonic-gate 		return (VOP_IOCTL(dcvp, cmd, arg, flag, cred, rvalp));
548*7c478bd9Sstevel@tonic-gate 	}
549*7c478bd9Sstevel@tonic-gate 
550*7c478bd9Sstevel@tonic-gate 	if ((rval = secpolicy_console(cred)) != 0)
551*7c478bd9Sstevel@tonic-gate 		return (EPERM);
552*7c478bd9Sstevel@tonic-gate 
553*7c478bd9Sstevel@tonic-gate 	infop = kmem_alloc(size, KM_SLEEP);
554*7c478bd9Sstevel@tonic-gate 	if (flag & FKIOCTL)
555*7c478bd9Sstevel@tonic-gate 		error = copystr((caddr_t)arg, infop, size, NULL);
556*7c478bd9Sstevel@tonic-gate 	else
557*7c478bd9Sstevel@tonic-gate 		error = copyinstr((caddr_t)arg, infop, size, NULL);
558*7c478bd9Sstevel@tonic-gate 
559*7c478bd9Sstevel@tonic-gate 	if (error) {
560*7c478bd9Sstevel@tonic-gate 		switch (cmd) {
561*7c478bd9Sstevel@tonic-gate 		case CIOCGETCONSOLE:
562*7c478bd9Sstevel@tonic-gate 			/*
563*7c478bd9Sstevel@tonic-gate 			 * If the buffer is null, then return a byte count
564*7c478bd9Sstevel@tonic-gate 			 * to user land.
565*7c478bd9Sstevel@tonic-gate 			 */
566*7c478bd9Sstevel@tonic-gate 			*rvalp = size;
567*7c478bd9Sstevel@tonic-gate 			goto err_exit;
568*7c478bd9Sstevel@tonic-gate 		default:
569*7c478bd9Sstevel@tonic-gate 			rval = EFAULT;
570*7c478bd9Sstevel@tonic-gate 			goto err_exit;
571*7c478bd9Sstevel@tonic-gate 		}
572*7c478bd9Sstevel@tonic-gate 	}
573*7c478bd9Sstevel@tonic-gate 
574*7c478bd9Sstevel@tonic-gate 	if (infop[0] != NULL) {
575*7c478bd9Sstevel@tonic-gate 		if ((rval = lookupname(infop, UIO_SYSSPACE, FOLLOW,
576*7c478bd9Sstevel@tonic-gate 		    NULLVPP, &vp)) == 0) {
577*7c478bd9Sstevel@tonic-gate 			if (vp->v_type != VCHR) {
578*7c478bd9Sstevel@tonic-gate 				VN_RELE(vp);
579*7c478bd9Sstevel@tonic-gate 				rval = EINVAL;
580*7c478bd9Sstevel@tonic-gate 				goto err_exit;
581*7c478bd9Sstevel@tonic-gate 			}
582*7c478bd9Sstevel@tonic-gate 			newdevt = vp->v_rdev;
583*7c478bd9Sstevel@tonic-gate 			VN_RELE(vp);
584*7c478bd9Sstevel@tonic-gate 		} else
585*7c478bd9Sstevel@tonic-gate 			goto err_exit;
586*7c478bd9Sstevel@tonic-gate 	}
587*7c478bd9Sstevel@tonic-gate 
588*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
589*7c478bd9Sstevel@tonic-gate 	case CIOCGETCONSOLE:
590*7c478bd9Sstevel@tonic-gate 		/*
591*7c478bd9Sstevel@tonic-gate 		 * Return the list of device names that are enabled.
592*7c478bd9Sstevel@tonic-gate 		 */
593*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < MAXDEVS; i++) {
594*7c478bd9Sstevel@tonic-gate 			rw_enter(&sysmcache[i].dca_lock, RW_READER);
595*7c478bd9Sstevel@tonic-gate 			if (sysmcache[i].dca_flags & SYSM_ENABLED) {
596*7c478bd9Sstevel@tonic-gate 				if (infop[0] != NULL)
597*7c478bd9Sstevel@tonic-gate 					(void) strcat(infop, " ");
598*7c478bd9Sstevel@tonic-gate 				(void) strcat(infop, sysmcache[i].dca_name);
599*7c478bd9Sstevel@tonic-gate 			}
600*7c478bd9Sstevel@tonic-gate 			rw_exit(&sysmcache[i].dca_lock);
601*7c478bd9Sstevel@tonic-gate 		}
602*7c478bd9Sstevel@tonic-gate 		if (rval == 0 && copyoutstr(infop, (void *)arg, size, NULL))
603*7c478bd9Sstevel@tonic-gate 			rval = EFAULT;
604*7c478bd9Sstevel@tonic-gate 		break;
605*7c478bd9Sstevel@tonic-gate 
606*7c478bd9Sstevel@tonic-gate 	case CIOCSETCONSOLE:
607*7c478bd9Sstevel@tonic-gate 		if ((rval = checkarg(newdevt)) != 0)
608*7c478bd9Sstevel@tonic-gate 			break;
609*7c478bd9Sstevel@tonic-gate 		/*
610*7c478bd9Sstevel@tonic-gate 		 * The device does not have to be open or disabled to
611*7c478bd9Sstevel@tonic-gate 		 * perform the set console.
612*7c478bd9Sstevel@tonic-gate 		 */
613*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < MAXDEVS; i++) {
614*7c478bd9Sstevel@tonic-gate 			rw_enter(&sysmcache[i].dca_lock, RW_WRITER);
615*7c478bd9Sstevel@tonic-gate 			if (sysmcache[i].dca_devt == newdevt &&
616*7c478bd9Sstevel@tonic-gate 			    (sysmcache[i].dca_flags & SYSM_ENABLED)) {
617*7c478bd9Sstevel@tonic-gate 				(void) strcpy(sysmcache[i].dca_name, infop);
618*7c478bd9Sstevel@tonic-gate 				rval = EEXIST;
619*7c478bd9Sstevel@tonic-gate 				rw_exit(&sysmcache[i].dca_lock);
620*7c478bd9Sstevel@tonic-gate 				break;
621*7c478bd9Sstevel@tonic-gate 			} else if (sysmcache[i].dca_devt == newdevt &&
622*7c478bd9Sstevel@tonic-gate 			    sysmcache[i].dca_flags == SYSM_DISABLED) {
623*7c478bd9Sstevel@tonic-gate 				sysmcache[i].dca_flags |= SYSM_ENABLED;
624*7c478bd9Sstevel@tonic-gate 				(void) strcpy(sysmcache[i].dca_name, infop);
625*7c478bd9Sstevel@tonic-gate 				rw_exit(&sysmcache[i].dca_lock);
626*7c478bd9Sstevel@tonic-gate 				found = 1;
627*7c478bd9Sstevel@tonic-gate 				break;
628*7c478bd9Sstevel@tonic-gate 			} else if (sysmcache[i].dca_devt == 0) {
629*7c478bd9Sstevel@tonic-gate 				ASSERT(sysmcache[i].dca_vp == NULL &&
630*7c478bd9Sstevel@tonic-gate 				    sysmcache[i].dca_flags == SYSM_DISABLED);
631*7c478bd9Sstevel@tonic-gate 				(void) strcpy(sysmcache[i].dca_name, infop);
632*7c478bd9Sstevel@tonic-gate 				sysmcache[i].dca_flags = SYSM_ENABLED;
633*7c478bd9Sstevel@tonic-gate 				sysmcache[i].dca_devt = newdevt;
634*7c478bd9Sstevel@tonic-gate 				rw_exit(&sysmcache[i].dca_lock);
635*7c478bd9Sstevel@tonic-gate 				found = 1;
636*7c478bd9Sstevel@tonic-gate 				break;
637*7c478bd9Sstevel@tonic-gate 			}
638*7c478bd9Sstevel@tonic-gate 			rw_exit(&sysmcache[i].dca_lock);
639*7c478bd9Sstevel@tonic-gate 		}
640*7c478bd9Sstevel@tonic-gate 		if (found == 0 && rval == 0)
641*7c478bd9Sstevel@tonic-gate 			rval = ENOENT;
642*7c478bd9Sstevel@tonic-gate 		break;
643*7c478bd9Sstevel@tonic-gate 
644*7c478bd9Sstevel@tonic-gate 	case CIOCRMCONSOLE:
645*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < MAXDEVS; i++) {
646*7c478bd9Sstevel@tonic-gate 			rw_enter(&sysmcache[i].dca_lock, RW_WRITER);
647*7c478bd9Sstevel@tonic-gate 			if (sysmcache[i].dca_devt == newdevt) {
648*7c478bd9Sstevel@tonic-gate 				sysmcache[i].dca_flags = SYSM_DISABLED;
649*7c478bd9Sstevel@tonic-gate 				sysmcache[i].dca_name[0] = '\0';
650*7c478bd9Sstevel@tonic-gate 				rw_exit(&sysmcache[i].dca_lock);
651*7c478bd9Sstevel@tonic-gate 				found = 1;
652*7c478bd9Sstevel@tonic-gate 				break;
653*7c478bd9Sstevel@tonic-gate 			}
654*7c478bd9Sstevel@tonic-gate 			rw_exit(&sysmcache[i].dca_lock);
655*7c478bd9Sstevel@tonic-gate 		}
656*7c478bd9Sstevel@tonic-gate 		if (found == 0)
657*7c478bd9Sstevel@tonic-gate 			rval = ENOENT;
658*7c478bd9Sstevel@tonic-gate 		break;
659*7c478bd9Sstevel@tonic-gate 
660*7c478bd9Sstevel@tonic-gate 	default:
661*7c478bd9Sstevel@tonic-gate 		break;
662*7c478bd9Sstevel@tonic-gate 	}
663*7c478bd9Sstevel@tonic-gate 
664*7c478bd9Sstevel@tonic-gate err_exit:
665*7c478bd9Sstevel@tonic-gate 	kmem_free(infop, size);
666*7c478bd9Sstevel@tonic-gate 	return (rval);
667*7c478bd9Sstevel@tonic-gate }
668*7c478bd9Sstevel@tonic-gate 
669*7c478bd9Sstevel@tonic-gate /* As with the read, we poll only the default console */
670*7c478bd9Sstevel@tonic-gate 
671*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
672*7c478bd9Sstevel@tonic-gate static int
673*7c478bd9Sstevel@tonic-gate sysmpoll(dev_t dev, short events, int anyyet, short *reventsp,
674*7c478bd9Sstevel@tonic-gate 	struct pollhead **phpp)
675*7c478bd9Sstevel@tonic-gate {
676*7c478bd9Sstevel@tonic-gate 	return (VOP_POLL(dcvp, events, anyyet, reventsp, phpp));
677*7c478bd9Sstevel@tonic-gate }
678*7c478bd9Sstevel@tonic-gate 
679*7c478bd9Sstevel@tonic-gate /* Sanity check that the device is good */
680*7c478bd9Sstevel@tonic-gate static int
681*7c478bd9Sstevel@tonic-gate checkarg(dev_t devt)
682*7c478bd9Sstevel@tonic-gate {
683*7c478bd9Sstevel@tonic-gate 	int rval = 0;
684*7c478bd9Sstevel@tonic-gate 	vnode_t	*vp;
685*7c478bd9Sstevel@tonic-gate 	extern dev_t rwsconsdev, rconsdev, uconsdev;
686*7c478bd9Sstevel@tonic-gate 
687*7c478bd9Sstevel@tonic-gate 	if (devt == rconsdev || devt == rwsconsdev || devt == uconsdev) {
688*7c478bd9Sstevel@tonic-gate 		rval = EBUSY;
689*7c478bd9Sstevel@tonic-gate 		goto err_exit;
690*7c478bd9Sstevel@tonic-gate 	}
691*7c478bd9Sstevel@tonic-gate 	if ((rval = lookupname("/dev/sysmsg", UIO_SYSSPACE, FOLLOW,
692*7c478bd9Sstevel@tonic-gate 	    NULLVPP, &vp)) == 0) {
693*7c478bd9Sstevel@tonic-gate 		if (devt == vp->v_rdev) {
694*7c478bd9Sstevel@tonic-gate 			VN_RELE(vp);
695*7c478bd9Sstevel@tonic-gate 			rval = EINVAL;
696*7c478bd9Sstevel@tonic-gate 			goto err_exit;
697*7c478bd9Sstevel@tonic-gate 		}
698*7c478bd9Sstevel@tonic-gate 		VN_RELE(vp);
699*7c478bd9Sstevel@tonic-gate 	}
700*7c478bd9Sstevel@tonic-gate 	if ((rval = lookupname("/dev/msglog", UIO_SYSSPACE, FOLLOW,
701*7c478bd9Sstevel@tonic-gate 	    NULLVPP, &vp)) == 0) {
702*7c478bd9Sstevel@tonic-gate 		if (devt == vp->v_rdev) {
703*7c478bd9Sstevel@tonic-gate 			VN_RELE(vp);
704*7c478bd9Sstevel@tonic-gate 			rval = EINVAL;
705*7c478bd9Sstevel@tonic-gate 			goto err_exit;
706*7c478bd9Sstevel@tonic-gate 		}
707*7c478bd9Sstevel@tonic-gate 		VN_RELE(vp);
708*7c478bd9Sstevel@tonic-gate 	}
709*7c478bd9Sstevel@tonic-gate 
710*7c478bd9Sstevel@tonic-gate err_exit:
711*7c478bd9Sstevel@tonic-gate 	return (rval);
712*7c478bd9Sstevel@tonic-gate }
713