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