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