17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 23*4bc0a2efScasper * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include "utils.h" 307c478bd9Sstevel@tonic-gate #include <locale.h> 317c478bd9Sstevel@tonic-gate #include <poll.h> 327c478bd9Sstevel@tonic-gate #include <setjmp.h> 337c478bd9Sstevel@tonic-gate #include <signal.h> 347c478bd9Sstevel@tonic-gate #include <strings.h> 357c478bd9Sstevel@tonic-gate #include <stropts.h> 367c478bd9Sstevel@tonic-gate #include <syslog.h> 377c478bd9Sstevel@tonic-gate #include <sys/sysmsg_impl.h> 387c478bd9Sstevel@tonic-gate #include <sys/stat.h> 397c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 407c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h> 417c478bd9Sstevel@tonic-gate #include <sys/termios.h> 427c478bd9Sstevel@tonic-gate #include <sys/types.h> 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate #define CONSADM "/usr/sbin/consadm" 457c478bd9Sstevel@tonic-gate #define CONSADMD "/usr/sbin/consadmd" 467c478bd9Sstevel@tonic-gate #define CONSADMLOCK "/tmp/CoNsAdM.lck" 477c478bd9Sstevel@tonic-gate #define CONSDAEMON "consadmd" 487c478bd9Sstevel@tonic-gate #define MSGLOG "/dev/msglog" 497c478bd9Sstevel@tonic-gate #define CONSOLE "/dev/console" 507c478bd9Sstevel@tonic-gate #define WSCONS "/dev/wscons" 517c478bd9Sstevel@tonic-gate #define CONSCONFIG "/etc/consadm.conf" 527c478bd9Sstevel@tonic-gate #define SETCONSOLEPID "/etc/consadm.pid" 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate #define CONFIG 0 557c478bd9Sstevel@tonic-gate #define UNCONFIG 1 567c478bd9Sstevel@tonic-gate #define COMMENT '#' 577c478bd9Sstevel@tonic-gate #define NEWLINE '\n' 587c478bd9Sstevel@tonic-gate #define SPACE ' ' 597c478bd9Sstevel@tonic-gate #define TAB ' ' 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate #define E_SUCCESS 0 /* Exit status for success */ 627c478bd9Sstevel@tonic-gate #define E_ERROR 1 /* Exit status for error */ 637c478bd9Sstevel@tonic-gate #define E_USAGE 2 /* Exit status for usage error */ 647c478bd9Sstevel@tonic-gate #define E_NO_CARRIER 3 /* Exit status for no carrier */ 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate /* useful data structures for lock function */ 677c478bd9Sstevel@tonic-gate static struct flock fl; 687c478bd9Sstevel@tonic-gate #define LOCK_EX F_WRLCK 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate static char usage[] = 717c478bd9Sstevel@tonic-gate "Usage: \n" 727c478bd9Sstevel@tonic-gate "\tconsadm [ -p ] [ -a device ... ]\n" 737c478bd9Sstevel@tonic-gate "\tconsadm [ -p ] [ -d device ... ]\n" 747c478bd9Sstevel@tonic-gate "\tconsadm [ -p ]\n"; 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate /* data structures ... */ 777c478bd9Sstevel@tonic-gate static char conshdr[] = 787c478bd9Sstevel@tonic-gate "#\n# consadm.conf\n#" 797c478bd9Sstevel@tonic-gate "# Configuration parameters for console message redirection.\n" 807c478bd9Sstevel@tonic-gate "# Do NOT edit this file by hand -- use consadm(1m) instead.\n" 817c478bd9Sstevel@tonic-gate "#\n"; 827c478bd9Sstevel@tonic-gate const char *pname; /* program name */ 837c478bd9Sstevel@tonic-gate static sigjmp_buf deadline; 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate /* command line arguments */ 867c478bd9Sstevel@tonic-gate static int display; 877c478bd9Sstevel@tonic-gate static int persist; 887c478bd9Sstevel@tonic-gate static int addflag; 897c478bd9Sstevel@tonic-gate static int deleteflag; 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate /* function headers */ 927c478bd9Sstevel@tonic-gate static void setaux(char *); 937c478bd9Sstevel@tonic-gate static void unsetaux(char *); 947c478bd9Sstevel@tonic-gate static void getconsole(void); 957c478bd9Sstevel@tonic-gate static boolean_t has_carrier(int fd); 967c478bd9Sstevel@tonic-gate static boolean_t modem_support(int fd); 977c478bd9Sstevel@tonic-gate static void setfallback(char *argv[]); 987c478bd9Sstevel@tonic-gate static void removefallback(void); 997c478bd9Sstevel@tonic-gate static void fallbackdaemon(void); 1007c478bd9Sstevel@tonic-gate static void persistlist(void); 1017c478bd9Sstevel@tonic-gate static int verifyarg(char *, int); 1027c478bd9Sstevel@tonic-gate static int safeopen(char *); 1037c478bd9Sstevel@tonic-gate static void catch_term(void); 1047c478bd9Sstevel@tonic-gate static void catch_alarm(void); 1057c478bd9Sstevel@tonic-gate static void catch_hup(void); 1067c478bd9Sstevel@tonic-gate static void cleanup_on_exit(void); 1077c478bd9Sstevel@tonic-gate static void addtolist(char *); 1087c478bd9Sstevel@tonic-gate static void removefromlist(char *); 1097c478bd9Sstevel@tonic-gate static int pathcmp(char *, char *); 1107c478bd9Sstevel@tonic-gate static int lckfunc(int, int); 1117c478bd9Sstevel@tonic-gate typedef void (*sig_handler_t)(); 1127c478bd9Sstevel@tonic-gate static int getlock(void); 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate /* 1157c478bd9Sstevel@tonic-gate * In main, return codes carry the following meaning: 1167c478bd9Sstevel@tonic-gate * 0 - successful 1177c478bd9Sstevel@tonic-gate * 1 - error during the command execution 1187c478bd9Sstevel@tonic-gate */ 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate int 1217c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 1227c478bd9Sstevel@tonic-gate { 1237c478bd9Sstevel@tonic-gate int index; 1247c478bd9Sstevel@tonic-gate struct sigaction sa; 1257c478bd9Sstevel@tonic-gate int c; 1267c478bd9Sstevel@tonic-gate char *p = strrchr(argv[0], '/'); 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate if (p == NULL) 1297c478bd9Sstevel@tonic-gate p = argv[0]; 1307c478bd9Sstevel@tonic-gate else 1317c478bd9Sstevel@tonic-gate p++; 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate pname = p; 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 1367c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 1377c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 1387c478bd9Sstevel@tonic-gate #endif 1397c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate if (getuid() != 0) 1427c478bd9Sstevel@tonic-gate die(gettext("must be root to run this program\n")); 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate /* 1457c478bd9Sstevel@tonic-gate * Handle normal termination signals that may be received. 1467c478bd9Sstevel@tonic-gate */ 1477c478bd9Sstevel@tonic-gate sa.sa_handler = SIG_IGN; 1487c478bd9Sstevel@tonic-gate sa.sa_flags = 0; 1497c478bd9Sstevel@tonic-gate (void) sigemptyset(&sa.sa_mask); 1507c478bd9Sstevel@tonic-gate (void) sigaction(SIGHUP, &sa, NULL); 1517c478bd9Sstevel@tonic-gate (void) sigaction(SIGINT, &sa, NULL); 1527c478bd9Sstevel@tonic-gate (void) sigaction(SIGQUIT, &sa, NULL); 1537c478bd9Sstevel@tonic-gate (void) sigaction(SIGTERM, &sa, NULL); 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate /* 1567c478bd9Sstevel@tonic-gate * To make sure persistent state gets removed. 1577c478bd9Sstevel@tonic-gate */ 1587c478bd9Sstevel@tonic-gate sa.sa_handler = cleanup_on_exit; 1597c478bd9Sstevel@tonic-gate sa.sa_flags = 0; 1607c478bd9Sstevel@tonic-gate (void) sigemptyset(&sa.sa_mask); 1617c478bd9Sstevel@tonic-gate (void) sigaction(SIGSEGV, &sa, NULL); 1627c478bd9Sstevel@tonic-gate (void) sigaction(SIGILL, &sa, NULL); 1637c478bd9Sstevel@tonic-gate (void) sigaction(SIGABRT, &sa, NULL); 1647c478bd9Sstevel@tonic-gate (void) sigaction(SIGBUS, &sa, NULL); 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate if (strcmp(pname, CONSDAEMON) == 0) { 1677c478bd9Sstevel@tonic-gate fallbackdaemon(); 1687c478bd9Sstevel@tonic-gate return (E_SUCCESS); 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate if (argc == 1) 1727c478bd9Sstevel@tonic-gate display++; 1737c478bd9Sstevel@tonic-gate else { 1747c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "adp")) != EOF) { 1757c478bd9Sstevel@tonic-gate switch (c) { 1767c478bd9Sstevel@tonic-gate case 'a': 1777c478bd9Sstevel@tonic-gate addflag++; 1787c478bd9Sstevel@tonic-gate break; 1797c478bd9Sstevel@tonic-gate case 'd': 1807c478bd9Sstevel@tonic-gate deleteflag++; 1817c478bd9Sstevel@tonic-gate break; 1827c478bd9Sstevel@tonic-gate case 'p': 1837c478bd9Sstevel@tonic-gate persist++; 1847c478bd9Sstevel@tonic-gate break; 1857c478bd9Sstevel@tonic-gate default: 1867c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(usage)); 1877c478bd9Sstevel@tonic-gate exit(E_USAGE); 1887c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1897c478bd9Sstevel@tonic-gate } 1907c478bd9Sstevel@tonic-gate } 1917c478bd9Sstevel@tonic-gate } 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate if (display) { 1947c478bd9Sstevel@tonic-gate getconsole(); 1957c478bd9Sstevel@tonic-gate return (E_SUCCESS); 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate if (addflag && deleteflag) { 1987c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(usage)); 1997c478bd9Sstevel@tonic-gate return (E_ERROR); 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate if (addflag) { 2027c478bd9Sstevel@tonic-gate if (optind == argc) { 2037c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(usage)); 2047c478bd9Sstevel@tonic-gate return (E_ERROR); 2057c478bd9Sstevel@tonic-gate } 2067c478bd9Sstevel@tonic-gate /* separately check every device path specified */ 2077c478bd9Sstevel@tonic-gate for (index = optind; index < argc; index++) { 2087c478bd9Sstevel@tonic-gate if (verifyarg(argv[index], addflag)) 2097c478bd9Sstevel@tonic-gate return (E_ERROR); 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate for (index = optind; index < argc; index++) { 2137c478bd9Sstevel@tonic-gate setaux(argv[index]); 2147c478bd9Sstevel@tonic-gate if (persist) 2157c478bd9Sstevel@tonic-gate addtolist(argv[index]); 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate /* 2197c478bd9Sstevel@tonic-gate * start/restart daemon based on the auxilary 2207c478bd9Sstevel@tonic-gate * consoles at this time. 2217c478bd9Sstevel@tonic-gate */ 2227c478bd9Sstevel@tonic-gate setfallback(argv); 2237c478bd9Sstevel@tonic-gate return (E_SUCCESS); 2247c478bd9Sstevel@tonic-gate } else if (deleteflag) { 2257c478bd9Sstevel@tonic-gate if (optind == argc) { 2267c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(usage)); 2277c478bd9Sstevel@tonic-gate return (E_ERROR); 2287c478bd9Sstevel@tonic-gate } 2297c478bd9Sstevel@tonic-gate /* separately check every device path specified */ 2307c478bd9Sstevel@tonic-gate for (index = optind; index < argc; index++) { 2317c478bd9Sstevel@tonic-gate if (verifyarg(argv[index], 0)) 2327c478bd9Sstevel@tonic-gate return (E_ERROR); 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate for (index = optind; index < argc; index++) { 2367c478bd9Sstevel@tonic-gate unsetaux(argv[index]); 2377c478bd9Sstevel@tonic-gate if (persist && deleteflag) 2387c478bd9Sstevel@tonic-gate removefromlist(argv[index]); 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate /* 2427c478bd9Sstevel@tonic-gate * kill off daemon and restart with 2437c478bd9Sstevel@tonic-gate * new list of auxiliary consoles 2447c478bd9Sstevel@tonic-gate */ 2457c478bd9Sstevel@tonic-gate setfallback(argv); 2467c478bd9Sstevel@tonic-gate return (E_SUCCESS); 2477c478bd9Sstevel@tonic-gate } else if (persist) { 2487c478bd9Sstevel@tonic-gate if (optind < argc) { 2497c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(usage)); 2507c478bd9Sstevel@tonic-gate return (E_ERROR); 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate persistlist(); 2547c478bd9Sstevel@tonic-gate return (E_SUCCESS); 2557c478bd9Sstevel@tonic-gate } else { 2567c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(usage)); 2577c478bd9Sstevel@tonic-gate return (E_ERROR); 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate } /* main */ 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate /* for daemon to handle termination from user command */ 2627c478bd9Sstevel@tonic-gate static void 2637c478bd9Sstevel@tonic-gate catch_term() 2647c478bd9Sstevel@tonic-gate { 2657c478bd9Sstevel@tonic-gate exit(E_SUCCESS); 2667c478bd9Sstevel@tonic-gate } 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate /* handle lack of carrier on open */ 2697c478bd9Sstevel@tonic-gate static void 2707c478bd9Sstevel@tonic-gate catch_alarm() 2717c478bd9Sstevel@tonic-gate { 2727c478bd9Sstevel@tonic-gate siglongjmp(deadline, 1); 2737c478bd9Sstevel@tonic-gate } 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate /* caught a sighup */ 2767c478bd9Sstevel@tonic-gate static void 2777c478bd9Sstevel@tonic-gate catch_hup() 2787c478bd9Sstevel@tonic-gate { 2797c478bd9Sstevel@tonic-gate /* 2807c478bd9Sstevel@tonic-gate * ttymon sends sighup to consadmd because it has the serial 2817c478bd9Sstevel@tonic-gate * port open. We catch the signal here, but process it 2827c478bd9Sstevel@tonic-gate * within fallbackdaemon(). We ignore the signal if the 2837c478bd9Sstevel@tonic-gate * errno returned was EINTR. 2847c478bd9Sstevel@tonic-gate */ 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate /* Remove persistent state on receiving signal. */ 2887c478bd9Sstevel@tonic-gate static void 2897c478bd9Sstevel@tonic-gate cleanup_on_exit() 2907c478bd9Sstevel@tonic-gate { 2917c478bd9Sstevel@tonic-gate (void) unlink(CONSADMLOCK); 2927c478bd9Sstevel@tonic-gate exit(E_ERROR); 2937c478bd9Sstevel@tonic-gate } 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate /* 2967c478bd9Sstevel@tonic-gate * send ioctl to /dev/sysmsg to route msgs of the device specified. 2977c478bd9Sstevel@tonic-gate */ 2987c478bd9Sstevel@tonic-gate static void 2997c478bd9Sstevel@tonic-gate setaux(char *dev) 3007c478bd9Sstevel@tonic-gate { 3017c478bd9Sstevel@tonic-gate int fd; 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate if ((fd = safeopen(SYSMSG)) < 0) 3047c478bd9Sstevel@tonic-gate die(gettext("%s is missing or not a valid device\n"), SYSMSG); 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate if (ioctl(fd, CIOCSETCONSOLE, dev) != 0) { 3077c478bd9Sstevel@tonic-gate /* 3087c478bd9Sstevel@tonic-gate * Let setting duplicate device be warning, consadm 3097c478bd9Sstevel@tonic-gate * must proceed to set persistence if requested. 3107c478bd9Sstevel@tonic-gate */ 3117c478bd9Sstevel@tonic-gate if (errno == EBUSY) 3127c478bd9Sstevel@tonic-gate die(gettext("%s is already the default console\n"), 3137c478bd9Sstevel@tonic-gate dev); 3147c478bd9Sstevel@tonic-gate else if (errno != EEXIST) 3157c478bd9Sstevel@tonic-gate die(gettext("cannot get table entry")); 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate syslog(LOG_WARNING, "%s: Added auxiliary device %s", CONSADM, dev); 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate (void) close(fd); 3207c478bd9Sstevel@tonic-gate } 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate /* 3237c478bd9Sstevel@tonic-gate * Send ioctl to device specified and 3247c478bd9Sstevel@tonic-gate * Remove the entry from the list of auxiliary devices. 3257c478bd9Sstevel@tonic-gate */ 3267c478bd9Sstevel@tonic-gate static void 3277c478bd9Sstevel@tonic-gate unsetaux(char *dev) 3287c478bd9Sstevel@tonic-gate { 3297c478bd9Sstevel@tonic-gate int fd; 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate if ((fd = safeopen(SYSMSG)) < 0) 3327c478bd9Sstevel@tonic-gate die(gettext("%s is missing or not a valid device\n"), SYSMSG); 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate if (ioctl(fd, CIOCRMCONSOLE, dev) != 0) { 3357c478bd9Sstevel@tonic-gate if (errno == EBUSY) 3367c478bd9Sstevel@tonic-gate die(gettext("cannot unset the default console\n")); 3377c478bd9Sstevel@tonic-gate } else 3387c478bd9Sstevel@tonic-gate syslog(LOG_WARNING, "%s: Removed auxiliary device %s", 3397c478bd9Sstevel@tonic-gate CONSADM, dev); 3407c478bd9Sstevel@tonic-gate (void) close(fd); 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate static int 3447c478bd9Sstevel@tonic-gate getlock(void) 3457c478bd9Sstevel@tonic-gate { 3467c478bd9Sstevel@tonic-gate int lckfd; 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate if ((lckfd = open(CONSADMLOCK, O_CREAT | O_EXCL | O_WRONLY, 3497c478bd9Sstevel@tonic-gate S_IRUSR | S_IWUSR)) < 0) { 3507c478bd9Sstevel@tonic-gate if (errno == EEXIST) 3517c478bd9Sstevel@tonic-gate die(gettext("currently busy, try again later.\n")); 3527c478bd9Sstevel@tonic-gate else 3537c478bd9Sstevel@tonic-gate die(gettext("cannot open %s"), CONSADMLOCK); 3547c478bd9Sstevel@tonic-gate } 3557c478bd9Sstevel@tonic-gate if (lckfunc(lckfd, LOCK_EX) == -1) { 3567c478bd9Sstevel@tonic-gate (void) close(lckfd); 3577c478bd9Sstevel@tonic-gate (void) unlink(CONSADMLOCK); 3587c478bd9Sstevel@tonic-gate die(gettext("fcntl operation failed")); 3597c478bd9Sstevel@tonic-gate } 3607c478bd9Sstevel@tonic-gate return (lckfd); 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate static void 3647c478bd9Sstevel@tonic-gate addtolist(char *dev) 3657c478bd9Sstevel@tonic-gate { 3667c478bd9Sstevel@tonic-gate int lckfd, fd; 3677c478bd9Sstevel@tonic-gate FILE *fp, *nfp; 3687c478bd9Sstevel@tonic-gate char newfile[MAXPATHLEN]; 3697c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 3707c478bd9Sstevel@tonic-gate int len; 3717c478bd9Sstevel@tonic-gate boolean_t found = B_FALSE; 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate /* update file of devices configured to get console msgs. */ 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate lckfd = getlock(); 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate /* Open new file */ 3787c478bd9Sstevel@tonic-gate (void) snprintf(newfile, sizeof (newfile), "%s%d", 3797c478bd9Sstevel@tonic-gate CONSCONFIG, (int)getpid()); 3807c478bd9Sstevel@tonic-gate if (((fd = creat(newfile, 0644)) < 0) || 3817c478bd9Sstevel@tonic-gate ((nfp = fdopen(fd, "w")) == NULL)) { 3827c478bd9Sstevel@tonic-gate (void) close(lckfd); 3837c478bd9Sstevel@tonic-gate (void) unlink(CONSADMLOCK); 3847c478bd9Sstevel@tonic-gate die(gettext("could not create new %s file"), CONSCONFIG); 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate /* Add header to new file */ 3887c478bd9Sstevel@tonic-gate (void) fprintf(nfp, "%s", conshdr); 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate /* Check that the file doesn't already exist */ 3917c478bd9Sstevel@tonic-gate if ((fp = fopen(CONSCONFIG, "r")) != NULL) { 3927c478bd9Sstevel@tonic-gate while (fgets(buf, MAXPATHLEN, fp) != NULL) { 3937c478bd9Sstevel@tonic-gate if (buf[0] == COMMENT || buf[0] == NEWLINE || 3947c478bd9Sstevel@tonic-gate buf[0] == SPACE || buf[0] == TAB) 3957c478bd9Sstevel@tonic-gate continue; 3967c478bd9Sstevel@tonic-gate len = strlen(buf); 3977c478bd9Sstevel@tonic-gate buf[len - 1] = NULL; /* Clear carriage return */ 3987c478bd9Sstevel@tonic-gate if (pathcmp(dev, buf) == 0) { 3997c478bd9Sstevel@tonic-gate /* they match so use name passed in. */ 4007c478bd9Sstevel@tonic-gate (void) fprintf(nfp, "%s\n", dev); 4017c478bd9Sstevel@tonic-gate found = B_TRUE; 4027c478bd9Sstevel@tonic-gate } else 4037c478bd9Sstevel@tonic-gate (void) fprintf(nfp, "%s\n", buf); 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate } 4067c478bd9Sstevel@tonic-gate /* User specified persistent settings */ 4077c478bd9Sstevel@tonic-gate if (found == B_FALSE) 4087c478bd9Sstevel@tonic-gate (void) fprintf(nfp, "%s\n", dev); 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate (void) fclose(fp); 4117c478bd9Sstevel@tonic-gate (void) fclose(nfp); 4127c478bd9Sstevel@tonic-gate (void) rename(newfile, CONSCONFIG); 4137c478bd9Sstevel@tonic-gate (void) close(lckfd); 4147c478bd9Sstevel@tonic-gate (void) unlink(CONSADMLOCK); 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate /* The list in CONSCONFIG gives the persistence capability in the proto */ 4187c478bd9Sstevel@tonic-gate static void 4197c478bd9Sstevel@tonic-gate removefromlist(char *dev) 4207c478bd9Sstevel@tonic-gate { 4217c478bd9Sstevel@tonic-gate int lckfd; 4227c478bd9Sstevel@tonic-gate FILE *fp, *nfp; 4237c478bd9Sstevel@tonic-gate char newfile[MAXPATHLEN + 1]; 4247c478bd9Sstevel@tonic-gate char len; 4257c478bd9Sstevel@tonic-gate char value[MAXPATHLEN + 1]; 4267c478bd9Sstevel@tonic-gate boolean_t newcontents = B_FALSE; 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate /* update file of devices configured to get console msgs. */ 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate lckfd = getlock(); 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate if ((fp = fopen(CONSCONFIG, "r")) == NULL) { 4337c478bd9Sstevel@tonic-gate (void) close(lckfd); 4347c478bd9Sstevel@tonic-gate (void) unlink(CONSADMLOCK); 4357c478bd9Sstevel@tonic-gate return; 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate /* Open new file */ 4397c478bd9Sstevel@tonic-gate (void) snprintf(newfile, sizeof (newfile), "%s%d", 4407c478bd9Sstevel@tonic-gate CONSCONFIG, (int)getpid()); 4417c478bd9Sstevel@tonic-gate if ((nfp = fopen(newfile, "w")) == NULL) { 4427c478bd9Sstevel@tonic-gate (void) close(lckfd); 4437c478bd9Sstevel@tonic-gate (void) unlink(CONSADMLOCK); 4447c478bd9Sstevel@tonic-gate die(gettext("cannot create new %s file"), CONSCONFIG); 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate /* Add header to new file */ 4487c478bd9Sstevel@tonic-gate (void) fprintf(nfp, "%s", conshdr); 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate /* 4517c478bd9Sstevel@tonic-gate * Check whether the path duplicates what is already in the 4527c478bd9Sstevel@tonic-gate * file. 4537c478bd9Sstevel@tonic-gate */ 4547c478bd9Sstevel@tonic-gate while (fgets(value, MAXPATHLEN, fp) != NULL) { 4557c478bd9Sstevel@tonic-gate /* skip comments */ 4567c478bd9Sstevel@tonic-gate if (value[0] == COMMENT || value[0] == NEWLINE || 4577c478bd9Sstevel@tonic-gate value[0] == SPACE || value[0] == TAB) 4587c478bd9Sstevel@tonic-gate continue; 4597c478bd9Sstevel@tonic-gate len = strlen(value); 4607c478bd9Sstevel@tonic-gate value[len - 1] = NULL; /* Clear carriage return */ 4617c478bd9Sstevel@tonic-gate if (pathcmp(dev, value) == 0) { 4627c478bd9Sstevel@tonic-gate /* they match so don't write it */ 4637c478bd9Sstevel@tonic-gate continue; 4647c478bd9Sstevel@tonic-gate } 4657c478bd9Sstevel@tonic-gate (void) fprintf(nfp, "%s\n", value); 4667c478bd9Sstevel@tonic-gate newcontents = B_TRUE; 4677c478bd9Sstevel@tonic-gate } 4687c478bd9Sstevel@tonic-gate (void) fclose(fp); 4697c478bd9Sstevel@tonic-gate (void) fclose(nfp); 4707c478bd9Sstevel@tonic-gate /* Remove the file if there aren't any auxiliary consoles */ 4717c478bd9Sstevel@tonic-gate if (newcontents) 4727c478bd9Sstevel@tonic-gate (void) rename(newfile, CONSCONFIG); 4737c478bd9Sstevel@tonic-gate else { 4747c478bd9Sstevel@tonic-gate (void) unlink(CONSCONFIG); 4757c478bd9Sstevel@tonic-gate (void) unlink(newfile); 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate (void) close(lckfd); 4787c478bd9Sstevel@tonic-gate (void) unlink(CONSADMLOCK); 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate static int 4827c478bd9Sstevel@tonic-gate pathcmp(char *adev, char *bdev) 4837c478bd9Sstevel@tonic-gate { 4847c478bd9Sstevel@tonic-gate struct stat st1; 4857c478bd9Sstevel@tonic-gate struct stat st2; 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate if (strcmp(adev, bdev) == 0) 4887c478bd9Sstevel@tonic-gate return (0); 4897c478bd9Sstevel@tonic-gate 490*4bc0a2efScasper if (stat(adev, &st1) != 0 || !S_ISCHR(st1.st_mode)) 4917c478bd9Sstevel@tonic-gate die(gettext("invalid device %s\n"), adev); 4927c478bd9Sstevel@tonic-gate 493*4bc0a2efScasper if (stat(bdev, &st2) != 0 || !S_ISCHR(st2.st_mode)) 4947c478bd9Sstevel@tonic-gate die(gettext("invalid device %s\n"), bdev); 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate if (st1.st_rdev == st2.st_rdev) 4977c478bd9Sstevel@tonic-gate return (0); 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate return (1); 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate /* 5037c478bd9Sstevel@tonic-gate * Display configured consoles. 5047c478bd9Sstevel@tonic-gate */ 5057c478bd9Sstevel@tonic-gate static void 5067c478bd9Sstevel@tonic-gate getconsole(void) 5077c478bd9Sstevel@tonic-gate { 5087c478bd9Sstevel@tonic-gate int fd; 5097c478bd9Sstevel@tonic-gate int bufsize = 0; /* size of device cache */ 5107c478bd9Sstevel@tonic-gate char *infop, *ptr, *p; /* info structure for ioctl's */ 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate if ((fd = safeopen(SYSMSG)) < 0) 5137c478bd9Sstevel@tonic-gate die(gettext("%s is missing or not a valid device\n"), SYSMSG); 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate if ((bufsize = ioctl(fd, CIOCGETCONSOLE, NULL)) < 0) 5167c478bd9Sstevel@tonic-gate die(gettext("cannot get table entry\n")); 5177c478bd9Sstevel@tonic-gate if (bufsize == 0) 5187c478bd9Sstevel@tonic-gate return; 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate if ((infop = calloc(bufsize, sizeof (char))) == NULL) 5217c478bd9Sstevel@tonic-gate die(gettext("cannot allocate buffer")); 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate if (ioctl(fd, CIOCGETCONSOLE, infop) < 0) 5247c478bd9Sstevel@tonic-gate die(gettext("cannot get table entry\n")); 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate ptr = infop; 5277c478bd9Sstevel@tonic-gate while (ptr != NULL) { 5287c478bd9Sstevel@tonic-gate p = strchr(ptr, ' '); 5297c478bd9Sstevel@tonic-gate if (p == NULL) { 5307c478bd9Sstevel@tonic-gate (void) printf("%s\n", ptr); 5317c478bd9Sstevel@tonic-gate break; 5327c478bd9Sstevel@tonic-gate } 5337c478bd9Sstevel@tonic-gate *p++ = '\0'; 5347c478bd9Sstevel@tonic-gate (void) printf("%s\n", ptr); 5357c478bd9Sstevel@tonic-gate ptr = p; 5367c478bd9Sstevel@tonic-gate } 5377c478bd9Sstevel@tonic-gate (void) close(fd); 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate /* 5417c478bd9Sstevel@tonic-gate * It is supposed that if the device supports TIOCMGET then it 5427c478bd9Sstevel@tonic-gate * might be a serial device. 5437c478bd9Sstevel@tonic-gate */ 5447c478bd9Sstevel@tonic-gate static boolean_t 5457c478bd9Sstevel@tonic-gate modem_support(int fd) 5467c478bd9Sstevel@tonic-gate { 5477c478bd9Sstevel@tonic-gate int modem_state; 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate if (ioctl(fd, TIOCMGET, &modem_state) == 0) 5507c478bd9Sstevel@tonic-gate return (B_TRUE); 5517c478bd9Sstevel@tonic-gate else 5527c478bd9Sstevel@tonic-gate return (B_FALSE); 5537c478bd9Sstevel@tonic-gate } 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate static boolean_t 5567c478bd9Sstevel@tonic-gate has_carrier(int fd) 5577c478bd9Sstevel@tonic-gate { 5587c478bd9Sstevel@tonic-gate int modem_state; 5597c478bd9Sstevel@tonic-gate 5607c478bd9Sstevel@tonic-gate if (ioctl(fd, TIOCMGET, &modem_state) == 0) 5617c478bd9Sstevel@tonic-gate return ((modem_state & TIOCM_CAR) != 0); 5627c478bd9Sstevel@tonic-gate else { 5637c478bd9Sstevel@tonic-gate return (B_FALSE); 5647c478bd9Sstevel@tonic-gate } 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate static void 5687c478bd9Sstevel@tonic-gate setfallback(char *argv[]) 5697c478bd9Sstevel@tonic-gate { 5707c478bd9Sstevel@tonic-gate pid_t pid; 5717c478bd9Sstevel@tonic-gate FILE *fp; 5727c478bd9Sstevel@tonic-gate char *cmd = CONSADMD; 5737c478bd9Sstevel@tonic-gate int lckfd, fd; 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate lckfd = getlock(); 5767c478bd9Sstevel@tonic-gate 5777c478bd9Sstevel@tonic-gate /* 5787c478bd9Sstevel@tonic-gate * kill off any existing daemon 5797c478bd9Sstevel@tonic-gate * remove /etc/consadm.pid 5807c478bd9Sstevel@tonic-gate */ 5817c478bd9Sstevel@tonic-gate removefallback(); 5827c478bd9Sstevel@tonic-gate 5837c478bd9Sstevel@tonic-gate /* kick off a daemon */ 5847c478bd9Sstevel@tonic-gate if ((pid = fork()) == (pid_t)0) { 5857c478bd9Sstevel@tonic-gate /* always fallback to /dev/console */ 5867c478bd9Sstevel@tonic-gate argv[0] = cmd; 5877c478bd9Sstevel@tonic-gate argv[1] = NULL; 5887c478bd9Sstevel@tonic-gate (void) close(0); 5897c478bd9Sstevel@tonic-gate (void) close(1); 5907c478bd9Sstevel@tonic-gate (void) close(2); 5917c478bd9Sstevel@tonic-gate (void) close(lckfd); 5927c478bd9Sstevel@tonic-gate if ((fd = open(MSGLOG, O_RDWR)) < 0) 5937c478bd9Sstevel@tonic-gate die(gettext("cannot open %s"), MSGLOG); 5947c478bd9Sstevel@tonic-gate (void) dup2(fd, 1); 5957c478bd9Sstevel@tonic-gate (void) dup2(fd, 2); 5967c478bd9Sstevel@tonic-gate (void) execv(cmd, argv); 5977c478bd9Sstevel@tonic-gate exit(E_SUCCESS); 5987c478bd9Sstevel@tonic-gate } else if (pid == -1) 5997c478bd9Sstevel@tonic-gate die(gettext("%s not started"), CONSADMD); 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate if ((fp = fopen(SETCONSOLEPID, "w")) == NULL) 6027c478bd9Sstevel@tonic-gate die(gettext("cannot open %s"), SETCONSOLEPID); 6037c478bd9Sstevel@tonic-gate /* write daemon pid to file */ 6047c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%d\n", (int)pid); 6057c478bd9Sstevel@tonic-gate (void) fclose(fp); 6067c478bd9Sstevel@tonic-gate (void) close(lckfd); 6077c478bd9Sstevel@tonic-gate (void) unlink(CONSADMLOCK); 6087c478bd9Sstevel@tonic-gate } 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate /* 6117c478bd9Sstevel@tonic-gate * Remove the daemon that would have implemented the automatic 6127c478bd9Sstevel@tonic-gate * fallback in event of carrier loss on the serial console. 6137c478bd9Sstevel@tonic-gate */ 6147c478bd9Sstevel@tonic-gate static void 6157c478bd9Sstevel@tonic-gate removefallback(void) 6167c478bd9Sstevel@tonic-gate { 6177c478bd9Sstevel@tonic-gate FILE *fp; 6187c478bd9Sstevel@tonic-gate int pid; 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate if ((fp = fopen(SETCONSOLEPID, "r+")) == NULL) 6217c478bd9Sstevel@tonic-gate /* file doesn't exist, so no work to do */ 6227c478bd9Sstevel@tonic-gate return; 6237c478bd9Sstevel@tonic-gate 6247c478bd9Sstevel@tonic-gate if (fscanf(fp, "%d\n", &pid) <= 0) { 6257c478bd9Sstevel@tonic-gate (void) fclose(fp); 6267c478bd9Sstevel@tonic-gate (void) unlink(SETCONSOLEPID); 6277c478bd9Sstevel@tonic-gate return; 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate 6307c478bd9Sstevel@tonic-gate /* 6317c478bd9Sstevel@tonic-gate * Don't shoot ourselves in the foot by killing init, 6327c478bd9Sstevel@tonic-gate * sched, pageout, or fsflush. 6337c478bd9Sstevel@tonic-gate */ 6347c478bd9Sstevel@tonic-gate if (pid == 0 || pid == 1 || pid == 2 || pid == 3) { 6357c478bd9Sstevel@tonic-gate (void) unlink(SETCONSOLEPID); 6367c478bd9Sstevel@tonic-gate return; 6377c478bd9Sstevel@tonic-gate } 6387c478bd9Sstevel@tonic-gate /* 6397c478bd9Sstevel@tonic-gate * kill off the existing daemon listed in 6407c478bd9Sstevel@tonic-gate * /etc/consadm.pid 6417c478bd9Sstevel@tonic-gate */ 6427c478bd9Sstevel@tonic-gate (void) kill((pid_t)pid, SIGTERM); 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate (void) fclose(fp); 6457c478bd9Sstevel@tonic-gate (void) unlink(SETCONSOLEPID); 6467c478bd9Sstevel@tonic-gate } 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate /* 6497c478bd9Sstevel@tonic-gate * Assume we always fall back to /dev/console. 6507c478bd9Sstevel@tonic-gate * parameter passed in will always be the auxiliary device. 6517c478bd9Sstevel@tonic-gate * The daemon will not start after the last device has been removed. 6527c478bd9Sstevel@tonic-gate */ 6537c478bd9Sstevel@tonic-gate static void 6547c478bd9Sstevel@tonic-gate fallbackdaemon(void) 6557c478bd9Sstevel@tonic-gate { 6567c478bd9Sstevel@tonic-gate int fd, sysmfd, ret = 0; 6577c478bd9Sstevel@tonic-gate char **devpaths; 6587c478bd9Sstevel@tonic-gate pollfd_t *fds; 6597c478bd9Sstevel@tonic-gate nfds_t nfds = 0; 6607c478bd9Sstevel@tonic-gate int index; 6617c478bd9Sstevel@tonic-gate int pollagain; 6627c478bd9Sstevel@tonic-gate struct sigaction sa; 6637c478bd9Sstevel@tonic-gate int bufsize = 0; /* length of device cache paths */ 6647c478bd9Sstevel@tonic-gate int cachesize = 0; /* size of device cache */ 6657c478bd9Sstevel@tonic-gate char *infop, *ptr, *p; /* info structure for ioctl's */ 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate /* 6687c478bd9Sstevel@tonic-gate * catch SIGTERM cause it might be coming from user via consadm 6697c478bd9Sstevel@tonic-gate */ 6707c478bd9Sstevel@tonic-gate sa.sa_handler = catch_term; 6717c478bd9Sstevel@tonic-gate sa.sa_flags = 0; 6727c478bd9Sstevel@tonic-gate (void) sigemptyset(&sa.sa_mask); 6737c478bd9Sstevel@tonic-gate (void) sigaction(SIGTERM, &sa, NULL); 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate /* 6767c478bd9Sstevel@tonic-gate * catch SIGHUP cause it might be coming from a disconnect 6777c478bd9Sstevel@tonic-gate */ 6787c478bd9Sstevel@tonic-gate sa.sa_handler = catch_hup; 6797c478bd9Sstevel@tonic-gate sa.sa_flags = 0; 6807c478bd9Sstevel@tonic-gate (void) sigemptyset(&sa.sa_mask); 6817c478bd9Sstevel@tonic-gate (void) sigaction(SIGHUP, &sa, NULL); 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate if ((sysmfd = safeopen(SYSMSG)) < 0) 6847c478bd9Sstevel@tonic-gate die(gettext("%s is missing or not a valid device\n"), SYSMSG); 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate if ((bufsize = ioctl(sysmfd, CIOCGETCONSOLE, NULL)) < 0) 6877c478bd9Sstevel@tonic-gate die(gettext("cannot get table entry\n")); 6887c478bd9Sstevel@tonic-gate if (bufsize == 0) 6897c478bd9Sstevel@tonic-gate return; 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate if ((infop = calloc(bufsize, sizeof (char))) == NULL) 6927c478bd9Sstevel@tonic-gate die(gettext("cannot allocate buffer")); 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate if (ioctl(sysmfd, CIOCGETCONSOLE, infop) < 0) 6957c478bd9Sstevel@tonic-gate die(gettext("cannot get table entry\n")); 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate ptr = infop; 6987c478bd9Sstevel@tonic-gate while (ptr != NULL) { 6997c478bd9Sstevel@tonic-gate p = strchr(ptr, ' '); 7007c478bd9Sstevel@tonic-gate if (p == NULL) { 7017c478bd9Sstevel@tonic-gate cachesize++; 7027c478bd9Sstevel@tonic-gate break; 7037c478bd9Sstevel@tonic-gate } 7047c478bd9Sstevel@tonic-gate p++; 7057c478bd9Sstevel@tonic-gate cachesize++; 7067c478bd9Sstevel@tonic-gate ptr = p; 7077c478bd9Sstevel@tonic-gate } 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate if ((fds = calloc(cachesize, sizeof (struct pollfd))) == NULL) 7107c478bd9Sstevel@tonic-gate die(gettext("cannot allocate buffer")); 7117c478bd9Sstevel@tonic-gate 7127c478bd9Sstevel@tonic-gate if ((devpaths = calloc(cachesize, sizeof (char *))) == NULL) 7137c478bd9Sstevel@tonic-gate die(gettext("cannot allocate buffer")); 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate ptr = infop; 7167c478bd9Sstevel@tonic-gate while (ptr != NULL) { 7177c478bd9Sstevel@tonic-gate p = strchr(ptr, ' '); 7187c478bd9Sstevel@tonic-gate if (p == NULL) { 7197c478bd9Sstevel@tonic-gate if ((fd = safeopen(ptr)) < 0) { 7207c478bd9Sstevel@tonic-gate warn(gettext("cannot open %s, continuing"), 7217c478bd9Sstevel@tonic-gate ptr); 7227c478bd9Sstevel@tonic-gate break; 7237c478bd9Sstevel@tonic-gate } 7247c478bd9Sstevel@tonic-gate if (!has_carrier(fd)) { 7257c478bd9Sstevel@tonic-gate (void) close(fd); 7267c478bd9Sstevel@tonic-gate warn(gettext( 7277c478bd9Sstevel@tonic-gate "no carrier on %s, device will not be monitored.\n"), 7287c478bd9Sstevel@tonic-gate ptr); 7297c478bd9Sstevel@tonic-gate break; 7307c478bd9Sstevel@tonic-gate } else { 7317c478bd9Sstevel@tonic-gate fds[nfds].fd = fd; 7327c478bd9Sstevel@tonic-gate fds[nfds].events = 0; 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate if ((devpaths[nfds] = 7357c478bd9Sstevel@tonic-gate malloc(strlen(ptr) + 1)) == NULL) 7367c478bd9Sstevel@tonic-gate die(gettext("cannot allocate buffer")); 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate (void) strcpy(devpaths[nfds], ptr); 7397c478bd9Sstevel@tonic-gate nfds++; 7407c478bd9Sstevel@tonic-gate if (nfds >= cachesize) 7417c478bd9Sstevel@tonic-gate break; 7427c478bd9Sstevel@tonic-gate } 7437c478bd9Sstevel@tonic-gate break; 7447c478bd9Sstevel@tonic-gate } 7457c478bd9Sstevel@tonic-gate *p++ = '\0'; 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate if ((fd = safeopen(ptr)) < 0) { 7487c478bd9Sstevel@tonic-gate warn(gettext("cannot open %s, continuing"), ptr); 7497c478bd9Sstevel@tonic-gate ptr = p; 7507c478bd9Sstevel@tonic-gate continue; 7517c478bd9Sstevel@tonic-gate } 7527c478bd9Sstevel@tonic-gate if (!has_carrier(fd)) { 7537c478bd9Sstevel@tonic-gate (void) close(fd); 7547c478bd9Sstevel@tonic-gate warn(gettext( 7557c478bd9Sstevel@tonic-gate "no carrier on %s, device will not be monitored.\n"), 7567c478bd9Sstevel@tonic-gate ptr); 7577c478bd9Sstevel@tonic-gate ptr = p; 7587c478bd9Sstevel@tonic-gate continue; 7597c478bd9Sstevel@tonic-gate } else { 7607c478bd9Sstevel@tonic-gate fds[nfds].fd = fd; 7617c478bd9Sstevel@tonic-gate fds[nfds].events = 0; 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate if ((devpaths[nfds] = malloc(strlen(ptr) + 1)) == NULL) 7647c478bd9Sstevel@tonic-gate die(gettext("cannot allocate buffer")); 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate (void) strcpy(devpaths[nfds], ptr); 7677c478bd9Sstevel@tonic-gate nfds++; 7687c478bd9Sstevel@tonic-gate if (nfds >= cachesize) 7697c478bd9Sstevel@tonic-gate break; 7707c478bd9Sstevel@tonic-gate } 7717c478bd9Sstevel@tonic-gate ptr = p; 7727c478bd9Sstevel@tonic-gate } 7737c478bd9Sstevel@tonic-gate (void) close(sysmfd); 7747c478bd9Sstevel@tonic-gate 7757c478bd9Sstevel@tonic-gate /* no point polling if no devices with carrier */ 7767c478bd9Sstevel@tonic-gate if (nfds == 0) 7777c478bd9Sstevel@tonic-gate return; 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate for (;;) { 7807c478bd9Sstevel@tonic-gate /* daemon sleeps waiting for a hangup on the console */ 7817c478bd9Sstevel@tonic-gate ret = poll(fds, nfds, INFTIM); 7827c478bd9Sstevel@tonic-gate if (ret == -1) { 7837c478bd9Sstevel@tonic-gate /* Check if ttymon is trying to get rid of us */ 7847c478bd9Sstevel@tonic-gate if (errno == EINTR) 7857c478bd9Sstevel@tonic-gate continue; 7867c478bd9Sstevel@tonic-gate warn(gettext("cannot poll device")); 7877c478bd9Sstevel@tonic-gate return; 7887c478bd9Sstevel@tonic-gate } else if (ret == 0) { 7897c478bd9Sstevel@tonic-gate warn(gettext("timeout (%d milleseconds) occured\n"), 7907c478bd9Sstevel@tonic-gate INFTIM); 7917c478bd9Sstevel@tonic-gate return; 7927c478bd9Sstevel@tonic-gate } else { 7937c478bd9Sstevel@tonic-gate /* Go through poll list looking for events. */ 7947c478bd9Sstevel@tonic-gate for (index = 0; index < nfds; index++) { 7957c478bd9Sstevel@tonic-gate /* expected result */ 7967c478bd9Sstevel@tonic-gate if ((fds[index].revents & POLLHUP) == 7977c478bd9Sstevel@tonic-gate POLLHUP) { 7987c478bd9Sstevel@tonic-gate /* 7997c478bd9Sstevel@tonic-gate * unsetaux console. Take out of list 8007c478bd9Sstevel@tonic-gate * of current auxiliary consoles. 8017c478bd9Sstevel@tonic-gate */ 8027c478bd9Sstevel@tonic-gate unsetaux((char *)devpaths[index]); 8037c478bd9Sstevel@tonic-gate warn(gettext( 8047c478bd9Sstevel@tonic-gate "lost carrier, unsetting console %s\n"), 8057c478bd9Sstevel@tonic-gate devpaths[index]); 8067c478bd9Sstevel@tonic-gate syslog(LOG_WARNING, 8077c478bd9Sstevel@tonic-gate "%s: lost carrier, unsetting auxiliary device %s", 8087c478bd9Sstevel@tonic-gate CONSADM, devpaths[index]); 8097c478bd9Sstevel@tonic-gate free(devpaths[index]); 8107c478bd9Sstevel@tonic-gate devpaths[index] = NULL; 8117c478bd9Sstevel@tonic-gate (void) close(fds[index].fd); 8127c478bd9Sstevel@tonic-gate fds[index].fd = -1; 8137c478bd9Sstevel@tonic-gate fds[index].revents = 0; 8147c478bd9Sstevel@tonic-gate continue; 8157c478bd9Sstevel@tonic-gate } 8167c478bd9Sstevel@tonic-gate if ((fds[index].revents & POLLERR) == 8177c478bd9Sstevel@tonic-gate POLLERR) { 8187c478bd9Sstevel@tonic-gate warn(gettext("poll error\n")); 8197c478bd9Sstevel@tonic-gate continue; 8207c478bd9Sstevel@tonic-gate } else if (fds[index].revents != 0) { 8217c478bd9Sstevel@tonic-gate warn(gettext( 8227c478bd9Sstevel@tonic-gate "unexpected poll result 0x%x\n"), 8237c478bd9Sstevel@tonic-gate fds[index].revents); 8247c478bd9Sstevel@tonic-gate continue; 8257c478bd9Sstevel@tonic-gate } 8267c478bd9Sstevel@tonic-gate } 8277c478bd9Sstevel@tonic-gate /* check whether any left to poll */ 8287c478bd9Sstevel@tonic-gate pollagain = B_FALSE; 8297c478bd9Sstevel@tonic-gate for (index = 0; index < nfds; index++) 8307c478bd9Sstevel@tonic-gate if (fds[index].fd != -1) 8317c478bd9Sstevel@tonic-gate pollagain = B_TRUE; 8327c478bd9Sstevel@tonic-gate if (pollagain == B_TRUE) 8337c478bd9Sstevel@tonic-gate continue; 8347c478bd9Sstevel@tonic-gate else 8357c478bd9Sstevel@tonic-gate return; 8367c478bd9Sstevel@tonic-gate } 8377c478bd9Sstevel@tonic-gate } 8387c478bd9Sstevel@tonic-gate } 8397c478bd9Sstevel@tonic-gate 8407c478bd9Sstevel@tonic-gate static void 8417c478bd9Sstevel@tonic-gate persistlist(void) 8427c478bd9Sstevel@tonic-gate { 8437c478bd9Sstevel@tonic-gate FILE *fp; 8447c478bd9Sstevel@tonic-gate char value[MAXPATHLEN + 1]; 8457c478bd9Sstevel@tonic-gate int lckfd; 8467c478bd9Sstevel@tonic-gate 8477c478bd9Sstevel@tonic-gate lckfd = getlock(); 8487c478bd9Sstevel@tonic-gate 8497c478bd9Sstevel@tonic-gate if ((fp = fopen(CONSCONFIG, "r")) != NULL) { 8507c478bd9Sstevel@tonic-gate while (fgets(value, MAXPATHLEN, fp) != NULL) { 8517c478bd9Sstevel@tonic-gate /* skip comments */ 8527c478bd9Sstevel@tonic-gate if (value[0] == COMMENT || 8537c478bd9Sstevel@tonic-gate value[0] == NEWLINE || 8547c478bd9Sstevel@tonic-gate value[0] == SPACE || value[0] == TAB) 8557c478bd9Sstevel@tonic-gate continue; 8567c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%s", value); 8577c478bd9Sstevel@tonic-gate } 8587c478bd9Sstevel@tonic-gate (void) fclose(fp); 8597c478bd9Sstevel@tonic-gate } 8607c478bd9Sstevel@tonic-gate (void) close(lckfd); 8617c478bd9Sstevel@tonic-gate (void) unlink(CONSADMLOCK); 8627c478bd9Sstevel@tonic-gate } 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate static int 8657c478bd9Sstevel@tonic-gate verifyarg(char *dev, int flag) 8667c478bd9Sstevel@tonic-gate { 8677c478bd9Sstevel@tonic-gate struct stat st; 8687c478bd9Sstevel@tonic-gate int fd; 8697c478bd9Sstevel@tonic-gate int ret = 0; 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate if (dev == NULL) { 8727c478bd9Sstevel@tonic-gate warn(gettext("specify device(s)\n")); 8737c478bd9Sstevel@tonic-gate ret = 1; 8747c478bd9Sstevel@tonic-gate goto err_exit; 8757c478bd9Sstevel@tonic-gate } 8767c478bd9Sstevel@tonic-gate 8777c478bd9Sstevel@tonic-gate if (dev[0] != '/') { 8787c478bd9Sstevel@tonic-gate warn(gettext("device name must begin with a '/'\n")); 8797c478bd9Sstevel@tonic-gate ret = 1; 8807c478bd9Sstevel@tonic-gate goto err_exit; 8817c478bd9Sstevel@tonic-gate } 8827c478bd9Sstevel@tonic-gate 8837c478bd9Sstevel@tonic-gate if ((pathcmp(dev, SYSMSG) == 0) || 8847c478bd9Sstevel@tonic-gate (pathcmp(dev, WSCONS) == 0) || 8857c478bd9Sstevel@tonic-gate (pathcmp(dev, CONSOLE) == 0)) { 8867c478bd9Sstevel@tonic-gate /* they match */ 8877c478bd9Sstevel@tonic-gate warn(gettext("invalid device %s\n"), dev); 8887c478bd9Sstevel@tonic-gate ret = 1; 8897c478bd9Sstevel@tonic-gate goto err_exit; 8907c478bd9Sstevel@tonic-gate } 8917c478bd9Sstevel@tonic-gate 8927c478bd9Sstevel@tonic-gate if (stat(dev, &st) || ! S_ISCHR(st.st_mode)) { 8937c478bd9Sstevel@tonic-gate warn(gettext("invalid device %s\n"), dev); 8947c478bd9Sstevel@tonic-gate ret = 1; 8957c478bd9Sstevel@tonic-gate goto err_exit; 8967c478bd9Sstevel@tonic-gate } 8977c478bd9Sstevel@tonic-gate 8987c478bd9Sstevel@tonic-gate /* Delete operation doesn't require this checking */ 8997c478bd9Sstevel@tonic-gate if ((fd = safeopen(dev)) < 0) { 9007c478bd9Sstevel@tonic-gate if (flag) { 9017c478bd9Sstevel@tonic-gate warn(gettext("invalid device %s\n"), dev); 9027c478bd9Sstevel@tonic-gate ret = 1; 9037c478bd9Sstevel@tonic-gate } 9047c478bd9Sstevel@tonic-gate goto err_exit; 9057c478bd9Sstevel@tonic-gate } 9067c478bd9Sstevel@tonic-gate if (!modem_support(fd)) { 9077c478bd9Sstevel@tonic-gate warn(gettext("invalid device %s\n"), dev); 9087c478bd9Sstevel@tonic-gate (void) close(fd); 9097c478bd9Sstevel@tonic-gate ret = 1; 9107c478bd9Sstevel@tonic-gate goto err_exit; 9117c478bd9Sstevel@tonic-gate } 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate /* Only verify carrier if it's an add operation */ 9147c478bd9Sstevel@tonic-gate if (flag) { 9157c478bd9Sstevel@tonic-gate if (!has_carrier(fd)) { 9167c478bd9Sstevel@tonic-gate warn(gettext("failure, no carrier on %s\n"), dev); 9177c478bd9Sstevel@tonic-gate ret = 1; 9187c478bd9Sstevel@tonic-gate goto err_exit; 9197c478bd9Sstevel@tonic-gate } 9207c478bd9Sstevel@tonic-gate } 9217c478bd9Sstevel@tonic-gate err_exit: 9227c478bd9Sstevel@tonic-gate return (ret); 9237c478bd9Sstevel@tonic-gate } 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate /* 9267c478bd9Sstevel@tonic-gate * Open the pseudo device, but be prepared to catch sigalarm if we block 9277c478bd9Sstevel@tonic-gate * cause there isn't any carrier present. 9287c478bd9Sstevel@tonic-gate */ 9297c478bd9Sstevel@tonic-gate static int 9307c478bd9Sstevel@tonic-gate safeopen(char *devp) 9317c478bd9Sstevel@tonic-gate { 9327c478bd9Sstevel@tonic-gate int fd; 9337c478bd9Sstevel@tonic-gate struct sigaction sigact; 9347c478bd9Sstevel@tonic-gate 9357c478bd9Sstevel@tonic-gate sigact.sa_flags = SA_RESETHAND | SA_NODEFER; 9367c478bd9Sstevel@tonic-gate sigact.sa_handler = catch_alarm; 9377c478bd9Sstevel@tonic-gate (void) sigemptyset(&sigact.sa_mask); 9387c478bd9Sstevel@tonic-gate (void) sigaction(SIGALRM, &sigact, NULL); 9397c478bd9Sstevel@tonic-gate if (sigsetjmp(deadline, 1) != 0) 9407c478bd9Sstevel@tonic-gate return (-1); 9417c478bd9Sstevel@tonic-gate (void) alarm(5); 9427c478bd9Sstevel@tonic-gate /* The sysmsg driver sets NONBLOCK and NDELAY, but what the hell */ 9437c478bd9Sstevel@tonic-gate if ((fd = open(devp, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY)) < 0) 9447c478bd9Sstevel@tonic-gate return (-1); 9457c478bd9Sstevel@tonic-gate (void) alarm(0); 9467c478bd9Sstevel@tonic-gate sigact.sa_flags = 0; 9477c478bd9Sstevel@tonic-gate sigact.sa_handler = SIG_DFL; 9487c478bd9Sstevel@tonic-gate (void) sigemptyset(&sigact.sa_mask); 9497c478bd9Sstevel@tonic-gate (void) sigaction(SIGALRM, &sigact, NULL); 9507c478bd9Sstevel@tonic-gate return (fd); 9517c478bd9Sstevel@tonic-gate } 9527c478bd9Sstevel@tonic-gate 9537c478bd9Sstevel@tonic-gate static int 9547c478bd9Sstevel@tonic-gate lckfunc(int fd, int flag) 9557c478bd9Sstevel@tonic-gate { 9567c478bd9Sstevel@tonic-gate fl.l_type = flag; 9577c478bd9Sstevel@tonic-gate return (fcntl(fd, F_SETLKW, &fl)); 9587c478bd9Sstevel@tonic-gate } 959