xref: /illumos-gate/usr/src/lib/libnsl/dial/line.c (revision d6bb6a8465e557cb946ef49d56ed3202f6218652)
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 
41 static 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 
84 static int Saved_line;		/* was savline() successful?	*/
85 static int Saved_termios;	/* was termios saved?	*/
86 static 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 
93 static const char P_PARITY[] = "Parity option error\r\n";
94 
95 static struct termio Savettyb;
96 static 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*/
110 static void
111 fixline(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 
217 static void
218 sethup(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 
230 static void
231 ttygenbrk(int fn)
232 {
233 	if (isatty(fn))
234 		(void) (*Ioctl)(fn, TCSBRK, 0);
235 }
236 
237 static int
238 savline(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 
258 static int
259 restline(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