xref: /illumos-gate/usr/src/cmd/bnu/line.c (revision 24da5b34f49324ed742a340010ed5bd3d4e06625)
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  * Copyright 1995 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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 
33 /* This is a new line.c, which consists of line.c and culine.c
34  * merged together.
35  */
36 
37 #include "uucp.h"
38 
39 static struct sg_spds {
40 	int	sp_val,
41 		sp_name;
42 } spds[] = {
43 	{  50,   B50},
44 	{  75,   B75},
45 	{ 110,  B110},
46 	{ 134,  B134},
47 	{ 150,  B150},
48 	{ 200,  B200},
49 	{ 300,  B300},
50 	{ 600,  B600},
51 	{1200, B1200},
52 	{1800, B1800},
53 	{2400, B2400},
54 	{4800, B4800},
55 	{9600, B9600},
56 #ifdef EXTA
57 	{19200,	EXTA},
58 #endif
59 #ifdef B19200
60 	{19200,	B19200},
61 #endif
62 #ifdef B38400
63 	{38400,	B38400},
64 #endif
65 	{57600, B57600},
66 	{76800, B76800},
67 	{115200, B115200},
68 	{153600, B153600},
69 	{230400, B230400},
70 	{307200, B307200},
71 	{460800, B460800},
72 	{0,    0}
73 };
74 
75 #define PACKSIZE	64
76 #define HEADERSIZE	6
77 
78 GLOBAL int
79      packsize = PACKSIZE,
80     xpacksize = PACKSIZE;
81 
82 #define SNDFILE	'S'
83 #define RCVFILE 'R'
84 #define RESET	'X'
85 
86 #ifdef PKSPEEDUP
87 GLOBAL int linebaudrate;	/* for speedup hook in pk1.c */
88 #endif /*  PKSPEEDUP  */
89 static int Saved_line;		/* was savline() successful?	*/
90 static int Saved_termios;	/* was termios saved?	*/
91 GLOBAL int
92 	Oddflag = 0,	/* Default is no parity */
93 	Evenflag = 0,	/* Default is no parity */
94 	Duplex = 1,	/* Default is full duplex */
95 	Terminal = 0,	/* Default is no terminal */
96 	term_8bit = -1,	/* Default to terminal setting or 8 bit */
97 	line_8bit = -1;	/* Default is same as terminal */
98 
99 static char *P_PARITY  = "Parity option error\r\n";
100 
101 #ifdef ATTSVTTY
102 
103 static struct termio Savettyb;
104 static struct termios Savettybs;
105 /*
106  * set speed/echo/mode...
107  *	tty 	-> terminal name
108  *	spwant 	-> speed
109  *	type	-> type
110  *
111  *	if spwant == 0, speed is untouched
112  *	type is unused, but needed for compatibility
113  *
114  * return:
115  *	none
116  */
117 /*ARGSUSED*/
118 GLOBAL void
119 fixline(tty, spwant, type)
120 int	tty, spwant, type;
121 {
122 	register struct sg_spds	*ps;
123 	struct termio		ttbuf;
124 	struct termios		ttbufs;
125 	int			speed = -1;
126 	int			i, istermios, ospeed;
127 
128 	DEBUG(6, "fixline(%d, ", tty);
129 	DEBUG(6, "%d)\n", spwant);
130 	if ((istermios = (*Ioctl)(tty, TCGETS, &ttbufs)) < 0) {
131 		if ((*Ioctl)(tty, TCGETA, &ttbuf) != 0) {
132 			return;
133 		} else {
134 			ttbufs.c_lflag = ttbuf.c_lflag;
135 			ttbufs.c_oflag = ttbuf.c_oflag;
136 			ttbufs.c_iflag = ttbuf.c_iflag;
137 			ttbufs.c_cflag = ttbuf.c_cflag;
138 			for(i = 0; i < NCC; i++)
139 				ttbufs.c_cc[i] = ttbuf.c_cc[i];
140 	    	}
141 	}
142 	if (spwant > 0) {
143 		for (ps = spds; ps->sp_val; ps++)
144 			if (ps->sp_val == spwant) {
145 				speed = ps->sp_name;
146 				break;
147 			}
148 		if ( speed < 0 )
149 		    DEBUG(5, "speed (%d) not supported\n", spwant);
150 		ASSERT(speed >= 0, "BAD SPEED", "", spwant);
151 		ttbufs.c_cflag &= 0xffff0000;
152 		cfsetospeed(&ttbufs, speed);
153 	} else { /* determine the current speed setting */
154 		ospeed = cfgetospeed(&ttbufs);
155 		ttbufs.c_cflag &= 0xffff0000;
156 		cfsetospeed(&ttbufs, ospeed);
157 		for (ps = spds; ps->sp_val; ps++)
158 			if (ps->sp_name == ospeed) {
159 				spwant = ps->sp_val;
160 				break;
161 			}
162 	}
163 	ttbufs.c_iflag &= 0xffff0000;
164 	ttbufs.c_oflag &= 0xffff0000;
165 	ttbufs.c_lflag &= 0xffff0000;
166 #ifdef PKSPEEDUP
167 	linebaudrate = spwant;
168 #endif /*  PKSPEEDUP  */
169 
170 #ifdef NO_MODEM_CTRL
171 	/*   CLOCAL may cause problems on pdp11s with DHs */
172 	if (type == D_DIRECT) {
173 		DEBUG(4, "fixline - direct\n%s", "");
174 		ttbufs.c_cflag |= CLOCAL;
175 	} else
176 #endif /* NO_MODEM_CTRL */
177 		ttbufs.c_cflag &= ~CLOCAL;
178 
179 	if ( !EQUALS(Progname, "uucico") ) {
180 
181 		/* set attributes associated with -h, -t, -e, and -o options */
182 
183 		ttbufs.c_iflag = (IGNPAR | IGNBRK | IXON | IXOFF);
184 		ttbufs.c_cc[VEOF] = '\1';
185 		ttbufs.c_cflag |= ( CREAD | (speed ? HUPCL : 0));
186 
187 		if ( line_8bit ) {
188 		    ttbufs.c_cflag |= CS8;
189 		    ttbufs.c_iflag &= ~ISTRIP;
190 		} else {
191 		    if (Evenflag) {			/*even parity -e */
192 			ttbufs.c_cflag &= ~PARODD;
193 		    } else if(Oddflag) {		/*odd parity -o */
194 			ttbufs.c_cflag |= PARODD;
195 		    }
196 		    ttbufs.c_cflag |= CS7|PARENB;
197 		    ttbufs.c_iflag |= ISTRIP;
198 		}
199 
200 		if(!Duplex)				/*half duplex -h */
201 		    ttbufs.c_iflag &= ~(IXON | IXOFF);
202 		if(Terminal)				/* -t */
203 		    ttbufs.c_oflag |= (OPOST | ONLCR);
204 
205 	} else { /* non-uucico */
206 		ttbufs.c_cflag |= (CS8 | CREAD | (speed ? HUPCL : 0));
207 		ttbufs.c_cc[VMIN] = HEADERSIZE;
208 		ttbufs.c_cc[VTIME] = 1;
209 	}
210 
211 	if (istermios < 0) {
212 		ttbuf.c_lflag = ttbufs.c_lflag;
213 		ttbuf.c_oflag = ttbufs.c_oflag;
214 		ttbuf.c_iflag = ttbufs.c_iflag;
215 		ttbuf.c_cflag = ttbufs.c_cflag;
216 		for(i = 0; i < NCC; i++)
217 			ttbuf.c_cc[i] = ttbufs.c_cc[i];
218 		ASSERT((*Ioctl)(tty, TCSETAW, &ttbuf) >= 0,
219 	    	    "RETURN FROM fixline ioctl", "", errno);
220 	} else {
221 		ASSERT((*Ioctl)(tty, TCSETSW, &ttbufs) >= 0,
222 	    	    "RETURN FROM fixline ioctl", "", errno);
223 	}
224 
225 	return;
226 }
227 
228 GLOBAL void
229 sethup(dcf)
230 int	dcf;
231 {
232 	struct termio ttbuf;
233 
234 	if ((*Ioctl)(dcf, TCGETA, &ttbuf) != 0)
235 		return;
236 	if (!(ttbuf.c_cflag & HUPCL)) {
237 		ttbuf.c_cflag |= HUPCL;
238 		(void) (*Ioctl)(dcf, TCSETAW, &ttbuf);
239 	}
240 	return;
241 }
242 
243 GLOBAL void
244 ttygenbrk(fn)
245 register int	fn;
246 {
247 	if (isatty(fn))
248 		(void) (*Ioctl)(fn, TCSBRK, 0);
249 	return;
250 }
251 
252 
253 /*
254  * optimize line setting for sending or receiving files
255  * return:
256  *	none
257  */
258 GLOBAL void
259 setline(type)
260 register char	type;
261 {
262 	static struct termio tbuf;
263 	static struct termios tbufs;
264 	int i, vtime, istermios, ospeed;
265 
266 	DEBUG(2, "setline - %c\n", type);
267 
268 	if ((istermios = (*Ioctl)(Ifn, TCGETS, &tbufs)) < 0) {
269 		if ((*Ioctl)(Ifn, TCGETA, &tbuf) != 0) {
270 			return;
271 		} else {
272 			tbufs.c_lflag = tbuf.c_lflag;
273 			tbufs.c_oflag = tbuf.c_oflag;
274 			tbufs.c_iflag = tbuf.c_iflag;
275 			tbufs.c_cflag = tbuf.c_cflag;
276 			for(i = 0; i < NCC; i++)
277 				tbufs.c_cc[i] = tbuf.c_cc[i];
278 		}
279 	}
280 	switch (type) {
281 	case RCVFILE:
282 		ospeed = cfgetospeed(&tbufs);
283 		switch (ospeed) {
284 #ifdef B19200
285 		case B19200:
286 #else
287 #ifdef EXTA
288 		case EXTA:
289 #endif
290 #endif
291 #ifdef B38400
292 		case B38400:
293 #endif
294 		case B57600:
295 		case B76800:
296 		case B115200:
297 		case B153600:
298 		case B230400:
299 		case B307200:
300 		case B460800:
301 		case B9600:
302 			vtime = 1;
303 			break;
304 		case B4800:
305 			vtime = 4;
306 			break;
307 		default:
308 			vtime = 8;
309 			break;
310 		}
311 		if (tbufs.c_cc[VMIN] != packsize ||
312 		    tbufs.c_cc[VTIME] != vtime) {
313 		    tbufs.c_cc[VMIN] = packsize;
314 		    tbufs.c_cc[VTIME] = vtime;
315 		    if (istermios < 0) {
316 			tbuf.c_lflag = tbufs.c_lflag;
317 			tbuf.c_oflag = tbufs.c_oflag;
318 			tbuf.c_iflag = tbufs.c_iflag;
319 			tbuf.c_cflag = tbufs.c_cflag;
320 			for(i = 0; i < NCC; i++)
321 				tbuf.c_cc[i] = tbufs.c_cc[i];
322 		        if ( (*Ioctl)(Ifn, TCSETAW, &tbuf) != 0 )
323 			    DEBUG(4, "setline Ioctl failed errno=%d\n", errno);
324 		    } else {
325 		        if ( (*Ioctl)(Ifn, TCSETSW, &tbufs) != 0 )
326 			    DEBUG(4, "setline Ioctl failed errno=%d\n", errno);
327 		    }
328 		}
329 		break;
330 
331 	case SNDFILE:
332 	case RESET:
333 		if (tbufs.c_cc[VMIN] != HEADERSIZE) {
334 		    tbufs.c_cc[VMIN] = HEADERSIZE;
335 		    if (istermios < 0) {
336 			tbuf.c_lflag = tbufs.c_lflag;
337 			tbuf.c_oflag = tbufs.c_oflag;
338 			tbuf.c_iflag = tbufs.c_iflag;
339 			tbuf.c_cflag = tbufs.c_cflag;
340 			for(i = 0; i < NCC; i++)
341 				tbuf.c_cc[i] = tbufs.c_cc[i];
342 		    	if ( (*Ioctl)(Ifn, TCSETAW, &tbuf) != 0 )
343 			    DEBUG(4, "setline Ioctl failed errno=%d\n", errno);
344 		    } else {
345 		        if ( (*Ioctl)(Ifn, TCSETSW, &tbufs) != 0 )
346 			    DEBUG(4, "setline Ioctl failed errno=%d\n", errno);
347 		    }
348 		}
349 		break;
350 	}
351 	return;
352 }
353 
354 GLOBAL int
355 savline()
356 {
357 	if ((Saved_termios = (*Ioctl)(0, TCGETS, &Savettybs)) < 0) {
358 	    if ( (*Ioctl)(0, TCGETA, &Savettyb) != 0 ) {
359 		Saved_line = FALSE;
360 	    } else {
361 		Saved_line = TRUE;
362 		Savettyb.c_cflag = (Savettyb.c_cflag & ~CS8) | CS7 | PARENB;
363 		Savettyb.c_oflag |= OPOST;
364 		Savettyb.c_lflag |= (ISIG|ICANON|ECHO);
365 	    }
366 	} else {
367 		Saved_line = TRUE;
368 		Savettybs.c_cflag = (Savettybs.c_cflag & ~CS8) | CS7 | PARENB;
369 		Savettybs.c_oflag |= OPOST;
370 		Savettybs.c_lflag |= (ISIG|ICANON|ECHO);
371 	}
372 	return(0);
373 }
374 
375 #ifdef SYTEK
376 
377 /*
378  *	sytfixline(tty, spwant)	set speed/echo/mode...
379  *	int tty, spwant;
380  *
381  *	return codes:  none
382  */
383 
384 GLOBAL void
385 sytfixline(tty, spwant)
386 int tty, spwant;
387 {
388 	struct termio ttbuf;
389 	struct termios ttbufs;
390 	struct sg_spds *ps;
391 	int speed = -1;
392 	int i, ret, istermios;
393 
394 	if ((istermios = (*Ioctl)(tty, TCGETS, &ttbufs)) < 0) {
395 		if ( (*Ioctl)(tty, TCGETA, &ttbuf) != 0 ) {
396 			return;
397 		} else {
398 			ttbufs.c_lflag = ttbuf.c_lflag;
399 			ttbufs.c_oflag = ttbuf.c_oflag;
400 			ttbufs.c_iflag = ttbuf.c_iflag;
401 			ttbufs.c_cflag = ttbuf.c_cflag;
402 			for(i = 0; i < NCC; i++)
403 				ttbufs.c_cc[i] = ttbuf.c_cc[i];
404 		}
405 	}
406 	for (ps = spds; ps->sp_val >= 0; ps++)
407 		if (ps->sp_val == spwant)
408 			speed = ps->sp_name;
409 	DEBUG(4, "sytfixline - speed= %d\n", speed);
410 	ASSERT(speed >= 0, "BAD SPEED", "", spwant);
411 	ttbufs.c_iflag &= 0xffff0000;
412 	ttbufs.c_oflag &= 0xffff0000;
413 	ttbufs.c_lflag &= 0xffff0000;
414 	ttbufs.c_cflag &= 0xffff0000;
415 	cfsetospeed(&ttbufs, speed);
416 	ttbufs.c_cflag |= (CS8|CLOCAL);
417 	ttbufs.c_cc[VMIN] = 6;
418 	ttbufs.c_cc[VTIME] = 1;
419 	if (istermios < 0) {
420 		ttbuf.c_lflag = ttbufs.c_lflag;
421 		ttbuf.c_oflag = ttbufs.c_oflag;
422 		ttbuf.c_iflag = ttbufs.c_iflag;
423 		ttbuf.c_cflag = ttbufs.c_cflag;
424 		for(i = 0; i < NCC; i++)
425 			ttbuf.c_cc[i] = ttbufs.c_cc[i];
426 		ret = (*Ioctl)(tty, TCSETAW, &ttbuf);
427 	} else
428 		ret = (*Ioctl)(tty, TCSETAWS &ttbufs);
429 	ASSERT(ret >= 0, "RETURN FROM sytfixline", "", ret);
430 	return;
431 }
432 
433 GLOBAL void
434 sytfix2line(tty)
435 int tty;
436 {
437 	struct termio ttbuf;
438 	int ret;
439 
440 	if ( (*Ioctl)(tty, TCGETA, &ttbuf) != 0 )
441 		return;
442 	ttbuf.c_cflag &= ~CLOCAL;
443 	ttbuf.c_cflag |= CREAD|HUPCL;
444 	ret = (*Ioctl)(tty, TCSETAW, &ttbuf);
445 	ASSERT(ret >= 0, "RETURN FROM sytfix2line", "", ret);
446 	return;
447 }
448 
449 #endif /* SYTEK */
450 
451 GLOBAL int
452 restline()
453 {
454 	if ( Saved_line == TRUE ) {
455 		if (Saved_termios < 0)
456 			return((*Ioctl)(0, TCSETAW, &Savettyb));
457 		else
458 			return((*Ioctl)(0, TCSETSW, &Savettybs));
459 	}
460 	return(0);
461 }
462 
463 #else /* !ATTSVTTY */
464 
465 static struct sgttyb Savettyb;
466 
467 /*
468  *	fixline(tty, spwant, type)	set speed/echo/mode...
469  *	int tty, spwant;
470  *
471  *	if spwant == 0, speed is untouched
472  *	type is unused, but needed for compatibility
473  *
474  *	return codes:  none
475  */
476 
477 /*ARGSUSED*/
478 GLOBAL void
479 fixline(tty, spwant, type)
480 int tty, spwant, type;
481 {
482 	struct sgttyb	ttbuf;
483 	struct sg_spds	*ps;
484 	int		 speed = -1;
485 
486 	DEBUG(6, "fixline(%d, ", tty);
487 	DEBUG(6, "%d)\n", spwant);
488 
489 	if ((*Ioctl)(tty, TIOCGETP, &ttbuf) != 0)
490 		return;
491 	if (spwant > 0) {
492 		for (ps = spds; ps->sp_val; ps++)
493 			if (ps->sp_val == spwant) {
494 				speed = ps->sp_name;
495 				break;
496 			}
497 		ASSERT(speed >= 0, "BAD SPEED", "", spwant);
498 		ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed;
499 	} else {
500 		for (ps = spds; ps->sp_val; ps++)
501 			if (ps->sp_name == ttbuf.sg_ispeed) {
502 				spwant = ps->sp_val;
503 				break;
504 			}
505 		ASSERT(spwant >= 0, "BAD SPEED", "", ttbuf.sg_ispeed);
506 	}
507 	ttbuf.sg_flags = (ANYP | RAW);
508 #ifdef PKSPEEDUP
509 	linebaudrate = spwant;
510 #endif /*  PKSPEEDUP  */
511 	(void) (*Ioctl)(tty, TIOCSETP, &ttbuf);
512 	(void) (*Ioctl)(tty, TIOCHPCL, STBNULL);
513 	(void) (*Ioctl)(tty, TIOCEXCL, STBNULL);
514 	return;
515 }
516 
517 GLOBAL void
518 sethup(dcf)
519 int	dcf;
520 {
521 	if (isatty(dcf))
522 		(void) (*Ioctl)(dcf, TIOCHPCL, STBNULL);
523 	return;
524 }
525 
526 /*
527  *	genbrk		send a break
528  *
529  *	return codes;  none
530  */
531 
532 GLOBAL void
533 ttygenbrk(fn)
534 {
535 	if (isatty(fn)) {
536 		(void) (*Ioctl)(fn, TIOCSBRK, 0);
537 #ifndef V8
538 		nap(HZ/10);				/* 0.1 second break */
539 		(void) (*Ioctl)(fn, TIOCCBRK, 0);
540 #endif
541 	}
542 	return;
543 }
544 
545 /*
546  * V7 and RT aren't smart enough for this -- linebaudrate is the best
547  * they can do.
548  */
549 /*ARGSUSED*/
550 GLOBAL void
551 setline(dummy) { }
552 
553 GLOBAL int
554 savline()
555 {
556 	if (  (*Ioctl)(0, TIOCGETP, &Savettyb) != 0 )
557 		Saved_line = FALSE;
558 	else {
559 		Saved_line = TRUE;
560 		Savettyb.sg_flags |= ECHO;
561 		Savettyb.sg_flags &= ~RAW;
562 	}
563 	return(0);
564 }
565 
566 GLOBAL int
567 restline()
568 {
569 	if ( Saved_line == TRUE )
570 		return((*Ioctl)(0, TIOCSETP, &Savettyb));
571 	return(0);
572 }
573 #endif
574