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