Home | History | Annotate | Download | only in bnu
      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 	/*
    164 	 * In order to prevent attempts at split speed, all baud rate
    165 	 * bitfields should be cleared. Thus cfsetispeed is used to
    166 	 * set the speed to zero.
    167 	 */
    168 	(void) cfsetispeed(&ttbufs, 0);
    169 	ttbufs.c_iflag &= 0xffff0000;
    170 	ttbufs.c_oflag &= 0xffff0000;
    171 	ttbufs.c_lflag &= 0xffff0000;
    172 #ifdef PKSPEEDUP
    173 	linebaudrate = spwant;
    174 #endif /*  PKSPEEDUP  */
    175 
    176 #ifdef NO_MODEM_CTRL
    177 	/*   CLOCAL may cause problems on pdp11s with DHs */
    178 	if (type == D_DIRECT) {
    179 		DEBUG(4, "fixline - direct\n%s", "");
    180 		ttbufs.c_cflag |= CLOCAL;
    181 	} else
    182 #endif /* NO_MODEM_CTRL */
    183 		ttbufs.c_cflag &= ~CLOCAL;
    184 
    185 	if ( !EQUALS(Progname, "uucico") ) {
    186 
    187 		/* set attributes associated with -h, -t, -e, and -o options */
    188 
    189 		ttbufs.c_iflag = (IGNPAR | IGNBRK | IXON | IXOFF);
    190 		ttbufs.c_cc[VEOF] = '\1';
    191 		ttbufs.c_cflag |= ( CREAD | (speed ? HUPCL : 0));
    192 
    193 		if ( line_8bit ) {
    194 		    ttbufs.c_cflag |= CS8;
    195 		    ttbufs.c_iflag &= ~ISTRIP;
    196 		} else {
    197 		    if (Evenflag) {			/*even parity -e */
    198 			ttbufs.c_cflag &= ~PARODD;
    199 		    } else if(Oddflag) {		/*odd parity -o */
    200 			ttbufs.c_cflag |= PARODD;
    201 		    }
    202 		    ttbufs.c_cflag |= CS7|PARENB;
    203 		    ttbufs.c_iflag |= ISTRIP;
    204 		}
    205 
    206 		if(!Duplex)				/*half duplex -h */
    207 		    ttbufs.c_iflag &= ~(IXON | IXOFF);
    208 		if(Terminal)				/* -t */
    209 		    ttbufs.c_oflag |= (OPOST | ONLCR);
    210 
    211 	} else { /* non-uucico */
    212 		ttbufs.c_cflag |= (CS8 | CREAD | (speed ? HUPCL : 0));
    213 		ttbufs.c_cc[VMIN] = HEADERSIZE;
    214 		ttbufs.c_cc[VTIME] = 1;
    215 	}
    216 
    217 	if (istermios < 0) {
    218 		ttbuf.c_lflag = ttbufs.c_lflag;
    219 		ttbuf.c_oflag = ttbufs.c_oflag;
    220 		ttbuf.c_iflag = ttbufs.c_iflag;
    221 		ttbuf.c_cflag = ttbufs.c_cflag;
    222 		for(i = 0; i < NCC; i++)
    223 			ttbuf.c_cc[i] = ttbufs.c_cc[i];
    224 		ASSERT((*Ioctl)(tty, TCSETAW, &ttbuf) >= 0,
    225 	    	    "RETURN FROM fixline ioctl", "", errno);
    226 	} else {
    227 		ASSERT((*Ioctl)(tty, TCSETSW, &ttbufs) >= 0,
    228 	    	    "RETURN FROM fixline ioctl", "", errno);
    229 	}
    230 
    231 	return;
    232 }
    233 
    234 GLOBAL void
    235 sethup(dcf)
    236 int	dcf;
    237 {
    238 	struct termio ttbuf;
    239 
    240 	if ((*Ioctl)(dcf, TCGETA, &ttbuf) != 0)
    241 		return;
    242 	if (!(ttbuf.c_cflag & HUPCL)) {
    243 		ttbuf.c_cflag |= HUPCL;
    244 		(void) (*Ioctl)(dcf, TCSETAW, &ttbuf);
    245 	}
    246 	return;
    247 }
    248 
    249 GLOBAL void
    250 ttygenbrk(fn)
    251 register int	fn;
    252 {
    253 	if (isatty(fn))
    254 		(void) (*Ioctl)(fn, TCSBRK, 0);
    255 	return;
    256 }
    257 
    258 
    259 /*
    260  * optimize line setting for sending or receiving files
    261  * return:
    262  *	none
    263  */
    264 GLOBAL void
    265 setline(type)
    266 register char	type;
    267 {
    268 	static struct termio tbuf;
    269 	static struct termios tbufs;
    270 	int i, vtime, istermios, ospeed;
    271 
    272 	DEBUG(2, "setline - %c\n", type);
    273 
    274 	if ((istermios = (*Ioctl)(Ifn, TCGETS, &tbufs)) < 0) {
    275 		if ((*Ioctl)(Ifn, TCGETA, &tbuf) != 0) {
    276 			return;
    277 		} else {
    278 			tbufs.c_lflag = tbuf.c_lflag;
    279 			tbufs.c_oflag = tbuf.c_oflag;
    280 			tbufs.c_iflag = tbuf.c_iflag;
    281 			tbufs.c_cflag = tbuf.c_cflag;
    282 			for(i = 0; i < NCC; i++)
    283 				tbufs.c_cc[i] = tbuf.c_cc[i];
    284 		}
    285 	}
    286 	switch (type) {
    287 	case RCVFILE:
    288 		ospeed = cfgetospeed(&tbufs);
    289 		switch (ospeed) {
    290 #ifdef B19200
    291 		case B19200:
    292 #else
    293 #ifdef EXTA
    294 		case EXTA:
    295 #endif
    296 #endif
    297 #ifdef B38400
    298 		case B38400:
    299 #endif
    300 		case B57600:
    301 		case B76800:
    302 		case B115200:
    303 		case B153600:
    304 		case B230400:
    305 		case B307200:
    306 		case B460800:
    307 		case B9600:
    308 			vtime = 1;
    309 			break;
    310 		case B4800:
    311 			vtime = 4;
    312 			break;
    313 		default:
    314 			vtime = 8;
    315 			break;
    316 		}
    317 		if (tbufs.c_cc[VMIN] != packsize ||
    318 		    tbufs.c_cc[VTIME] != vtime) {
    319 		    tbufs.c_cc[VMIN] = packsize;
    320 		    tbufs.c_cc[VTIME] = vtime;
    321 		    if (istermios < 0) {
    322 			tbuf.c_lflag = tbufs.c_lflag;
    323 			tbuf.c_oflag = tbufs.c_oflag;
    324 			tbuf.c_iflag = tbufs.c_iflag;
    325 			tbuf.c_cflag = tbufs.c_cflag;
    326 			for(i = 0; i < NCC; i++)
    327 				tbuf.c_cc[i] = tbufs.c_cc[i];
    328 		        if ( (*Ioctl)(Ifn, TCSETAW, &tbuf) != 0 )
    329 			    DEBUG(4, "setline Ioctl failed errno=%d\n", errno);
    330 		    } else {
    331 		        if ( (*Ioctl)(Ifn, TCSETSW, &tbufs) != 0 )
    332 			    DEBUG(4, "setline Ioctl failed errno=%d\n", errno);
    333 		    }
    334 		}
    335 		break;
    336 
    337 	case SNDFILE:
    338 	case RESET:
    339 		if (tbufs.c_cc[VMIN] != HEADERSIZE) {
    340 		    tbufs.c_cc[VMIN] = HEADERSIZE;
    341 		    if (istermios < 0) {
    342 			tbuf.c_lflag = tbufs.c_lflag;
    343 			tbuf.c_oflag = tbufs.c_oflag;
    344 			tbuf.c_iflag = tbufs.c_iflag;
    345 			tbuf.c_cflag = tbufs.c_cflag;
    346 			for(i = 0; i < NCC; i++)
    347 				tbuf.c_cc[i] = tbufs.c_cc[i];
    348 		    	if ( (*Ioctl)(Ifn, TCSETAW, &tbuf) != 0 )
    349 			    DEBUG(4, "setline Ioctl failed errno=%d\n", errno);
    350 		    } else {
    351 		        if ( (*Ioctl)(Ifn, TCSETSW, &tbufs) != 0 )
    352 			    DEBUG(4, "setline Ioctl failed errno=%d\n", errno);
    353 		    }
    354 		}
    355 		break;
    356 	}
    357 	return;
    358 }
    359 
    360 GLOBAL int
    361 savline()
    362 {
    363 	if ((Saved_termios = (*Ioctl)(0, TCGETS, &Savettybs)) < 0) {
    364 	    if ( (*Ioctl)(0, TCGETA, &Savettyb) != 0 ) {
    365 		Saved_line = FALSE;
    366 	    } else {
    367 		Saved_line = TRUE;
    368 		Savettyb.c_cflag = (Savettyb.c_cflag & ~CS8) | CS7 | PARENB;
    369 		Savettyb.c_oflag |= OPOST;
    370 		Savettyb.c_lflag |= (ISIG|ICANON|ECHO);
    371 	    }
    372 	} else {
    373 		Saved_line = TRUE;
    374 		Savettybs.c_cflag = (Savettybs.c_cflag & ~CS8) | CS7 | PARENB;
    375 		Savettybs.c_oflag |= OPOST;
    376 		Savettybs.c_lflag |= (ISIG|ICANON|ECHO);
    377 	}
    378 	return(0);
    379 }
    380 
    381 #ifdef SYTEK
    382 
    383 /*
    384  *	sytfixline(tty, spwant)	set speed/echo/mode...
    385  *	int tty, spwant;
    386  *
    387  *	return codes:  none
    388  */
    389 
    390 GLOBAL void
    391 sytfixline(tty, spwant)
    392 int tty, spwant;
    393 {
    394 	struct termio ttbuf;
    395 	struct termios ttbufs;
    396 	struct sg_spds *ps;
    397 	int speed = -1;
    398 	int i, ret, istermios;
    399 
    400 	if ((istermios = (*Ioctl)(tty, TCGETS, &ttbufs)) < 0) {
    401 		if ( (*Ioctl)(tty, TCGETA, &ttbuf) != 0 ) {
    402 			return;
    403 		} else {
    404 			ttbufs.c_lflag = ttbuf.c_lflag;
    405 			ttbufs.c_oflag = ttbuf.c_oflag;
    406 			ttbufs.c_iflag = ttbuf.c_iflag;
    407 			ttbufs.c_cflag = ttbuf.c_cflag;
    408 			for(i = 0; i < NCC; i++)
    409 				ttbufs.c_cc[i] = ttbuf.c_cc[i];
    410 		}
    411 	}
    412 	for (ps = spds; ps->sp_val >= 0; ps++)
    413 		if (ps->sp_val == spwant)
    414 			speed = ps->sp_name;
    415 	DEBUG(4, "sytfixline - speed= %d\n", speed);
    416 	ASSERT(speed >= 0, "BAD SPEED", "", spwant);
    417 	ttbufs.c_iflag &= 0xffff0000;
    418 	ttbufs.c_oflag &= 0xffff0000;
    419 	ttbufs.c_lflag &= 0xffff0000;
    420 	ttbufs.c_cflag &= 0xffff0000;
    421 	cfsetospeed(&ttbufs, speed);
    422 	ttbufs.c_cflag |= (CS8|CLOCAL);
    423 	ttbufs.c_cc[VMIN] = 6;
    424 	ttbufs.c_cc[VTIME] = 1;
    425 	if (istermios < 0) {
    426 		ttbuf.c_lflag = ttbufs.c_lflag;
    427 		ttbuf.c_oflag = ttbufs.c_oflag;
    428 		ttbuf.c_iflag = ttbufs.c_iflag;
    429 		ttbuf.c_cflag = ttbufs.c_cflag;
    430 		for(i = 0; i < NCC; i++)
    431 			ttbuf.c_cc[i] = ttbufs.c_cc[i];
    432 		ret = (*Ioctl)(tty, TCSETAW, &ttbuf);
    433 	} else
    434 		ret = (*Ioctl)(tty, TCSETAWS &ttbufs);
    435 	ASSERT(ret >= 0, "RETURN FROM sytfixline", "", ret);
    436 	return;
    437 }
    438 
    439 GLOBAL void
    440 sytfix2line(tty)
    441 int tty;
    442 {
    443 	struct termio ttbuf;
    444 	int ret;
    445 
    446 	if ( (*Ioctl)(tty, TCGETA, &ttbuf) != 0 )
    447 		return;
    448 	ttbuf.c_cflag &= ~CLOCAL;
    449 	ttbuf.c_cflag |= CREAD|HUPCL;
    450 	ret = (*Ioctl)(tty, TCSETAW, &ttbuf);
    451 	ASSERT(ret >= 0, "RETURN FROM sytfix2line", "", ret);
    452 	return;
    453 }
    454 
    455 #endif /* SYTEK */
    456 
    457 GLOBAL int
    458 restline()
    459 {
    460 	if ( Saved_line == TRUE ) {
    461 		if (Saved_termios < 0)
    462 			return((*Ioctl)(0, TCSETAW, &Savettyb));
    463 		else
    464 			return((*Ioctl)(0, TCSETSW, &Savettybs));
    465 	}
    466 	return(0);
    467 }
    468 
    469 #else /* !ATTSVTTY */
    470 
    471 static struct sgttyb Savettyb;
    472 
    473 /*
    474  *	fixline(tty, spwant, type)	set speed/echo/mode...
    475  *	int tty, spwant;
    476  *
    477  *	if spwant == 0, speed is untouched
    478  *	type is unused, but needed for compatibility
    479  *
    480  *	return codes:  none
    481  */
    482 
    483 /*ARGSUSED*/
    484 GLOBAL void
    485 fixline(tty, spwant, type)
    486 int tty, spwant, type;
    487 {
    488 	struct sgttyb	ttbuf;
    489 	struct sg_spds	*ps;
    490 	int		 speed = -1;
    491 
    492 	DEBUG(6, "fixline(%d, ", tty);
    493 	DEBUG(6, "%d)\n", spwant);
    494 
    495 	if ((*Ioctl)(tty, TIOCGETP, &ttbuf) != 0)
    496 		return;
    497 	if (spwant > 0) {
    498 		for (ps = spds; ps->sp_val; ps++)
    499 			if (ps->sp_val == spwant) {
    500 				speed = ps->sp_name;
    501 				break;
    502 			}
    503 		ASSERT(speed >= 0, "BAD SPEED", "", spwant);
    504 		ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed;
    505 	} else {
    506 		for (ps = spds; ps->sp_val; ps++)
    507 			if (ps->sp_name == ttbuf.sg_ispeed) {
    508 				spwant = ps->sp_val;
    509 				break;
    510 			}
    511 		ASSERT(spwant >= 0, "BAD SPEED", "", ttbuf.sg_ispeed);
    512 	}
    513 	ttbuf.sg_flags = (ANYP | RAW);
    514 #ifdef PKSPEEDUP
    515 	linebaudrate = spwant;
    516 #endif /*  PKSPEEDUP  */
    517 	(void) (*Ioctl)(tty, TIOCSETP, &ttbuf);
    518 	(void) (*Ioctl)(tty, TIOCHPCL, STBNULL);
    519 	(void) (*Ioctl)(tty, TIOCEXCL, STBNULL);
    520 	return;
    521 }
    522 
    523 GLOBAL void
    524 sethup(dcf)
    525 int	dcf;
    526 {
    527 	if (isatty(dcf))
    528 		(void) (*Ioctl)(dcf, TIOCHPCL, STBNULL);
    529 	return;
    530 }
    531 
    532 /*
    533  *	genbrk		send a break
    534  *
    535  *	return codes;  none
    536  */
    537 
    538 GLOBAL void
    539 ttygenbrk(fn)
    540 {
    541 	if (isatty(fn)) {
    542 		(void) (*Ioctl)(fn, TIOCSBRK, 0);
    543 #ifndef V8
    544 		nap(HZ/10);				/* 0.1 second break */
    545 		(void) (*Ioctl)(fn, TIOCCBRK, 0);
    546 #endif
    547 	}
    548 	return;
    549 }
    550 
    551 /*
    552  * V7 and RT aren't smart enough for this -- linebaudrate is the best
    553  * they can do.
    554  */
    555 /*ARGSUSED*/
    556 GLOBAL void
    557 setline(dummy) { }
    558 
    559 GLOBAL int
    560 savline()
    561 {
    562 	if (  (*Ioctl)(0, TIOCGETP, &Savettyb) != 0 )
    563 		Saved_line = FALSE;
    564 	else {
    565 		Saved_line = TRUE;
    566 		Savettyb.sg_flags |= ECHO;
    567 		Savettyb.sg_flags &= ~RAW;
    568 	}
    569 	return(0);
    570 }
    571 
    572 GLOBAL int
    573 restline()
    574 {
    575 	if ( Saved_line == TRUE )
    576 		return((*Ioctl)(0, TIOCSETP, &Savettyb));
    577 	return(0);
    578 }
    579 #endif
    580