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
set_termio(int fd,char * options,char * aspeed,int clear,long mode)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 */
turnon_canon(int fd)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
flush_input(int fd)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
push_linedisc(int fd,char * modules,char * device)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
hang_up_line(int fd)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
initial_termio(int fd,struct pmtab * pmptr)242 initial_termio(int fd, struct pmtab *pmptr)
243 {
244 int ret;
245 struct Gdef *speedef;
246
247 speedef = get_speed(pmptr);
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