line.c revision 1219:f89f56c2d9ac
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/*
24 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
25 * Use is subject to license terms.
26 */
27
28/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
29/*	  All Rights Reserved  	*/
30
31#pragma ident	"%Z%%M%	%I%	%E% SMI"
32
33/*
34 * This is a new line.c, which consists of line.c and culine.c
35 * merged together.
36 */
37
38#include "mt.h"
39#include "uucp.h"
40
41static const struct sg_spds {
42	int	sp_val,
43		sp_name;
44} spds[] = {
45	{  50,   B50},
46	{  75,   B75},
47	{ 110,  B110},
48	{ 134,  B134},
49	{ 150,  B150},
50	{ 200,  B200},
51	{ 300,  B300},
52	{ 600,  B600},
53	{1200, B1200},
54	{1800, B1800},
55	{2400, B2400},
56	{4800, B4800},
57	{9600, B9600},
58#ifdef EXTA
59	{19200,	EXTA},
60#endif
61#ifdef B19200
62	{19200,	B19200},
63#endif
64#ifdef B38400
65	{38400,	B38400},
66#endif
67	{57600, B57600},
68	{76800, B76800},
69	{115200, B115200},
70	{153600, B153600},
71	{230400, B230400},
72	{307200, B307200},
73	{460800, B460800},
74	{0,    0}
75};
76
77#define	PACKSIZE	64
78#define	HEADERSIZE	6
79
80#define	SNDFILE	'S'
81#define	RCVFILE 'R'
82#define	RESET	'X'
83
84static int Saved_line;		/* was savline() successful?	*/
85static int Saved_termios;	/* was termios saved?	*/
86static int
87	Oddflag,	/* Default is no parity */
88	Evenflag,	/* Default is no parity */
89	Duplex = 1,	/* Default is full duplex */
90	Terminal,	/* Default is no terminal */
91	line_8bit = -1;	/* Default is same as terminal */
92
93static const char P_PARITY[] = "Parity option error\r\n";
94
95static struct termio Savettyb;
96static struct termios Savettybs;
97/*
98 * set speed/echo/mode...
99 *	tty 	-> terminal name
100 *	spwant 	-> speed
101 *	type	-> type
102 *
103 *	if spwant == 0, speed is untouched
104 *	type is unused, but needed for compatibility
105 *
106 * return:
107 *	none
108 */
109/*ARGSUSED*/
110static void
111fixline(int tty, int spwant, int type)
112{
113	register const struct sg_spds	*ps;
114	struct termio		ttbuf;
115	struct termios		ttbufs;
116	int			speed = -1;
117	int			i, istermios, ospeed;
118
119	DEBUG(6, "fixline(%d, ", tty);
120	DEBUG(6, "%d)\n", spwant);
121	if ((istermios = (*Ioctl)(tty, TCGETS, &ttbufs)) < 0) {
122		if ((*Ioctl)(tty, TCGETA, &ttbuf) != 0)
123			return;
124		ttbufs.c_lflag = ttbuf.c_lflag;
125		ttbufs.c_oflag = ttbuf.c_oflag;
126		ttbufs.c_iflag = ttbuf.c_iflag;
127		ttbufs.c_cflag = ttbuf.c_cflag;
128		for (i = 0; i < NCC; i++)
129			ttbufs.c_cc[i] = ttbuf.c_cc[i];
130	}
131	if (spwant > 0) {
132		for (ps = spds; ps->sp_val; ps++)
133			if (ps->sp_val == spwant) {
134				speed = ps->sp_name;
135				break;
136			}
137		if (speed < 0) {
138			/*EMPTY*/
139			DEBUG(5, "speed (%d) not supported\n", spwant);
140		}
141		ASSERT(speed >= 0, "BAD SPEED", "", spwant);
142		ttbufs.c_cflag &= 0xffff0000;
143		(void) cfsetospeed(&ttbufs, speed);
144	} else { /* determine the current speed setting */
145		ospeed = cfgetospeed(&ttbufs);
146		ttbufs.c_cflag &= 0xffff0000;
147		(void) cfsetospeed(&ttbufs, ospeed);
148		for (ps = spds; ps->sp_val; ps++)
149			if (ps->sp_name == ospeed) {
150				spwant = ps->sp_val;
151				break;
152			}
153	}
154	ttbufs.c_iflag &= 0xffff0000;
155	ttbufs.c_oflag &= 0xffff0000;
156	ttbufs.c_lflag &= 0xffff0000;
157
158	ttbufs.c_cflag &= ~CLOCAL;
159
160	if (EQUALS(Progname, "cu")) {
161
162		/* set attributes associated with -h, -t, -e, and -o options */
163
164		ttbufs.c_iflag = (IGNPAR | IGNBRK | IXON | IXOFF);
165		if (line_8bit) {
166			ttbufs.c_cflag |= CS8;
167			ttbufs.c_iflag &= ~ISTRIP;
168		} else {
169			ttbufs.c_cflag |= CS7;
170			ttbufs.c_iflag |= ISTRIP;
171		}
172
173		ttbufs.c_cc[VEOF] = '\1';
174		ttbufs.c_cflag |= (CREAD | (speed ? HUPCL : 0));
175
176		if (Evenflag) {				/* even parity -e */
177			if (ttbufs.c_cflag & PARENB) {
178				VERBOSE(P_PARITY, 0);
179				exit(1);
180			}
181			ttbufs.c_cflag |= PARENB;
182		} else if (Oddflag) {			/* odd parity -o */
183			if (ttbufs.c_cflag & PARENB) {
184				VERBOSE(P_PARITY, 0);
185				exit(1);
186			}
187			ttbufs.c_cflag |= PARODD;
188			ttbufs.c_cflag |= PARENB;
189		}
190
191		if (!Duplex)				/* half duplex -h */
192			ttbufs.c_iflag &= ~(IXON | IXOFF);
193		if (Terminal)				/* -t */
194			ttbufs.c_oflag |= (OPOST | ONLCR);
195
196	} else { /* non-cu */
197		ttbufs.c_cflag |= (CS8 | CREAD | (speed ? HUPCL : 0));
198		ttbufs.c_cc[VMIN] = HEADERSIZE;
199		ttbufs.c_cc[VTIME] = 1;
200	}
201
202	if (istermios < 0) {
203		ttbuf.c_lflag = ttbufs.c_lflag;
204		ttbuf.c_oflag = ttbufs.c_oflag;
205		ttbuf.c_iflag = ttbufs.c_iflag;
206		ttbuf.c_cflag = ttbufs.c_cflag;
207		for (i = 0; i < NCC; i++)
208			ttbuf.c_cc[i] = ttbufs.c_cc[i];
209		ASSERT((*Ioctl)(tty, TCSETAW, &ttbuf) >= 0,
210			"RETURN FROM fixline ioctl", "", errno);
211	} else {
212		ASSERT((*Ioctl)(tty, TCSETSW, &ttbufs) >= 0,
213			"RETURN FROM fixline ioctl", "", errno);
214	}
215}
216
217static void
218sethup(int dcf)
219{
220	struct termio ttbuf;
221
222	if ((*Ioctl)(dcf, TCGETA, &ttbuf) != 0)
223		return;
224	if (!(ttbuf.c_cflag & HUPCL)) {
225		ttbuf.c_cflag |= HUPCL;
226		(void) (*Ioctl)(dcf, TCSETAW, &ttbuf);
227	}
228}
229
230static void
231ttygenbrk(int fn)
232{
233	if (isatty(fn))
234		(void) (*Ioctl)(fn, TCSBRK, 0);
235}
236
237static int
238savline(void)
239{
240	if ((Saved_termios = (*Ioctl)(0, TCGETS, &Savettybs)) < 0) {
241		if ((*Ioctl)(0, TCGETA, &Savettyb) != 0) {
242			Saved_line = FALSE;
243		} else {
244			Saved_line = TRUE;
245			Savettyb.c_cflag = (Savettyb.c_cflag & ~CS8) | CS7;
246			Savettyb.c_oflag |= OPOST;
247			Savettyb.c_lflag |= (ISIG|ICANON|ECHO);
248		}
249	} else {
250		Saved_line = TRUE;
251		Savettybs.c_cflag = (Savettybs.c_cflag & ~CS8) | CS7;
252		Savettybs.c_oflag |= OPOST;
253		Savettybs.c_lflag |= (ISIG|ICANON|ECHO);
254	}
255	return (0);
256}
257
258static int
259restline(void)
260{
261	if (Saved_line == TRUE) {
262		if (Saved_termios < 0)
263			return ((*Ioctl)(0, TCSETAW, &Savettyb));
264		else
265			return ((*Ioctl)(0, TCSETSW, &Savettybs));
266	}
267	return (0);
268}
269