xref: /illumos-gate/usr/src/lib/libnsl/dial/line.c (revision 598f4ceed9327d2d6c2325dd67cae3aa06f7fea6)
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 
38 static 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 
82 static int Saved_line;		/* was savline() successful?	*/
83 static int Saved_termios;	/* was termios saved?	*/
84 static 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 
91 static const char P_PARITY[] = "Parity option error\r\n";
92 
93 static struct termio Savettyb;
94 static 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*/
108 static void
109 fixline(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 
215 static void
216 sethup(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 
228 static void
229 ttygenbrk(int fn)
230 {
231 	if (isatty(fn))
232 		(void) (*Ioctl)(fn, TCSBRK, 0);
233 }
234 
235 static int
236 savline(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 
256 static int
257 restline(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