1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 34 #include <stdlib.h> 35 #include <stdio.h> 36 #include <errno.h> 37 #include <termio.h> 38 #include <sys/stermio.h> 39 #include <sys/termiox.h> 40 #include <string.h> 41 #include <ctype.h> 42 #include <unistd.h> 43 #include <sys/types.h> 44 #include "sys/stropts.h" 45 #include "sys/signal.h" 46 #include "ttymon.h" 47 #include "tmstruct.h" 48 #include "tmextern.h" 49 50 extern void mkargv(); 51 52 /* 53 * set_termio - set termio on device 54 * fd - fd for the device 55 * options - stty termio options 56 * aspeed - autobaud speed 57 * clear - if TRUE, current flags will be set to some defaults 58 * before applying the options 59 * - if FALSE, current flags will not be cleared 60 * mode - terminal mode, CANON, RAW 61 */ 62 63 64 65 int 66 set_termio(fd,options,aspeed,clear,mode) 67 int fd; 68 char *options; 69 char *aspeed; 70 int clear; 71 long mode; 72 { 73 struct termio termio; 74 struct termios termios; 75 struct stio stermio; 76 struct termiox termiox; 77 struct winsize winsize; 78 struct winsize owinsize; 79 int term; 80 int cnt = 1; 81 char *uarg; 82 char *argvp[MAXARGS]; /* stty args */ 83 static char *binstty = "/usr/bin/stty"; 84 static char buf[BUFSIZ]; 85 extern int get_ttymode(), set_ttymode(); 86 extern char *sttyparse(); 87 88 #ifdef DEBUG 89 debug("in set_termio"); 90 #endif 91 92 if ((term = get_ttymode(fd, &termio, &termios, &stermio, 93 &termiox, &winsize)) < 0) { 94 log("set_termio: get_ttymode failed: %s", strerror(errno)); 95 return(-1); 96 } 97 owinsize = winsize; 98 if (clear) { 99 if (mode & CANON) { 100 /* could have removed these too - rely on defaults */ 101 termios.c_cc[VEOF] = CEOF; 102 termios.c_cc[VEOL] = CNUL; 103 } 104 else { 105 termios.c_lflag &= ECHO; 106 termios.c_cc[VMIN] = 1; 107 termios.c_cc[VTIME] = 0; 108 } 109 110 } 111 112 if (options != NULL && *options != '\0') { 113 /* just a place holder to make it look like invoking stty */ 114 argvp[0] = binstty; 115 (void)strcpy(buf,options); 116 mkargv(buf,&argvp[1],&cnt,MAXARGS-1); 117 if (aspeed != NULL && *aspeed != '\0') { 118 argvp[cnt++] = aspeed; 119 } 120 argvp[cnt] = (char *)0; 121 if ((uarg = sttyparse(cnt, argvp, term, &termio, &termios, 122 &termiox, &winsize)) != NULL) { 123 log("sttyparse unknown mode: %s", uarg); 124 return(-1); 125 } 126 } 127 128 129 if (set_ttymode(fd, term, &termio, &termios, &stermio, 130 &termiox, &winsize, &owinsize) != 0) { 131 log("set_termio: set_ttymode failed", strerror(errno)); 132 return(-1); 133 } 134 135 return(0); 136 } 137 138 #ifdef NOT_USE 139 /* 140 * turnon_canon - turn on canonical processing 141 * - return 0 if succeeds, -1 if fails 142 */ 143 turnon_canon(fd) 144 int fd; 145 { 146 struct termio termio; 147 148 #ifdef DEBUG 149 debug("in turnon_canon"); 150 #endif 151 if (ioctl(fd, TCGETA, &termio) != 0) { 152 log("turnon_canon: TCGETA failed, fd = %d: %s", fd, 153 strerror(errno)); 154 return(-1); 155 } 156 termio.c_lflag |= (ISIG|ICANON|ECHO|ECHOE|ECHOK); 157 termio.c_cc[VEOF] = CEOF; 158 termio.c_cc[VEOL] = CNUL; 159 if (ioctl(fd, TCSETA, &termio) != 0) { 160 log("turnon_canon: TCSETA failed, fd = %d: %s", fd, 161 strerror(errno)); 162 return(-1); 163 } 164 return(0); 165 } 166 #endif 167 168 /* 169 * flush_input - flush the input queue 170 */ 171 void 172 flush_input(fd) 173 int fd; 174 { 175 if (ioctl(fd, I_FLUSH, FLUSHR) == -1) 176 log("flush_input failed, fd = %d: %s", fd, strerror(errno)); 177 178 if (ioctl(fd, TCSBRK, 1) == -1) 179 log("drain of ouput failed, fd = %d: %s", fd, strerror(errno)); 180 181 return; 182 } 183 184 /* 185 * push_linedisc - if modules is not NULL, pop everything 186 * - then push modules specified by "modules" 187 */ 188 int 189 push_linedisc( 190 int fd, /* fd to push modules on */ 191 char *modules, /* ptr to a list of comma separated module names */ 192 char *device) /* device name for printing msg */ 193 { 194 char *p, *tp; 195 char buf[BUFSIZ]; 196 197 #ifdef DEBUG 198 debug("in push_linedisc"); 199 #endif 200 /* 201 * copy modules into buf so we won't mess up the original buffer 202 * because strtok will chop the string 203 */ 204 p = strcpy(buf,modules); 205 206 while(ioctl(fd, I_POP, 0) >= 0) /* pop everything */ 207 ; 208 for (p=(char *)strtok(p,","); p!=(char *)NULL; 209 p=(char *)strtok(NULL,",")) { 210 for (tp = p + strlen(p) - 1; tp >= p && isspace(*tp); --tp) 211 *tp = '\0'; 212 if (ioctl(fd, I_PUSH, p) == -1) { 213 log("push (%s) on %s failed: %s", p, device, 214 strerror(errno)); 215 return(-1); 216 } 217 } 218 return(0); 219 } 220 221 /* 222 * hang_up_line - set speed to B0. This will drop DTR 223 */ 224 int 225 hang_up_line(int fd) 226 { 227 struct termio termio; 228 struct termios termios; 229 230 #ifdef DEBUG 231 debug("in hang_up_line"); 232 #endif 233 if (ioctl(fd,TCGETS,&termios) < 0) { 234 if (ioctl(fd,TCGETA,&termio) < 0) { 235 log("hang_up_line: TCGETA failed: %s", strerror(errno)); 236 return(-1); 237 } 238 termio.c_cflag &= ~CBAUD; 239 termio.c_cflag |= B0; 240 241 if (ioctl(fd,TCSETA,&termio) < 0) { 242 log("hang_up_line: TCSETA failed: %s", strerror(errno)); 243 return(-1); 244 } 245 } else { 246 cfsetospeed(&termios, B0); 247 248 if (ioctl(fd,TCSETS,&termios) < 0) { 249 log("hang_up_line: TCSETS failed: %s", strerror(errno)); 250 return(-1); 251 } 252 } 253 return(0); 254 } 255 256 /* 257 * initial_termio - set initial termios 258 * - return 0 if successful, -1 if failed. 259 */ 260 int 261 initial_termio(fd,pmptr) 262 int fd; 263 struct pmtab *pmptr; 264 { 265 int ret; 266 struct Gdef *speedef; 267 struct Gdef *get_speed(); 268 extern int auto_termio(); 269 270 speedef = get_speed(pmptr->p_ttylabel); 271 if (speedef->g_autobaud & A_FLAG) { 272 pmptr->p_ttyflags |= A_FLAG; 273 if (auto_termio(fd) == -1) { 274 (void)close(fd); 275 return(-1); 276 } 277 } 278 else { 279 if (pmptr->p_ttyflags & R_FLAG) 280 ret = set_termio(fd,speedef->g_iflags, 281 (char *)NULL, TRUE, (long)RAW); 282 else 283 ret = set_termio(fd,speedef->g_iflags, 284 (char *)NULL, TRUE, (long)CANON); 285 if (ret == -1) { 286 log("initial termio on (%s) failed", pmptr->p_device); 287 (void)close(fd); 288 return(-1); 289 } 290 } 291 return(0); 292 } 293