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