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