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 5e9c71215SVikram Hegde * Common Development and Distribution License (the "License"). 6e9c71215SVikram Hegde * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21de81e71eSTim Marsland 227c478bd9Sstevel@tonic-gate /* 23*506aa7c6SGarrett D'Amore * Copyright 2013 Garrett D'Amore <garrett@damore.org> 2494c894bbSVikram Hegde * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include <unistd.h> 287c478bd9Sstevel@tonic-gate #include <stdio.h> 297c478bd9Sstevel@tonic-gate #include <stdlib.h> 307c478bd9Sstevel@tonic-gate #include <string.h> 317c478bd9Sstevel@tonic-gate #include <regex.h> 327c478bd9Sstevel@tonic-gate #include <sac.h> 337c478bd9Sstevel@tonic-gate #include <errno.h> 347c478bd9Sstevel@tonic-gate #include <dirent.h> 357c478bd9Sstevel@tonic-gate #include <limits.h> 367c478bd9Sstevel@tonic-gate #include <sys/types.h> 377c478bd9Sstevel@tonic-gate #include <sys/stat.h> 387c478bd9Sstevel@tonic-gate #include <sys/wait.h> 397c478bd9Sstevel@tonic-gate #include <fcntl.h> 407c478bd9Sstevel@tonic-gate #include <devfsadm.h> 41de81e71eSTim Marsland #include <syslog.h> 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate /* 447c478bd9Sstevel@tonic-gate * sacadm output parsing 457c478bd9Sstevel@tonic-gate */ 467c478bd9Sstevel@tonic-gate #define PMTAB_MAXLINE 512 477c478bd9Sstevel@tonic-gate #define PMTAB_SEPR ':' 487c478bd9Sstevel@tonic-gate #define PMTAB_DEVNAME_FIELD 7 /* field containing /dev/term/n */ 497c478bd9Sstevel@tonic-gate #define DIALOUT_SUFFIX ",cu" 507c478bd9Sstevel@tonic-gate #define DEVNAME_SEPR '/' 517c478bd9Sstevel@tonic-gate #define MN_SEPR ',' 527c478bd9Sstevel@tonic-gate #define MN_NULLCHAR '\0' 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate /* 557c478bd9Sstevel@tonic-gate * sacadm/pmadm exit codes (see /usr/include/sac.h) 567c478bd9Sstevel@tonic-gate */ 577c478bd9Sstevel@tonic-gate static char *sacerrs[] = { 587c478bd9Sstevel@tonic-gate "UNKNOWN", "Unknown exit code", 597c478bd9Sstevel@tonic-gate "E_BADARGS", "Invalid arguments", 607c478bd9Sstevel@tonic-gate "E_NOPRIV", "Not privileged", 617c478bd9Sstevel@tonic-gate "E_SAFERR", "SAF error", 627c478bd9Sstevel@tonic-gate "E_SYSERR", "System error", 637c478bd9Sstevel@tonic-gate "E_NOEXIST", "Entry does not exist", 647c478bd9Sstevel@tonic-gate "E_DUP", "Entry already exists", 657c478bd9Sstevel@tonic-gate "E_PMRUN", "Port monitor already running", 667c478bd9Sstevel@tonic-gate "E_PMNOTRUN", "Port monitor not running", 677c478bd9Sstevel@tonic-gate "E_RECOVER", "In recovery", 687c478bd9Sstevel@tonic-gate "E_SACNOTRUN", "SAC daemon not running", 697c478bd9Sstevel@tonic-gate }; 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate #define SAC_EXITVAL(x) ((x) >> 8) 727c478bd9Sstevel@tonic-gate #define SAC_EID(x) \ 737c478bd9Sstevel@tonic-gate (sacerrs[((uint_t)(x) > E_SACNOTRUN ? 0 : ((x)<<1))]) 747c478bd9Sstevel@tonic-gate #define SAC_EMSG(x) \ 757c478bd9Sstevel@tonic-gate (sacerrs[((uint_t)(x) > E_SACNOTRUN ? 1 : (((x)<<1) + 1))]) 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate /* 807c478bd9Sstevel@tonic-gate * create port monitors for each group of PM_GRPSZ port devices. 817c478bd9Sstevel@tonic-gate */ 827c478bd9Sstevel@tonic-gate #define PM_GRPSZ 64 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate /* 857c478bd9Sstevel@tonic-gate * compute port monitor # and base index 867c478bd9Sstevel@tonic-gate */ 877c478bd9Sstevel@tonic-gate #define PM_NUM(p) ((p) / PM_GRPSZ) 887c478bd9Sstevel@tonic-gate #define PM_SLOT(p) (PM_NUM(p) * PM_GRPSZ) 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate /* 927c478bd9Sstevel@tonic-gate * default maxports value 937c478bd9Sstevel@tonic-gate * override by setting SUNW_port_link.maxports in default/devfsadm 947c478bd9Sstevel@tonic-gate */ 957c478bd9Sstevel@tonic-gate #define MAXPORTS_DEFAULT 2048 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate /* 987c478bd9Sstevel@tonic-gate * command line buffer size for sacadm 997c478bd9Sstevel@tonic-gate */ 1007c478bd9Sstevel@tonic-gate #define CMDLEN 1024 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate struct pm_alloc { 1037c478bd9Sstevel@tonic-gate uint_t flags; 1047c478bd9Sstevel@tonic-gate char *pm_tag; 1057c478bd9Sstevel@tonic-gate }; 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate /* port monitor entry flags */ 1087c478bd9Sstevel@tonic-gate #define PM_HAS_ENTRY 0x1 /* pm entry for this port */ 1097c478bd9Sstevel@tonic-gate #define HAS_PORT_DEVICE 0x2 /* device exists */ 1107c478bd9Sstevel@tonic-gate #define PORT_REMOVED 0x4 /* dangling port */ 1117c478bd9Sstevel@tonic-gate #define HAS_PORT_MON 0x8 /* port monitor active */ 1127c478bd9Sstevel@tonic-gate #define PM_NEEDED 0x10 /* port monitor needed */ 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate static int maxports; 1157c478bd9Sstevel@tonic-gate static struct pm_alloc *pma; 1167c478bd9Sstevel@tonic-gate static char *modname = "SUNW_port_link"; 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate /* 1197c478bd9Sstevel@tonic-gate * devfsadm_print message id 1207c478bd9Sstevel@tonic-gate */ 1217c478bd9Sstevel@tonic-gate #define PORT_MID "SUNW_port_link" 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate /* 1247c478bd9Sstevel@tonic-gate * enumeration regular expressions, port and onboard port devices 1257c478bd9Sstevel@tonic-gate * On x86, /dev/term|cua/[a..z] namespace is split into 2: 1267c478bd9Sstevel@tonic-gate * a-d are assigned based on minor name. e-z are 1277c478bd9Sstevel@tonic-gate * assigned via enumeration. 1287c478bd9Sstevel@tonic-gate */ 1297c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t port_rules[] = 1307c478bd9Sstevel@tonic-gate {"^(term|cua)$/^([0-9]+)$", 1, MATCH_MINOR, "1"}; 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate #ifdef __i386 1337c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t obport_rules[] = 1347c478bd9Sstevel@tonic-gate {"^(term|cua)$/^([e-z])$", 1, MATCH_MINOR, "1"}; 1357c478bd9Sstevel@tonic-gate static char start_id[] = "e"; 1367c478bd9Sstevel@tonic-gate #else 1377c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t obport_rules[] = 1387c478bd9Sstevel@tonic-gate {"^(term|cua)$/^([a-z])$", 1, MATCH_MINOR, "1"}; 1397c478bd9Sstevel@tonic-gate static char start_id[] = "a"; 1407c478bd9Sstevel@tonic-gate #endif 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate static int serial_port_create(di_minor_t minor, di_node_t node); 1437c478bd9Sstevel@tonic-gate static int onbrd_port_create(di_minor_t minor, di_node_t node); 1447c478bd9Sstevel@tonic-gate static int dialout_create(di_minor_t minor, di_node_t node); 1457c478bd9Sstevel@tonic-gate static int onbrd_dialout_create(di_minor_t minor, di_node_t node); 1467c478bd9Sstevel@tonic-gate static int rsc_port_create(di_minor_t minor, di_node_t node); 1477c478bd9Sstevel@tonic-gate static int lom_port_create(di_minor_t minor, di_node_t node); 1487c478bd9Sstevel@tonic-gate static void rm_dangling_port(char *devname); 1497c478bd9Sstevel@tonic-gate static void update_sacadm_db(void); 1507c478bd9Sstevel@tonic-gate static int parse_portno(char *dname); 1517c478bd9Sstevel@tonic-gate static int is_dialout(char *dname); 1527c478bd9Sstevel@tonic-gate static int load_ttymondb(void); 1537c478bd9Sstevel@tonic-gate static void remove_pm_entry(char *pmtag, int port); 1547c478bd9Sstevel@tonic-gate static void add_pm_entry(int port); 1557c478bd9Sstevel@tonic-gate static void delete_port_monitor(int port); 1567c478bd9Sstevel@tonic-gate static void add_port_monitor(int port); 1577c478bd9Sstevel@tonic-gate static int execute(const char *s); 1587c478bd9Sstevel@tonic-gate static char *pmtab_parse_portname(char *cmdbuf); 1597c478bd9Sstevel@tonic-gate static void *pma_alloc(void); 1607c478bd9Sstevel@tonic-gate static void pma_free(void); 1617c478bd9Sstevel@tonic-gate extern char *defread(char *varname); 162e9c71215SVikram Hegde extern int defopen(char *fname); 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate /* 1657c478bd9Sstevel@tonic-gate * devfs create callback register 1667c478bd9Sstevel@tonic-gate */ 1677c478bd9Sstevel@tonic-gate static devfsadm_create_t ports_cbt[] = { 1687c478bd9Sstevel@tonic-gate {"pseudo", "ddi_pseudo", "su", 1697c478bd9Sstevel@tonic-gate TYPE_EXACT | DRV_EXACT, ILEVEL_1, rsc_port_create}, 1707c478bd9Sstevel@tonic-gate {"port", "ddi_serial:lomcon", "su", 1717c478bd9Sstevel@tonic-gate TYPE_EXACT | DRV_EXACT, ILEVEL_1, lom_port_create}, 1727c478bd9Sstevel@tonic-gate {"port", "ddi_serial", NULL, 1737c478bd9Sstevel@tonic-gate TYPE_EXACT, ILEVEL_0, serial_port_create}, 1747c478bd9Sstevel@tonic-gate {"port", "ddi_serial:mb", NULL, 1757c478bd9Sstevel@tonic-gate TYPE_EXACT, ILEVEL_0, onbrd_port_create}, 1767c478bd9Sstevel@tonic-gate {"port", "ddi_serial:dialout", NULL, 1777c478bd9Sstevel@tonic-gate TYPE_EXACT, ILEVEL_0, dialout_create}, 1787c478bd9Sstevel@tonic-gate {"port", "ddi_serial:dialout,mb", NULL, 1797c478bd9Sstevel@tonic-gate TYPE_EXACT, ILEVEL_0, onbrd_dialout_create}, 1807c478bd9Sstevel@tonic-gate }; 1817c478bd9Sstevel@tonic-gate DEVFSADM_CREATE_INIT_V0(ports_cbt); 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate /* 1847c478bd9Sstevel@tonic-gate * devfs cleanup register 1857c478bd9Sstevel@tonic-gate * no cleanup rules for PCMCIA port devices 1867c478bd9Sstevel@tonic-gate */ 1877c478bd9Sstevel@tonic-gate static devfsadm_remove_t ports_remove_cbt[] = { 18894ee2d0fSJimmy Vetayases {"port", "^term/[0-9]+$", RM_PRE | RM_ALWAYS | RM_HOT, ILEVEL_0, 18994ee2d0fSJimmy Vetayases rm_dangling_port}, 19094ee2d0fSJimmy Vetayases {"port", "^cua/[0-9]+$", RM_PRE | RM_ALWAYS | RM_HOT, ILEVEL_0, 19194ee2d0fSJimmy Vetayases devfsadm_rm_all}, 1927c478bd9Sstevel@tonic-gate {"port", "^(term|cua)/[a-z]$", 19394ee2d0fSJimmy Vetayases RM_PRE | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all}, 1947c478bd9Sstevel@tonic-gate }; 1957c478bd9Sstevel@tonic-gate DEVFSADM_REMOVE_INIT_V0(ports_remove_cbt); 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate int 1987c478bd9Sstevel@tonic-gate minor_init() 1997c478bd9Sstevel@tonic-gate { 2007c478bd9Sstevel@tonic-gate char *maxport_str; 2017c478bd9Sstevel@tonic-gate 202e9c71215SVikram Hegde if (defopen("/etc/default/devfsadm") == 0) { 2037c478bd9Sstevel@tonic-gate maxport_str = defread("SUNW_port_link.maxports"); 2047c478bd9Sstevel@tonic-gate if ((maxport_str == NULL) || 205e9c71215SVikram Hegde (sscanf(maxport_str, "%d", &maxports) != 1)) { 2067c478bd9Sstevel@tonic-gate maxports = MAXPORTS_DEFAULT; 207e9c71215SVikram Hegde } 208e9c71215SVikram Hegde /* close defaults file */ 209e9c71215SVikram Hegde (void) defopen(NULL); 210e9c71215SVikram Hegde } else { 211e9c71215SVikram Hegde maxports = MAXPORTS_DEFAULT; 212e9c71215SVikram Hegde } 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate devfsadm_print(CHATTY_MID, "%s: maximum number of port devices (%d)\n", 2157c478bd9Sstevel@tonic-gate modname, maxports); 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate if (pma_alloc() == NULL) 2187c478bd9Sstevel@tonic-gate return (DEVFSADM_FAILURE); 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate return (DEVFSADM_SUCCESS); 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate int 2247c478bd9Sstevel@tonic-gate minor_fini() 2257c478bd9Sstevel@tonic-gate { 2267c478bd9Sstevel@tonic-gate /* 2277c478bd9Sstevel@tonic-gate * update the sacadm database only if we are updating 2287c478bd9Sstevel@tonic-gate * this platform (no -r option) 2297c478bd9Sstevel@tonic-gate */ 2307c478bd9Sstevel@tonic-gate if (strcmp(devfsadm_root_path(), "/") == 0) 2317c478bd9Sstevel@tonic-gate update_sacadm_db(); 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate pma_free(); 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate return (DEVFSADM_SUCCESS); 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate /* 2397c478bd9Sstevel@tonic-gate * Called for all serial devices that are NOT onboard 2407c478bd9Sstevel@tonic-gate * Creates links of the form "/dev/term/[0..n]" 2417c478bd9Sstevel@tonic-gate * Schedules an update the sacadm (portmon). 2427c478bd9Sstevel@tonic-gate */ 2437c478bd9Sstevel@tonic-gate static int 2447c478bd9Sstevel@tonic-gate serial_port_create(di_minor_t minor, di_node_t node) 2457c478bd9Sstevel@tonic-gate { 2467c478bd9Sstevel@tonic-gate char l_path[MAXPATHLEN], p_path[MAXPATHLEN]; 2477c478bd9Sstevel@tonic-gate char *devfspath, *buf, *minor_name; 2487c478bd9Sstevel@tonic-gate int port_num; 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate devfspath = di_devfs_path(node); 2517c478bd9Sstevel@tonic-gate if (devfspath == NULL) { 2527c478bd9Sstevel@tonic-gate devfsadm_errprint("%s: di_devfs_path() failed\n", modname); 2537c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 2547c478bd9Sstevel@tonic-gate } 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate if ((minor_name = di_minor_name(minor)) == NULL) { 2577c478bd9Sstevel@tonic-gate devfsadm_errprint("%s: NULL minor name\n\t%s\n", modname, 2587c478bd9Sstevel@tonic-gate devfspath); 2597c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 2607c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate /* 2647c478bd9Sstevel@tonic-gate * verify dialout ports do not come in on this nodetype 2657c478bd9Sstevel@tonic-gate */ 2667c478bd9Sstevel@tonic-gate if (is_dialout(minor_name)) { 2677c478bd9Sstevel@tonic-gate devfsadm_errprint("%s: dialout device\n\t%s:%s\n", 2687c478bd9Sstevel@tonic-gate modname, devfspath, minor_name); 2697c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 2707c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate /* 2747c478bd9Sstevel@tonic-gate * add the minor name to the physical path so we can 275de81e71eSTim Marsland * enum the port# and create the link. 2767c478bd9Sstevel@tonic-gate */ 2777c478bd9Sstevel@tonic-gate (void) strcpy(p_path, devfspath); 2787c478bd9Sstevel@tonic-gate (void) strcat(p_path, ":"); 2797c478bd9Sstevel@tonic-gate (void) strcat(p_path, minor_name); 2807c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate if (devfsadm_enumerate_int(p_path, 0, &buf, port_rules, 1)) { 2837c478bd9Sstevel@tonic-gate devfsadm_errprint("%s:serial_port_create:" 2847c478bd9Sstevel@tonic-gate " enumerate_int() failed\n\t%s\n", 2857c478bd9Sstevel@tonic-gate modname, p_path); 2867c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 2877c478bd9Sstevel@tonic-gate } 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate (void) strcpy(l_path, "term/"); 2907c478bd9Sstevel@tonic-gate (void) strcat(l_path, buf); 2917c478bd9Sstevel@tonic-gate (void) devfsadm_mklink(l_path, node, minor, 0); 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate /* 294de81e71eSTim Marsland * This is probably a USB serial port coming into the system 295de81e71eSTim Marsland * because someone just plugged one in. Log an indication of 296de81e71eSTim Marsland * this to syslog just in case someone wants to know what the 297de81e71eSTim Marsland * name of the new serial device is .. 298de81e71eSTim Marsland */ 299de81e71eSTim Marsland (void) syslog(LOG_INFO, "serial device /dev/%s present", l_path); 300de81e71eSTim Marsland 301de81e71eSTim Marsland /* 3027c478bd9Sstevel@tonic-gate * update the portmon database if this port falls within 3037c478bd9Sstevel@tonic-gate * the valid range of ports. 3047c478bd9Sstevel@tonic-gate */ 3057c478bd9Sstevel@tonic-gate if ((port_num = parse_portno(buf)) != -1) { 3067c478bd9Sstevel@tonic-gate pma[port_num].flags |= HAS_PORT_DEVICE; 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate free(buf); 3107c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 3117c478bd9Sstevel@tonic-gate } 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate /* 3147c478bd9Sstevel@tonic-gate * Called for all dialout devices that are NOT onboard 3157c478bd9Sstevel@tonic-gate * Creates links of the form "/dev/cua/[0..n]" 3167c478bd9Sstevel@tonic-gate */ 3177c478bd9Sstevel@tonic-gate static int 3187c478bd9Sstevel@tonic-gate dialout_create(di_minor_t minor, di_node_t node) 3197c478bd9Sstevel@tonic-gate { 3207c478bd9Sstevel@tonic-gate char l_path[MAXPATHLEN], p_path[MAXPATHLEN]; 3217c478bd9Sstevel@tonic-gate char *devfspath, *buf, *mn; 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate devfspath = di_devfs_path(node); 3247c478bd9Sstevel@tonic-gate if (devfspath == NULL) { 3257c478bd9Sstevel@tonic-gate devfsadm_errprint("%s: di_devfs_path() failed\n", modname); 3267c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate if ((mn = di_minor_name(minor)) == NULL) { 3307c478bd9Sstevel@tonic-gate devfsadm_errprint("%s: NULL minorname\n\t%s\n", 3317c478bd9Sstevel@tonic-gate modname, devfspath); 3327c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 3337c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate if (!is_dialout(mn)) { 3377c478bd9Sstevel@tonic-gate devfsadm_errprint("%s: invalid minor name\n\t%s:%s\n", 3387c478bd9Sstevel@tonic-gate modname, devfspath, mn); 3397c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 3407c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate (void) strcpy(p_path, devfspath); 3447c478bd9Sstevel@tonic-gate (void) strcat(p_path, ":"); 3457c478bd9Sstevel@tonic-gate (void) strcat(p_path, mn); 3467c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate if (devfsadm_enumerate_int(p_path, 0, &buf, port_rules, 1)) { 3497c478bd9Sstevel@tonic-gate devfsadm_errprint("%s:dialout_create:" 3507c478bd9Sstevel@tonic-gate " enumerate_int() failed\n\t%s\n", 3517c478bd9Sstevel@tonic-gate modname, p_path); 3527c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 3537c478bd9Sstevel@tonic-gate } 3547c478bd9Sstevel@tonic-gate (void) strcpy(l_path, "cua/"); 3557c478bd9Sstevel@tonic-gate (void) strcat(l_path, buf); 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate /* 3587c478bd9Sstevel@tonic-gate * add the minor name to the physical path so we can create 3597c478bd9Sstevel@tonic-gate * the link. 3607c478bd9Sstevel@tonic-gate */ 3617c478bd9Sstevel@tonic-gate (void) devfsadm_mklink(l_path, node, minor, 0); 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate free(buf); 3647c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate #ifdef __i386 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate static int 3707c478bd9Sstevel@tonic-gate portcmp(char *devfs_path, char *phys_path) 3717c478bd9Sstevel@tonic-gate { 3727c478bd9Sstevel@tonic-gate char *p1, *p2; 3737c478bd9Sstevel@tonic-gate int rv; 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate p2 = NULL; 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate p1 = strrchr(devfs_path, ':'); 3787c478bd9Sstevel@tonic-gate if (p1 == NULL) 3797c478bd9Sstevel@tonic-gate return (1); 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate p1 = strchr(p1, ','); 3827c478bd9Sstevel@tonic-gate if (p1) 3837c478bd9Sstevel@tonic-gate *p1 = '\0'; 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate p2 = strrchr(phys_path, ':'); 3867c478bd9Sstevel@tonic-gate if (p2 == NULL) { 3877c478bd9Sstevel@tonic-gate rv = -1; 3887c478bd9Sstevel@tonic-gate goto out; 3897c478bd9Sstevel@tonic-gate } 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate p2 = strchr(p2, ','); 3927c478bd9Sstevel@tonic-gate if (p2) 3937c478bd9Sstevel@tonic-gate *p2 = '\0'; 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate rv = strcmp(devfs_path, phys_path); 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate out: 3987c478bd9Sstevel@tonic-gate if (p1) 3997c478bd9Sstevel@tonic-gate *p1 = ','; 4007c478bd9Sstevel@tonic-gate if (p2) 4017c478bd9Sstevel@tonic-gate *p2 = ','; 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate return (rv); 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate /* 4077c478bd9Sstevel@tonic-gate * If the minor name begins with [a-d] and the 4087c478bd9Sstevel@tonic-gate * links in /dev/term/<char> and /dev/cua/<char> 4097c478bd9Sstevel@tonic-gate * don't point at a different minor, then we can 4107c478bd9Sstevel@tonic-gate * create compatibility links for this minor. 4117c478bd9Sstevel@tonic-gate * Returns: 4127c478bd9Sstevel@tonic-gate * port id if a compatibility link can be created. 4137c478bd9Sstevel@tonic-gate * NULL otherwise 4147c478bd9Sstevel@tonic-gate */ 4157c478bd9Sstevel@tonic-gate static char * 41694c894bbSVikram Hegde check_compat_ports(di_node_t node, char *phys_path, char *minor) 4177c478bd9Sstevel@tonic-gate { 4187c478bd9Sstevel@tonic-gate char portid = *minor; 4197c478bd9Sstevel@tonic-gate char port[PATH_MAX]; 4207c478bd9Sstevel@tonic-gate char *devfs_path; 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate if (portid < 'a' || portid > 'd') 4237c478bd9Sstevel@tonic-gate return (NULL); 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate (void) snprintf(port, sizeof (port), "term/%c", portid); 42694c894bbSVikram Hegde if (devfsadm_read_link(node, port, &devfs_path) == DEVFSADM_SUCCESS && 4277c478bd9Sstevel@tonic-gate portcmp(devfs_path, phys_path) != 0) { 4287c478bd9Sstevel@tonic-gate free(devfs_path); 4297c478bd9Sstevel@tonic-gate return (NULL); 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate free(devfs_path); 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate (void) snprintf(port, sizeof (port), "cua/%c", portid); 43594c894bbSVikram Hegde if (devfsadm_read_link(node, port, &devfs_path) == DEVFSADM_SUCCESS && 4367c478bd9Sstevel@tonic-gate portcmp(devfs_path, phys_path) != 0) { 4377c478bd9Sstevel@tonic-gate free(devfs_path); 4387c478bd9Sstevel@tonic-gate return (NULL); 4397c478bd9Sstevel@tonic-gate } 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate free(devfs_path); 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate /* 4447c478bd9Sstevel@tonic-gate * Neither link exists or both links point at "phys_path" 4457c478bd9Sstevel@tonic-gate * We can safely create compatibility links. 4467c478bd9Sstevel@tonic-gate */ 4477c478bd9Sstevel@tonic-gate port[0] = portid; 4487c478bd9Sstevel@tonic-gate port[1] = '\0'; 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate return (s_strdup(port)); 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate #endif 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate /* 4567c478bd9Sstevel@tonic-gate * Called for all Onboard serial devices 4577c478bd9Sstevel@tonic-gate * Creates links of the form "/dev/term/[a..z]" 4587c478bd9Sstevel@tonic-gate */ 4597c478bd9Sstevel@tonic-gate static int 4607c478bd9Sstevel@tonic-gate onbrd_port_create(di_minor_t minor, di_node_t node) 4617c478bd9Sstevel@tonic-gate { 4627c478bd9Sstevel@tonic-gate char l_path[MAXPATHLEN], p_path[MAXPATHLEN]; 4637c478bd9Sstevel@tonic-gate char *devfspath, *buf, *minor_name; 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate devfspath = di_devfs_path(node); 4667c478bd9Sstevel@tonic-gate if (devfspath == NULL) { 4677c478bd9Sstevel@tonic-gate devfsadm_errprint("%s: di_devfs_path() failed\n", modname); 4687c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 4697c478bd9Sstevel@tonic-gate } 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate if ((minor_name = di_minor_name(minor)) == NULL) { 4727c478bd9Sstevel@tonic-gate devfsadm_errprint("%s: NULL minor name\n\t%s\n", 4737c478bd9Sstevel@tonic-gate modname, devfspath); 4747c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 4757c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate /* 4797c478bd9Sstevel@tonic-gate * verify dialout ports do not come in on this nodetype 4807c478bd9Sstevel@tonic-gate */ 4817c478bd9Sstevel@tonic-gate if (is_dialout(minor_name)) { 4827c478bd9Sstevel@tonic-gate devfsadm_errprint("%s: dialout device\n\t%s:%s\n", modname, 4837c478bd9Sstevel@tonic-gate devfspath, minor_name); 4847c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 4857c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate (void) strcpy(p_path, devfspath); 4897c478bd9Sstevel@tonic-gate (void) strcat(p_path, ":"); 4907c478bd9Sstevel@tonic-gate (void) strcat(p_path, minor_name); 4917c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate buf = NULL; 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate #ifdef __i386 49794c894bbSVikram Hegde buf = check_compat_ports(node, p_path, minor_name); 4987c478bd9Sstevel@tonic-gate #endif 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate /* 5017c478bd9Sstevel@tonic-gate * devfsadm_enumerate_char_start() is a private interface for use by the 5027c478bd9Sstevel@tonic-gate * ports module only 5037c478bd9Sstevel@tonic-gate */ 5047c478bd9Sstevel@tonic-gate if (!buf && devfsadm_enumerate_char_start(p_path, 0, &buf, obport_rules, 5057c478bd9Sstevel@tonic-gate 1, start_id)) { 5067c478bd9Sstevel@tonic-gate devfsadm_errprint("%s: devfsadm_enumerate_char_start() failed" 5077c478bd9Sstevel@tonic-gate "\n\t%s\n", modname, p_path); 5087c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 5097c478bd9Sstevel@tonic-gate } 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate (void) strcpy(l_path, "term/"); 5127c478bd9Sstevel@tonic-gate (void) strcat(l_path, buf); 5137c478bd9Sstevel@tonic-gate (void) devfsadm_mklink(l_path, node, minor, 0); 5147c478bd9Sstevel@tonic-gate free(buf); 5157c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 5167c478bd9Sstevel@tonic-gate } 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate /* 5197c478bd9Sstevel@tonic-gate * Onboard dialout devices 5207c478bd9Sstevel@tonic-gate * Creates links of the form "/dev/cua/[a..z]" 5217c478bd9Sstevel@tonic-gate */ 5227c478bd9Sstevel@tonic-gate static int 5237c478bd9Sstevel@tonic-gate onbrd_dialout_create(di_minor_t minor, di_node_t node) 5247c478bd9Sstevel@tonic-gate { 5257c478bd9Sstevel@tonic-gate char l_path[MAXPATHLEN], p_path[MAXPATHLEN]; 5267c478bd9Sstevel@tonic-gate char *devfspath, *buf, *mn; 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate devfspath = di_devfs_path(node); 5297c478bd9Sstevel@tonic-gate if (devfspath == NULL) { 5307c478bd9Sstevel@tonic-gate devfsadm_errprint("%s: di_devfs_path() failed\n", modname); 5317c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 5327c478bd9Sstevel@tonic-gate } 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate if ((mn = di_minor_name(minor)) == NULL) { 5357c478bd9Sstevel@tonic-gate devfsadm_errprint("%s: NULL minor name\n\t%s\n", 5367c478bd9Sstevel@tonic-gate modname, devfspath); 5377c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 5387c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate /* 5427c478bd9Sstevel@tonic-gate * verify this is a dialout port 5437c478bd9Sstevel@tonic-gate */ 5447c478bd9Sstevel@tonic-gate if (!is_dialout(mn)) { 5457c478bd9Sstevel@tonic-gate devfsadm_errprint("%s: not a dialout device\n\t%s:%s\n", 5467c478bd9Sstevel@tonic-gate modname, devfspath, mn); 5477c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 5487c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 5497c478bd9Sstevel@tonic-gate } 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate (void) strcpy(p_path, devfspath); 5527c478bd9Sstevel@tonic-gate (void) strcat(p_path, ":"); 5537c478bd9Sstevel@tonic-gate (void) strcat(p_path, mn); 5547c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate buf = NULL; 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate #ifdef __i386 55994c894bbSVikram Hegde buf = check_compat_ports(node, p_path, mn); 5607c478bd9Sstevel@tonic-gate #endif 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate /* 5637c478bd9Sstevel@tonic-gate * devfsadm_enumerate_char_start() is a private interface 5647c478bd9Sstevel@tonic-gate * for use by the ports module only. 5657c478bd9Sstevel@tonic-gate */ 5667c478bd9Sstevel@tonic-gate if (!buf && devfsadm_enumerate_char_start(p_path, 0, &buf, obport_rules, 5677c478bd9Sstevel@tonic-gate 1, start_id)) { 5687c478bd9Sstevel@tonic-gate devfsadm_errprint("%s: devfsadm_enumerate_char_start() failed" 5697c478bd9Sstevel@tonic-gate "\n\t%s\n", modname, p_path); 5707c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 5717c478bd9Sstevel@tonic-gate } 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate /* 5747c478bd9Sstevel@tonic-gate * create the logical link 5757c478bd9Sstevel@tonic-gate */ 5767c478bd9Sstevel@tonic-gate (void) strcpy(l_path, "cua/"); 5777c478bd9Sstevel@tonic-gate (void) strcat(l_path, buf); 5787c478bd9Sstevel@tonic-gate (void) devfsadm_mklink(l_path, node, minor, 0); 5797c478bd9Sstevel@tonic-gate free(buf); 5807c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 5817c478bd9Sstevel@tonic-gate } 5827c478bd9Sstevel@tonic-gate 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate /* 5857c478bd9Sstevel@tonic-gate * Remote System Controller (RSC) serial ports 5867c478bd9Sstevel@tonic-gate * Creates links of the form "/dev/rsc-control" | "/dev/term/rsc-console". 5877c478bd9Sstevel@tonic-gate */ 5887c478bd9Sstevel@tonic-gate static int 5897c478bd9Sstevel@tonic-gate rsc_port_create(di_minor_t minor, di_node_t node) 5907c478bd9Sstevel@tonic-gate { 5917c478bd9Sstevel@tonic-gate char *devfspath; 5927c478bd9Sstevel@tonic-gate char *minor_name; 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate devfspath = di_devfs_path(node); 5967c478bd9Sstevel@tonic-gate if (devfspath == NULL) { 5977c478bd9Sstevel@tonic-gate devfsadm_errprint("%s: di_devfs_path() failed\n", modname); 5987c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 5997c478bd9Sstevel@tonic-gate } 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate if ((minor_name = di_minor_name(minor)) == NULL) { 6027c478bd9Sstevel@tonic-gate devfsadm_errprint("%s: NULL minor name\n\t%s\n", 6037c478bd9Sstevel@tonic-gate modname, devfspath); 6047c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 6057c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 6067c478bd9Sstevel@tonic-gate } 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate /* 6097c478bd9Sstevel@tonic-gate * if this is the RSC console serial port (i.e. the minor name == ssp), 6107c478bd9Sstevel@tonic-gate * create /dev/term/rsc-console link and then we are done with this 6117c478bd9Sstevel@tonic-gate * node. 6127c478bd9Sstevel@tonic-gate */ 6137c478bd9Sstevel@tonic-gate if (strcmp(minor_name, "ssp") == 0) { 6147c478bd9Sstevel@tonic-gate (void) devfsadm_mklink("term/rsc-console", node, minor, 0); 6157c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 6167c478bd9Sstevel@tonic-gate return (DEVFSADM_TERMINATE); 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate /* 6197c478bd9Sstevel@tonic-gate * else if this is the RSC control serial port (i.e. the minor name == 6207c478bd9Sstevel@tonic-gate * sspctl), create /dev/rsc-control link and then we are done with this 6217c478bd9Sstevel@tonic-gate * node. 6227c478bd9Sstevel@tonic-gate */ 6237c478bd9Sstevel@tonic-gate } else if (strcmp(minor_name, "sspctl") == 0) { 6247c478bd9Sstevel@tonic-gate (void) devfsadm_mklink("rsc-control", node, minor, 0); 6257c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 6267c478bd9Sstevel@tonic-gate return (DEVFSADM_TERMINATE); 6277c478bd9Sstevel@tonic-gate } 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate /* This is not an RSC node, continue... */ 6307c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 6317c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 6327c478bd9Sstevel@tonic-gate } 6337c478bd9Sstevel@tonic-gate 6347c478bd9Sstevel@tonic-gate /* 6357c478bd9Sstevel@tonic-gate * Lights Out Management (LOM) serial ports 6367c478bd9Sstevel@tonic-gate * Creates links of the form "/dev/term/lom-console". 6377c478bd9Sstevel@tonic-gate */ 6387c478bd9Sstevel@tonic-gate static int 6397c478bd9Sstevel@tonic-gate lom_port_create(di_minor_t minor, di_node_t node) 6407c478bd9Sstevel@tonic-gate { 6417c478bd9Sstevel@tonic-gate char *devfspath; 6427c478bd9Sstevel@tonic-gate char *minor_name; 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate devfspath = di_devfs_path(node); 6457c478bd9Sstevel@tonic-gate if (devfspath == NULL) { 6467c478bd9Sstevel@tonic-gate devfsadm_errprint("%s: di_devfs_path() failed\n", modname); 6477c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate if ((minor_name = di_minor_name(minor)) == NULL) { 6517c478bd9Sstevel@tonic-gate devfsadm_errprint("%s: NULL minor name\n\t%s\n", 6527c478bd9Sstevel@tonic-gate modname, devfspath); 6537c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 6547c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 6557c478bd9Sstevel@tonic-gate } 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate /* 6587c478bd9Sstevel@tonic-gate * if this is the LOM console serial port (i.e. the minor 6597c478bd9Sstevel@tonic-gate * name == lom-console ), create /dev/term/lom-console link and 6607c478bd9Sstevel@tonic-gate * then we are done with this node. 6617c478bd9Sstevel@tonic-gate */ 6627c478bd9Sstevel@tonic-gate if (strcmp(minor_name, "lom-console") == 0) { 6637c478bd9Sstevel@tonic-gate (void) devfsadm_mklink("term/lom-console", node, minor, 0); 6647c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 6657c478bd9Sstevel@tonic-gate return (DEVFSADM_TERMINATE); 6667c478bd9Sstevel@tonic-gate } 6677c478bd9Sstevel@tonic-gate 6687c478bd9Sstevel@tonic-gate /* This is not a LOM node, continue... */ 6697c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 6707c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 6717c478bd9Sstevel@tonic-gate } 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate 6747c478bd9Sstevel@tonic-gate /* 6757c478bd9Sstevel@tonic-gate * Removes port entries that no longer have devices 6767c478bd9Sstevel@tonic-gate * backing them 6777c478bd9Sstevel@tonic-gate * Schedules an update the sacadm (portmon) database 6787c478bd9Sstevel@tonic-gate */ 6797c478bd9Sstevel@tonic-gate static void 6807c478bd9Sstevel@tonic-gate rm_dangling_port(char *devname) 6817c478bd9Sstevel@tonic-gate { 6827c478bd9Sstevel@tonic-gate char *portstr; 6837c478bd9Sstevel@tonic-gate int portnum; 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate devfsadm_print(PORT_MID, "%s:rm_stale_port: %s\n", 6867c478bd9Sstevel@tonic-gate modname, devname); 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate if ((portstr = strrchr(devname, (int)'/')) == NULL) { 6897c478bd9Sstevel@tonic-gate devfsadm_errprint("%s: invalid name: %s\n", 6907c478bd9Sstevel@tonic-gate modname, devname); 6917c478bd9Sstevel@tonic-gate return; 6927c478bd9Sstevel@tonic-gate } 6937c478bd9Sstevel@tonic-gate portstr++; 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate /* 6967c478bd9Sstevel@tonic-gate * mark for removal from sacadm database 6977c478bd9Sstevel@tonic-gate */ 6987c478bd9Sstevel@tonic-gate if ((portnum = parse_portno(portstr)) != -1) 6997c478bd9Sstevel@tonic-gate pma[portnum].flags |= PORT_REMOVED; 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate devfsadm_rm_all(devname); 7027c478bd9Sstevel@tonic-gate } 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate /* 7057c478bd9Sstevel@tonic-gate * Algorithm is to step through ports; checking for unneeded PM entries 7067c478bd9Sstevel@tonic-gate * entries that should be there but are not. Every PM_GRPSZ entries 7077c478bd9Sstevel@tonic-gate * check to see if there are any entries for the port monitor group; 7087c478bd9Sstevel@tonic-gate * if not, delete the group. 7097c478bd9Sstevel@tonic-gate */ 7107c478bd9Sstevel@tonic-gate static void 7117c478bd9Sstevel@tonic-gate update_sacadm_db(void) 7127c478bd9Sstevel@tonic-gate { 7137c478bd9Sstevel@tonic-gate int i; 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate if (load_ttymondb() != DEVFSADM_SUCCESS) 7167c478bd9Sstevel@tonic-gate return; 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate for (i = 0; i < maxports; i++) { 7197c478bd9Sstevel@tonic-gate /* 7207c478bd9Sstevel@tonic-gate * if this port was removed and has a port 7217c478bd9Sstevel@tonic-gate * monitor entry, remove the entry from the sacadm db 7227c478bd9Sstevel@tonic-gate */ 7237c478bd9Sstevel@tonic-gate if ((pma[i].flags & PORT_REMOVED) != 0) { 7247c478bd9Sstevel@tonic-gate if ((pma[i].flags & PM_HAS_ENTRY) != 0) 7257c478bd9Sstevel@tonic-gate remove_pm_entry(pma[i].pm_tag, i); 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate /* 7297c478bd9Sstevel@tonic-gate * if this port is present and lacks a port monitor 7307c478bd9Sstevel@tonic-gate * add an entry to the sacadm db 7317c478bd9Sstevel@tonic-gate */ 7327c478bd9Sstevel@tonic-gate if (pma[i].flags & HAS_PORT_DEVICE) { 7337c478bd9Sstevel@tonic-gate if (!(pma[i].flags & PM_HAS_ENTRY)) 7347c478bd9Sstevel@tonic-gate add_pm_entry(i); 7357c478bd9Sstevel@tonic-gate } 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate /* 7387c478bd9Sstevel@tonic-gate * if this port has a pm entry, mark as needing 7397c478bd9Sstevel@tonic-gate * a port monitor within this range of ports 7407c478bd9Sstevel@tonic-gate */ 7417c478bd9Sstevel@tonic-gate if ((pma[i].flags & PM_HAS_ENTRY)) 7427c478bd9Sstevel@tonic-gate pma[PM_SLOT(i)].flags |= PM_NEEDED; 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate /* 7457c478bd9Sstevel@tonic-gate * continue for the range of ports per-portmon 7467c478bd9Sstevel@tonic-gate */ 7477c478bd9Sstevel@tonic-gate if (((i + 1) % PM_GRPSZ) != 0) 7487c478bd9Sstevel@tonic-gate continue; 7497c478bd9Sstevel@tonic-gate 7507c478bd9Sstevel@tonic-gate /* 7517c478bd9Sstevel@tonic-gate * if there are no ports active on the range we have 7527c478bd9Sstevel@tonic-gate * just completed, remove the port monitor entry if 7537c478bd9Sstevel@tonic-gate * it exists 7547c478bd9Sstevel@tonic-gate */ 7557c478bd9Sstevel@tonic-gate if ((pma[PM_SLOT(i)].flags & (PM_NEEDED | HAS_PORT_MON)) == 7567c478bd9Sstevel@tonic-gate HAS_PORT_MON) { 7577c478bd9Sstevel@tonic-gate delete_port_monitor(i); 7587c478bd9Sstevel@tonic-gate } 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate } 7617c478bd9Sstevel@tonic-gate 7627c478bd9Sstevel@tonic-gate /* 7637c478bd9Sstevel@tonic-gate * cleanup remaining port monitor, if active 7647c478bd9Sstevel@tonic-gate */ 7657c478bd9Sstevel@tonic-gate if ((i % PM_GRPSZ != 0) && 7667c478bd9Sstevel@tonic-gate ((pma[PM_SLOT(i)].flags & (PM_NEEDED | HAS_PORT_MON)) == 7677c478bd9Sstevel@tonic-gate HAS_PORT_MON)) { 7687c478bd9Sstevel@tonic-gate delete_port_monitor(i); 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate } 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate /* 7737c478bd9Sstevel@tonic-gate * Determine which port monitor entries already exist by invoking pmadm(1m) 7747c478bd9Sstevel@tonic-gate * to list all configured 'ttymon' port monitor entries. 7757c478bd9Sstevel@tonic-gate * Do not explicitly report errors from executing pmadm(1m) or sacadm(1m) 7767c478bd9Sstevel@tonic-gate * commands to remain compatible with the ports(1m) implementation. 7777c478bd9Sstevel@tonic-gate */ 7787c478bd9Sstevel@tonic-gate static int 7797c478bd9Sstevel@tonic-gate load_ttymondb(void) 7807c478bd9Sstevel@tonic-gate { 7817c478bd9Sstevel@tonic-gate char cmdline[CMDLEN]; 7827c478bd9Sstevel@tonic-gate char cmdbuf[PMTAB_MAXLINE+1]; 7837c478bd9Sstevel@tonic-gate int sac_exitval; 7847c478bd9Sstevel@tonic-gate FILE *fs_popen; 7857c478bd9Sstevel@tonic-gate char *portname; /* pointer to a tty name */ 7867c478bd9Sstevel@tonic-gate int portnum; 7877c478bd9Sstevel@tonic-gate char *ptr; 7887c478bd9Sstevel@tonic-gate char *error_msg = "%s: failed to load port monitor database\n"; 7897c478bd9Sstevel@tonic-gate 7907c478bd9Sstevel@tonic-gate (void) strcpy(cmdline, "/usr/sbin/pmadm -L -t ttymon"); 7917c478bd9Sstevel@tonic-gate fs_popen = popen(cmdline, "r"); 7927c478bd9Sstevel@tonic-gate if (fs_popen == NULL) { 7937c478bd9Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, error_msg, modname); 7947c478bd9Sstevel@tonic-gate return (DEVFSADM_FAILURE); 7957c478bd9Sstevel@tonic-gate } 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate while (fgets(cmdbuf, PMTAB_MAXLINE, fs_popen) != NULL) { 7987c478bd9Sstevel@tonic-gate if ((portname = pmtab_parse_portname(cmdbuf)) == NULL) { 7997c478bd9Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, 8007c478bd9Sstevel@tonic-gate "load_ttymondb: failed to parse portname\n"); 8017c478bd9Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, 8027c478bd9Sstevel@tonic-gate "load_ttymondb: buffer \"%s\"\n", cmdbuf); 8037c478bd9Sstevel@tonic-gate goto load_failed; 8047c478bd9Sstevel@tonic-gate } 8057c478bd9Sstevel@tonic-gate 8067c478bd9Sstevel@tonic-gate devfsadm_print(PORT_MID, "%s:load_ttymondb: port %s ", 8077c478bd9Sstevel@tonic-gate modname, portname); 8087c478bd9Sstevel@tonic-gate 8097c478bd9Sstevel@tonic-gate /* 8107c478bd9Sstevel@tonic-gate * skip onboard ports 8117c478bd9Sstevel@tonic-gate * There is no reliable way to determine if we 8127c478bd9Sstevel@tonic-gate * should start a port monitor on these lines. 8137c478bd9Sstevel@tonic-gate */ 8147c478bd9Sstevel@tonic-gate if ((portnum = parse_portno(portname)) == -1) { 8157c478bd9Sstevel@tonic-gate devfsadm_print(PORT_MID, "ignored\n"); 8167c478bd9Sstevel@tonic-gate continue; 8177c478bd9Sstevel@tonic-gate } 8187c478bd9Sstevel@tonic-gate 8197c478bd9Sstevel@tonic-gate /* 8207c478bd9Sstevel@tonic-gate * the first field of the pmadm output is 8217c478bd9Sstevel@tonic-gate * the port monitor name for this entry 8227c478bd9Sstevel@tonic-gate */ 8237c478bd9Sstevel@tonic-gate if ((ptr = strchr(cmdbuf, PMTAB_SEPR)) == NULL) { 8247c478bd9Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, 8257c478bd9Sstevel@tonic-gate "load_ttymondb: no portmon tag\n"); 8267c478bd9Sstevel@tonic-gate goto load_failed; 8277c478bd9Sstevel@tonic-gate } 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate *ptr = MN_NULLCHAR; 8307c478bd9Sstevel@tonic-gate if ((pma[portnum].pm_tag = strdup(cmdbuf)) == NULL) { 8317c478bd9Sstevel@tonic-gate devfsadm_errprint("load_ttymondb: failed strdup\n"); 8327c478bd9Sstevel@tonic-gate goto load_failed; 8337c478bd9Sstevel@tonic-gate } 8347c478bd9Sstevel@tonic-gate pma[portnum].flags |= PM_HAS_ENTRY; 8357c478bd9Sstevel@tonic-gate pma[PM_SLOT(portnum)].flags |= HAS_PORT_MON; 8367c478bd9Sstevel@tonic-gate devfsadm_print(PORT_MID, "present\n"); 8377c478bd9Sstevel@tonic-gate } 8387c478bd9Sstevel@tonic-gate (void) pclose(fs_popen); 8397c478bd9Sstevel@tonic-gate return (DEVFSADM_SUCCESS); 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate load_failed: 8427c478bd9Sstevel@tonic-gate 8437c478bd9Sstevel@tonic-gate /* 8447c478bd9Sstevel@tonic-gate * failed to load the port monitor database 8457c478bd9Sstevel@tonic-gate */ 8467c478bd9Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, error_msg, modname); 8477c478bd9Sstevel@tonic-gate sac_exitval = SAC_EXITVAL(pclose(fs_popen)); 8487c478bd9Sstevel@tonic-gate if (sac_exitval != 0) { 8497c478bd9Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, 8507c478bd9Sstevel@tonic-gate "pmadm: (%s) %s\n", SAC_EID(sac_exitval), 8517c478bd9Sstevel@tonic-gate SAC_EMSG(sac_exitval)); 8527c478bd9Sstevel@tonic-gate } 8537c478bd9Sstevel@tonic-gate return (DEVFSADM_FAILURE); 8547c478bd9Sstevel@tonic-gate } 8557c478bd9Sstevel@tonic-gate 8567c478bd9Sstevel@tonic-gate /* 8577c478bd9Sstevel@tonic-gate * add a port monitor entry for device /dev/term/"port" 8587c478bd9Sstevel@tonic-gate */ 8597c478bd9Sstevel@tonic-gate static void 8607c478bd9Sstevel@tonic-gate add_pm_entry(int port) 8617c478bd9Sstevel@tonic-gate { 8627c478bd9Sstevel@tonic-gate char cmdline[CMDLEN]; 8637c478bd9Sstevel@tonic-gate int sac_exitval; 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate add_port_monitor(port); 8667c478bd9Sstevel@tonic-gate (void) sprintf(cmdline, 8677c478bd9Sstevel@tonic-gate "/usr/sbin/pmadm -a -p ttymon%d -s %d -i root" 8687c478bd9Sstevel@tonic-gate " -v `/usr/sbin/ttyadm -V` -fux -y\"/dev/term/%d\"" 8697c478bd9Sstevel@tonic-gate " -m \"`/usr/sbin/ttyadm -d /dev/term/%d -s /usr/bin/login" 8707c478bd9Sstevel@tonic-gate " -l 9600 -p \\\"login: \\\"`\"", PM_NUM(port), port, port, port); 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate if (devfsadm_noupdate() == DEVFSADM_FALSE) { 8737c478bd9Sstevel@tonic-gate sac_exitval = execute(cmdline); 8747c478bd9Sstevel@tonic-gate if ((sac_exitval != 0) && (sac_exitval != E_SACNOTRUN)) { 8757c478bd9Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, 8767c478bd9Sstevel@tonic-gate "failed to add port monitor entry" 8777c478bd9Sstevel@tonic-gate " for /dev/term/%d\n", port); 8787c478bd9Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, "pmadm: (%s) %s\n", 8797c478bd9Sstevel@tonic-gate SAC_EID(sac_exitval), SAC_EMSG(sac_exitval)); 8807c478bd9Sstevel@tonic-gate } 8817c478bd9Sstevel@tonic-gate } 8827c478bd9Sstevel@tonic-gate pma[port].flags |= PM_HAS_ENTRY; 8837c478bd9Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, "%s: /dev/term/%d added to sacadm\n", 8847c478bd9Sstevel@tonic-gate modname, port); 8857c478bd9Sstevel@tonic-gate } 8867c478bd9Sstevel@tonic-gate 8877c478bd9Sstevel@tonic-gate static void 8887c478bd9Sstevel@tonic-gate remove_pm_entry(char *pmtag, int port) 8897c478bd9Sstevel@tonic-gate { 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate char cmdline[CMDLEN]; 8927c478bd9Sstevel@tonic-gate int sac_exitval; 8937c478bd9Sstevel@tonic-gate 8947c478bd9Sstevel@tonic-gate if (devfsadm_noupdate() == DEVFSADM_FALSE) { 8957c478bd9Sstevel@tonic-gate (void) snprintf(cmdline, sizeof (cmdline), 8967c478bd9Sstevel@tonic-gate "/usr/sbin/pmadm -r -p %s -s %d", pmtag, port); 8977c478bd9Sstevel@tonic-gate sac_exitval = execute(cmdline); 8987c478bd9Sstevel@tonic-gate if ((sac_exitval != 0) && (sac_exitval != E_SACNOTRUN)) { 8997c478bd9Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, 9007c478bd9Sstevel@tonic-gate "failed to remove port monitor entry" 9017c478bd9Sstevel@tonic-gate " for /dev/term/%d\n", port); 9027c478bd9Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, "pmadm: (%s) %s\n", 9037c478bd9Sstevel@tonic-gate SAC_EID(sac_exitval), SAC_EMSG(sac_exitval)); 9047c478bd9Sstevel@tonic-gate } 9057c478bd9Sstevel@tonic-gate } 9067c478bd9Sstevel@tonic-gate pma[port].flags &= ~PM_HAS_ENTRY; 9077c478bd9Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, "%s: /dev/term/%d removed from sacadm\n", 9087c478bd9Sstevel@tonic-gate modname, port); 9097c478bd9Sstevel@tonic-gate } 9107c478bd9Sstevel@tonic-gate 9117c478bd9Sstevel@tonic-gate 9127c478bd9Sstevel@tonic-gate /* 9137c478bd9Sstevel@tonic-gate * delete_port_monitor() 9147c478bd9Sstevel@tonic-gate * Check for the existence of a port monitor for "port" and remove it if 9157c478bd9Sstevel@tonic-gate * one exists 9167c478bd9Sstevel@tonic-gate */ 9177c478bd9Sstevel@tonic-gate static void 9187c478bd9Sstevel@tonic-gate delete_port_monitor(int port) 9197c478bd9Sstevel@tonic-gate { 9207c478bd9Sstevel@tonic-gate char cmdline[CMDLEN]; 9217c478bd9Sstevel@tonic-gate int sac_exitval; 9227c478bd9Sstevel@tonic-gate 9237c478bd9Sstevel@tonic-gate (void) sprintf(cmdline, "/usr/sbin/sacadm -L -p ttymon%d", 9247c478bd9Sstevel@tonic-gate PM_NUM(port)); 9257c478bd9Sstevel@tonic-gate sac_exitval = execute(cmdline); 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate /* clear the PM tag and return if the port monitor is not active */ 9287c478bd9Sstevel@tonic-gate if (sac_exitval == E_NOEXIST) { 9297c478bd9Sstevel@tonic-gate pma[PM_SLOT(port)].flags &= ~HAS_PORT_MON; 9307c478bd9Sstevel@tonic-gate return; 9317c478bd9Sstevel@tonic-gate } 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate /* some other sacadm(1m) error, log and return */ 9347c478bd9Sstevel@tonic-gate if (sac_exitval != 0) { 9357c478bd9Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, "sacadm: (%s) %s\n", 9367c478bd9Sstevel@tonic-gate SAC_EID(sac_exitval), SAC_EMSG(sac_exitval)); 9377c478bd9Sstevel@tonic-gate return; 9387c478bd9Sstevel@tonic-gate } 9397c478bd9Sstevel@tonic-gate 9407c478bd9Sstevel@tonic-gate if (devfsadm_noupdate() == DEVFSADM_FALSE) { 9417c478bd9Sstevel@tonic-gate (void) sprintf(cmdline, 9427c478bd9Sstevel@tonic-gate "/usr/sbin/sacadm -r -p ttymon%d", PM_NUM(port)); 9437c478bd9Sstevel@tonic-gate if (sac_exitval = execute(cmdline)) { 9447c478bd9Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, 9457c478bd9Sstevel@tonic-gate "failed to remove port monitor ttymon%d\n", 9467c478bd9Sstevel@tonic-gate PM_NUM(port)); 9477c478bd9Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, "sacadm: (%s) %s\n", 9487c478bd9Sstevel@tonic-gate SAC_EID(sac_exitval), SAC_EMSG(sac_exitval)); 9497c478bd9Sstevel@tonic-gate } 9507c478bd9Sstevel@tonic-gate } 9517c478bd9Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, "%s: port monitor ttymon%d removed\n", 9527c478bd9Sstevel@tonic-gate modname, PM_NUM(port)); 9537c478bd9Sstevel@tonic-gate pma[PM_SLOT(port)].flags &= ~HAS_PORT_MON; 9547c478bd9Sstevel@tonic-gate } 9557c478bd9Sstevel@tonic-gate 9567c478bd9Sstevel@tonic-gate static void 9577c478bd9Sstevel@tonic-gate add_port_monitor(int port) 9587c478bd9Sstevel@tonic-gate { 9597c478bd9Sstevel@tonic-gate char cmdline[CMDLEN]; 9607c478bd9Sstevel@tonic-gate int sac_exitval; 9617c478bd9Sstevel@tonic-gate 9627c478bd9Sstevel@tonic-gate if ((pma[PM_SLOT(port)].flags & HAS_PORT_MON) != 0) { 9637c478bd9Sstevel@tonic-gate return; 9647c478bd9Sstevel@tonic-gate } 9657c478bd9Sstevel@tonic-gate 9667c478bd9Sstevel@tonic-gate (void) sprintf(cmdline, 9677c478bd9Sstevel@tonic-gate "/usr/sbin/sacadm -l -p ttymon%d", PM_NUM(port)); 9687c478bd9Sstevel@tonic-gate sac_exitval = execute(cmdline); 9697c478bd9Sstevel@tonic-gate if (sac_exitval == E_NOEXIST) { 9707c478bd9Sstevel@tonic-gate (void) sprintf(cmdline, 9717c478bd9Sstevel@tonic-gate "/usr/sbin/sacadm -a -n 2 -p ttymon%d -t ttymon" 9727c478bd9Sstevel@tonic-gate " -c /usr/lib/saf/ttymon -v \"`/usr/sbin/ttyadm" 9737c478bd9Sstevel@tonic-gate " -V`\" -y \"Ports %d-%d\"", PM_NUM(port), PM_SLOT(port), 9747c478bd9Sstevel@tonic-gate PM_SLOT(port) + (PM_GRPSZ - 1)); 9757c478bd9Sstevel@tonic-gate if (devfsadm_noupdate() == DEVFSADM_FALSE) { 9767c478bd9Sstevel@tonic-gate if (sac_exitval = execute(cmdline)) { 9777c478bd9Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, 9787c478bd9Sstevel@tonic-gate "failed to add port monitor ttymon%d\n", 9797c478bd9Sstevel@tonic-gate PM_NUM(port)); 9807c478bd9Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, "sacadm: (%s) %s\n", 9817c478bd9Sstevel@tonic-gate SAC_EID(sac_exitval), 9827c478bd9Sstevel@tonic-gate SAC_EMSG(sac_exitval)); 9837c478bd9Sstevel@tonic-gate } 9847c478bd9Sstevel@tonic-gate } 9857c478bd9Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, "%s: port monitor ttymon%d added\n", 9867c478bd9Sstevel@tonic-gate modname, PM_NUM(port)); 9877c478bd9Sstevel@tonic-gate } 9887c478bd9Sstevel@tonic-gate pma[PM_SLOT(port)].flags |= HAS_PORT_MON; 9897c478bd9Sstevel@tonic-gate } 9907c478bd9Sstevel@tonic-gate 9917c478bd9Sstevel@tonic-gate /* 9927c478bd9Sstevel@tonic-gate * parse port number from string 9937c478bd9Sstevel@tonic-gate * returns port number if in range [0..maxports] 9947c478bd9Sstevel@tonic-gate */ 9957c478bd9Sstevel@tonic-gate static int 9967c478bd9Sstevel@tonic-gate parse_portno(char *dname) 9977c478bd9Sstevel@tonic-gate { 9987c478bd9Sstevel@tonic-gate int pn; 9997c478bd9Sstevel@tonic-gate 10007c478bd9Sstevel@tonic-gate if (sscanf(dname, "%d", &pn) != 1) 10017c478bd9Sstevel@tonic-gate return (-1); 10027c478bd9Sstevel@tonic-gate 10037c478bd9Sstevel@tonic-gate if ((pn < 0) || (pn > maxports)) { 10047c478bd9Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, 10057c478bd9Sstevel@tonic-gate "%s:parse_portno: %d not in range (0..%d)\n", 10067c478bd9Sstevel@tonic-gate modname, pn, maxports); 10077c478bd9Sstevel@tonic-gate return (-1); 10087c478bd9Sstevel@tonic-gate } 10097c478bd9Sstevel@tonic-gate 10107c478bd9Sstevel@tonic-gate return (pn); 10117c478bd9Sstevel@tonic-gate } 10127c478bd9Sstevel@tonic-gate 10137c478bd9Sstevel@tonic-gate 10147c478bd9Sstevel@tonic-gate /* 10157c478bd9Sstevel@tonic-gate * fork and exec a command, waiting for the command to 10167c478bd9Sstevel@tonic-gate * complete and return it's status 10177c478bd9Sstevel@tonic-gate */ 10187c478bd9Sstevel@tonic-gate static int 10197c478bd9Sstevel@tonic-gate execute(const char *s) 10207c478bd9Sstevel@tonic-gate { 10217c478bd9Sstevel@tonic-gate int status; 10227c478bd9Sstevel@tonic-gate int fd; 10237c478bd9Sstevel@tonic-gate pid_t pid; 10247c478bd9Sstevel@tonic-gate pid_t w; 10257c478bd9Sstevel@tonic-gate 10267c478bd9Sstevel@tonic-gate /* 10277c478bd9Sstevel@tonic-gate * fork a single threaded child proc to execute the 10287c478bd9Sstevel@tonic-gate * sacadm command string 10297c478bd9Sstevel@tonic-gate */ 10307c478bd9Sstevel@tonic-gate devfsadm_print(PORT_MID, "%s: execute:\n\t%s\n", modname, s); 10317c478bd9Sstevel@tonic-gate if ((pid = fork1()) == 0) { 10327c478bd9Sstevel@tonic-gate (void) close(0); 10337c478bd9Sstevel@tonic-gate (void) close(1); 10347c478bd9Sstevel@tonic-gate (void) close(2); 10357c478bd9Sstevel@tonic-gate fd = open("/dev/null", O_RDWR); 10367c478bd9Sstevel@tonic-gate (void) dup(fd); 10377c478bd9Sstevel@tonic-gate (void) dup(fd); 10387c478bd9Sstevel@tonic-gate (void) execl("/sbin/sh", "sh", "-c", s, 0); 10397c478bd9Sstevel@tonic-gate /* 10407c478bd9Sstevel@tonic-gate * return the sacadm exit status (see _exit(2)) 10417c478bd9Sstevel@tonic-gate */ 10427c478bd9Sstevel@tonic-gate _exit(127); 10437c478bd9Sstevel@tonic-gate } 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate /* 10467c478bd9Sstevel@tonic-gate * wait for child process to terminate 10477c478bd9Sstevel@tonic-gate */ 10487c478bd9Sstevel@tonic-gate for (;;) { 10497c478bd9Sstevel@tonic-gate w = wait(&status); 10507c478bd9Sstevel@tonic-gate if (w == pid) { 10517c478bd9Sstevel@tonic-gate devfsadm_print(PORT_MID, "%s:exit status (%d)\n", 10527c478bd9Sstevel@tonic-gate modname, SAC_EXITVAL(status)); 10537c478bd9Sstevel@tonic-gate return (SAC_EXITVAL(status)); 10547c478bd9Sstevel@tonic-gate } 10557c478bd9Sstevel@tonic-gate if (w == (pid_t)-1) { 10567c478bd9Sstevel@tonic-gate devfsadm_print(VERBOSE_MID, "%s: exec failed\n", 10577c478bd9Sstevel@tonic-gate modname); 10587c478bd9Sstevel@tonic-gate return (-1); 10597c478bd9Sstevel@tonic-gate } 10607c478bd9Sstevel@tonic-gate } 10617c478bd9Sstevel@tonic-gate 10627c478bd9Sstevel@tonic-gate /* NOTREACHED */ 10637c478bd9Sstevel@tonic-gate } 10647c478bd9Sstevel@tonic-gate 10657c478bd9Sstevel@tonic-gate 10667c478bd9Sstevel@tonic-gate /* 10677c478bd9Sstevel@tonic-gate * check if the minor name is suffixed with ",cu" 10687c478bd9Sstevel@tonic-gate */ 10697c478bd9Sstevel@tonic-gate static int 10707c478bd9Sstevel@tonic-gate is_dialout(char *name) 10717c478bd9Sstevel@tonic-gate { 10727c478bd9Sstevel@tonic-gate char *s_chr; 10737c478bd9Sstevel@tonic-gate 10747c478bd9Sstevel@tonic-gate if ((name == NULL) || (s_chr = strrchr(name, MN_SEPR)) == NULL) 10757c478bd9Sstevel@tonic-gate return (0); 10767c478bd9Sstevel@tonic-gate 10777c478bd9Sstevel@tonic-gate if (strcmp(s_chr, DIALOUT_SUFFIX) == 0) { 10787c478bd9Sstevel@tonic-gate return (1); 10797c478bd9Sstevel@tonic-gate } else { 10807c478bd9Sstevel@tonic-gate return (0); 10817c478bd9Sstevel@tonic-gate } 10827c478bd9Sstevel@tonic-gate } 10837c478bd9Sstevel@tonic-gate 10847c478bd9Sstevel@tonic-gate 10857c478bd9Sstevel@tonic-gate /* 10867c478bd9Sstevel@tonic-gate * Get the name of the port device from a pmtab entry. 10877c478bd9Sstevel@tonic-gate * Note the /dev/term/ part is taken off. 10887c478bd9Sstevel@tonic-gate */ 10897c478bd9Sstevel@tonic-gate static char * 10907c478bd9Sstevel@tonic-gate pmtab_parse_portname(char *buffer) 10917c478bd9Sstevel@tonic-gate { 10927c478bd9Sstevel@tonic-gate int i; 10937c478bd9Sstevel@tonic-gate char *bufp, *devnamep, *portnamep; 10947c478bd9Sstevel@tonic-gate 10957c478bd9Sstevel@tonic-gate /* 10967c478bd9Sstevel@tonic-gate * position to the device name (field 8) 10977c478bd9Sstevel@tonic-gate */ 10987c478bd9Sstevel@tonic-gate bufp = strchr(buffer, PMTAB_SEPR); 10997c478bd9Sstevel@tonic-gate for (i = 0; i < PMTAB_DEVNAME_FIELD; i++) { 11007c478bd9Sstevel@tonic-gate if (bufp == NULL) 11017c478bd9Sstevel@tonic-gate return (NULL); 11027c478bd9Sstevel@tonic-gate bufp = strchr(++bufp, PMTAB_SEPR); 11037c478bd9Sstevel@tonic-gate } 11047c478bd9Sstevel@tonic-gate 11057c478bd9Sstevel@tonic-gate /* move past the ':' and locate the end of the devname */ 11067c478bd9Sstevel@tonic-gate devnamep = bufp++; 11077c478bd9Sstevel@tonic-gate if ((bufp = strchr(bufp, PMTAB_SEPR)) == NULL) 11087c478bd9Sstevel@tonic-gate return (NULL); 11097c478bd9Sstevel@tonic-gate 11107c478bd9Sstevel@tonic-gate *bufp = MN_NULLCHAR; 11117c478bd9Sstevel@tonic-gate if ((portnamep = strrchr(devnamep, DEVNAME_SEPR)) == NULL) { 11127c478bd9Sstevel@tonic-gate *bufp = PMTAB_SEPR; 11137c478bd9Sstevel@tonic-gate return (NULL); 11147c478bd9Sstevel@tonic-gate } 11157c478bd9Sstevel@tonic-gate 11167c478bd9Sstevel@tonic-gate /* return with "buffer" chopped after the /dev/term entry */ 11177c478bd9Sstevel@tonic-gate 11187c478bd9Sstevel@tonic-gate return (++portnamep); 11197c478bd9Sstevel@tonic-gate } 11207c478bd9Sstevel@tonic-gate 11217c478bd9Sstevel@tonic-gate /* 11227c478bd9Sstevel@tonic-gate * port monitor array mgmt 11237c478bd9Sstevel@tonic-gate */ 11247c478bd9Sstevel@tonic-gate static void * 11257c478bd9Sstevel@tonic-gate pma_alloc(void) 11267c478bd9Sstevel@tonic-gate { 11277c478bd9Sstevel@tonic-gate 11287c478bd9Sstevel@tonic-gate if (pma != NULL) { 11297c478bd9Sstevel@tonic-gate devfsadm_errprint("%s:pma_alloc:pma != NULL\n", modname); 11307c478bd9Sstevel@tonic-gate return (NULL); 11317c478bd9Sstevel@tonic-gate } 11327c478bd9Sstevel@tonic-gate 11337c478bd9Sstevel@tonic-gate if ((pma = calloc(maxports + 1, sizeof (*pma))) == NULL) { 11347c478bd9Sstevel@tonic-gate devfsadm_errprint("%s:pma_alloc:pma alloc failure\n", modname); 11357c478bd9Sstevel@tonic-gate return (NULL); 11367c478bd9Sstevel@tonic-gate } 11377c478bd9Sstevel@tonic-gate 11387c478bd9Sstevel@tonic-gate return ((void *)pma); 11397c478bd9Sstevel@tonic-gate } 11407c478bd9Sstevel@tonic-gate 11417c478bd9Sstevel@tonic-gate static void 11427c478bd9Sstevel@tonic-gate pma_free(void) 11437c478bd9Sstevel@tonic-gate { 11447c478bd9Sstevel@tonic-gate 11457c478bd9Sstevel@tonic-gate int i; 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate if (pma == NULL) 11487c478bd9Sstevel@tonic-gate return; 11497c478bd9Sstevel@tonic-gate 11507c478bd9Sstevel@tonic-gate /* 11517c478bd9Sstevel@tonic-gate * free any strings we had allocated 11527c478bd9Sstevel@tonic-gate */ 11537c478bd9Sstevel@tonic-gate for (i = 0; i <= maxports; i++) { 11547c478bd9Sstevel@tonic-gate if (pma[i].pm_tag != NULL) 11557c478bd9Sstevel@tonic-gate free(pma[i].pm_tag); 11567c478bd9Sstevel@tonic-gate } 11577c478bd9Sstevel@tonic-gate 11587c478bd9Sstevel@tonic-gate free(pma); 11597c478bd9Sstevel@tonic-gate pma = NULL; 11607c478bd9Sstevel@tonic-gate } 1161