10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*1253Slq150181 * Common Development and Distribution License (the "License"). 6*1253Slq150181 * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 21*1253Slq150181 220Sstevel@tonic-gate /* 23*1253Slq150181 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 270Sstevel@tonic-gate /* All Rights Reserved */ 280Sstevel@tonic-gate 290Sstevel@tonic-gate 300Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 310Sstevel@tonic-gate 320Sstevel@tonic-gate #include <stdio.h> 330Sstevel@tonic-gate #include <stdlib.h> 340Sstevel@tonic-gate #include <unistd.h> 350Sstevel@tonic-gate #include <fcntl.h> 360Sstevel@tonic-gate #include <errno.h> 370Sstevel@tonic-gate #include <ctype.h> 380Sstevel@tonic-gate #include <string.h> 390Sstevel@tonic-gate #include <signal.h> 400Sstevel@tonic-gate #include <sys/stat.h> 410Sstevel@tonic-gate #include <utmpx.h> 420Sstevel@tonic-gate #include <pwd.h> 430Sstevel@tonic-gate #include <dirent.h> 440Sstevel@tonic-gate #include <sys/param.h> 450Sstevel@tonic-gate #include <sys/acl.h> 46*1253Slq150181 #include <sys/stat.h> 47*1253Slq150181 #include <sys/types.h> 48*1253Slq150181 #include <sys/console.h> 490Sstevel@tonic-gate #include "ttymon.h" 500Sstevel@tonic-gate #include "tmextern.h" 510Sstevel@tonic-gate #include "tmstruct.h" 520Sstevel@tonic-gate 530Sstevel@tonic-gate static char devbuf[BUFSIZ]; 540Sstevel@tonic-gate static char *devname; 550Sstevel@tonic-gate 560Sstevel@tonic-gate static int parse_args(); 570Sstevel@tonic-gate static void ttymon_options(); 580Sstevel@tonic-gate static void getty_options(); 590Sstevel@tonic-gate static void usage(); 600Sstevel@tonic-gate static char *find_ttyname(); 610Sstevel@tonic-gate 620Sstevel@tonic-gate extern void tmchild(); 630Sstevel@tonic-gate extern int vml(); 640Sstevel@tonic-gate 650Sstevel@tonic-gate void revokedevaccess(char *, uid_t, gid_t, mode_t); 660Sstevel@tonic-gate /* cannot include libdevinfo.h */ 670Sstevel@tonic-gate extern int di_devperm_logout(const char *); 680Sstevel@tonic-gate 690Sstevel@tonic-gate /* 700Sstevel@tonic-gate * ttymon_express - This is call when ttymon is invoked with args 710Sstevel@tonic-gate * or invoked as getty 720Sstevel@tonic-gate * - This special version of ttymon will monitor 730Sstevel@tonic-gate * one port only 740Sstevel@tonic-gate * - It is intended to be used when some process 750Sstevel@tonic-gate * wants to have a login session on the fly 760Sstevel@tonic-gate */ 770Sstevel@tonic-gate void 780Sstevel@tonic-gate ttymon_express(int argc, char **argv) 790Sstevel@tonic-gate { 800Sstevel@tonic-gate struct pmtab *pmtab; 810Sstevel@tonic-gate struct sigaction sigact; 820Sstevel@tonic-gate extern int Retry; 830Sstevel@tonic-gate extern void open_device(); 840Sstevel@tonic-gate extern void read_ttydefs(); 850Sstevel@tonic-gate extern int checkut_line(); 860Sstevel@tonic-gate #ifdef DEBUG 870Sstevel@tonic-gate extern FILE *Debugfp; 880Sstevel@tonic-gate extern void opendebug(); 890Sstevel@tonic-gate #endif 900Sstevel@tonic-gate 910Sstevel@tonic-gate #ifdef DEBUG 920Sstevel@tonic-gate opendebug(TRUE); 930Sstevel@tonic-gate #endif 940Sstevel@tonic-gate 950Sstevel@tonic-gate sigact.sa_flags = 0; 960Sstevel@tonic-gate sigact.sa_handler = SIG_IGN; 970Sstevel@tonic-gate (void) sigemptyset(&sigact.sa_mask); 980Sstevel@tonic-gate (void) sigaction(SIGINT, &sigact, NULL); 990Sstevel@tonic-gate 1000Sstevel@tonic-gate if ((pmtab = ALLOC_PMTAB) == PNULL) { 1010Sstevel@tonic-gate log("ttymon_express: ALLOC_PMTAB failed"); 1020Sstevel@tonic-gate exit(1); 1030Sstevel@tonic-gate } 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate if (parse_args(argc, argv, pmtab) != 0) { 1060Sstevel@tonic-gate log("ttymon_express: parse_args failed"); 1070Sstevel@tonic-gate exit(1); 1080Sstevel@tonic-gate } 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate read_ttydefs(NULL, FALSE); 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate if ((pmtab->p_device != NULL) && (*(pmtab->p_device) != '\0') && 1130Sstevel@tonic-gate strcmp(pmtab->p_device, "/dev/console") == 0) { 1140Sstevel@tonic-gate while (checkut_line(pmtab->p_device)) 1150Sstevel@tonic-gate sleep(15); 1160Sstevel@tonic-gate } 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate if ((pmtab->p_device == NULL) || (*(pmtab->p_device) == '\0')) { 1190Sstevel@tonic-gate devname = find_ttyname(0); 1200Sstevel@tonic-gate if ((devname == NULL) || (*devname == '\0')) { 1210Sstevel@tonic-gate log("ttyname cannot find the device on fd 0"); 1220Sstevel@tonic-gate exit(1); 1230Sstevel@tonic-gate } 1240Sstevel@tonic-gate pmtab->p_device = devname; 1250Sstevel@tonic-gate #ifdef DEBUG 1260Sstevel@tonic-gate debug("ttymon_express: devname = %s", devname); 1270Sstevel@tonic-gate #endif 1280Sstevel@tonic-gate /* 1290Sstevel@tonic-gate * become session leader 1300Sstevel@tonic-gate * fd 0 is closed and reopened just to make sure 1310Sstevel@tonic-gate * controlling tty is set up right 1320Sstevel@tonic-gate */ 1330Sstevel@tonic-gate (void) setsid(); 1340Sstevel@tonic-gate (void) close(0); 1350Sstevel@tonic-gate revokedevaccess(pmtab->p_device, 0, 0, 0); 1360Sstevel@tonic-gate if (open(pmtab->p_device, O_RDWR) < 0) { 1370Sstevel@tonic-gate log("open %s failed: %s", pmtab->p_device, 1380Sstevel@tonic-gate strerror(errno)); 1390Sstevel@tonic-gate exit(1); 1400Sstevel@tonic-gate } 1410Sstevel@tonic-gate if ((pmtab->p_modules != NULL) && 1420Sstevel@tonic-gate (*(pmtab->p_modules) != '\0')) { 1430Sstevel@tonic-gate if (push_linedisc(0, pmtab->p_modules, 1440Sstevel@tonic-gate pmtab->p_device) == -1) 1450Sstevel@tonic-gate exit(1); 1460Sstevel@tonic-gate } 1470Sstevel@tonic-gate if (initial_termio(0, pmtab) == -1) 1480Sstevel@tonic-gate exit(1); 1490Sstevel@tonic-gate di_devperm_logout((const char *)pmtab->p_device); 1500Sstevel@tonic-gate } else { 1510Sstevel@tonic-gate (void) setsid(); 1520Sstevel@tonic-gate (void) close(0); 1530Sstevel@tonic-gate Retry = FALSE; 1540Sstevel@tonic-gate open_device(pmtab); 1550Sstevel@tonic-gate if (Retry) /* open failed */ 1560Sstevel@tonic-gate exit(1); 1570Sstevel@tonic-gate } 1580Sstevel@tonic-gate tmchild(pmtab); 1590Sstevel@tonic-gate exit(1); /*NOTREACHED*/ 1600Sstevel@tonic-gate } 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate /* 1630Sstevel@tonic-gate * parse_arg - parse cmd line arguments 1640Sstevel@tonic-gate */ 1650Sstevel@tonic-gate static int 1660Sstevel@tonic-gate parse_args(int argc, char **argv, struct pmtab *pmtab) 1670Sstevel@tonic-gate { 1680Sstevel@tonic-gate static char p_server[] = "/usr/bin/login"; 1690Sstevel@tonic-gate extern char *lastname(); 1700Sstevel@tonic-gate extern void getty_account(); 171*1253Slq150181 static char termbuf[MAX_TERM_TYPE_LEN]; 172*1253Slq150181 static struct cons_getterm cnterm = {sizeof (termbuf), termbuf}; 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate /* initialize fields to some default first */ 1750Sstevel@tonic-gate pmtab->p_tag = ""; 1760Sstevel@tonic-gate pmtab->p_flags = 0; 1770Sstevel@tonic-gate pmtab->p_identity = "root"; 1780Sstevel@tonic-gate pmtab->p_res1 = "reserved"; 1790Sstevel@tonic-gate pmtab->p_res2 = "reserved"; 1800Sstevel@tonic-gate pmtab->p_res3 = "reserved"; 1810Sstevel@tonic-gate pmtab->p_uid = 0; 1820Sstevel@tonic-gate pmtab->p_gid = 0; 1830Sstevel@tonic-gate pmtab->p_dir = "/"; 1840Sstevel@tonic-gate pmtab->p_ttyflags = 0; 1850Sstevel@tonic-gate pmtab->p_count = 0; 1860Sstevel@tonic-gate pmtab->p_server = p_server; 1870Sstevel@tonic-gate pmtab->p_timeout = 0; 1880Sstevel@tonic-gate pmtab->p_modules = ""; 1890Sstevel@tonic-gate pmtab->p_prompt = "login: "; 1900Sstevel@tonic-gate pmtab->p_dmsg = ""; 1910Sstevel@tonic-gate pmtab->p_termtype = ""; 1920Sstevel@tonic-gate pmtab->p_device = ""; 1930Sstevel@tonic-gate pmtab->p_status = GETTY; 1940Sstevel@tonic-gate if (strcmp(lastname(argv[0]), "getty") == 0) { 1950Sstevel@tonic-gate pmtab->p_ttylabel = "300"; 1960Sstevel@tonic-gate getty_options(argc, argv, pmtab); 1970Sstevel@tonic-gate } else { 198*1253Slq150181 int cn_fd; 199*1253Slq150181 2000Sstevel@tonic-gate pmtab->p_ttylabel = "9600"; 2010Sstevel@tonic-gate ttymon_options(argc, argv, pmtab); 202*1253Slq150181 203*1253Slq150181 /* 204*1253Slq150181 * The following code is only reached if -g was specified. 205*1253Slq150181 * It attempts to determine a suitable terminal type for 206*1253Slq150181 * the console login process. 207*1253Slq150181 * 208*1253Slq150181 * If -d /dev/console also specified, we send an ioctl 209*1253Slq150181 * to the console device to query the TERM type. 210*1253Slq150181 * 211*1253Slq150181 * If any of the tests, system calls, or ioctls fail 212*1253Slq150181 * then pmtab->p_termtype retains its default value 213*1253Slq150181 * of "". otherwise it is set to a term type value 214*1253Slq150181 * that was returned. 215*1253Slq150181 */ 216*1253Slq150181 if ((strlen(pmtab->p_termtype) == 0) && 217*1253Slq150181 (strcmp(pmtab->p_device, "/dev/console") == 0) && 218*1253Slq150181 ((cn_fd = open("/dev/console", O_RDONLY)) != -1)) { 219*1253Slq150181 220*1253Slq150181 if (ioctl(cn_fd, CONS_GETTERM, &cnterm) != -1) 221*1253Slq150181 pmtab->p_termtype = cnterm.cn_term_type; 222*1253Slq150181 (void) close(cn_fd); 223*1253Slq150181 } 2240Sstevel@tonic-gate } 225*1253Slq150181 2260Sstevel@tonic-gate if ((pmtab->p_device != NULL) && (*(pmtab->p_device) != '\0')) 2270Sstevel@tonic-gate getty_account(pmtab->p_device); /* utmp accounting */ 2280Sstevel@tonic-gate return (0); 2290Sstevel@tonic-gate } 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate /* 2330Sstevel@tonic-gate * ttymon_options - scan and check args for ttymon express 2340Sstevel@tonic-gate */ 2350Sstevel@tonic-gate 2360Sstevel@tonic-gate static void 2370Sstevel@tonic-gate ttymon_options(int argc, char **argv, struct pmtab *pmtab) 2380Sstevel@tonic-gate { 2390Sstevel@tonic-gate int c; /* option letter */ 2400Sstevel@tonic-gate char *timeout; 2410Sstevel@tonic-gate int gflag = 0; /* -g seen */ 2420Sstevel@tonic-gate int size = 0; 2430Sstevel@tonic-gate char tbuf[BUFSIZ]; 2440Sstevel@tonic-gate 2450Sstevel@tonic-gate extern char *optarg; 2460Sstevel@tonic-gate extern int optind; 2470Sstevel@tonic-gate extern void copystr(); 2480Sstevel@tonic-gate extern char *strsave(); 2490Sstevel@tonic-gate extern char *getword(); 2500Sstevel@tonic-gate 2510Sstevel@tonic-gate while ((c = getopt(argc, argv, "T:gd:ht:p:m:l:")) != -1) { 2520Sstevel@tonic-gate switch (c) { 2530Sstevel@tonic-gate case 'g': 2540Sstevel@tonic-gate gflag = 1; 2550Sstevel@tonic-gate break; 2560Sstevel@tonic-gate case 'd': 2570Sstevel@tonic-gate pmtab->p_device = optarg; 2580Sstevel@tonic-gate break; 2590Sstevel@tonic-gate case 'h': 2600Sstevel@tonic-gate pmtab->p_ttyflags &= ~H_FLAG; 2610Sstevel@tonic-gate break; 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate case 'T': 2640Sstevel@tonic-gate pmtab->p_termtype = optarg; 2650Sstevel@tonic-gate break; 2660Sstevel@tonic-gate /* 2670Sstevel@tonic-gate * case 'b': 2680Sstevel@tonic-gate * pmtab->p_ttyflags |= B_FLAG; 2690Sstevel@tonic-gate * pmtab->p_ttyflags |= R_FLAG; 2700Sstevel@tonic-gate * break; 2710Sstevel@tonic-gate */ 2720Sstevel@tonic-gate case 't': 2730Sstevel@tonic-gate timeout = optarg; 2740Sstevel@tonic-gate while (*optarg) { 2750Sstevel@tonic-gate if (!isdigit(*optarg++)) { 2760Sstevel@tonic-gate log("Invalid argument for " 2770Sstevel@tonic-gate "\"-t\" -- number expected."); 2780Sstevel@tonic-gate usage(); 2790Sstevel@tonic-gate } 2800Sstevel@tonic-gate } 2810Sstevel@tonic-gate pmtab->p_timeout = atoi(timeout); 2820Sstevel@tonic-gate break; 2830Sstevel@tonic-gate case 'p': 2840Sstevel@tonic-gate copystr(tbuf, optarg); 2850Sstevel@tonic-gate pmtab->p_prompt = strsave(getword(tbuf, &size, TRUE)); 2860Sstevel@tonic-gate break; 2870Sstevel@tonic-gate case 'm': 2880Sstevel@tonic-gate pmtab->p_modules = optarg; 2890Sstevel@tonic-gate if (vml(pmtab->p_modules) != 0) 2900Sstevel@tonic-gate usage(); 2910Sstevel@tonic-gate break; 2920Sstevel@tonic-gate case 'l': 2930Sstevel@tonic-gate pmtab->p_ttylabel = optarg; 2940Sstevel@tonic-gate break; 2950Sstevel@tonic-gate case '?': 2960Sstevel@tonic-gate usage(); 2970Sstevel@tonic-gate break; /*NOTREACHED*/ 2980Sstevel@tonic-gate } 2990Sstevel@tonic-gate } 3000Sstevel@tonic-gate if (optind < argc) 3010Sstevel@tonic-gate usage(); 3020Sstevel@tonic-gate 3030Sstevel@tonic-gate if (!gflag) 3040Sstevel@tonic-gate usage(); 3050Sstevel@tonic-gate } 3060Sstevel@tonic-gate 3070Sstevel@tonic-gate /* 3080Sstevel@tonic-gate * usage - print out a usage message 3090Sstevel@tonic-gate */ 3100Sstevel@tonic-gate 3110Sstevel@tonic-gate static void 3120Sstevel@tonic-gate usage() 3130Sstevel@tonic-gate { 3140Sstevel@tonic-gate char *umsg = "Usage: ttymon\n ttymon -g [-h] [-d device] " 3150Sstevel@tonic-gate "[-l ttylabel] [-t timeout] [-p prompt] [-m modules]\n"; 3160Sstevel@tonic-gate 3170Sstevel@tonic-gate if (isatty(STDERR_FILENO)) 3180Sstevel@tonic-gate (void) fprintf(stderr, "%s", umsg); 3190Sstevel@tonic-gate else 3200Sstevel@tonic-gate cons_printf(umsg); 3210Sstevel@tonic-gate exit(1); 3220Sstevel@tonic-gate } 3230Sstevel@tonic-gate 3240Sstevel@tonic-gate /* 3250Sstevel@tonic-gate * getty_options - this is cut from getty.c 3260Sstevel@tonic-gate * - it scan getty cmd args 3270Sstevel@tonic-gate * - modification is made to stuff args in pmtab 3280Sstevel@tonic-gate */ 3290Sstevel@tonic-gate static void 3300Sstevel@tonic-gate getty_options(argc, argv, pmtab) 3310Sstevel@tonic-gate int argc; 3320Sstevel@tonic-gate char **argv; 3330Sstevel@tonic-gate struct pmtab *pmtab; 3340Sstevel@tonic-gate { 3350Sstevel@tonic-gate char *ptr; 3360Sstevel@tonic-gate 3370Sstevel@tonic-gate /* 3380Sstevel@tonic-gate * the pre-4.0 getty's hang_up_line() is a no-op. 3390Sstevel@tonic-gate * For compatibility, H_FLAG cannot be set for this "getty". 3400Sstevel@tonic-gate */ 3410Sstevel@tonic-gate pmtab->p_ttyflags &= ~(H_FLAG); 3420Sstevel@tonic-gate 3430Sstevel@tonic-gate while (--argc && **++argv == '-') { 3440Sstevel@tonic-gate for (ptr = *argv + 1; *ptr; ptr++) 3450Sstevel@tonic-gate switch (*ptr) { 3460Sstevel@tonic-gate case 'h': 3470Sstevel@tonic-gate break; 3480Sstevel@tonic-gate case 't': 3490Sstevel@tonic-gate if (isdigit(*++ptr)) { 3500Sstevel@tonic-gate (void) sscanf(ptr, "%d", &(pmtab->p_timeout)); 3510Sstevel@tonic-gate while (isdigit(*++ptr)); 3520Sstevel@tonic-gate ptr--; 3530Sstevel@tonic-gate } else if (--argc) { 3540Sstevel@tonic-gate if (isdigit(*(ptr = *++argv))) 3550Sstevel@tonic-gate (void) sscanf(ptr, "%d", 3560Sstevel@tonic-gate &(pmtab->p_timeout)); 3570Sstevel@tonic-gate else { 3580Sstevel@tonic-gate log("getty: timeout argument <%s> " 3590Sstevel@tonic-gate "invalid", *argv); 3600Sstevel@tonic-gate exit(1); 3610Sstevel@tonic-gate } 3620Sstevel@tonic-gate } 3630Sstevel@tonic-gate break; 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate case 'c': 3660Sstevel@tonic-gate log("Use \"sttydefs -l\" to check /etc/ttydefs."); 3670Sstevel@tonic-gate exit(0); 3680Sstevel@tonic-gate default: 3690Sstevel@tonic-gate break; 3700Sstevel@tonic-gate } 3710Sstevel@tonic-gate } 3720Sstevel@tonic-gate 3730Sstevel@tonic-gate if (argc < 1) { 3740Sstevel@tonic-gate log("getty: no terminal line specified."); 3750Sstevel@tonic-gate exit(1); 3760Sstevel@tonic-gate } else { 3770Sstevel@tonic-gate (void) strcat(devbuf, "/dev/"); 3780Sstevel@tonic-gate (void) strcat(devbuf, *argv); 3790Sstevel@tonic-gate pmtab->p_device = devbuf; 3800Sstevel@tonic-gate } 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate if (--argc > 0) { 3830Sstevel@tonic-gate pmtab->p_ttylabel = *++argv; 3840Sstevel@tonic-gate } 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate /* 3870Sstevel@tonic-gate * every thing after this will be ignored 3880Sstevel@tonic-gate * i.e. termtype and linedisc are ignored 3890Sstevel@tonic-gate */ 3900Sstevel@tonic-gate } 3910Sstevel@tonic-gate 3920Sstevel@tonic-gate /* 3930Sstevel@tonic-gate * find_ttyname(fd) - find the name of device associated with fd. 3940Sstevel@tonic-gate * - it first tries utmpx to see if an entry exists 3950Sstevel@tonic-gate * - with my pid and ut_line is defined. If ut_line 3960Sstevel@tonic-gate * - is defined, it will see if the major and minor 3970Sstevel@tonic-gate * - number of fd and devname from utmpx match. 3980Sstevel@tonic-gate * - If utmpx search fails, ttyname(fd) will be called. 3990Sstevel@tonic-gate */ 4000Sstevel@tonic-gate static char * 4010Sstevel@tonic-gate find_ttyname(fd) 4020Sstevel@tonic-gate int fd; 4030Sstevel@tonic-gate { 4040Sstevel@tonic-gate pid_t ownpid; 4050Sstevel@tonic-gate struct utmpx *u; 4060Sstevel@tonic-gate static struct stat statf, statu; 4070Sstevel@tonic-gate static char buf[BUFSIZ]; 4080Sstevel@tonic-gate 4090Sstevel@tonic-gate ownpid = getpid(); 4100Sstevel@tonic-gate setutxent(); 4110Sstevel@tonic-gate while ((u = getutxent()) != NULL) { 4120Sstevel@tonic-gate if (u->ut_pid == ownpid) { 4130Sstevel@tonic-gate if (strlen(u->ut_line) != 0) { 4140Sstevel@tonic-gate if (*(u->ut_line) != '/') { 4150Sstevel@tonic-gate (void) strcpy(buf, "/dev/"); 4160Sstevel@tonic-gate (void) strncat(buf, u->ut_line, 4170Sstevel@tonic-gate sizeof (u->ut_line)); 4180Sstevel@tonic-gate } else { 4190Sstevel@tonic-gate (void) strncat(buf, u->ut_line, 4200Sstevel@tonic-gate sizeof (u->ut_line)); 4210Sstevel@tonic-gate } 4220Sstevel@tonic-gate } 4230Sstevel@tonic-gate else 4240Sstevel@tonic-gate u = NULL; 4250Sstevel@tonic-gate break; 4260Sstevel@tonic-gate } 4270Sstevel@tonic-gate } 4280Sstevel@tonic-gate endutxent(); 4290Sstevel@tonic-gate if ((u != NULL) && 4300Sstevel@tonic-gate (fstat(fd, &statf) == 0) && 4310Sstevel@tonic-gate (stat(buf, &statu) == 0) && 4320Sstevel@tonic-gate (statf.st_dev == statu.st_dev) && 4330Sstevel@tonic-gate (statf.st_rdev == statu.st_rdev)) { 4340Sstevel@tonic-gate #ifdef DEBUG 4350Sstevel@tonic-gate debug("ttymon_express: find device name from utmpx."); 4360Sstevel@tonic-gate #endif 4370Sstevel@tonic-gate return (buf); 4380Sstevel@tonic-gate } else { 4390Sstevel@tonic-gate #ifdef DEBUG 4400Sstevel@tonic-gate debug("ttymon_express: calling ttyname to find device name."); 4410Sstevel@tonic-gate #endif 4420Sstevel@tonic-gate return (ttyname(fd)); 4430Sstevel@tonic-gate } 4440Sstevel@tonic-gate } 4450Sstevel@tonic-gate 4460Sstevel@tonic-gate /* 4470Sstevel@tonic-gate * Revoke all access to a device node and make sure that there are 4480Sstevel@tonic-gate * no interposed streams devices attached. Must be called before a 4490Sstevel@tonic-gate * device is actually opened. 4500Sstevel@tonic-gate * When fdetach is called, the underlying device node is revealed; it 4510Sstevel@tonic-gate * will have the previous owner and that owner can re-attach; so we 4520Sstevel@tonic-gate * retry until we win. 4530Sstevel@tonic-gate * Ignore non-existent devices. 4540Sstevel@tonic-gate */ 4550Sstevel@tonic-gate void 4560Sstevel@tonic-gate revokedevaccess(char *dev, uid_t uid, gid_t gid, mode_t mode) 4570Sstevel@tonic-gate { 4580Sstevel@tonic-gate do { 4590Sstevel@tonic-gate if (chown(dev, uid, gid) == -1) 4600Sstevel@tonic-gate return; 4610Sstevel@tonic-gate } while (fdetach(dev) == 0); 4620Sstevel@tonic-gate 4630Sstevel@tonic-gate /* Remove ACLs */ 4640Sstevel@tonic-gate 465789Sahrens (void) acl_strip(dev, uid, gid, mode); 4660Sstevel@tonic-gate } 467