17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 23*ad1660d0Smeem * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * System message redirection driver for Sun. 317c478bd9Sstevel@tonic-gate * 327c478bd9Sstevel@tonic-gate * Redirects system message output to the device designated as the underlying 337c478bd9Sstevel@tonic-gate * "hardware" console, as given by the value of sysmvp. The implementation 347c478bd9Sstevel@tonic-gate * assumes that sysmvp denotes a STREAMS device; the assumption is justified 357c478bd9Sstevel@tonic-gate * since consoles must be capable of effecting tty semantics. 367c478bd9Sstevel@tonic-gate */ 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate #include <sys/types.h> 397c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 407c478bd9Sstevel@tonic-gate #include <sys/open.h> 417c478bd9Sstevel@tonic-gate #include <sys/param.h> 427c478bd9Sstevel@tonic-gate #include <sys/systm.h> 437c478bd9Sstevel@tonic-gate #include <sys/signal.h> 447c478bd9Sstevel@tonic-gate #include <sys/cred.h> 457c478bd9Sstevel@tonic-gate #include <sys/user.h> 467c478bd9Sstevel@tonic-gate #include <sys/proc.h> 477c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 487c478bd9Sstevel@tonic-gate #include <sys/uio.h> 497c478bd9Sstevel@tonic-gate #include <sys/stat.h> 507c478bd9Sstevel@tonic-gate #include <sys/file.h> 51*ad1660d0Smeem #include <sys/session.h> 527c478bd9Sstevel@tonic-gate #include <sys/stream.h> 537c478bd9Sstevel@tonic-gate #include <sys/strsubr.h> 547c478bd9Sstevel@tonic-gate #include <sys/poll.h> 557c478bd9Sstevel@tonic-gate #include <sys/debug.h> 567c478bd9Sstevel@tonic-gate #include <sys/sysmsg_impl.h> 577c478bd9Sstevel@tonic-gate #include <sys/conf.h> 587c478bd9Sstevel@tonic-gate #include <sys/termios.h> 597c478bd9Sstevel@tonic-gate #include <sys/errno.h> 607c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 617c478bd9Sstevel@tonic-gate #include <sys/pathname.h> 627c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 637c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 647c478bd9Sstevel@tonic-gate #include <sys/consdev.h> 657c478bd9Sstevel@tonic-gate #include <sys/policy.h> 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate /* 687c478bd9Sstevel@tonic-gate * internal functions 697c478bd9Sstevel@tonic-gate */ 707c478bd9Sstevel@tonic-gate static int sysmopen(dev_t *, int, int, cred_t *); 717c478bd9Sstevel@tonic-gate static int sysmclose(dev_t, int, int, cred_t *); 727c478bd9Sstevel@tonic-gate static int sysmread(dev_t, struct uio *, cred_t *); 737c478bd9Sstevel@tonic-gate static int sysmwrite(dev_t, struct uio *, cred_t *); 747c478bd9Sstevel@tonic-gate static int sysmioctl(dev_t, int, intptr_t, int, cred_t *, int *); 757c478bd9Sstevel@tonic-gate static int sysmpoll(dev_t, short, int, short *, struct pollhead **); 767c478bd9Sstevel@tonic-gate static int sysm_info(dev_info_t *, ddi_info_cmd_t, void *, void **); 777c478bd9Sstevel@tonic-gate static int sysm_attach(dev_info_t *, ddi_attach_cmd_t); 787c478bd9Sstevel@tonic-gate static int sysm_detach(dev_info_t *, ddi_detach_cmd_t); 797c478bd9Sstevel@tonic-gate static void bind_consadm_conf(char *); 807c478bd9Sstevel@tonic-gate static int checkarg(dev_t); 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate static dev_info_t *sysm_dip; /* private copy of devinfo pointer */ 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate static struct cb_ops sysm_cb_ops = { 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate sysmopen, /* open */ 877c478bd9Sstevel@tonic-gate sysmclose, /* close */ 887c478bd9Sstevel@tonic-gate nodev, /* strategy */ 897c478bd9Sstevel@tonic-gate nodev, /* print */ 907c478bd9Sstevel@tonic-gate nodev, /* dump */ 917c478bd9Sstevel@tonic-gate sysmread, /* read */ 927c478bd9Sstevel@tonic-gate sysmwrite, /* write */ 937c478bd9Sstevel@tonic-gate sysmioctl, /* ioctl */ 947c478bd9Sstevel@tonic-gate nodev, /* devmap */ 957c478bd9Sstevel@tonic-gate nodev, /* mmap */ 967c478bd9Sstevel@tonic-gate nodev, /* segmap */ 977c478bd9Sstevel@tonic-gate sysmpoll, /* poll */ 987c478bd9Sstevel@tonic-gate ddi_prop_op, /* cb_prop_op */ 997c478bd9Sstevel@tonic-gate NULL, /* streamtab */ 1007c478bd9Sstevel@tonic-gate D_NEW | D_MP, /* Driver compatibility flag */ 1017c478bd9Sstevel@tonic-gate CB_REV, /* cb_rev */ 1027c478bd9Sstevel@tonic-gate nodev, /* aread */ 1037c478bd9Sstevel@tonic-gate nodev /* awrite */ 1047c478bd9Sstevel@tonic-gate }; 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate static struct dev_ops sysm_ops = { 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate DEVO_REV, /* devo_rev, */ 1097c478bd9Sstevel@tonic-gate 0, /* refcnt */ 1107c478bd9Sstevel@tonic-gate sysm_info, /* info */ 1117c478bd9Sstevel@tonic-gate nulldev, /* identify */ 1127c478bd9Sstevel@tonic-gate nulldev, /* probe */ 1137c478bd9Sstevel@tonic-gate sysm_attach, /* attach */ 1147c478bd9Sstevel@tonic-gate sysm_detach, /* detach */ 1157c478bd9Sstevel@tonic-gate nodev, /* reset */ 1167c478bd9Sstevel@tonic-gate &sysm_cb_ops, /* driver operations */ 1177c478bd9Sstevel@tonic-gate (struct bus_ops *)0, /* bus operations */ 1187c478bd9Sstevel@tonic-gate nulldev /* power */ 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate }; 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate /* 1237c478bd9Sstevel@tonic-gate * Global variables associated with the console device: 1247c478bd9Sstevel@tonic-gate */ 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate #define SYS_SYSMIN 0 /* sysmsg minor number */ 1277c478bd9Sstevel@tonic-gate #define SYS_MSGMIN 1 /* msglog minor number */ 1287c478bd9Sstevel@tonic-gate #define SYSPATHLEN 255 /* length of device path */ 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate /* 1317c478bd9Sstevel@tonic-gate * Private driver state: 1327c478bd9Sstevel@tonic-gate */ 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate #define MAXDEVS 5 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate typedef struct { 1377c478bd9Sstevel@tonic-gate dev_t dca_devt; 1387c478bd9Sstevel@tonic-gate int dca_flags; 1397c478bd9Sstevel@tonic-gate vnode_t *dca_vp; 1407c478bd9Sstevel@tonic-gate krwlock_t dca_lock; 1417c478bd9Sstevel@tonic-gate char dca_name[SYSPATHLEN]; 1427c478bd9Sstevel@tonic-gate } devicecache_t; 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate /* list of dyn. + persist. config'ed dev's */ 1457c478bd9Sstevel@tonic-gate static devicecache_t sysmcache[MAXDEVS]; 1467c478bd9Sstevel@tonic-gate static kmutex_t dcvp_mutex; 1477c478bd9Sstevel@tonic-gate static vnode_t *dcvp = NULL; 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate /* flags for device cache */ 1507c478bd9Sstevel@tonic-gate #define SYSM_DISABLED 0x0 1517c478bd9Sstevel@tonic-gate #define SYSM_ENABLED 0x1 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate /* 1547c478bd9Sstevel@tonic-gate * Module linkage information for the kernel. 1557c478bd9Sstevel@tonic-gate */ 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate static struct modldrv modldrv = { 1587c478bd9Sstevel@tonic-gate &mod_driverops, /* Type of module. This one is a pseudo driver */ 1597c478bd9Sstevel@tonic-gate "System message redirection (fanout) driver %I%", 1607c478bd9Sstevel@tonic-gate &sysm_ops, /* driver ops */ 1617c478bd9Sstevel@tonic-gate }; 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 1647c478bd9Sstevel@tonic-gate MODREV_1, 1657c478bd9Sstevel@tonic-gate &modldrv, 1667c478bd9Sstevel@tonic-gate NULL 1677c478bd9Sstevel@tonic-gate }; 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate int 1707c478bd9Sstevel@tonic-gate _init(void) 1717c478bd9Sstevel@tonic-gate { 1727c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage)); 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate int 1767c478bd9Sstevel@tonic-gate _fini(void) 1777c478bd9Sstevel@tonic-gate { 1787c478bd9Sstevel@tonic-gate return (mod_remove(&modlinkage)); 1797c478bd9Sstevel@tonic-gate } 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate int 1827c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 1837c478bd9Sstevel@tonic-gate { 1847c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 1857c478bd9Sstevel@tonic-gate } 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate /* 1887c478bd9Sstevel@tonic-gate * DDI glue routines 1897c478bd9Sstevel@tonic-gate */ 1907c478bd9Sstevel@tonic-gate static int 1917c478bd9Sstevel@tonic-gate sysm_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 1927c478bd9Sstevel@tonic-gate { 1937c478bd9Sstevel@tonic-gate int i; 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate switch (cmd) { 1967c478bd9Sstevel@tonic-gate case DDI_ATTACH: 1977c478bd9Sstevel@tonic-gate ASSERT(sysm_dip == NULL); 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate if (ddi_create_minor_node(devi, "sysmsg", S_IFCHR, 2007c478bd9Sstevel@tonic-gate SYS_SYSMIN, DDI_PSEUDO, NULL) == DDI_FAILURE || 2017c478bd9Sstevel@tonic-gate ddi_create_minor_node(devi, "msglog", S_IFCHR, 2027c478bd9Sstevel@tonic-gate SYS_MSGMIN, DDI_PSEUDO, NULL) == DDI_FAILURE) { 2037c478bd9Sstevel@tonic-gate ddi_remove_minor_node(devi, NULL); 2047c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 2057c478bd9Sstevel@tonic-gate } 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate for (i = 0; i < MAXDEVS; i++) { 2087c478bd9Sstevel@tonic-gate rw_init(&sysmcache[i].dca_lock, NULL, RW_DRIVER, NULL); 2097c478bd9Sstevel@tonic-gate } 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate /* set everything up .. */ 2127c478bd9Sstevel@tonic-gate bind_consadm_conf("/etc/consadm.conf"); 2137c478bd9Sstevel@tonic-gate sysm_dip = devi; 2147c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 2157c478bd9Sstevel@tonic-gate case DDI_SUSPEND: 2167c478bd9Sstevel@tonic-gate case DDI_PM_SUSPEND: 2177c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 2187c478bd9Sstevel@tonic-gate default: 2197c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate static int 2247c478bd9Sstevel@tonic-gate sysm_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 2257c478bd9Sstevel@tonic-gate { 2267c478bd9Sstevel@tonic-gate int i; 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate switch (cmd) { 2297c478bd9Sstevel@tonic-gate case DDI_DETACH: 2307c478bd9Sstevel@tonic-gate ASSERT(sysm_dip == devi); 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate if (dcvp) { 2337c478bd9Sstevel@tonic-gate (void) VOP_CLOSE(dcvp, FWRITE, 1, (offset_t)0, kcred); 2347c478bd9Sstevel@tonic-gate VN_RELE(dcvp); 2357c478bd9Sstevel@tonic-gate dcvp = NULL; 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate for (i = 0; i < MAXDEVS; i++) { 2387c478bd9Sstevel@tonic-gate if (sysmcache[i].dca_vp != NULL) { 2397c478bd9Sstevel@tonic-gate (void) VOP_CLOSE(sysmcache[i].dca_vp, 0, 2407c478bd9Sstevel@tonic-gate 1, (offset_t)0, 0); 2417c478bd9Sstevel@tonic-gate VN_RELE(sysmcache[i].dca_vp); 2427c478bd9Sstevel@tonic-gate } 2437c478bd9Sstevel@tonic-gate sysmcache[i].dca_vp = NULL; 2447c478bd9Sstevel@tonic-gate rw_destroy(&sysmcache[i].dca_lock); 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate ddi_remove_minor_node(devi, NULL); 2487c478bd9Sstevel@tonic-gate sysm_dip = NULL; 2497c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate case DDI_SUSPEND: 2527c478bd9Sstevel@tonic-gate case DDI_PM_SUSPEND: 2537c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 2547c478bd9Sstevel@tonic-gate default: 2557c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2617c478bd9Sstevel@tonic-gate static int 2627c478bd9Sstevel@tonic-gate sysm_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 2637c478bd9Sstevel@tonic-gate { 2647c478bd9Sstevel@tonic-gate int rval = DDI_FAILURE; 2657c478bd9Sstevel@tonic-gate minor_t instance; 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate instance = getminor((dev_t)arg); 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate switch (infocmd) { 2707c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 2717c478bd9Sstevel@tonic-gate if (sysm_dip != NULL && 2727c478bd9Sstevel@tonic-gate (instance == SYS_SYSMIN || instance == SYS_MSGMIN)) { 2737c478bd9Sstevel@tonic-gate *result = sysm_dip; 2747c478bd9Sstevel@tonic-gate rval = DDI_SUCCESS; 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate break; 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 2797c478bd9Sstevel@tonic-gate if (instance == SYS_SYSMIN || instance == SYS_MSGMIN) { 2807c478bd9Sstevel@tonic-gate *result = NULL; 2817c478bd9Sstevel@tonic-gate rval = DDI_SUCCESS; 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate break; 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate default: 2867c478bd9Sstevel@tonic-gate break; 2877c478bd9Sstevel@tonic-gate } 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate return (rval); 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate /* 2937c478bd9Sstevel@tonic-gate * Parse the contents of the buffer, and bind the named 2947c478bd9Sstevel@tonic-gate * devices as auxiliary consoles using our own ioctl routine. 2957c478bd9Sstevel@tonic-gate * 2967c478bd9Sstevel@tonic-gate * Comments begin with '#' and are terminated only by a newline 2977c478bd9Sstevel@tonic-gate * Device names begin with a '/', and are terminated by a newline, 2987c478bd9Sstevel@tonic-gate * space, '#' or tab. 2997c478bd9Sstevel@tonic-gate */ 3007c478bd9Sstevel@tonic-gate static void 3017c478bd9Sstevel@tonic-gate parse_buffer(char *buf, ssize_t fsize) 3027c478bd9Sstevel@tonic-gate { 3037c478bd9Sstevel@tonic-gate char *ebuf = buf + fsize; 3047c478bd9Sstevel@tonic-gate char *devname = NULL; 3057c478bd9Sstevel@tonic-gate int eatcomments = 0; 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate while (buf < ebuf) { 3087c478bd9Sstevel@tonic-gate if (eatcomments) { 3097c478bd9Sstevel@tonic-gate if (*buf++ == '\n') 3107c478bd9Sstevel@tonic-gate eatcomments = 0; 3117c478bd9Sstevel@tonic-gate continue; 3127c478bd9Sstevel@tonic-gate } 3137c478bd9Sstevel@tonic-gate switch (*buf) { 3147c478bd9Sstevel@tonic-gate case '/': 3157c478bd9Sstevel@tonic-gate if (devname == NULL) 3167c478bd9Sstevel@tonic-gate devname = buf; 3177c478bd9Sstevel@tonic-gate break; 3187c478bd9Sstevel@tonic-gate case '#': 3197c478bd9Sstevel@tonic-gate eatcomments = 1; 3207c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 3217c478bd9Sstevel@tonic-gate case ' ': 3227c478bd9Sstevel@tonic-gate case '\t': 3237c478bd9Sstevel@tonic-gate case '\n': 3247c478bd9Sstevel@tonic-gate *buf = '\0'; 3257c478bd9Sstevel@tonic-gate if (devname == NULL) 3267c478bd9Sstevel@tonic-gate break; 3277c478bd9Sstevel@tonic-gate (void) sysmioctl(NODEV, CIOCSETCONSOLE, 3287c478bd9Sstevel@tonic-gate (intptr_t)devname, FNATIVE|FKIOCTL|FREAD|FWRITE, 3297c478bd9Sstevel@tonic-gate kcred, NULL); 3307c478bd9Sstevel@tonic-gate devname = NULL; 3317c478bd9Sstevel@tonic-gate break; 3327c478bd9Sstevel@tonic-gate default: 3337c478bd9Sstevel@tonic-gate break; 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate buf++; 3367c478bd9Sstevel@tonic-gate } 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate #define CNSADM_BYTES_MAX 2000 /* XXX nasty fixed size */ 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate static void 3427c478bd9Sstevel@tonic-gate bind_consadm_conf(char *path) 3437c478bd9Sstevel@tonic-gate { 3447c478bd9Sstevel@tonic-gate struct vattr vattr; 3457c478bd9Sstevel@tonic-gate vnode_t *vp; 3467c478bd9Sstevel@tonic-gate void *buf; 3477c478bd9Sstevel@tonic-gate size_t size; 3487c478bd9Sstevel@tonic-gate ssize_t resid; 3497c478bd9Sstevel@tonic-gate int err = 0; 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate if (vn_open(path, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0) != 0) 3527c478bd9Sstevel@tonic-gate return; 3537c478bd9Sstevel@tonic-gate vattr.va_mask = AT_SIZE; 3547c478bd9Sstevel@tonic-gate if ((err = VOP_GETATTR(vp, &vattr, 0, kcred)) != 0) { 3557c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "sysmsg: getattr: '%s': error %d", 3567c478bd9Sstevel@tonic-gate path, err); 3577c478bd9Sstevel@tonic-gate goto closevp; 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate size = vattr.va_size > CNSADM_BYTES_MAX ? 3617c478bd9Sstevel@tonic-gate CNSADM_BYTES_MAX : (ssize_t)vattr.va_size; 3627c478bd9Sstevel@tonic-gate buf = kmem_alloc(size, KM_SLEEP); 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate if ((err = vn_rdwr(UIO_READ, vp, buf, size, (offset_t)0, 3657c478bd9Sstevel@tonic-gate UIO_SYSSPACE, 0, (rlim64_t)0, kcred, &resid)) != 0) 3667c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "sysmsg: vn_rdwr: '%s': error %d", 3677c478bd9Sstevel@tonic-gate path, err); 3687c478bd9Sstevel@tonic-gate else 3697c478bd9Sstevel@tonic-gate parse_buffer(buf, size - resid); 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate kmem_free(buf, size); 3727c478bd9Sstevel@tonic-gate closevp: 3737c478bd9Sstevel@tonic-gate (void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, kcred); 3747c478bd9Sstevel@tonic-gate VN_RELE(vp); 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate /* ARGSUSED */ 3787c478bd9Sstevel@tonic-gate static int 3797c478bd9Sstevel@tonic-gate sysmopen(dev_t *dev, int flag, int state, cred_t *cred) 3807c478bd9Sstevel@tonic-gate { 3817c478bd9Sstevel@tonic-gate int i; 3827c478bd9Sstevel@tonic-gate vnode_t *vp; 3837c478bd9Sstevel@tonic-gate minor_t instance; 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate instance = getminor(*dev); 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate if (state != OTYP_CHR || (instance != 0 && instance != 1)) 3887c478bd9Sstevel@tonic-gate return (ENXIO); 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate mutex_enter(&dcvp_mutex); 3917c478bd9Sstevel@tonic-gate if ((dcvp == NULL) && (vn_open("/dev/console", 3927c478bd9Sstevel@tonic-gate UIO_SYSSPACE, FWRITE, 0, &dcvp, 0, 0) != 0)) { 3937c478bd9Sstevel@tonic-gate mutex_exit(&dcvp_mutex); 3947c478bd9Sstevel@tonic-gate return (ENXIO); 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate mutex_exit(&dcvp_mutex); 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate for (i = 0; i < MAXDEVS; i++) { 3997c478bd9Sstevel@tonic-gate rw_enter(&sysmcache[i].dca_lock, RW_WRITER); 4007c478bd9Sstevel@tonic-gate if ((sysmcache[i].dca_flags & SYSM_ENABLED) && 4017c478bd9Sstevel@tonic-gate sysmcache[i].dca_vp == NULL) { 4027c478bd9Sstevel@tonic-gate /* 4037c478bd9Sstevel@tonic-gate * 4196476 - FTRUNC was causing E10K to return EINVAL 4047c478bd9Sstevel@tonic-gate * on open 4057c478bd9Sstevel@tonic-gate */ 4067c478bd9Sstevel@tonic-gate flag = flag & ~FTRUNC; 4077c478bd9Sstevel@tonic-gate /* 4087c478bd9Sstevel@tonic-gate * Open failures on the auxiliary consoles are 4097c478bd9Sstevel@tonic-gate * not returned because we don't care if some 4107c478bd9Sstevel@tonic-gate * subset get an error. We know the default console 4117c478bd9Sstevel@tonic-gate * is okay, and preserve the semantics of the 4127c478bd9Sstevel@tonic-gate * open for the default console. 4137c478bd9Sstevel@tonic-gate * Set NONBLOCK|NDELAY in case there's no carrier. 4147c478bd9Sstevel@tonic-gate */ 4157c478bd9Sstevel@tonic-gate if (vn_open(sysmcache[i].dca_name, UIO_SYSSPACE, 4167c478bd9Sstevel@tonic-gate flag | FNONBLOCK | FNDELAY, 0, &vp, 0, 0) == 0) 4177c478bd9Sstevel@tonic-gate sysmcache[i].dca_vp = vp; 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate rw_exit(&sysmcache[i].dca_lock); 4207c478bd9Sstevel@tonic-gate } 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate return (0); 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate /* ARGSUSED */ 4267c478bd9Sstevel@tonic-gate static int 4277c478bd9Sstevel@tonic-gate sysmclose(dev_t dev, int flag, int state, cred_t *cred) 4287c478bd9Sstevel@tonic-gate { 4297c478bd9Sstevel@tonic-gate int i; 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate if (state != OTYP_CHR) 4327c478bd9Sstevel@tonic-gate return (ENXIO); 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate /* 4357c478bd9Sstevel@tonic-gate * Close the auxiliary consoles, we're not concerned with 4367c478bd9Sstevel@tonic-gate * passing up the errors. 4377c478bd9Sstevel@tonic-gate */ 4387c478bd9Sstevel@tonic-gate for (i = 0; i < MAXDEVS; i++) { 4397c478bd9Sstevel@tonic-gate rw_enter(&sysmcache[i].dca_lock, RW_WRITER); 4407c478bd9Sstevel@tonic-gate if (sysmcache[i].dca_vp != NULL) { 4417c478bd9Sstevel@tonic-gate (void) VOP_CLOSE(sysmcache[i].dca_vp, flag, 4427c478bd9Sstevel@tonic-gate 1, (offset_t)0, cred); 4437c478bd9Sstevel@tonic-gate VN_RELE(sysmcache[i].dca_vp); 4447c478bd9Sstevel@tonic-gate sysmcache[i].dca_vp = NULL; 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate rw_exit(&sysmcache[i].dca_lock); 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate return (0); 4507c478bd9Sstevel@tonic-gate } 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate /* Reads occur only on the default console */ 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate /* ARGSUSED */ 4557c478bd9Sstevel@tonic-gate static int 4567c478bd9Sstevel@tonic-gate sysmread(dev_t dev, struct uio *uio, cred_t *cred) 4577c478bd9Sstevel@tonic-gate { 4587c478bd9Sstevel@tonic-gate ASSERT(dcvp != NULL); 4597c478bd9Sstevel@tonic-gate return (VOP_READ(dcvp, uio, 0, cred, NULL)); 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate /* ARGSUSED */ 4637c478bd9Sstevel@tonic-gate static int 4647c478bd9Sstevel@tonic-gate sysmwrite(dev_t dev, struct uio *uio, cred_t *cred) 4657c478bd9Sstevel@tonic-gate { 4667c478bd9Sstevel@tonic-gate int i = 0; 4677c478bd9Sstevel@tonic-gate iovec_t uio_iov; 4687c478bd9Sstevel@tonic-gate struct uio tuio; 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate ASSERT(dcvp != NULL); 4717c478bd9Sstevel@tonic-gate ASSERT(uio != NULL); 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate for (i = 0; i < MAXDEVS; i++) { 4747c478bd9Sstevel@tonic-gate rw_enter(&sysmcache[i].dca_lock, RW_READER); 4757c478bd9Sstevel@tonic-gate if (sysmcache[i].dca_vp != NULL && 4767c478bd9Sstevel@tonic-gate (sysmcache[i].dca_flags & SYSM_ENABLED)) { 4777c478bd9Sstevel@tonic-gate tuio = *uio; 4787c478bd9Sstevel@tonic-gate uio_iov = *(uio->uio_iov); 4797c478bd9Sstevel@tonic-gate tuio.uio_iov = &uio_iov; 4807c478bd9Sstevel@tonic-gate (void) VOP_WRITE(sysmcache[i].dca_vp, &tuio, 0, cred, 4817c478bd9Sstevel@tonic-gate NULL); 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate rw_exit(&sysmcache[i].dca_lock); 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate return (VOP_WRITE(dcvp, uio, 0, cred, NULL)); 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate /* ARGSUSED */ 4897c478bd9Sstevel@tonic-gate static int 4907c478bd9Sstevel@tonic-gate sysmioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cred, int *rvalp) 4917c478bd9Sstevel@tonic-gate { 4927c478bd9Sstevel@tonic-gate int rval = 0; 4937c478bd9Sstevel@tonic-gate int error = 0; 4947c478bd9Sstevel@tonic-gate size_t size = 0; 4957c478bd9Sstevel@tonic-gate int i; 4967c478bd9Sstevel@tonic-gate char *infop; 4977c478bd9Sstevel@tonic-gate char found = 0; 4987c478bd9Sstevel@tonic-gate dev_t newdevt = (dev_t)NODEV; /* because 0 == /dev/console */ 4997c478bd9Sstevel@tonic-gate vnode_t *vp; 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate switch (cmd) { 5027c478bd9Sstevel@tonic-gate case CIOCGETCONSOLE: 5037c478bd9Sstevel@tonic-gate /* Sum over the number of enabled devices */ 5047c478bd9Sstevel@tonic-gate for (i = 0; i < MAXDEVS; i++) { 5057c478bd9Sstevel@tonic-gate if (sysmcache[i].dca_flags & SYSM_ENABLED) 5067c478bd9Sstevel@tonic-gate /* list is space separated, followed by NULL */ 5077c478bd9Sstevel@tonic-gate size += strlen(sysmcache[i].dca_name) + 1; 5087c478bd9Sstevel@tonic-gate } 5097c478bd9Sstevel@tonic-gate if (size == 0) 5107c478bd9Sstevel@tonic-gate return (0); 5117c478bd9Sstevel@tonic-gate break; 5127c478bd9Sstevel@tonic-gate case CIOCSETCONSOLE: 5137c478bd9Sstevel@tonic-gate case CIOCRMCONSOLE: 5147c478bd9Sstevel@tonic-gate size = sizeof (sysmcache[0].dca_name); 5157c478bd9Sstevel@tonic-gate break; 5167c478bd9Sstevel@tonic-gate case CIOCTTYCONSOLE: 5177c478bd9Sstevel@tonic-gate { 5187c478bd9Sstevel@tonic-gate dev_t d; 5197c478bd9Sstevel@tonic-gate dev32_t d32; 5207c478bd9Sstevel@tonic-gate extern dev_t rwsconsdev, rconsdev, uconsdev; 5217c478bd9Sstevel@tonic-gate proc_t *p; 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate if (drv_getparm(UPROCP, &p) != 0) 5247c478bd9Sstevel@tonic-gate return (ENODEV); 5257c478bd9Sstevel@tonic-gate else 5267c478bd9Sstevel@tonic-gate d = cttydev(p); 5277c478bd9Sstevel@tonic-gate /* 5287c478bd9Sstevel@tonic-gate * If the controlling terminal is the real 5297c478bd9Sstevel@tonic-gate * or workstation console device, map to what the 5307c478bd9Sstevel@tonic-gate * user thinks is the console device. 5317c478bd9Sstevel@tonic-gate */ 5327c478bd9Sstevel@tonic-gate if (d == rwsconsdev || d == rconsdev) 5337c478bd9Sstevel@tonic-gate d = uconsdev; 5347c478bd9Sstevel@tonic-gate if ((flag & FMODELS) != FNATIVE) { 5357c478bd9Sstevel@tonic-gate if (!cmpldev(&d32, d)) 5367c478bd9Sstevel@tonic-gate return (EOVERFLOW); 5377c478bd9Sstevel@tonic-gate if (ddi_copyout(&d32, (caddr_t)arg, sizeof (d32), 5387c478bd9Sstevel@tonic-gate flag)) 5397c478bd9Sstevel@tonic-gate return (EFAULT); 5407c478bd9Sstevel@tonic-gate } else { 5417c478bd9Sstevel@tonic-gate if (ddi_copyout(&d, (caddr_t)arg, sizeof (d), flag)) 5427c478bd9Sstevel@tonic-gate return (EFAULT); 5437c478bd9Sstevel@tonic-gate } 5447c478bd9Sstevel@tonic-gate return (0); 5457c478bd9Sstevel@tonic-gate } 5467c478bd9Sstevel@tonic-gate default: 5477c478bd9Sstevel@tonic-gate /* everything else is sent to the console device */ 5487c478bd9Sstevel@tonic-gate return (VOP_IOCTL(dcvp, cmd, arg, flag, cred, rvalp)); 5497c478bd9Sstevel@tonic-gate } 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate if ((rval = secpolicy_console(cred)) != 0) 5527c478bd9Sstevel@tonic-gate return (EPERM); 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate infop = kmem_alloc(size, KM_SLEEP); 5557c478bd9Sstevel@tonic-gate if (flag & FKIOCTL) 5567c478bd9Sstevel@tonic-gate error = copystr((caddr_t)arg, infop, size, NULL); 5577c478bd9Sstevel@tonic-gate else 5587c478bd9Sstevel@tonic-gate error = copyinstr((caddr_t)arg, infop, size, NULL); 5597c478bd9Sstevel@tonic-gate 5607c478bd9Sstevel@tonic-gate if (error) { 5617c478bd9Sstevel@tonic-gate switch (cmd) { 5627c478bd9Sstevel@tonic-gate case CIOCGETCONSOLE: 5637c478bd9Sstevel@tonic-gate /* 5647c478bd9Sstevel@tonic-gate * If the buffer is null, then return a byte count 5657c478bd9Sstevel@tonic-gate * to user land. 5667c478bd9Sstevel@tonic-gate */ 5677c478bd9Sstevel@tonic-gate *rvalp = size; 5687c478bd9Sstevel@tonic-gate goto err_exit; 5697c478bd9Sstevel@tonic-gate default: 5707c478bd9Sstevel@tonic-gate rval = EFAULT; 5717c478bd9Sstevel@tonic-gate goto err_exit; 5727c478bd9Sstevel@tonic-gate } 5737c478bd9Sstevel@tonic-gate } 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate if (infop[0] != NULL) { 5767c478bd9Sstevel@tonic-gate if ((rval = lookupname(infop, UIO_SYSSPACE, FOLLOW, 5777c478bd9Sstevel@tonic-gate NULLVPP, &vp)) == 0) { 5787c478bd9Sstevel@tonic-gate if (vp->v_type != VCHR) { 5797c478bd9Sstevel@tonic-gate VN_RELE(vp); 5807c478bd9Sstevel@tonic-gate rval = EINVAL; 5817c478bd9Sstevel@tonic-gate goto err_exit; 5827c478bd9Sstevel@tonic-gate } 5837c478bd9Sstevel@tonic-gate newdevt = vp->v_rdev; 5847c478bd9Sstevel@tonic-gate VN_RELE(vp); 5857c478bd9Sstevel@tonic-gate } else 5867c478bd9Sstevel@tonic-gate goto err_exit; 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate switch (cmd) { 5907c478bd9Sstevel@tonic-gate case CIOCGETCONSOLE: 5917c478bd9Sstevel@tonic-gate /* 5927c478bd9Sstevel@tonic-gate * Return the list of device names that are enabled. 5937c478bd9Sstevel@tonic-gate */ 5947c478bd9Sstevel@tonic-gate for (i = 0; i < MAXDEVS; i++) { 5957c478bd9Sstevel@tonic-gate rw_enter(&sysmcache[i].dca_lock, RW_READER); 5967c478bd9Sstevel@tonic-gate if (sysmcache[i].dca_flags & SYSM_ENABLED) { 5977c478bd9Sstevel@tonic-gate if (infop[0] != NULL) 5987c478bd9Sstevel@tonic-gate (void) strcat(infop, " "); 5997c478bd9Sstevel@tonic-gate (void) strcat(infop, sysmcache[i].dca_name); 6007c478bd9Sstevel@tonic-gate } 6017c478bd9Sstevel@tonic-gate rw_exit(&sysmcache[i].dca_lock); 6027c478bd9Sstevel@tonic-gate } 6037c478bd9Sstevel@tonic-gate if (rval == 0 && copyoutstr(infop, (void *)arg, size, NULL)) 6047c478bd9Sstevel@tonic-gate rval = EFAULT; 6057c478bd9Sstevel@tonic-gate break; 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate case CIOCSETCONSOLE: 6087c478bd9Sstevel@tonic-gate if ((rval = checkarg(newdevt)) != 0) 6097c478bd9Sstevel@tonic-gate break; 6107c478bd9Sstevel@tonic-gate /* 6117c478bd9Sstevel@tonic-gate * The device does not have to be open or disabled to 6127c478bd9Sstevel@tonic-gate * perform the set console. 6137c478bd9Sstevel@tonic-gate */ 6147c478bd9Sstevel@tonic-gate for (i = 0; i < MAXDEVS; i++) { 6157c478bd9Sstevel@tonic-gate rw_enter(&sysmcache[i].dca_lock, RW_WRITER); 6167c478bd9Sstevel@tonic-gate if (sysmcache[i].dca_devt == newdevt && 6177c478bd9Sstevel@tonic-gate (sysmcache[i].dca_flags & SYSM_ENABLED)) { 6187c478bd9Sstevel@tonic-gate (void) strcpy(sysmcache[i].dca_name, infop); 6197c478bd9Sstevel@tonic-gate rval = EEXIST; 6207c478bd9Sstevel@tonic-gate rw_exit(&sysmcache[i].dca_lock); 6217c478bd9Sstevel@tonic-gate break; 6227c478bd9Sstevel@tonic-gate } else if (sysmcache[i].dca_devt == newdevt && 6237c478bd9Sstevel@tonic-gate sysmcache[i].dca_flags == SYSM_DISABLED) { 6247c478bd9Sstevel@tonic-gate sysmcache[i].dca_flags |= SYSM_ENABLED; 6257c478bd9Sstevel@tonic-gate (void) strcpy(sysmcache[i].dca_name, infop); 6267c478bd9Sstevel@tonic-gate rw_exit(&sysmcache[i].dca_lock); 6277c478bd9Sstevel@tonic-gate found = 1; 6287c478bd9Sstevel@tonic-gate break; 6297c478bd9Sstevel@tonic-gate } else if (sysmcache[i].dca_devt == 0) { 6307c478bd9Sstevel@tonic-gate ASSERT(sysmcache[i].dca_vp == NULL && 6317c478bd9Sstevel@tonic-gate sysmcache[i].dca_flags == SYSM_DISABLED); 6327c478bd9Sstevel@tonic-gate (void) strcpy(sysmcache[i].dca_name, infop); 6337c478bd9Sstevel@tonic-gate sysmcache[i].dca_flags = SYSM_ENABLED; 6347c478bd9Sstevel@tonic-gate sysmcache[i].dca_devt = newdevt; 6357c478bd9Sstevel@tonic-gate rw_exit(&sysmcache[i].dca_lock); 6367c478bd9Sstevel@tonic-gate found = 1; 6377c478bd9Sstevel@tonic-gate break; 6387c478bd9Sstevel@tonic-gate } 6397c478bd9Sstevel@tonic-gate rw_exit(&sysmcache[i].dca_lock); 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate if (found == 0 && rval == 0) 6427c478bd9Sstevel@tonic-gate rval = ENOENT; 6437c478bd9Sstevel@tonic-gate break; 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate case CIOCRMCONSOLE: 6467c478bd9Sstevel@tonic-gate for (i = 0; i < MAXDEVS; i++) { 6477c478bd9Sstevel@tonic-gate rw_enter(&sysmcache[i].dca_lock, RW_WRITER); 6487c478bd9Sstevel@tonic-gate if (sysmcache[i].dca_devt == newdevt) { 6497c478bd9Sstevel@tonic-gate sysmcache[i].dca_flags = SYSM_DISABLED; 6507c478bd9Sstevel@tonic-gate sysmcache[i].dca_name[0] = '\0'; 6517c478bd9Sstevel@tonic-gate rw_exit(&sysmcache[i].dca_lock); 6527c478bd9Sstevel@tonic-gate found = 1; 6537c478bd9Sstevel@tonic-gate break; 6547c478bd9Sstevel@tonic-gate } 6557c478bd9Sstevel@tonic-gate rw_exit(&sysmcache[i].dca_lock); 6567c478bd9Sstevel@tonic-gate } 6577c478bd9Sstevel@tonic-gate if (found == 0) 6587c478bd9Sstevel@tonic-gate rval = ENOENT; 6597c478bd9Sstevel@tonic-gate break; 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate default: 6627c478bd9Sstevel@tonic-gate break; 6637c478bd9Sstevel@tonic-gate } 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate err_exit: 6667c478bd9Sstevel@tonic-gate kmem_free(infop, size); 6677c478bd9Sstevel@tonic-gate return (rval); 6687c478bd9Sstevel@tonic-gate } 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate /* As with the read, we poll only the default console */ 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate /* ARGSUSED */ 6737c478bd9Sstevel@tonic-gate static int 6747c478bd9Sstevel@tonic-gate sysmpoll(dev_t dev, short events, int anyyet, short *reventsp, 6757c478bd9Sstevel@tonic-gate struct pollhead **phpp) 6767c478bd9Sstevel@tonic-gate { 6777c478bd9Sstevel@tonic-gate return (VOP_POLL(dcvp, events, anyyet, reventsp, phpp)); 6787c478bd9Sstevel@tonic-gate } 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate /* Sanity check that the device is good */ 6817c478bd9Sstevel@tonic-gate static int 6827c478bd9Sstevel@tonic-gate checkarg(dev_t devt) 6837c478bd9Sstevel@tonic-gate { 6847c478bd9Sstevel@tonic-gate int rval = 0; 6857c478bd9Sstevel@tonic-gate vnode_t *vp; 6867c478bd9Sstevel@tonic-gate extern dev_t rwsconsdev, rconsdev, uconsdev; 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate if (devt == rconsdev || devt == rwsconsdev || devt == uconsdev) { 6897c478bd9Sstevel@tonic-gate rval = EBUSY; 6907c478bd9Sstevel@tonic-gate goto err_exit; 6917c478bd9Sstevel@tonic-gate } 6927c478bd9Sstevel@tonic-gate if ((rval = lookupname("/dev/sysmsg", UIO_SYSSPACE, FOLLOW, 6937c478bd9Sstevel@tonic-gate NULLVPP, &vp)) == 0) { 6947c478bd9Sstevel@tonic-gate if (devt == vp->v_rdev) { 6957c478bd9Sstevel@tonic-gate VN_RELE(vp); 6967c478bd9Sstevel@tonic-gate rval = EINVAL; 6977c478bd9Sstevel@tonic-gate goto err_exit; 6987c478bd9Sstevel@tonic-gate } 6997c478bd9Sstevel@tonic-gate VN_RELE(vp); 7007c478bd9Sstevel@tonic-gate } 7017c478bd9Sstevel@tonic-gate if ((rval = lookupname("/dev/msglog", UIO_SYSSPACE, FOLLOW, 7027c478bd9Sstevel@tonic-gate NULLVPP, &vp)) == 0) { 7037c478bd9Sstevel@tonic-gate if (devt == vp->v_rdev) { 7047c478bd9Sstevel@tonic-gate VN_RELE(vp); 7057c478bd9Sstevel@tonic-gate rval = EINVAL; 7067c478bd9Sstevel@tonic-gate goto err_exit; 7077c478bd9Sstevel@tonic-gate } 7087c478bd9Sstevel@tonic-gate VN_RELE(vp); 7097c478bd9Sstevel@tonic-gate } 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate err_exit: 7127c478bd9Sstevel@tonic-gate return (rval); 7137c478bd9Sstevel@tonic-gate } 714