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 #include <stdlib.h> 31 #include <stdio.h> 32 #include <errno.h> 33 #include <termio.h> 34 #include <sys/stermio.h> 35 #include <sys/termiox.h> 36 #include <string.h> 37 #include <ctype.h> 38 #include <unistd.h> 39 #include <sys/types.h> 40 #include "sys/stropts.h" 41 #include "sys/signal.h" 42 #include "ttymon.h" 43 #include "tmstruct.h" 44 #include "tmextern.h" 45 46 /* 47 * set_termio - set termio on device 48 * fd - fd for the device 49 * options - stty termio options 50 * aspeed - autobaud speed 51 * clear - if TRUE, current flags will be set to some defaults 52 * before applying the options 53 * - if FALSE, current flags will not be cleared 54 * mode - terminal mode, CANON, RAW 55 */ 56 57 58 59 int 60 set_termio(int fd, char *options, char *aspeed, int clear, long mode) 61 { 62 struct termio termio; 63 struct termios termios; 64 struct stio stermio; 65 struct termiox termiox; 66 struct winsize winsize; 67 struct winsize owinsize; 68 int term; 69 int cnt = 1; 70 char *uarg; 71 char *argvp[MAXARGS]; /* stty args */ 72 static char *binstty = "/usr/bin/stty"; 73 static char buf[BUFSIZ]; 74 75 #ifdef DEBUG 76 debug("in set_termio"); 77 #endif 78 79 if ((term = get_ttymode(fd, &termio, &termios, &stermio, 80 &termiox, &winsize)) < 0) { 81 log("set_termio: get_ttymode failed: %s", strerror(errno)); 82 return (-1); 83 } 84 owinsize = winsize; 85 if (clear) { 86 if (mode & CANON) { 87 /* could have removed these too - rely on defaults */ 88 termios.c_cc[VEOF] = CEOF; 89 termios.c_cc[VEOL] = CNUL; 90 } else { 91 termios.c_lflag &= ECHO; 92 termios.c_cc[VMIN] = 1; 93 termios.c_cc[VTIME] = 0; 94 } 95 96 } 97 98 if (options != NULL && *options != '\0') { 99 /* just a place holder to make it look like invoking stty */ 100 argvp[0] = binstty; 101 (void) strcpy(buf, options); 102 mkargv(buf, &argvp[1], &cnt, MAXARGS - 1); 103 if (aspeed != NULL && *aspeed != '\0') { 104 argvp[cnt++] = aspeed; 105 } 106 argvp[cnt] = (char *)0; 107 if ((uarg = sttyparse(cnt, argvp, term, &termio, &termios, 108 &termiox, &winsize)) != NULL) { 109 log("sttyparse unknown mode: %s", uarg); 110 return (-1); 111 } 112 } 113 114 115 if (set_ttymode(fd, term, &termio, &termios, &stermio, 116 &termiox, &winsize, &owinsize) != 0) { 117 log("set_termio: set_ttymode failed", strerror(errno)); 118 return (-1); 119 } 120 121 return (0); 122 } 123 124 #ifdef NOT_USE 125 /* 126 * turnon_canon - turn on canonical processing 127 * - return 0 if succeeds, -1 if fails 128 */ 129 turnon_canon(int fd) 130 { 131 struct termio termio; 132 133 #ifdef DEBUG 134 debug("in turnon_canon"); 135 #endif 136 if (ioctl(fd, TCGETA, &termio) != 0) { 137 log("turnon_canon: TCGETA failed, fd = %d: %s", fd, 138 strerror(errno)); 139 return (-1); 140 } 141 termio.c_lflag |= (ISIG|ICANON|ECHO|ECHOE|ECHOK); 142 termio.c_cc[VEOF] = CEOF; 143 termio.c_cc[VEOL] = CNUL; 144 if (ioctl(fd, TCSETA, &termio) != 0) { 145 log("turnon_canon: TCSETA failed, fd = %d: %s", fd, 146 strerror(errno)); 147 return (-1); 148 } 149 return (0); 150 } 151 #endif 152 153 /* 154 * flush_input - flush the input queue 155 */ 156 void 157 flush_input(int fd) 158 { 159 if (ioctl(fd, I_FLUSH, FLUSHR) == -1) 160 log("flush_input failed, fd = %d: %s", fd, strerror(errno)); 161 162 if (ioctl(fd, TCSBRK, 1) == -1) 163 log("drain of ouput failed, fd = %d: %s", fd, strerror(errno)); 164 } 165 166 /* 167 * push_linedisc - if modules is not NULL, pop everything 168 * - then push modules specified by "modules" 169 */ 170 int 171 push_linedisc( 172 int fd, /* fd to push modules on */ 173 char *modules, /* ptr to a list of comma separated module names */ 174 char *device) /* device name for printing msg */ 175 { 176 char *p, *tp; 177 char buf[BUFSIZ]; 178 179 #ifdef DEBUG 180 debug("in push_linedisc"); 181 #endif 182 /* 183 * copy modules into buf so we won't mess up the original buffer 184 * because strtok will chop the string 185 */ 186 p = strcpy(buf, modules); 187 188 while (ioctl(fd, I_POP, 0) >= 0) /* pop everything */ 189 ; 190 for (p = strtok(p, ","); p != NULL; p = strtok(NULL, ",")) { 191 for (tp = p + strlen(p) - 1; tp >= p && isspace(*tp); --tp) 192 *tp = '\0'; 193 if (ioctl(fd, I_PUSH, p) == -1) { 194 log("push (%s) on %s failed: %s", p, device, 195 strerror(errno)); 196 return (-1); 197 } 198 } 199 return (0); 200 } 201 202 /* 203 * hang_up_line - set speed to B0. This will drop DTR 204 */ 205 int 206 hang_up_line(int fd) 207 { 208 struct termio termio; 209 struct termios termios; 210 211 #ifdef DEBUG 212 debug("in hang_up_line"); 213 #endif 214 if (ioctl(fd, TCGETS, &termios) < 0) { 215 if (ioctl(fd, TCGETA, &termio) < 0) { 216 log("hang_up_line: TCGETA failed: %s", strerror(errno)); 217 return (-1); 218 } 219 termio.c_cflag &= ~CBAUD; 220 termio.c_cflag |= B0; 221 222 if (ioctl(fd, TCSETA, &termio) < 0) { 223 log("hang_up_line: TCSETA failed: %s", strerror(errno)); 224 return (-1); 225 } 226 } else { 227 (void) cfsetospeed(&termios, B0); 228 229 if (ioctl(fd, TCSETS, &termios) < 0) { 230 log("hang_up_line: TCSETS failed: %s", strerror(errno)); 231 return (-1); 232 } 233 } 234 return (0); 235 } 236 237 /* 238 * initial_termio - set initial termios 239 * - return 0 if successful, -1 if failed. 240 */ 241 int 242 initial_termio(int fd, struct pmtab *pmptr) 243 { 244 int ret; 245 struct Gdef *speedef; 246 247 speedef = get_speed(pmptr->p_ttylabel); 248 if (speedef->g_autobaud & A_FLAG) { 249 pmptr->p_ttyflags |= A_FLAG; 250 if (auto_termio(fd) == -1) { 251 (void) close(fd); 252 return (-1); 253 } 254 } else { 255 if (pmptr->p_ttyflags & R_FLAG) 256 ret = set_termio(fd, speedef->g_iflags, 257 NULL, TRUE, (long)RAW); 258 else 259 ret = set_termio(fd, speedef->g_iflags, 260 NULL, TRUE, (long)CANON); 261 if (ret == -1) { 262 log("initial termio on (%s) failed", pmptr->p_device); 263 (void) close(fd); 264 return (-1); 265 } 266 } 267 return (0); 268 } 269