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
50extern	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
65int
66set_termio(fd,options,aspeed,clear,mode)
67int	fd;
68char	*options;
69char	*aspeed;
70int	clear;
71long	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 */
143turnon_canon(fd)
144int	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 */
171void
172flush_input(fd)
173int	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 */
188int
189push_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 */
224int
225hang_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 */
260int
261initial_termio(fd,pmptr)
262int	fd;
263struct	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