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 int 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 { 19200, B19200 }, 55 { 38400, B38400 }, 56 { 57600, B57600 }, 57 { 76800, B76800 }, 58 { 115200, B115200 }, 59 { 153600, B153600 }, 60 { 230400, B230400 }, 61 { 307200, B307200 }, 62 { 460800, B460800 }, 63 { 921600, B921600 }, 64 { 1000000, B1000000 }, 65 { 1152000, B1152000 }, 66 { 1500000, B1500000 }, 67 { 2000000, B2000000 }, 68 { 2500000, B2500000 }, 69 { 3000000, B3000000 }, 70 { 3500000, B3500000 }, 71 { 4000000, B4000000 }, 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 232 GLOBAL void 233 sethup(dcf) 234 int dcf; 235 { 236 struct termio ttbuf; 237 238 if ((*Ioctl)(dcf, TCGETA, &ttbuf) != 0) 239 return; 240 if (!(ttbuf.c_cflag & HUPCL)) { 241 ttbuf.c_cflag |= HUPCL; 242 (void) (*Ioctl)(dcf, TCSETAW, &ttbuf); 243 } 244 } 245 246 GLOBAL void 247 ttygenbrk(fn) 248 register int fn; 249 { 250 if (isatty(fn)) 251 (void) (*Ioctl)(fn, TCSBRK, 0); 252 } 253 254 255 /* 256 * optimize line setting for sending or receiving files 257 * return: 258 * none 259 */ 260 GLOBAL void 261 setline(type) 262 register char type; 263 { 264 static struct termio tbuf; 265 static struct termios tbufs; 266 int i, vtime, istermios, ospeed; 267 268 DEBUG(2, "setline - %c\n", type); 269 270 if ((istermios = (*Ioctl)(Ifn, TCGETS, &tbufs)) < 0) { 271 if ((*Ioctl)(Ifn, TCGETA, &tbuf) != 0) { 272 return; 273 } else { 274 tbufs.c_lflag = tbuf.c_lflag; 275 tbufs.c_oflag = tbuf.c_oflag; 276 tbufs.c_iflag = tbuf.c_iflag; 277 tbufs.c_cflag = tbuf.c_cflag; 278 for (i = 0; i < NCC; i++) 279 tbufs.c_cc[i] = tbuf.c_cc[i]; 280 } 281 } 282 switch (type) { 283 case RCVFILE: 284 ospeed = cfgetospeed(&tbufs); 285 switch (ospeed) { 286 #ifdef B19200 287 case B19200: 288 #else 289 #ifdef EXTA 290 case EXTA: 291 #endif 292 #endif 293 #ifdef B38400 294 case B38400: 295 #endif 296 case B57600: 297 case B76800: 298 case B115200: 299 case B153600: 300 case B230400: 301 case B307200: 302 case B460800: 303 case B921600: 304 case B9600: 305 vtime = 1; 306 break; 307 case B4800: 308 vtime = 4; 309 break; 310 default: 311 vtime = 8; 312 break; 313 } 314 if (tbufs.c_cc[VMIN] != packsize || 315 tbufs.c_cc[VTIME] != vtime) { 316 tbufs.c_cc[VMIN] = packsize; 317 tbufs.c_cc[VTIME] = vtime; 318 if (istermios < 0) { 319 tbuf.c_lflag = tbufs.c_lflag; 320 tbuf.c_oflag = tbufs.c_oflag; 321 tbuf.c_iflag = tbufs.c_iflag; 322 tbuf.c_cflag = tbufs.c_cflag; 323 for (i = 0; i < NCC; i++) 324 tbuf.c_cc[i] = tbufs.c_cc[i]; 325 if ((*Ioctl)(Ifn, TCSETAW, &tbuf) != 0) 326 DEBUG(4, "setline Ioctl failed errno=%d\n", 327 errno); 328 } else { 329 if ((*Ioctl)(Ifn, TCSETSW, &tbufs) != 0) 330 DEBUG(4, 331 "setline Ioctl failed errno=%d\n", 332 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, 350 "setline Ioctl failed errno=%d\n", 351 errno); 352 } else { 353 if ((*Ioctl)(Ifn, TCSETSW, &tbufs) != 0) 354 DEBUG(4, 355 "setline Ioctl failed errno=%d\n", 356 errno); 357 } 358 } 359 break; 360 } 361 } 362 363 GLOBAL int 364 savline() 365 { 366 if ((Saved_termios = (*Ioctl)(0, TCGETS, &Savettybs)) < 0) { 367 if ((*Ioctl)(0, TCGETA, &Savettyb) != 0) { 368 Saved_line = FALSE; 369 } else { 370 Saved_line = TRUE; 371 Savettyb.c_cflag = 372 (Savettyb.c_cflag & ~CS8) | CS7 | PARENB; 373 Savettyb.c_oflag |= OPOST; 374 Savettyb.c_lflag |= (ISIG|ICANON|ECHO); 375 } 376 } else { 377 Saved_line = TRUE; 378 Savettybs.c_cflag = (Savettybs.c_cflag & ~CS8) | CS7 | PARENB; 379 Savettybs.c_oflag |= OPOST; 380 Savettybs.c_lflag |= (ISIG|ICANON|ECHO); 381 } 382 return (0); 383 } 384 385 #ifdef SYTEK 386 387 /* 388 * sytfixline(tty, spwant) set speed/echo/mode... 389 * int tty, spwant; 390 * 391 * return codes: none 392 */ 393 394 GLOBAL void 395 sytfixline(tty, spwant) 396 int tty, spwant; 397 { 398 struct termio ttbuf; 399 struct termios ttbufs; 400 struct sg_spds *ps; 401 int speed = -1; 402 int i, ret, istermios; 403 404 if ((istermios = (*Ioctl)(tty, TCGETS, &ttbufs)) < 0) { 405 if ((*Ioctl)(tty, TCGETA, &ttbuf) != 0) { 406 return; 407 } else { 408 ttbufs.c_lflag = ttbuf.c_lflag; 409 ttbufs.c_oflag = ttbuf.c_oflag; 410 ttbufs.c_iflag = ttbuf.c_iflag; 411 ttbufs.c_cflag = ttbuf.c_cflag; 412 for (i = 0; i < NCC; i++) 413 ttbufs.c_cc[i] = ttbuf.c_cc[i]; 414 } 415 } 416 for (ps = spds; ps->sp_val >= 0; ps++) 417 if (ps->sp_val == spwant) 418 speed = ps->sp_name; 419 DEBUG(4, "sytfixline - speed= %d\n", speed); 420 ASSERT(speed >= 0, "BAD SPEED", "", spwant); 421 ttbufs.c_iflag &= 0xffff0000; 422 ttbufs.c_oflag &= 0xffff0000; 423 ttbufs.c_lflag &= 0xffff0000; 424 ttbufs.c_cflag &= 0xffff0000; 425 cfsetospeed(&ttbufs, speed); 426 ttbufs.c_cflag |= (CS8|CLOCAL); 427 ttbufs.c_cc[VMIN] = 6; 428 ttbufs.c_cc[VTIME] = 1; 429 if (istermios < 0) { 430 ttbuf.c_lflag = ttbufs.c_lflag; 431 ttbuf.c_oflag = ttbufs.c_oflag; 432 ttbuf.c_iflag = ttbufs.c_iflag; 433 ttbuf.c_cflag = ttbufs.c_cflag; 434 for (i = 0; i < NCC; i++) 435 ttbuf.c_cc[i] = ttbufs.c_cc[i]; 436 ret = (*Ioctl)(tty, TCSETAW, &ttbuf); 437 } else 438 ret = (*Ioctl)(tty, TCSETAWS &ttbufs); 439 ASSERT(ret >= 0, "RETURN FROM sytfixline", "", ret); 440 } 441 442 GLOBAL void 443 sytfix2line(tty) 444 int tty; 445 { 446 struct termio ttbuf; 447 int ret; 448 449 if ((*Ioctl)(tty, TCGETA, &ttbuf) != 0) 450 return; 451 ttbuf.c_cflag &= ~CLOCAL; 452 ttbuf.c_cflag |= CREAD|HUPCL; 453 ret = (*Ioctl)(tty, TCSETAW, &ttbuf); 454 ASSERT(ret >= 0, "RETURN FROM sytfix2line", "", ret); 455 } 456 457 #endif /* SYTEK */ 458 459 GLOBAL int 460 restline() 461 { 462 if (Saved_line == TRUE) { 463 if (Saved_termios < 0) 464 return ((*Ioctl)(0, TCSETAW, &Savettyb)); 465 else 466 return ((*Ioctl)(0, TCSETSW, &Savettybs)); 467 } 468 return (0); 469 } 470 471 #else /* !ATTSVTTY */ 472 473 static struct sgttyb Savettyb; 474 475 /* 476 * fixline(tty, spwant, type) set speed/echo/mode... 477 * int tty, spwant; 478 * 479 * if spwant == 0, speed is untouched 480 * type is unused, but needed for compatibility 481 * 482 * return codes: none 483 */ 484 485 /*ARGSUSED*/ 486 GLOBAL void 487 fixline(tty, spwant, type) 488 int tty, spwant, type; 489 { 490 struct sgttyb ttbuf; 491 struct sg_spds *ps; 492 int speed = -1; 493 494 DEBUG(6, "fixline(%d, ", tty); 495 DEBUG(6, "%d)\n", spwant); 496 497 if ((*Ioctl)(tty, TIOCGETP, &ttbuf) != 0) 498 return; 499 if (spwant > 0) { 500 for (ps = spds; ps->sp_val; ps++) 501 if (ps->sp_val == spwant) { 502 speed = ps->sp_name; 503 break; 504 } 505 ASSERT(speed >= 0, "BAD SPEED", "", spwant); 506 ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed; 507 } else { 508 for (ps = spds; ps->sp_val; ps++) 509 if (ps->sp_name == ttbuf.sg_ispeed) { 510 spwant = ps->sp_val; 511 break; 512 } 513 ASSERT(spwant >= 0, "BAD SPEED", "", ttbuf.sg_ispeed); 514 } 515 ttbuf.sg_flags = (ANYP | RAW); 516 #ifdef PKSPEEDUP 517 linebaudrate = spwant; 518 #endif /* PKSPEEDUP */ 519 (void) (*Ioctl)(tty, TIOCSETP, &ttbuf); 520 (void) (*Ioctl)(tty, TIOCHPCL, STBNULL); 521 (void) (*Ioctl)(tty, TIOCEXCL, STBNULL); 522 } 523 524 GLOBAL void 525 sethup(dcf) 526 int dcf; 527 { 528 if (isatty(dcf)) 529 (void) (*Ioctl)(dcf, TIOCHPCL, STBNULL); 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 } 549 550 /* 551 * V7 and RT aren't smart enough for this -- linebaudrate is the best 552 * they can do. 553 */ 554 /*ARGSUSED*/ 555 GLOBAL void 556 setline(dummy) { } 557 558 GLOBAL int 559 savline() 560 { 561 if ((*Ioctl)(0, TIOCGETP, &Savettyb) != 0) 562 Saved_line = FALSE; 563 else { 564 Saved_line = TRUE; 565 Savettyb.sg_flags |= ECHO; 566 Savettyb.sg_flags &= ~RAW; 567 } 568 return (0); 569 } 570 571 GLOBAL int 572 restline() 573 { 574 if (Saved_line == TRUE) 575 return ((*Ioctl)(0, TIOCSETP, &Savettyb)); 576 return (0); 577 } 578 #endif 579