1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <unistd.h> 30*0Sstevel@tonic-gate #include <stdio.h> 31*0Sstevel@tonic-gate #include <stdlib.h> 32*0Sstevel@tonic-gate #include <string.h> 33*0Sstevel@tonic-gate #include <regex.h> 34*0Sstevel@tonic-gate #include <sac.h> 35*0Sstevel@tonic-gate #include <errno.h> 36*0Sstevel@tonic-gate #include <dirent.h> 37*0Sstevel@tonic-gate #include <limits.h> 38*0Sstevel@tonic-gate #include <sys/types.h> 39*0Sstevel@tonic-gate #include <sys/stat.h> 40*0Sstevel@tonic-gate #include <sys/wait.h> 41*0Sstevel@tonic-gate #include <fcntl.h> 42*0Sstevel@tonic-gate #include <devfsadm.h> 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate /* 45*0Sstevel@tonic-gate * sacadm output parsing 46*0Sstevel@tonic-gate */ 47*0Sstevel@tonic-gate #define PMTAB_MAXLINE 512 48*0Sstevel@tonic-gate #define PMTAB_SEPR ':' 49*0Sstevel@tonic-gate #define PMTAB_DEVNAME_FIELD 7 /* field containing /dev/term/n */ 50*0Sstevel@tonic-gate #define DIALOUT_SUFFIX ",cu" 51*0Sstevel@tonic-gate #define DEVNAME_SEPR '/' 52*0Sstevel@tonic-gate #define MN_SEPR ',' 53*0Sstevel@tonic-gate #define MN_NULLCHAR '\0' 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate /* 56*0Sstevel@tonic-gate * sacadm/pmadm exit codes (see /usr/include/sac.h) 57*0Sstevel@tonic-gate */ 58*0Sstevel@tonic-gate static char *sacerrs[] = { 59*0Sstevel@tonic-gate "UNKNOWN", "Unknown exit code", 60*0Sstevel@tonic-gate "E_BADARGS", "Invalid arguments", 61*0Sstevel@tonic-gate "E_NOPRIV", "Not privileged", 62*0Sstevel@tonic-gate "E_SAFERR", "SAF error", 63*0Sstevel@tonic-gate "E_SYSERR", "System error", 64*0Sstevel@tonic-gate "E_NOEXIST", "Entry does not exist", 65*0Sstevel@tonic-gate "E_DUP", "Entry already exists", 66*0Sstevel@tonic-gate "E_PMRUN", "Port monitor already running", 67*0Sstevel@tonic-gate "E_PMNOTRUN", "Port monitor not running", 68*0Sstevel@tonic-gate "E_RECOVER", "In recovery", 69*0Sstevel@tonic-gate "E_SACNOTRUN", "SAC daemon not running", 70*0Sstevel@tonic-gate }; 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate #define SAC_EXITVAL(x) ((x) >> 8) 73*0Sstevel@tonic-gate #define SAC_EID(x) \ 74*0Sstevel@tonic-gate (sacerrs[((uint_t)(x) > E_SACNOTRUN ? 0 : ((x)<<1))]) 75*0Sstevel@tonic-gate #define SAC_EMSG(x) \ 76*0Sstevel@tonic-gate (sacerrs[((uint_t)(x) > E_SACNOTRUN ? 1 : (((x)<<1) + 1))]) 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate /* 81*0Sstevel@tonic-gate * create port monitors for each group of PM_GRPSZ port devices. 82*0Sstevel@tonic-gate */ 83*0Sstevel@tonic-gate #define PM_GRPSZ 64 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate /* 86*0Sstevel@tonic-gate * compute port monitor # and base index 87*0Sstevel@tonic-gate */ 88*0Sstevel@tonic-gate #define PM_NUM(p) ((p) / PM_GRPSZ) 89*0Sstevel@tonic-gate #define PM_SLOT(p) (PM_NUM(p) * PM_GRPSZ) 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate /* 93*0Sstevel@tonic-gate * default maxports value 94*0Sstevel@tonic-gate * override by setting SUNW_port_link.maxports in default/devfsadm 95*0Sstevel@tonic-gate */ 96*0Sstevel@tonic-gate #define MAXPORTS_DEFAULT 2048 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate /* 99*0Sstevel@tonic-gate * command line buffer size for sacadm 100*0Sstevel@tonic-gate */ 101*0Sstevel@tonic-gate #define CMDLEN 1024 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate struct pm_alloc { 104*0Sstevel@tonic-gate uint_t flags; 105*0Sstevel@tonic-gate char *pm_tag; 106*0Sstevel@tonic-gate }; 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate /* port monitor entry flags */ 109*0Sstevel@tonic-gate #define PM_HAS_ENTRY 0x1 /* pm entry for this port */ 110*0Sstevel@tonic-gate #define HAS_PORT_DEVICE 0x2 /* device exists */ 111*0Sstevel@tonic-gate #define PORT_REMOVED 0x4 /* dangling port */ 112*0Sstevel@tonic-gate #define HAS_PORT_MON 0x8 /* port monitor active */ 113*0Sstevel@tonic-gate #define PM_NEEDED 0x10 /* port monitor needed */ 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate static int maxports; 116*0Sstevel@tonic-gate static struct pm_alloc *pma; 117*0Sstevel@tonic-gate static char *modname = "SUNW_port_link"; 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate /* 120*0Sstevel@tonic-gate * devfsadm_print message id 121*0Sstevel@tonic-gate */ 122*0Sstevel@tonic-gate #define PORT_MID "SUNW_port_link" 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate /* 125*0Sstevel@tonic-gate * enumeration regular expressions, port and onboard port devices 126*0Sstevel@tonic-gate * On x86, /dev/term|cua/[a..z] namespace is split into 2: 127*0Sstevel@tonic-gate * a-d are assigned based on minor name. e-z are 128*0Sstevel@tonic-gate * assigned via enumeration. 129*0Sstevel@tonic-gate */ 130*0Sstevel@tonic-gate static devfsadm_enumerate_t port_rules[] = 131*0Sstevel@tonic-gate {"^(term|cua)$/^([0-9]+)$", 1, MATCH_MINOR, "1"}; 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate #ifdef __i386 134*0Sstevel@tonic-gate static devfsadm_enumerate_t obport_rules[] = 135*0Sstevel@tonic-gate {"^(term|cua)$/^([e-z])$", 1, MATCH_MINOR, "1"}; 136*0Sstevel@tonic-gate static char start_id[] = "e"; 137*0Sstevel@tonic-gate #else 138*0Sstevel@tonic-gate static devfsadm_enumerate_t obport_rules[] = 139*0Sstevel@tonic-gate {"^(term|cua)$/^([a-z])$", 1, MATCH_MINOR, "1"}; 140*0Sstevel@tonic-gate static char start_id[] = "a"; 141*0Sstevel@tonic-gate #endif 142*0Sstevel@tonic-gate 143*0Sstevel@tonic-gate static int serial_port_create(di_minor_t minor, di_node_t node); 144*0Sstevel@tonic-gate static int onbrd_port_create(di_minor_t minor, di_node_t node); 145*0Sstevel@tonic-gate static int dialout_create(di_minor_t minor, di_node_t node); 146*0Sstevel@tonic-gate static int onbrd_dialout_create(di_minor_t minor, di_node_t node); 147*0Sstevel@tonic-gate static int rsc_port_create(di_minor_t minor, di_node_t node); 148*0Sstevel@tonic-gate static int lom_port_create(di_minor_t minor, di_node_t node); 149*0Sstevel@tonic-gate static int pcmcia_port_create(di_minor_t minor, di_node_t node); 150*0Sstevel@tonic-gate static int pcmcia_dialout_create(di_minor_t minor, di_node_t node); 151*0Sstevel@tonic-gate static void rm_dangling_port(char *devname); 152*0Sstevel@tonic-gate static void update_sacadm_db(void); 153*0Sstevel@tonic-gate static int parse_portno(char *dname); 154*0Sstevel@tonic-gate static int is_dialout(char *dname); 155*0Sstevel@tonic-gate static int load_ttymondb(void); 156*0Sstevel@tonic-gate static void remove_pm_entry(char *pmtag, int port); 157*0Sstevel@tonic-gate static void add_pm_entry(int port); 158*0Sstevel@tonic-gate static void delete_port_monitor(int port); 159*0Sstevel@tonic-gate static void add_port_monitor(int port); 160*0Sstevel@tonic-gate static int execute(const char *s); 161*0Sstevel@tonic-gate static char *pmtab_parse_portname(char *cmdbuf); 162*0Sstevel@tonic-gate static void *pma_alloc(void); 163*0Sstevel@tonic-gate static void pma_free(void); 164*0Sstevel@tonic-gate extern char *defread(char *varname); 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate /* 167*0Sstevel@tonic-gate * devfs create callback register 168*0Sstevel@tonic-gate */ 169*0Sstevel@tonic-gate static devfsadm_create_t ports_cbt[] = { 170*0Sstevel@tonic-gate {"pseudo", "ddi_pseudo", "su", 171*0Sstevel@tonic-gate TYPE_EXACT | DRV_EXACT, ILEVEL_1, rsc_port_create}, 172*0Sstevel@tonic-gate {"port", "ddi_serial:lomcon", "su", 173*0Sstevel@tonic-gate TYPE_EXACT | DRV_EXACT, ILEVEL_1, lom_port_create}, 174*0Sstevel@tonic-gate {"port", "ddi_serial", "pcser", 175*0Sstevel@tonic-gate TYPE_EXACT | DRV_EXACT, ILEVEL_1, pcmcia_port_create}, 176*0Sstevel@tonic-gate {"port", "ddi_serial:dialout", "pcser", 177*0Sstevel@tonic-gate TYPE_EXACT | DRV_EXACT, ILEVEL_1, pcmcia_dialout_create}, 178*0Sstevel@tonic-gate {"port", "ddi_serial", NULL, 179*0Sstevel@tonic-gate TYPE_EXACT, ILEVEL_0, serial_port_create}, 180*0Sstevel@tonic-gate {"port", "ddi_serial:mb", NULL, 181*0Sstevel@tonic-gate TYPE_EXACT, ILEVEL_0, onbrd_port_create}, 182*0Sstevel@tonic-gate {"port", "ddi_serial:dialout", NULL, 183*0Sstevel@tonic-gate TYPE_EXACT, ILEVEL_0, dialout_create}, 184*0Sstevel@tonic-gate {"port", "ddi_serial:dialout,mb", NULL, 185*0Sstevel@tonic-gate TYPE_EXACT, ILEVEL_0, onbrd_dialout_create}, 186*0Sstevel@tonic-gate }; 187*0Sstevel@tonic-gate DEVFSADM_CREATE_INIT_V0(ports_cbt); 188*0Sstevel@tonic-gate 189*0Sstevel@tonic-gate /* 190*0Sstevel@tonic-gate * devfs cleanup register 191*0Sstevel@tonic-gate * no cleanup rules for PCMCIA port devices 192*0Sstevel@tonic-gate */ 193*0Sstevel@tonic-gate static devfsadm_remove_t ports_remove_cbt[] = { 194*0Sstevel@tonic-gate {"port", "^term/[0-9]+$", RM_PRE | RM_HOT, ILEVEL_0, rm_dangling_port}, 195*0Sstevel@tonic-gate {"port", "^cua/[0-9]+$", RM_PRE | RM_HOT, ILEVEL_0, devfsadm_rm_all}, 196*0Sstevel@tonic-gate {"port", "^(term|cua)/[a-z]$", 197*0Sstevel@tonic-gate RM_PRE, ILEVEL_0, devfsadm_rm_all}, 198*0Sstevel@tonic-gate }; 199*0Sstevel@tonic-gate DEVFSADM_REMOVE_INIT_V0(ports_remove_cbt); 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate int 202*0Sstevel@tonic-gate minor_init() 203*0Sstevel@tonic-gate { 204*0Sstevel@tonic-gate char *maxport_str; 205*0Sstevel@tonic-gate 206*0Sstevel@tonic-gate maxport_str = defread("SUNW_port_link.maxports"); 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate if ((maxport_str == NULL) || 209*0Sstevel@tonic-gate (sscanf(maxport_str, "%d", &maxports) != 1)) 210*0Sstevel@tonic-gate maxports = MAXPORTS_DEFAULT; 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate devfsadm_print(CHATTY_MID, "%s: maximum number of port devices (%d)\n", 213*0Sstevel@tonic-gate modname, maxports); 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate if (pma_alloc() == NULL) 216*0Sstevel@tonic-gate return (DEVFSADM_FAILURE); 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate return (DEVFSADM_SUCCESS); 219*0Sstevel@tonic-gate } 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gate int 222*0Sstevel@tonic-gate minor_fini() 223*0Sstevel@tonic-gate { 224*0Sstevel@tonic-gate /* 225*0Sstevel@tonic-gate * update the sacadm database only if we are updating 226*0Sstevel@tonic-gate * this platform (no -r option) 227*0Sstevel@tonic-gate */ 228*0Sstevel@tonic-gate if (strcmp(devfsadm_root_path(), "/") == 0) 229*0Sstevel@tonic-gate update_sacadm_db(); 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate pma_free(); 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate return (DEVFSADM_SUCCESS); 234*0Sstevel@tonic-gate } 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gate /* 237*0Sstevel@tonic-gate * Called for all serial devices that are NOT onboard 238*0Sstevel@tonic-gate * Creates links of the form "/dev/term/[0..n]" 239*0Sstevel@tonic-gate * Schedules an update the sacadm (portmon). 240*0Sstevel@tonic-gate */ 241*0Sstevel@tonic-gate static int 242*0Sstevel@tonic-gate serial_port_create(di_minor_t minor, di_node_t node) 243*0Sstevel@tonic-gate { 244*0Sstevel@tonic-gate char l_path[MAXPATHLEN], p_path[MAXPATHLEN]; 245*0Sstevel@tonic-gate char *devfspath, *buf, *minor_name; 246*0Sstevel@tonic-gate int port_num; 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate devfspath = di_devfs_path(node); 249*0Sstevel@tonic-gate if (devfspath == NULL) { 250*0Sstevel@tonic-gate devfsadm_errprint("%s: di_devfs_path() failed\n", modname); 251*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 252*0Sstevel@tonic-gate } 253*0Sstevel@tonic-gate 254*0Sstevel@tonic-gate if ((minor_name = di_minor_name(minor)) == NULL) { 255*0Sstevel@tonic-gate devfsadm_errprint("%s: NULL minor name\n\t%s\n", modname, 256*0Sstevel@tonic-gate devfspath); 257*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 258*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 259*0Sstevel@tonic-gate } 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate /* 262*0Sstevel@tonic-gate * verify dialout ports do not come in on this nodetype 263*0Sstevel@tonic-gate */ 264*0Sstevel@tonic-gate if (is_dialout(minor_name)) { 265*0Sstevel@tonic-gate devfsadm_errprint("%s: dialout device\n\t%s:%s\n", 266*0Sstevel@tonic-gate modname, devfspath, minor_name); 267*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 268*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 269*0Sstevel@tonic-gate } 270*0Sstevel@tonic-gate 271*0Sstevel@tonic-gate /* 272*0Sstevel@tonic-gate * add the minor name to the physical path so we can 273*0Sstevel@tonic-gate * enum the port# and create the the link. 274*0Sstevel@tonic-gate */ 275*0Sstevel@tonic-gate (void) strcpy(p_path, devfspath); 276*0Sstevel@tonic-gate (void) strcat(p_path, ":"); 277*0Sstevel@tonic-gate (void) strcat(p_path, minor_name); 278*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate if (devfsadm_enumerate_int(p_path, 0, &buf, port_rules, 1)) { 281*0Sstevel@tonic-gate devfsadm_errprint("%s:serial_port_create:" 282*0Sstevel@tonic-gate " enumerate_int() failed\n\t%s\n", 283*0Sstevel@tonic-gate modname, p_path); 284*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 285*0Sstevel@tonic-gate } 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gate (void) strcpy(l_path, "term/"); 288*0Sstevel@tonic-gate (void) strcat(l_path, buf); 289*0Sstevel@tonic-gate (void) devfsadm_mklink(l_path, node, minor, 0); 290*0Sstevel@tonic-gate 291*0Sstevel@tonic-gate /* 292*0Sstevel@tonic-gate * update the portmon database if this port falls within 293*0Sstevel@tonic-gate * the valid range of ports. 294*0Sstevel@tonic-gate */ 295*0Sstevel@tonic-gate if ((port_num = parse_portno(buf)) != -1) { 296*0Sstevel@tonic-gate pma[port_num].flags |= HAS_PORT_DEVICE; 297*0Sstevel@tonic-gate } 298*0Sstevel@tonic-gate 299*0Sstevel@tonic-gate free(buf); 300*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 301*0Sstevel@tonic-gate } 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate /* 304*0Sstevel@tonic-gate * Called for all dialout devices that are NOT onboard 305*0Sstevel@tonic-gate * Creates links of the form "/dev/cua/[0..n]" 306*0Sstevel@tonic-gate */ 307*0Sstevel@tonic-gate static int 308*0Sstevel@tonic-gate dialout_create(di_minor_t minor, di_node_t node) 309*0Sstevel@tonic-gate { 310*0Sstevel@tonic-gate char l_path[MAXPATHLEN], p_path[MAXPATHLEN]; 311*0Sstevel@tonic-gate char *devfspath, *buf, *mn; 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate devfspath = di_devfs_path(node); 314*0Sstevel@tonic-gate if (devfspath == NULL) { 315*0Sstevel@tonic-gate devfsadm_errprint("%s: di_devfs_path() failed\n", modname); 316*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 317*0Sstevel@tonic-gate } 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gate if ((mn = di_minor_name(minor)) == NULL) { 320*0Sstevel@tonic-gate devfsadm_errprint("%s: NULL minorname\n\t%s\n", 321*0Sstevel@tonic-gate modname, devfspath); 322*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 323*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 324*0Sstevel@tonic-gate } 325*0Sstevel@tonic-gate 326*0Sstevel@tonic-gate if (!is_dialout(mn)) { 327*0Sstevel@tonic-gate devfsadm_errprint("%s: invalid minor name\n\t%s:%s\n", 328*0Sstevel@tonic-gate modname, devfspath, mn); 329*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 330*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 331*0Sstevel@tonic-gate } 332*0Sstevel@tonic-gate 333*0Sstevel@tonic-gate (void) strcpy(p_path, devfspath); 334*0Sstevel@tonic-gate (void) strcat(p_path, ":"); 335*0Sstevel@tonic-gate (void) strcat(p_path, mn); 336*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 337*0Sstevel@tonic-gate 338*0Sstevel@tonic-gate if (devfsadm_enumerate_int(p_path, 0, &buf, port_rules, 1)) { 339*0Sstevel@tonic-gate devfsadm_errprint("%s:dialout_create:" 340*0Sstevel@tonic-gate " enumerate_int() failed\n\t%s\n", 341*0Sstevel@tonic-gate modname, p_path); 342*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 343*0Sstevel@tonic-gate } 344*0Sstevel@tonic-gate (void) strcpy(l_path, "cua/"); 345*0Sstevel@tonic-gate (void) strcat(l_path, buf); 346*0Sstevel@tonic-gate 347*0Sstevel@tonic-gate /* 348*0Sstevel@tonic-gate * add the minor name to the physical path so we can create 349*0Sstevel@tonic-gate * the link. 350*0Sstevel@tonic-gate */ 351*0Sstevel@tonic-gate (void) devfsadm_mklink(l_path, node, minor, 0); 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate free(buf); 354*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 355*0Sstevel@tonic-gate } 356*0Sstevel@tonic-gate 357*0Sstevel@tonic-gate #ifdef __i386 358*0Sstevel@tonic-gate 359*0Sstevel@tonic-gate static int 360*0Sstevel@tonic-gate portcmp(char *devfs_path, char *phys_path) 361*0Sstevel@tonic-gate { 362*0Sstevel@tonic-gate char *p1, *p2; 363*0Sstevel@tonic-gate int rv; 364*0Sstevel@tonic-gate 365*0Sstevel@tonic-gate p2 = NULL; 366*0Sstevel@tonic-gate 367*0Sstevel@tonic-gate p1 = strrchr(devfs_path, ':'); 368*0Sstevel@tonic-gate if (p1 == NULL) 369*0Sstevel@tonic-gate return (1); 370*0Sstevel@tonic-gate 371*0Sstevel@tonic-gate p1 = strchr(p1, ','); 372*0Sstevel@tonic-gate if (p1) 373*0Sstevel@tonic-gate *p1 = '\0'; 374*0Sstevel@tonic-gate 375*0Sstevel@tonic-gate p2 = strrchr(phys_path, ':'); 376*0Sstevel@tonic-gate if (p2 == NULL) { 377*0Sstevel@tonic-gate rv = -1; 378*0Sstevel@tonic-gate goto out; 379*0Sstevel@tonic-gate } 380*0Sstevel@tonic-gate 381*0Sstevel@tonic-gate p2 = strchr(p2, ','); 382*0Sstevel@tonic-gate if (p2) 383*0Sstevel@tonic-gate *p2 = '\0'; 384*0Sstevel@tonic-gate 385*0Sstevel@tonic-gate rv = strcmp(devfs_path, phys_path); 386*0Sstevel@tonic-gate 387*0Sstevel@tonic-gate out: 388*0Sstevel@tonic-gate if (p1) 389*0Sstevel@tonic-gate *p1 = ','; 390*0Sstevel@tonic-gate if (p2) 391*0Sstevel@tonic-gate *p2 = ','; 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate return (rv); 394*0Sstevel@tonic-gate } 395*0Sstevel@tonic-gate 396*0Sstevel@tonic-gate /* 397*0Sstevel@tonic-gate * If the minor name begins with [a-d] and the 398*0Sstevel@tonic-gate * links in /dev/term/<char> and /dev/cua/<char> 399*0Sstevel@tonic-gate * don't point at a different minor, then we can 400*0Sstevel@tonic-gate * create compatibility links for this minor. 401*0Sstevel@tonic-gate * Returns: 402*0Sstevel@tonic-gate * port id if a compatibility link can be created. 403*0Sstevel@tonic-gate * NULL otherwise 404*0Sstevel@tonic-gate */ 405*0Sstevel@tonic-gate static char * 406*0Sstevel@tonic-gate check_compat_ports(char *phys_path, char *minor) 407*0Sstevel@tonic-gate { 408*0Sstevel@tonic-gate char portid = *minor; 409*0Sstevel@tonic-gate char port[PATH_MAX]; 410*0Sstevel@tonic-gate char *devfs_path; 411*0Sstevel@tonic-gate 412*0Sstevel@tonic-gate if (portid < 'a' || portid > 'd') 413*0Sstevel@tonic-gate return (NULL); 414*0Sstevel@tonic-gate 415*0Sstevel@tonic-gate (void) snprintf(port, sizeof (port), "term/%c", portid); 416*0Sstevel@tonic-gate if (devfsadm_read_link(port, &devfs_path) == DEVFSADM_SUCCESS && 417*0Sstevel@tonic-gate portcmp(devfs_path, phys_path) != 0) { 418*0Sstevel@tonic-gate free(devfs_path); 419*0Sstevel@tonic-gate return (NULL); 420*0Sstevel@tonic-gate } 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gate free(devfs_path); 423*0Sstevel@tonic-gate 424*0Sstevel@tonic-gate (void) snprintf(port, sizeof (port), "cua/%c", portid); 425*0Sstevel@tonic-gate if (devfsadm_read_link(port, &devfs_path) == DEVFSADM_SUCCESS && 426*0Sstevel@tonic-gate portcmp(devfs_path, phys_path) != 0) { 427*0Sstevel@tonic-gate free(devfs_path); 428*0Sstevel@tonic-gate return (NULL); 429*0Sstevel@tonic-gate } 430*0Sstevel@tonic-gate 431*0Sstevel@tonic-gate free(devfs_path); 432*0Sstevel@tonic-gate 433*0Sstevel@tonic-gate /* 434*0Sstevel@tonic-gate * Neither link exists or both links point at "phys_path" 435*0Sstevel@tonic-gate * We can safely create compatibility links. 436*0Sstevel@tonic-gate */ 437*0Sstevel@tonic-gate port[0] = portid; 438*0Sstevel@tonic-gate port[1] = '\0'; 439*0Sstevel@tonic-gate 440*0Sstevel@tonic-gate return (s_strdup(port)); 441*0Sstevel@tonic-gate } 442*0Sstevel@tonic-gate 443*0Sstevel@tonic-gate #endif 444*0Sstevel@tonic-gate 445*0Sstevel@tonic-gate /* 446*0Sstevel@tonic-gate * Called for all Onboard serial devices 447*0Sstevel@tonic-gate * Creates links of the form "/dev/term/[a..z]" 448*0Sstevel@tonic-gate */ 449*0Sstevel@tonic-gate static int 450*0Sstevel@tonic-gate onbrd_port_create(di_minor_t minor, di_node_t node) 451*0Sstevel@tonic-gate { 452*0Sstevel@tonic-gate char l_path[MAXPATHLEN], p_path[MAXPATHLEN]; 453*0Sstevel@tonic-gate char *devfspath, *buf, *minor_name; 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate devfspath = di_devfs_path(node); 456*0Sstevel@tonic-gate if (devfspath == NULL) { 457*0Sstevel@tonic-gate devfsadm_errprint("%s: di_devfs_path() failed\n", modname); 458*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 459*0Sstevel@tonic-gate } 460*0Sstevel@tonic-gate 461*0Sstevel@tonic-gate if ((minor_name = di_minor_name(minor)) == NULL) { 462*0Sstevel@tonic-gate devfsadm_errprint("%s: NULL minor name\n\t%s\n", 463*0Sstevel@tonic-gate modname, devfspath); 464*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 465*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 466*0Sstevel@tonic-gate } 467*0Sstevel@tonic-gate 468*0Sstevel@tonic-gate /* 469*0Sstevel@tonic-gate * verify dialout ports do not come in on this nodetype 470*0Sstevel@tonic-gate */ 471*0Sstevel@tonic-gate if (is_dialout(minor_name)) { 472*0Sstevel@tonic-gate devfsadm_errprint("%s: dialout device\n\t%s:%s\n", modname, 473*0Sstevel@tonic-gate devfspath, minor_name); 474*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 475*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 476*0Sstevel@tonic-gate } 477*0Sstevel@tonic-gate 478*0Sstevel@tonic-gate (void) strcpy(p_path, devfspath); 479*0Sstevel@tonic-gate (void) strcat(p_path, ":"); 480*0Sstevel@tonic-gate (void) strcat(p_path, minor_name); 481*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 482*0Sstevel@tonic-gate 483*0Sstevel@tonic-gate 484*0Sstevel@tonic-gate buf = NULL; 485*0Sstevel@tonic-gate 486*0Sstevel@tonic-gate #ifdef __i386 487*0Sstevel@tonic-gate buf = check_compat_ports(p_path, minor_name); 488*0Sstevel@tonic-gate #endif 489*0Sstevel@tonic-gate 490*0Sstevel@tonic-gate /* 491*0Sstevel@tonic-gate * devfsadm_enumerate_char_start() is a private interface for use by the 492*0Sstevel@tonic-gate * ports module only 493*0Sstevel@tonic-gate */ 494*0Sstevel@tonic-gate if (!buf && devfsadm_enumerate_char_start(p_path, 0, &buf, obport_rules, 495*0Sstevel@tonic-gate 1, start_id)) { 496*0Sstevel@tonic-gate devfsadm_errprint("%s: devfsadm_enumerate_char_start() failed" 497*0Sstevel@tonic-gate "\n\t%s\n", modname, p_path); 498*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 499*0Sstevel@tonic-gate } 500*0Sstevel@tonic-gate 501*0Sstevel@tonic-gate (void) strcpy(l_path, "term/"); 502*0Sstevel@tonic-gate (void) strcat(l_path, buf); 503*0Sstevel@tonic-gate (void) devfsadm_mklink(l_path, node, minor, 0); 504*0Sstevel@tonic-gate free(buf); 505*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 506*0Sstevel@tonic-gate } 507*0Sstevel@tonic-gate 508*0Sstevel@tonic-gate /* 509*0Sstevel@tonic-gate * Onboard dialout devices 510*0Sstevel@tonic-gate * Creates links of the form "/dev/cua/[a..z]" 511*0Sstevel@tonic-gate */ 512*0Sstevel@tonic-gate static int 513*0Sstevel@tonic-gate onbrd_dialout_create(di_minor_t minor, di_node_t node) 514*0Sstevel@tonic-gate { 515*0Sstevel@tonic-gate char l_path[MAXPATHLEN], p_path[MAXPATHLEN]; 516*0Sstevel@tonic-gate char *devfspath, *buf, *mn; 517*0Sstevel@tonic-gate 518*0Sstevel@tonic-gate devfspath = di_devfs_path(node); 519*0Sstevel@tonic-gate if (devfspath == NULL) { 520*0Sstevel@tonic-gate devfsadm_errprint("%s: di_devfs_path() failed\n", modname); 521*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 522*0Sstevel@tonic-gate } 523*0Sstevel@tonic-gate 524*0Sstevel@tonic-gate if ((mn = di_minor_name(minor)) == NULL) { 525*0Sstevel@tonic-gate devfsadm_errprint("%s: NULL minor name\n\t%s\n", 526*0Sstevel@tonic-gate modname, devfspath); 527*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 528*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 529*0Sstevel@tonic-gate } 530*0Sstevel@tonic-gate 531*0Sstevel@tonic-gate /* 532*0Sstevel@tonic-gate * verify this is a dialout port 533*0Sstevel@tonic-gate */ 534*0Sstevel@tonic-gate if (!is_dialout(mn)) { 535*0Sstevel@tonic-gate devfsadm_errprint("%s: not a dialout device\n\t%s:%s\n", 536*0Sstevel@tonic-gate modname, devfspath, mn); 537*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 538*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 539*0Sstevel@tonic-gate } 540*0Sstevel@tonic-gate 541*0Sstevel@tonic-gate (void) strcpy(p_path, devfspath); 542*0Sstevel@tonic-gate (void) strcat(p_path, ":"); 543*0Sstevel@tonic-gate (void) strcat(p_path, mn); 544*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 545*0Sstevel@tonic-gate 546*0Sstevel@tonic-gate buf = NULL; 547*0Sstevel@tonic-gate 548*0Sstevel@tonic-gate #ifdef __i386 549*0Sstevel@tonic-gate buf = check_compat_ports(p_path, mn); 550*0Sstevel@tonic-gate #endif 551*0Sstevel@tonic-gate 552*0Sstevel@tonic-gate /* 553*0Sstevel@tonic-gate * devfsadm_enumerate_char_start() is a private interface 554*0Sstevel@tonic-gate * for use by the ports module only. 555*0Sstevel@tonic-gate */ 556*0Sstevel@tonic-gate if (!buf && devfsadm_enumerate_char_start(p_path, 0, &buf, obport_rules, 557*0Sstevel@tonic-gate 1, start_id)) { 558*0Sstevel@tonic-gate devfsadm_errprint("%s: devfsadm_enumerate_char_start() failed" 559*0Sstevel@tonic-gate "\n\t%s\n", modname, p_path); 560*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 561*0Sstevel@tonic-gate } 562*0Sstevel@tonic-gate 563*0Sstevel@tonic-gate /* 564*0Sstevel@tonic-gate * create the logical link 565*0Sstevel@tonic-gate */ 566*0Sstevel@tonic-gate (void) strcpy(l_path, "cua/"); 567*0Sstevel@tonic-gate (void) strcat(l_path, buf); 568*0Sstevel@tonic-gate (void) devfsadm_mklink(l_path, node, minor, 0); 569*0Sstevel@tonic-gate free(buf); 570*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 571*0Sstevel@tonic-gate } 572*0Sstevel@tonic-gate 573*0Sstevel@tonic-gate 574*0Sstevel@tonic-gate /* 575*0Sstevel@tonic-gate * Remote System Controller (RSC) serial ports 576*0Sstevel@tonic-gate * Creates links of the form "/dev/rsc-control" | "/dev/term/rsc-console". 577*0Sstevel@tonic-gate */ 578*0Sstevel@tonic-gate static int 579*0Sstevel@tonic-gate rsc_port_create(di_minor_t minor, di_node_t node) 580*0Sstevel@tonic-gate { 581*0Sstevel@tonic-gate char *devfspath; 582*0Sstevel@tonic-gate char *minor_name; 583*0Sstevel@tonic-gate 584*0Sstevel@tonic-gate 585*0Sstevel@tonic-gate devfspath = di_devfs_path(node); 586*0Sstevel@tonic-gate if (devfspath == NULL) { 587*0Sstevel@tonic-gate devfsadm_errprint("%s: di_devfs_path() failed\n", modname); 588*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 589*0Sstevel@tonic-gate } 590*0Sstevel@tonic-gate 591*0Sstevel@tonic-gate if ((minor_name = di_minor_name(minor)) == NULL) { 592*0Sstevel@tonic-gate devfsadm_errprint("%s: NULL minor name\n\t%s\n", 593*0Sstevel@tonic-gate modname, devfspath); 594*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 595*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 596*0Sstevel@tonic-gate } 597*0Sstevel@tonic-gate 598*0Sstevel@tonic-gate /* 599*0Sstevel@tonic-gate * if this is the RSC console serial port (i.e. the minor name == ssp), 600*0Sstevel@tonic-gate * create /dev/term/rsc-console link and then we are done with this 601*0Sstevel@tonic-gate * node. 602*0Sstevel@tonic-gate */ 603*0Sstevel@tonic-gate if (strcmp(minor_name, "ssp") == 0) { 604*0Sstevel@tonic-gate (void) devfsadm_mklink("term/rsc-console", node, minor, 0); 605*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 606*0Sstevel@tonic-gate return (DEVFSADM_TERMINATE); 607*0Sstevel@tonic-gate 608*0Sstevel@tonic-gate /* 609*0Sstevel@tonic-gate * else if this is the RSC control serial port (i.e. the minor name == 610*0Sstevel@tonic-gate * sspctl), create /dev/rsc-control link and then we are done with this 611*0Sstevel@tonic-gate * node. 612*0Sstevel@tonic-gate */ 613*0Sstevel@tonic-gate } else if (strcmp(minor_name, "sspctl") == 0) { 614*0Sstevel@tonic-gate (void) devfsadm_mklink("rsc-control", node, minor, 0); 615*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 616*0Sstevel@tonic-gate return (DEVFSADM_TERMINATE); 617*0Sstevel@tonic-gate } 618*0Sstevel@tonic-gate 619*0Sstevel@tonic-gate /* This is not an RSC node, continue... */ 620*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 621*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 622*0Sstevel@tonic-gate } 623*0Sstevel@tonic-gate 624*0Sstevel@tonic-gate /* 625*0Sstevel@tonic-gate * Lights Out Management (LOM) serial ports 626*0Sstevel@tonic-gate * Creates links of the form "/dev/term/lom-console". 627*0Sstevel@tonic-gate */ 628*0Sstevel@tonic-gate static int 629*0Sstevel@tonic-gate lom_port_create(di_minor_t minor, di_node_t node) 630*0Sstevel@tonic-gate { 631*0Sstevel@tonic-gate char *devfspath; 632*0Sstevel@tonic-gate char *minor_name; 633*0Sstevel@tonic-gate 634*0Sstevel@tonic-gate devfspath = di_devfs_path(node); 635*0Sstevel@tonic-gate if (devfspath == NULL) { 636*0Sstevel@tonic-gate devfsadm_errprint("%s: di_devfs_path() failed\n", modname); 637*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 638*0Sstevel@tonic-gate } 639*0Sstevel@tonic-gate 640*0Sstevel@tonic-gate if ((minor_name = di_minor_name(minor)) == NULL) { 641*0Sstevel@tonic-gate devfsadm_errprint("%s: NULL minor name\n\t%s\n", 642*0Sstevel@tonic-gate modname, devfspath); 643*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 644*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 645*0Sstevel@tonic-gate } 646*0Sstevel@tonic-gate 647*0Sstevel@tonic-gate /* 648*0Sstevel@tonic-gate * if this is the LOM console serial port (i.e. the minor 649*0Sstevel@tonic-gate * name == lom-console ), create /dev/term/lom-console link and 650*0Sstevel@tonic-gate * then we are done with this node. 651*0Sstevel@tonic-gate */ 652*0Sstevel@tonic-gate if (strcmp(minor_name, "lom-console") == 0) { 653*0Sstevel@tonic-gate (void) devfsadm_mklink("term/lom-console", node, minor, 0); 654*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 655*0Sstevel@tonic-gate return (DEVFSADM_TERMINATE); 656*0Sstevel@tonic-gate } 657*0Sstevel@tonic-gate 658*0Sstevel@tonic-gate /* This is not a LOM node, continue... */ 659*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 660*0Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 661*0Sstevel@tonic-gate } 662*0Sstevel@tonic-gate 663*0Sstevel@tonic-gate /* 664*0Sstevel@tonic-gate * PCMCIA serial ports 665*0Sstevel@tonic-gate * Creates links of the form "/dev/term/pcN", where N is the PCMCIA 666*0Sstevel@tonic-gate * socket # the device is plugged into. 667*0Sstevel@tonic-gate */ 668*0Sstevel@tonic-gate #define PCMCIA_MAX_SOCKETS 64 669*0Sstevel@tonic-gate #define PCMCIA_SOCKETNO(x) ((x) & (PCMCIA_MAX_SOCKETS - 1)) 670*0Sstevel@tonic-gate 671*0Sstevel@tonic-gate static int 672*0Sstevel@tonic-gate pcmcia_port_create(di_minor_t minor, di_node_t node) 673*0Sstevel@tonic-gate { 674*0Sstevel@tonic-gate char l_path[MAXPATHLEN]; 675*0Sstevel@tonic-gate char *devfspath; 676*0Sstevel@tonic-gate int socket, *intp; 677*0Sstevel@tonic-gate 678*0Sstevel@tonic-gate devfspath = di_devfs_path(node); 679*0Sstevel@tonic-gate if (devfspath == NULL) { 680*0Sstevel@tonic-gate devfsadm_errprint("%s: di_devfs_path() failed\n", modname); 681*0Sstevel@tonic-gate return (DEVFSADM_TERMINATE); 682*0Sstevel@tonic-gate } 683*0Sstevel@tonic-gate 684*0Sstevel@tonic-gate if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "socket", &intp) <= 0) { 685*0Sstevel@tonic-gate devfsadm_errprint("%s: failed pcmcia socket lookup\n\t%s\n", 686*0Sstevel@tonic-gate modname, devfspath); 687*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 688*0Sstevel@tonic-gate return (DEVFSADM_TERMINATE); 689*0Sstevel@tonic-gate } 690*0Sstevel@tonic-gate 691*0Sstevel@tonic-gate socket = PCMCIA_SOCKETNO(*intp); 692*0Sstevel@tonic-gate 693*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 694*0Sstevel@tonic-gate 695*0Sstevel@tonic-gate (void) sprintf(l_path, "term/pc%d", socket); 696*0Sstevel@tonic-gate (void) devfsadm_mklink(l_path, node, minor, 0); 697*0Sstevel@tonic-gate 698*0Sstevel@tonic-gate return (DEVFSADM_TERMINATE); 699*0Sstevel@tonic-gate } 700*0Sstevel@tonic-gate 701*0Sstevel@tonic-gate /* 702*0Sstevel@tonic-gate * PCMCIA dialout serial ports 703*0Sstevel@tonic-gate * Creates links of the form "/dev/cua/pcN", where N is the PCMCIA 704*0Sstevel@tonic-gate * socket number the device is plugged into. 705*0Sstevel@tonic-gate */ 706*0Sstevel@tonic-gate static int 707*0Sstevel@tonic-gate pcmcia_dialout_create(di_minor_t minor, di_node_t node) 708*0Sstevel@tonic-gate { 709*0Sstevel@tonic-gate char l_path[MAXPATHLEN]; 710*0Sstevel@tonic-gate char *devfspath; 711*0Sstevel@tonic-gate int socket, *intp; 712*0Sstevel@tonic-gate 713*0Sstevel@tonic-gate devfspath = di_devfs_path(node); 714*0Sstevel@tonic-gate if (devfspath == NULL) { 715*0Sstevel@tonic-gate devfsadm_errprint("%s: di_devfs_path() failed\n", modname); 716*0Sstevel@tonic-gate return (DEVFSADM_TERMINATE); 717*0Sstevel@tonic-gate } 718*0Sstevel@tonic-gate 719*0Sstevel@tonic-gate if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "socket", &intp) <= 0) { 720*0Sstevel@tonic-gate devfsadm_errprint("%s: failed socket lookup\n\t%s\n", 721*0Sstevel@tonic-gate modname, devfspath); 722*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 723*0Sstevel@tonic-gate return (DEVFSADM_TERMINATE); 724*0Sstevel@tonic-gate } 725*0Sstevel@tonic-gate 726*0Sstevel@tonic-gate socket = PCMCIA_SOCKETNO(*intp); 727*0Sstevel@tonic-gate 728*0Sstevel@tonic-gate di_devfs_path_free(devfspath); 729*0Sstevel@tonic-gate (void) sprintf(l_path, "cua/pc%d", socket); 730*0Sstevel@tonic-gate (void) devfsadm_mklink(l_path, node, minor, 0); 731*0Sstevel@tonic-gate 732*0Sstevel@tonic-gate return (DEVFSADM_TERMINATE); 733*0Sstevel@tonic-gate } 734*0Sstevel@tonic-gate 735*0Sstevel@tonic-gate 736*0Sstevel@tonic-gate /* 737*0Sstevel@tonic-gate * Removes port entries that no longer have devices 738*0Sstevel@tonic-gate * backing them 739*0Sstevel@tonic-gate * Schedules an update the sacadm (portmon) database 740*0Sstevel@tonic-gate */ 741*0Sstevel@tonic-gate static void 742*0Sstevel@tonic-gate rm_dangling_port(char *devname) 743*0Sstevel@tonic-gate { 744*0Sstevel@tonic-gate char *portstr; 745*0Sstevel@tonic-gate int portnum; 746*0Sstevel@tonic-gate 747*0Sstevel@tonic-gate devfsadm_print(PORT_MID, "%s:rm_stale_port: %s\n", 748*0Sstevel@tonic-gate modname, devname); 749*0Sstevel@tonic-gate 750*0Sstevel@tonic-gate if ((portstr = strrchr(devname, (int)'/')) == NULL) { 751*0Sstevel@tonic-gate devfsadm_errprint("%s: invalid name: %s\n", 752*0Sstevel@tonic-gate modname, devname); 753*0Sstevel@tonic-gate return; 754*0Sstevel@tonic-gate } 755*0Sstevel@tonic-gate portstr++; 756*0Sstevel@tonic-gate 757*0Sstevel@tonic-gate /* 758*0Sstevel@tonic-gate * mark for removal from sacadm database 759*0Sstevel@tonic-gate */ 760*0Sstevel@tonic-gate if ((portnum = parse_portno(portstr)) != -1) 761*0Sstevel@tonic-gate pma[portnum].flags |= PORT_REMOVED; 762*0Sstevel@tonic-gate 763*0Sstevel@tonic-gate devfsadm_rm_all(devname); 764*0Sstevel@tonic-gate } 765*0Sstevel@tonic-gate 766*0Sstevel@tonic-gate /* 767*0Sstevel@tonic-gate * Algorithm is to step through ports; checking for unneeded PM entries 768*0Sstevel@tonic-gate * entries that should be there but are not. Every PM_GRPSZ entries 769*0Sstevel@tonic-gate * check to see if there are any entries for the port monitor group; 770*0Sstevel@tonic-gate * if not, delete the group. 771*0Sstevel@tonic-gate */ 772*0Sstevel@tonic-gate static void 773*0Sstevel@tonic-gate update_sacadm_db(void) 774*0Sstevel@tonic-gate { 775*0Sstevel@tonic-gate int i; 776*0Sstevel@tonic-gate 777*0Sstevel@tonic-gate if (load_ttymondb() != DEVFSADM_SUCCESS) 778*0Sstevel@tonic-gate return; 779*0Sstevel@tonic-gate 780*0Sstevel@tonic-gate for (i = 0; i < maxports; i++) { 781*0Sstevel@tonic-gate /* 782*0Sstevel@tonic-gate * if this port was removed and has a port 783*0Sstevel@tonic-gate * monitor entry, remove the entry from the sacadm db 784*0Sstevel@tonic-gate */ 785*0Sstevel@tonic-gate if ((pma[i].flags & PORT_REMOVED) != 0) { 786*0Sstevel@tonic-gate if ((pma[i].flags & PM_HAS_ENTRY) != 0) 787*0Sstevel@tonic-gate remove_pm_entry(pma[i].pm_tag, i); 788*0Sstevel@tonic-gate } 789*0Sstevel@tonic-gate 790*0Sstevel@tonic-gate /* 791*0Sstevel@tonic-gate * if this port is present and lacks a port monitor 792*0Sstevel@tonic-gate * add an entry to the sacadm db 793*0Sstevel@tonic-gate */ 794*0Sstevel@tonic-gate if (pma[i].flags & HAS_PORT_DEVICE) { 795*0Sstevel@tonic-gate if (!(pma[i].flags & PM_HAS_ENTRY)) 796*0Sstevel@tonic-gate add_pm_entry(i); 797*0Sstevel@tonic-gate } 798*0Sstevel@tonic-gate 799*0Sstevel@tonic-gate /* 800*0Sstevel@tonic-gate * if this port has a pm entry, mark as needing 801*0Sstevel@tonic-gate * a port monitor within this range of ports 802*0Sstevel@tonic-gate */ 803*0Sstevel@tonic-gate if ((pma[i].flags & PM_HAS_ENTRY)) 804*0Sstevel@tonic-gate pma[PM_SLOT(i)].flags |= PM_NEEDED; 805*0Sstevel@tonic-gate 806*0Sstevel@tonic-gate /* 807*0Sstevel@tonic-gate * continue for the range of ports per-portmon 808*0Sstevel@tonic-gate */ 809*0Sstevel@tonic-gate if (((i + 1) % PM_GRPSZ) != 0) 810*0Sstevel@tonic-gate continue; 811*0Sstevel@tonic-gate 812*0Sstevel@tonic-gate /* 813*0Sstevel@tonic-gate * if there are no ports active on the range we have 814*0Sstevel@tonic-gate * just completed, remove the port monitor entry if 815*0Sstevel@tonic-gate * it exists 816*0Sstevel@tonic-gate */ 817*0Sstevel@tonic-gate if ((pma[PM_SLOT(i)].flags & (PM_NEEDED | HAS_PORT_MON)) == 818*0Sstevel@tonic-gate HAS_PORT_MON) { 819*0Sstevel@tonic-gate delete_port_monitor(i); 820*0Sstevel@tonic-gate } 821*0Sstevel@tonic-gate 822*0Sstevel@tonic-gate } 823*0Sstevel@tonic-gate 824*0Sstevel@tonic-gate /* 825*0Sstevel@tonic-gate * cleanup remaining port monitor, if active 826*0Sstevel@tonic-gate */ 827*0Sstevel@tonic-gate if ((i % PM_GRPSZ != 0) && 828*0Sstevel@tonic-gate ((pma[PM_SLOT(i)].flags & (PM_NEEDED | HAS_PORT_MON)) == 829*0Sstevel@tonic-gate HAS_PORT_MON)) { 830*0Sstevel@tonic-gate delete_port_monitor(i); 831*0Sstevel@tonic-gate } 832*0Sstevel@tonic-gate } 833*0Sstevel@tonic-gate 834*0Sstevel@tonic-gate /* 835*0Sstevel@tonic-gate * Determine which port monitor entries already exist by invoking pmadm(1m) 836*0Sstevel@tonic-gate * to list all configured 'ttymon' port monitor entries. 837*0Sstevel@tonic-gate * Do not explicitly report errors from executing pmadm(1m) or sacadm(1m) 838*0Sstevel@tonic-gate * commands to remain compatible with the ports(1m) implementation. 839*0Sstevel@tonic-gate */ 840*0Sstevel@tonic-gate static int 841*0Sstevel@tonic-gate load_ttymondb(void) 842*0Sstevel@tonic-gate { 843*0Sstevel@tonic-gate char cmdline[CMDLEN]; 844*0Sstevel@tonic-gate char cmdbuf[PMTAB_MAXLINE+1]; 845*0Sstevel@tonic-gate int sac_exitval; 846*0Sstevel@tonic-gate FILE *fs_popen; 847*0Sstevel@tonic-gate char *portname; /* pointer to a tty name */ 848*0Sstevel@tonic-gate int portnum; 849*0Sstevel@tonic-gate char *ptr; 850*0Sstevel@tonic-gate char *error_msg = "%s: failed to load port monitor database\n"; 851*0Sstevel@tonic-gate 852*0Sstevel@tonic-gate (void) strcpy(cmdline, "/usr/sbin/pmadm -L -t ttymon"); 853*0Sstevel@tonic-gate fs_popen = popen(cmdline, "r"); 854*0Sstevel@tonic-gate if (fs_popen == NULL) { 855*0Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, error_msg, modname); 856*0Sstevel@tonic-gate return (DEVFSADM_FAILURE); 857*0Sstevel@tonic-gate } 858*0Sstevel@tonic-gate 859*0Sstevel@tonic-gate while (fgets(cmdbuf, PMTAB_MAXLINE, fs_popen) != NULL) { 860*0Sstevel@tonic-gate if ((portname = pmtab_parse_portname(cmdbuf)) == NULL) { 861*0Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, 862*0Sstevel@tonic-gate "load_ttymondb: failed to parse portname\n"); 863*0Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, 864*0Sstevel@tonic-gate "load_ttymondb: buffer \"%s\"\n", cmdbuf); 865*0Sstevel@tonic-gate goto load_failed; 866*0Sstevel@tonic-gate } 867*0Sstevel@tonic-gate 868*0Sstevel@tonic-gate devfsadm_print(PORT_MID, "%s:load_ttymondb: port %s ", 869*0Sstevel@tonic-gate modname, portname); 870*0Sstevel@tonic-gate 871*0Sstevel@tonic-gate /* 872*0Sstevel@tonic-gate * skip onboard ports 873*0Sstevel@tonic-gate * There is no reliable way to determine if we 874*0Sstevel@tonic-gate * should start a port monitor on these lines. 875*0Sstevel@tonic-gate */ 876*0Sstevel@tonic-gate if ((portnum = parse_portno(portname)) == -1) { 877*0Sstevel@tonic-gate devfsadm_print(PORT_MID, "ignored\n"); 878*0Sstevel@tonic-gate continue; 879*0Sstevel@tonic-gate } 880*0Sstevel@tonic-gate 881*0Sstevel@tonic-gate /* 882*0Sstevel@tonic-gate * the first field of the pmadm output is 883*0Sstevel@tonic-gate * the port monitor name for this entry 884*0Sstevel@tonic-gate */ 885*0Sstevel@tonic-gate if ((ptr = strchr(cmdbuf, PMTAB_SEPR)) == NULL) { 886*0Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, 887*0Sstevel@tonic-gate "load_ttymondb: no portmon tag\n"); 888*0Sstevel@tonic-gate goto load_failed; 889*0Sstevel@tonic-gate } 890*0Sstevel@tonic-gate 891*0Sstevel@tonic-gate *ptr = MN_NULLCHAR; 892*0Sstevel@tonic-gate if ((pma[portnum].pm_tag = strdup(cmdbuf)) == NULL) { 893*0Sstevel@tonic-gate devfsadm_errprint("load_ttymondb: failed strdup\n"); 894*0Sstevel@tonic-gate goto load_failed; 895*0Sstevel@tonic-gate } 896*0Sstevel@tonic-gate pma[portnum].flags |= PM_HAS_ENTRY; 897*0Sstevel@tonic-gate pma[PM_SLOT(portnum)].flags |= HAS_PORT_MON; 898*0Sstevel@tonic-gate devfsadm_print(PORT_MID, "present\n"); 899*0Sstevel@tonic-gate } 900*0Sstevel@tonic-gate (void) pclose(fs_popen); 901*0Sstevel@tonic-gate return (DEVFSADM_SUCCESS); 902*0Sstevel@tonic-gate 903*0Sstevel@tonic-gate load_failed: 904*0Sstevel@tonic-gate 905*0Sstevel@tonic-gate /* 906*0Sstevel@tonic-gate * failed to load the port monitor database 907*0Sstevel@tonic-gate */ 908*0Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, error_msg, modname); 909*0Sstevel@tonic-gate sac_exitval = SAC_EXITVAL(pclose(fs_popen)); 910*0Sstevel@tonic-gate if (sac_exitval != 0) { 911*0Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, 912*0Sstevel@tonic-gate "pmadm: (%s) %s\n", SAC_EID(sac_exitval), 913*0Sstevel@tonic-gate SAC_EMSG(sac_exitval)); 914*0Sstevel@tonic-gate } 915*0Sstevel@tonic-gate return (DEVFSADM_FAILURE); 916*0Sstevel@tonic-gate } 917*0Sstevel@tonic-gate 918*0Sstevel@tonic-gate /* 919*0Sstevel@tonic-gate * add a port monitor entry for device /dev/term/"port" 920*0Sstevel@tonic-gate */ 921*0Sstevel@tonic-gate static void 922*0Sstevel@tonic-gate add_pm_entry(int port) 923*0Sstevel@tonic-gate { 924*0Sstevel@tonic-gate char cmdline[CMDLEN]; 925*0Sstevel@tonic-gate int sac_exitval; 926*0Sstevel@tonic-gate 927*0Sstevel@tonic-gate add_port_monitor(port); 928*0Sstevel@tonic-gate (void) sprintf(cmdline, 929*0Sstevel@tonic-gate "/usr/sbin/pmadm -a -p ttymon%d -s %d -i root" 930*0Sstevel@tonic-gate " -v `/usr/sbin/ttyadm -V` -fux -y\"/dev/term/%d\"" 931*0Sstevel@tonic-gate " -m \"`/usr/sbin/ttyadm -d /dev/term/%d -s /usr/bin/login" 932*0Sstevel@tonic-gate " -l 9600 -p \\\"login: \\\"`\"", PM_NUM(port), port, port, port); 933*0Sstevel@tonic-gate 934*0Sstevel@tonic-gate if (devfsadm_noupdate() == DEVFSADM_FALSE) { 935*0Sstevel@tonic-gate sac_exitval = execute(cmdline); 936*0Sstevel@tonic-gate if ((sac_exitval != 0) && (sac_exitval != E_SACNOTRUN)) { 937*0Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, 938*0Sstevel@tonic-gate "failed to add port monitor entry" 939*0Sstevel@tonic-gate " for /dev/term/%d\n", port); 940*0Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, "pmadm: (%s) %s\n", 941*0Sstevel@tonic-gate SAC_EID(sac_exitval), SAC_EMSG(sac_exitval)); 942*0Sstevel@tonic-gate } 943*0Sstevel@tonic-gate } 944*0Sstevel@tonic-gate pma[port].flags |= PM_HAS_ENTRY; 945*0Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, "%s: /dev/term/%d added to sacadm\n", 946*0Sstevel@tonic-gate modname, port); 947*0Sstevel@tonic-gate } 948*0Sstevel@tonic-gate 949*0Sstevel@tonic-gate static void 950*0Sstevel@tonic-gate remove_pm_entry(char *pmtag, int port) 951*0Sstevel@tonic-gate { 952*0Sstevel@tonic-gate 953*0Sstevel@tonic-gate char cmdline[CMDLEN]; 954*0Sstevel@tonic-gate int sac_exitval; 955*0Sstevel@tonic-gate 956*0Sstevel@tonic-gate if (devfsadm_noupdate() == DEVFSADM_FALSE) { 957*0Sstevel@tonic-gate (void) snprintf(cmdline, sizeof (cmdline), 958*0Sstevel@tonic-gate "/usr/sbin/pmadm -r -p %s -s %d", pmtag, port); 959*0Sstevel@tonic-gate sac_exitval = execute(cmdline); 960*0Sstevel@tonic-gate if ((sac_exitval != 0) && (sac_exitval != E_SACNOTRUN)) { 961*0Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, 962*0Sstevel@tonic-gate "failed to remove port monitor entry" 963*0Sstevel@tonic-gate " for /dev/term/%d\n", port); 964*0Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, "pmadm: (%s) %s\n", 965*0Sstevel@tonic-gate SAC_EID(sac_exitval), SAC_EMSG(sac_exitval)); 966*0Sstevel@tonic-gate } 967*0Sstevel@tonic-gate } 968*0Sstevel@tonic-gate pma[port].flags &= ~PM_HAS_ENTRY; 969*0Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, "%s: /dev/term/%d removed from sacadm\n", 970*0Sstevel@tonic-gate modname, port); 971*0Sstevel@tonic-gate } 972*0Sstevel@tonic-gate 973*0Sstevel@tonic-gate 974*0Sstevel@tonic-gate /* 975*0Sstevel@tonic-gate * delete_port_monitor() 976*0Sstevel@tonic-gate * Check for the existence of a port monitor for "port" and remove it if 977*0Sstevel@tonic-gate * one exists 978*0Sstevel@tonic-gate */ 979*0Sstevel@tonic-gate static void 980*0Sstevel@tonic-gate delete_port_monitor(int port) 981*0Sstevel@tonic-gate { 982*0Sstevel@tonic-gate char cmdline[CMDLEN]; 983*0Sstevel@tonic-gate int sac_exitval; 984*0Sstevel@tonic-gate 985*0Sstevel@tonic-gate (void) sprintf(cmdline, "/usr/sbin/sacadm -L -p ttymon%d", 986*0Sstevel@tonic-gate PM_NUM(port)); 987*0Sstevel@tonic-gate sac_exitval = execute(cmdline); 988*0Sstevel@tonic-gate 989*0Sstevel@tonic-gate /* clear the PM tag and return if the port monitor is not active */ 990*0Sstevel@tonic-gate if (sac_exitval == E_NOEXIST) { 991*0Sstevel@tonic-gate pma[PM_SLOT(port)].flags &= ~HAS_PORT_MON; 992*0Sstevel@tonic-gate return; 993*0Sstevel@tonic-gate } 994*0Sstevel@tonic-gate 995*0Sstevel@tonic-gate /* some other sacadm(1m) error, log and return */ 996*0Sstevel@tonic-gate if (sac_exitval != 0) { 997*0Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, "sacadm: (%s) %s\n", 998*0Sstevel@tonic-gate SAC_EID(sac_exitval), SAC_EMSG(sac_exitval)); 999*0Sstevel@tonic-gate return; 1000*0Sstevel@tonic-gate } 1001*0Sstevel@tonic-gate 1002*0Sstevel@tonic-gate if (devfsadm_noupdate() == DEVFSADM_FALSE) { 1003*0Sstevel@tonic-gate (void) sprintf(cmdline, 1004*0Sstevel@tonic-gate "/usr/sbin/sacadm -r -p ttymon%d", PM_NUM(port)); 1005*0Sstevel@tonic-gate if (sac_exitval = execute(cmdline)) { 1006*0Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, 1007*0Sstevel@tonic-gate "failed to remove port monitor ttymon%d\n", 1008*0Sstevel@tonic-gate PM_NUM(port)); 1009*0Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, "sacadm: (%s) %s\n", 1010*0Sstevel@tonic-gate SAC_EID(sac_exitval), SAC_EMSG(sac_exitval)); 1011*0Sstevel@tonic-gate } 1012*0Sstevel@tonic-gate } 1013*0Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, "%s: port monitor ttymon%d removed\n", 1014*0Sstevel@tonic-gate modname, PM_NUM(port)); 1015*0Sstevel@tonic-gate pma[PM_SLOT(port)].flags &= ~HAS_PORT_MON; 1016*0Sstevel@tonic-gate } 1017*0Sstevel@tonic-gate 1018*0Sstevel@tonic-gate static void 1019*0Sstevel@tonic-gate add_port_monitor(int port) 1020*0Sstevel@tonic-gate { 1021*0Sstevel@tonic-gate char cmdline[CMDLEN]; 1022*0Sstevel@tonic-gate int sac_exitval; 1023*0Sstevel@tonic-gate 1024*0Sstevel@tonic-gate if ((pma[PM_SLOT(port)].flags & HAS_PORT_MON) != 0) { 1025*0Sstevel@tonic-gate return; 1026*0Sstevel@tonic-gate } 1027*0Sstevel@tonic-gate 1028*0Sstevel@tonic-gate (void) sprintf(cmdline, 1029*0Sstevel@tonic-gate "/usr/sbin/sacadm -l -p ttymon%d", PM_NUM(port)); 1030*0Sstevel@tonic-gate sac_exitval = execute(cmdline); 1031*0Sstevel@tonic-gate if (sac_exitval == E_NOEXIST) { 1032*0Sstevel@tonic-gate (void) sprintf(cmdline, 1033*0Sstevel@tonic-gate "/usr/sbin/sacadm -a -n 2 -p ttymon%d -t ttymon" 1034*0Sstevel@tonic-gate " -c /usr/lib/saf/ttymon -v \"`/usr/sbin/ttyadm" 1035*0Sstevel@tonic-gate " -V`\" -y \"Ports %d-%d\"", PM_NUM(port), PM_SLOT(port), 1036*0Sstevel@tonic-gate PM_SLOT(port) + (PM_GRPSZ - 1)); 1037*0Sstevel@tonic-gate if (devfsadm_noupdate() == DEVFSADM_FALSE) { 1038*0Sstevel@tonic-gate if (sac_exitval = execute(cmdline)) { 1039*0Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, 1040*0Sstevel@tonic-gate "failed to add port monitor ttymon%d\n", 1041*0Sstevel@tonic-gate PM_NUM(port)); 1042*0Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, "sacadm: (%s) %s\n", 1043*0Sstevel@tonic-gate SAC_EID(sac_exitval), 1044*0Sstevel@tonic-gate SAC_EMSG(sac_exitval)); 1045*0Sstevel@tonic-gate } 1046*0Sstevel@tonic-gate } 1047*0Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, "%s: port monitor ttymon%d added\n", 1048*0Sstevel@tonic-gate modname, PM_NUM(port)); 1049*0Sstevel@tonic-gate } 1050*0Sstevel@tonic-gate pma[PM_SLOT(port)].flags |= HAS_PORT_MON; 1051*0Sstevel@tonic-gate } 1052*0Sstevel@tonic-gate 1053*0Sstevel@tonic-gate /* 1054*0Sstevel@tonic-gate * parse port number from string 1055*0Sstevel@tonic-gate * returns port number if in range [0..maxports] 1056*0Sstevel@tonic-gate */ 1057*0Sstevel@tonic-gate static int 1058*0Sstevel@tonic-gate parse_portno(char *dname) 1059*0Sstevel@tonic-gate { 1060*0Sstevel@tonic-gate int pn; 1061*0Sstevel@tonic-gate 1062*0Sstevel@tonic-gate if (sscanf(dname, "%d", &pn) != 1) 1063*0Sstevel@tonic-gate return (-1); 1064*0Sstevel@tonic-gate 1065*0Sstevel@tonic-gate if ((pn < 0) || (pn > maxports)) { 1066*0Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, 1067*0Sstevel@tonic-gate "%s:parse_portno: %d not in range (0..%d)\n", 1068*0Sstevel@tonic-gate modname, pn, maxports); 1069*0Sstevel@tonic-gate return (-1); 1070*0Sstevel@tonic-gate } 1071*0Sstevel@tonic-gate 1072*0Sstevel@tonic-gate return (pn); 1073*0Sstevel@tonic-gate } 1074*0Sstevel@tonic-gate 1075*0Sstevel@tonic-gate 1076*0Sstevel@tonic-gate /* 1077*0Sstevel@tonic-gate * fork and exec a command, waiting for the command to 1078*0Sstevel@tonic-gate * complete and return it's status 1079*0Sstevel@tonic-gate */ 1080*0Sstevel@tonic-gate static int 1081*0Sstevel@tonic-gate execute(const char *s) 1082*0Sstevel@tonic-gate { 1083*0Sstevel@tonic-gate int status; 1084*0Sstevel@tonic-gate int fd; 1085*0Sstevel@tonic-gate pid_t pid; 1086*0Sstevel@tonic-gate pid_t w; 1087*0Sstevel@tonic-gate 1088*0Sstevel@tonic-gate /* 1089*0Sstevel@tonic-gate * fork a single threaded child proc to execute the 1090*0Sstevel@tonic-gate * sacadm command string 1091*0Sstevel@tonic-gate */ 1092*0Sstevel@tonic-gate devfsadm_print(PORT_MID, "%s: execute:\n\t%s\n", modname, s); 1093*0Sstevel@tonic-gate if ((pid = fork1()) == 0) { 1094*0Sstevel@tonic-gate (void) close(0); 1095*0Sstevel@tonic-gate (void) close(1); 1096*0Sstevel@tonic-gate (void) close(2); 1097*0Sstevel@tonic-gate fd = open("/dev/null", O_RDWR); 1098*0Sstevel@tonic-gate (void) dup(fd); 1099*0Sstevel@tonic-gate (void) dup(fd); 1100*0Sstevel@tonic-gate (void) execl("/sbin/sh", "sh", "-c", s, 0); 1101*0Sstevel@tonic-gate /* 1102*0Sstevel@tonic-gate * return the sacadm exit status (see _exit(2)) 1103*0Sstevel@tonic-gate */ 1104*0Sstevel@tonic-gate _exit(127); 1105*0Sstevel@tonic-gate } 1106*0Sstevel@tonic-gate 1107*0Sstevel@tonic-gate /* 1108*0Sstevel@tonic-gate * wait for child process to terminate 1109*0Sstevel@tonic-gate */ 1110*0Sstevel@tonic-gate for (;;) { 1111*0Sstevel@tonic-gate w = wait(&status); 1112*0Sstevel@tonic-gate if (w == pid) { 1113*0Sstevel@tonic-gate devfsadm_print(PORT_MID, "%s:exit status (%d)\n", 1114*0Sstevel@tonic-gate modname, SAC_EXITVAL(status)); 1115*0Sstevel@tonic-gate return (SAC_EXITVAL(status)); 1116*0Sstevel@tonic-gate } 1117*0Sstevel@tonic-gate if (w == (pid_t)-1) { 1118*0Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, "%s: exec failed\n", 1119*0Sstevel@tonic-gate modname); 1120*0Sstevel@tonic-gate return (-1); 1121*0Sstevel@tonic-gate } 1122*0Sstevel@tonic-gate } 1123*0Sstevel@tonic-gate 1124*0Sstevel@tonic-gate /* NOTREACHED */ 1125*0Sstevel@tonic-gate } 1126*0Sstevel@tonic-gate 1127*0Sstevel@tonic-gate 1128*0Sstevel@tonic-gate /* 1129*0Sstevel@tonic-gate * check if the minor name is suffixed with ",cu" 1130*0Sstevel@tonic-gate */ 1131*0Sstevel@tonic-gate static int 1132*0Sstevel@tonic-gate is_dialout(char *name) 1133*0Sstevel@tonic-gate { 1134*0Sstevel@tonic-gate char *s_chr; 1135*0Sstevel@tonic-gate 1136*0Sstevel@tonic-gate if ((name == NULL) || (s_chr = strrchr(name, MN_SEPR)) == NULL) 1137*0Sstevel@tonic-gate return (0); 1138*0Sstevel@tonic-gate 1139*0Sstevel@tonic-gate if (strcmp(s_chr, DIALOUT_SUFFIX) == 0) { 1140*0Sstevel@tonic-gate return (1); 1141*0Sstevel@tonic-gate } else { 1142*0Sstevel@tonic-gate return (0); 1143*0Sstevel@tonic-gate } 1144*0Sstevel@tonic-gate } 1145*0Sstevel@tonic-gate 1146*0Sstevel@tonic-gate 1147*0Sstevel@tonic-gate /* 1148*0Sstevel@tonic-gate * Get the name of the port device from a pmtab entry. 1149*0Sstevel@tonic-gate * Note the /dev/term/ part is taken off. 1150*0Sstevel@tonic-gate */ 1151*0Sstevel@tonic-gate static char * 1152*0Sstevel@tonic-gate pmtab_parse_portname(char *buffer) 1153*0Sstevel@tonic-gate { 1154*0Sstevel@tonic-gate int i; 1155*0Sstevel@tonic-gate char *bufp, *devnamep, *portnamep; 1156*0Sstevel@tonic-gate 1157*0Sstevel@tonic-gate /* 1158*0Sstevel@tonic-gate * position to the device name (field 8) 1159*0Sstevel@tonic-gate */ 1160*0Sstevel@tonic-gate bufp = strchr(buffer, PMTAB_SEPR); 1161*0Sstevel@tonic-gate for (i = 0; i < PMTAB_DEVNAME_FIELD; i++) { 1162*0Sstevel@tonic-gate if (bufp == NULL) 1163*0Sstevel@tonic-gate return (NULL); 1164*0Sstevel@tonic-gate bufp = strchr(++bufp, PMTAB_SEPR); 1165*0Sstevel@tonic-gate } 1166*0Sstevel@tonic-gate 1167*0Sstevel@tonic-gate /* move past the ':' and locate the end of the devname */ 1168*0Sstevel@tonic-gate devnamep = bufp++; 1169*0Sstevel@tonic-gate if ((bufp = strchr(bufp, PMTAB_SEPR)) == NULL) 1170*0Sstevel@tonic-gate return (NULL); 1171*0Sstevel@tonic-gate 1172*0Sstevel@tonic-gate *bufp = MN_NULLCHAR; 1173*0Sstevel@tonic-gate if ((portnamep = strrchr(devnamep, DEVNAME_SEPR)) == NULL) { 1174*0Sstevel@tonic-gate *bufp = PMTAB_SEPR; 1175*0Sstevel@tonic-gate return (NULL); 1176*0Sstevel@tonic-gate } 1177*0Sstevel@tonic-gate 1178*0Sstevel@tonic-gate /* return with "buffer" chopped after the /dev/term entry */ 1179*0Sstevel@tonic-gate 1180*0Sstevel@tonic-gate return (++portnamep); 1181*0Sstevel@tonic-gate } 1182*0Sstevel@tonic-gate 1183*0Sstevel@tonic-gate /* 1184*0Sstevel@tonic-gate * port monitor array mgmt 1185*0Sstevel@tonic-gate */ 1186*0Sstevel@tonic-gate static void * 1187*0Sstevel@tonic-gate pma_alloc(void) 1188*0Sstevel@tonic-gate { 1189*0Sstevel@tonic-gate 1190*0Sstevel@tonic-gate if (pma != NULL) { 1191*0Sstevel@tonic-gate devfsadm_errprint("%s:pma_alloc:pma != NULL\n", modname); 1192*0Sstevel@tonic-gate return (NULL); 1193*0Sstevel@tonic-gate } 1194*0Sstevel@tonic-gate 1195*0Sstevel@tonic-gate if ((pma = calloc(maxports + 1, sizeof (*pma))) == NULL) { 1196*0Sstevel@tonic-gate devfsadm_errprint("%s:pma_alloc:pma alloc failure\n", modname); 1197*0Sstevel@tonic-gate return (NULL); 1198*0Sstevel@tonic-gate } 1199*0Sstevel@tonic-gate 1200*0Sstevel@tonic-gate return ((void *)pma); 1201*0Sstevel@tonic-gate } 1202*0Sstevel@tonic-gate 1203*0Sstevel@tonic-gate static void 1204*0Sstevel@tonic-gate pma_free(void) 1205*0Sstevel@tonic-gate { 1206*0Sstevel@tonic-gate 1207*0Sstevel@tonic-gate int i; 1208*0Sstevel@tonic-gate 1209*0Sstevel@tonic-gate if (pma == NULL) 1210*0Sstevel@tonic-gate return; 1211*0Sstevel@tonic-gate 1212*0Sstevel@tonic-gate /* 1213*0Sstevel@tonic-gate * free any strings we had allocated 1214*0Sstevel@tonic-gate */ 1215*0Sstevel@tonic-gate for (i = 0; i <= maxports; i++) { 1216*0Sstevel@tonic-gate if (pma[i].pm_tag != NULL) 1217*0Sstevel@tonic-gate free(pma[i].pm_tag); 1218*0Sstevel@tonic-gate } 1219*0Sstevel@tonic-gate 1220*0Sstevel@tonic-gate free(pma); 1221*0Sstevel@tonic-gate pma = NULL; 1222*0Sstevel@tonic-gate } 1223