xref: /illumos-gate/usr/src/lib/libnsl/dial/line.c (revision d9c3e05c)
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 	int 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 	{ 19200,	B19200 },
56 	{ 38400,	B38400 },
57 	{ 57600,	B57600 },
58 	{ 76800,	B76800 },
59 	{ 115200,	B115200 },
60 	{ 153600,	B153600 },
61 	{ 230400,	B230400 },
62 	{ 307200,	B307200 },
63 	{ 460800,	B460800 },
64 	{ 921600,	B921600 },
65 	{ 1000000,	B1000000 },
66 	{ 1152000,	B1152000 },
67 	{ 1500000,	B1500000 },
68 	{ 2000000,	B2000000 },
69 	{ 2500000,	B2500000 },
70 	{ 3000000,	B3000000 },
71 	{ 3500000,	B3500000 },
72 	{ 4000000,	B4000000 },
73 	{ 0,		0}
74 };
75 
76 #define	HEADERSIZE	6
77 
78 static int Saved_line;		/* was savline() successful?	*/
79 static int Saved_termios;	/* was termios saved?	*/
80 static int
81 	Oddflag,	/* Default is no parity */
82 	Evenflag,	/* Default is no parity */
83 	Duplex = 1,	/* Default is full duplex */
84 	Terminal,	/* Default is no terminal */
85 	line_8bit = -1;	/* Default is same as terminal */
86 
87 static const char P_PARITY[] = "Parity option error\r\n";
88 
89 static struct termio Savettyb;
90 static struct termios Savettybs;
91 /*
92  * set speed/echo/mode...
93  *	tty 	-> terminal name
94  *	spwant 	-> speed
95  *	type	-> type
96  *
97  *	if spwant == 0, speed is untouched
98  *	type is unused, but needed for compatibility
99  *
100  * return:
101  *	none
102  */
103 /*ARGSUSED*/
104 static void
fixline(int tty,int spwant,int type)105 fixline(int tty, int spwant, int type)
106 {
107 	register const struct sg_spds	*ps;
108 	struct termio		ttbuf;
109 	struct termios		ttbufs;
110 	int			speed = -1;
111 	int			i, istermios, ospeed;
112 
113 	DEBUG(6, "fixline(%d, ", tty);
114 	DEBUG(6, "%d)\n", spwant);
115 	if ((istermios = (*Ioctl)(tty, TCGETS, &ttbufs)) < 0) {
116 		if ((*Ioctl)(tty, TCGETA, &ttbuf) != 0)
117 			return;
118 		ttbufs.c_lflag = ttbuf.c_lflag;
119 		ttbufs.c_oflag = ttbuf.c_oflag;
120 		ttbufs.c_iflag = ttbuf.c_iflag;
121 		ttbufs.c_cflag = ttbuf.c_cflag;
122 		for (i = 0; i < NCC; i++)
123 			ttbufs.c_cc[i] = ttbuf.c_cc[i];
124 	}
125 	if (spwant > 0) {
126 		for (ps = spds; ps->sp_val != 0; ps++)
127 			if (ps->sp_val == spwant) {
128 				speed = ps->sp_name;
129 				break;
130 			}
131 		if (speed < 0) {
132 			/*EMPTY*/
133 			DEBUG(5, "speed (%d) not supported\n", spwant);
134 		}
135 		ASSERT(speed >= 0, "BAD SPEED", "", spwant);
136 		ttbufs.c_cflag &= 0xffff0000;
137 		(void) cfsetospeed(&ttbufs, speed);
138 	} else { /* determine the current speed setting */
139 		ospeed = cfgetospeed(&ttbufs);
140 		ttbufs.c_cflag &= 0xffff0000;
141 		(void) cfsetospeed(&ttbufs, ospeed);
142 		for (ps = spds; ps->sp_val != 0; ps++)
143 			if (ps->sp_name == ospeed) {
144 				spwant = ps->sp_val;
145 				break;
146 			}
147 	}
148 	ttbufs.c_iflag &= 0xffff0000;
149 	ttbufs.c_oflag &= 0xffff0000;
150 	ttbufs.c_lflag &= 0xffff0000;
151 
152 	ttbufs.c_cflag &= ~CLOCAL;
153 
154 	if (EQUALS(Progname, "cu")) {
155 
156 		/* set attributes associated with -h, -t, -e, and -o options */
157 
158 		ttbufs.c_iflag = (IGNPAR | IGNBRK | IXON | IXOFF);
159 		if (line_8bit) {
160 			ttbufs.c_cflag |= CS8;
161 			ttbufs.c_iflag &= ~ISTRIP;
162 		} else {
163 			ttbufs.c_cflag |= CS7;
164 			ttbufs.c_iflag |= ISTRIP;
165 		}
166 
167 		ttbufs.c_cc[VEOF] = '\1';
168 		ttbufs.c_cflag |= (CREAD | (speed ? HUPCL : 0));
169 
170 		if (Evenflag) {				/* even parity -e */
171 			if (ttbufs.c_cflag & PARENB) {
172 				VERBOSE(P_PARITY, 0);
173 				exit(1);
174 			}
175 			ttbufs.c_cflag |= PARENB;
176 		} else if (Oddflag) {			/* odd parity -o */
177 			if (ttbufs.c_cflag & PARENB) {
178 				VERBOSE(P_PARITY, 0);
179 				exit(1);
180 			}
181 			ttbufs.c_cflag |= PARODD;
182 			ttbufs.c_cflag |= PARENB;
183 		}
184 
185 		if (!Duplex)				/* half duplex -h */
186 			ttbufs.c_iflag &= ~(IXON | IXOFF);
187 		if (Terminal)				/* -t */
188 			ttbufs.c_oflag |= (OPOST | ONLCR);
189 
190 	} else { /* non-cu */
191 		ttbufs.c_cflag |= (CS8 | CREAD | (speed ? HUPCL : 0));
192 		ttbufs.c_cc[VMIN] = HEADERSIZE;
193 		ttbufs.c_cc[VTIME] = 1;
194 	}
195 
196 	if (istermios < 0) {
197 		ttbuf.c_lflag = ttbufs.c_lflag;
198 		ttbuf.c_oflag = ttbufs.c_oflag;
199 		ttbuf.c_iflag = ttbufs.c_iflag;
200 		ttbuf.c_cflag = ttbufs.c_cflag;
201 		for (i = 0; i < NCC; i++)
202 			ttbuf.c_cc[i] = ttbufs.c_cc[i];
203 		ASSERT((*Ioctl)(tty, TCSETAW, &ttbuf) >= 0,
204 		    "RETURN FROM fixline ioctl", "", errno);
205 	} else {
206 		ASSERT((*Ioctl)(tty, TCSETSW, &ttbufs) >= 0,
207 		    "RETURN FROM fixline ioctl", "", errno);
208 	}
209 }
210 
211 static void
sethup(int dcf)212 sethup(int dcf)
213 {
214 	struct termio ttbuf;
215 
216 	if ((*Ioctl)(dcf, TCGETA, &ttbuf) != 0)
217 		return;
218 	if (!(ttbuf.c_cflag & HUPCL)) {
219 		ttbuf.c_cflag |= HUPCL;
220 		(void) (*Ioctl)(dcf, TCSETAW, &ttbuf);
221 	}
222 }
223 
224 static void
ttygenbrk(int fn)225 ttygenbrk(int fn)
226 {
227 	if (isatty(fn))
228 		(void) (*Ioctl)(fn, TCSBRK, 0);
229 }
230 
231 static int
savline(void)232 savline(void)
233 {
234 	if ((Saved_termios = (*Ioctl)(0, TCGETS, &Savettybs)) < 0) {
235 		if ((*Ioctl)(0, TCGETA, &Savettyb) != 0) {
236 			Saved_line = FALSE;
237 		} else {
238 			Saved_line = TRUE;
239 			Savettyb.c_cflag = (Savettyb.c_cflag & ~CS8) | CS7;
240 			Savettyb.c_oflag |= OPOST;
241 			Savettyb.c_lflag |= (ISIG|ICANON|ECHO);
242 		}
243 	} else {
244 		Saved_line = TRUE;
245 		Savettybs.c_cflag = (Savettybs.c_cflag & ~CS8) | CS7;
246 		Savettybs.c_oflag |= OPOST;
247 		Savettybs.c_lflag |= (ISIG|ICANON|ECHO);
248 	}
249 	return (0);
250 }
251 
252 static int
restline(void)253 restline(void)
254 {
255 	if (Saved_line == TRUE) {
256 		if (Saved_termios < 0)
257 			return ((*Ioctl)(0, TCSETAW, &Savettyb));
258 		else
259 			return ((*Ioctl)(0, TCSETSW, &Savettybs));
260 	}
261 	return (0);
262 }
263