1 /* 2 rbsb.c - terminal handling stuff for lrzsz 3 Copyright (C) until 1988 Chuck Forsberg (Omen Technology INC) 4 Copyright (C) 1994 Matt Porter, Michael D. Black 5 Copyright (C) 1996, 1997 Uwe Ohse 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2, or (at your option) 10 any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 20 02111-1307, USA. 21 22 originally written by Chuck Forsberg 23 */ 24 25 /* 26 * Rev 05-05-1988 27 * ============== (not quite, but originated there :-). -- uwe 28 */ 29 #include "zglobal.h" 30 31 #include <stdio.h> 32 #include <errno.h> 33 34 #ifndef HAVE_ERRNO_DECLARATION 35 extern int errno; 36 #endif 37 38 #ifdef USE_SGTTY 39 # ifdef LLITOUT 40 long Locmode; /* Saved "local mode" for 4.x BSD "new driver" */ 41 long Locbit = LLITOUT; /* Bit SUPPOSED to disable output translations */ 42 # endif 43 #endif 44 45 #ifdef HAVE_SYS_IOCTL_H 46 #include <sys/ioctl.h> 47 #endif 48 49 #ifdef MAJOR_IN_MKDEV 50 #include <sys/mkdev.h> 51 #else 52 # ifdef MAJOR_IN_SYSMACROS 53 # include <sys/sysmacros.h> 54 # endif 55 #endif 56 #ifndef HOWMANY 57 #ifdef NFGVMIN 58 #define HOWMANY MAX_BLOCK 59 #else 60 #define HOWMANY 255 61 #endif 62 #endif 63 64 65 #if defined(HOWMANY) && HOWMANY > 255 66 #ifndef NFGVMIN 67 Howmany must be 255 or less 68 #endif 69 #endif 70 71 #define B110 110 72 #define B300 300 73 #define B600 600 74 #define B1200 1200 75 #define B2400 2400 76 #define B2400 2400 77 static struct { 78 unsigned baudr; 79 int speedcode; 80 } speeds[] = { 81 {110, B110}, 82 {300, B300}, 83 {600, B600}, 84 {1200, B1200}, 85 #ifdef B19200 86 {19200, B19200}, 87 #endif 88 #ifdef B38400 89 {38400, B38400}, 90 #endif 91 #ifdef B57600 92 {57600, B57600}, 93 #endif 94 #ifdef B115200 95 {115200, B115200}, 96 #endif 97 #ifdef B230400 98 {230400, B230400}, 99 #endif 100 #ifdef B460800 101 {460800, B460800}, 102 #endif 103 #ifdef EXTA 104 {19200, EXTA}, 105 #endif 106 #ifdef EXTB 107 {38400, EXTB}, 108 #endif 109 {0, 0} 110 }; 111 112 static unsigned 113 getspeed(int code) 114 { 115 int n; 116 117 for (n=0; speeds[n].baudr; ++n) 118 if (speeds[n].speedcode == code) 119 return speeds[n].baudr; 120 return 38400; /* Assume fifo if ioctl failed */ 121 } 122 123 /* 124 * return 1 if stdout and stderr are different devices 125 * indicating this program operating with a modem on a 126 * different line 127 */ 128 int Fromcu; /* Were called from cu or yam */ 129 int 130 from_cu(void) 131 { 132 #if 0 133 #ifdef HAVE_ST_RDEV 134 struct stat a, b; 135 #if defined(makedev) 136 dev_t help=makedev(0,0); 137 #else 138 int help=0; 139 #endif 140 141 /* in case fstat fails */ 142 a.st_rdev=b.st_rdev=a.st_dev=b.st_dev=help; 143 144 fstat(1, &a); fstat(2, &b); 145 146 #if defined(major) && defined(minor) 147 if (major(a.st_rdev) != major(b.st_rdev) 148 || minor(a.st_rdev) != minor(b.st_rdev)) 149 Fromcu=1; 150 else if (major(a.st_dev) != major(b.st_dev) 151 || minor(a.st_dev) != minor(b.st_dev)) 152 Fromcu=1; 153 else 154 Fromcu=0; 155 #else 156 Fromcu = (a.st_rdev != b.st_rdev) || (a.st_dev != b.st_dev); 157 #endif 158 #else 159 Fromcu = 1; /* a bad guess .. */ 160 #endif 161 return Fromcu; 162 #endif 163 return 0; 164 } 165 166 167 168 int Twostop; /* Use two stop bits */ 169 170 171 #ifdef READCHECK_FIONREAD 172 /* 173 * Return non 0 if something to read from io descriptor f 174 */ 175 int 176 rdchk(int fd) 177 { 178 static long lf; 179 180 ioctl(fd, FIONREAD, &lf); 181 return ((int) lf); 182 } 183 #endif 184 185 #ifdef READCHECK_GETFL 186 unsigned char checked = '\0' ; 187 /* 188 * Nonblocking I/O is a bit different in System V, Release 2 189 */ 190 int 191 rdchk(int fd) 192 { 193 int lf, savestat; 194 195 savestat = fcntl(fd, F_GETFL) ; 196 if (savestat == -1) 197 return 0; 198 #ifdef OVERLY_PARANOID 199 if (-1==fcntl(fd, F_SETFL, savestat | O_NDELAY)) 200 return 0; 201 lf = read(fd, &checked, 1) ; 202 if (-1==fcntl(fd, F_SETFL, savestat)) { 203 #ifdef ENABLE_SYSLOG 204 if (enable_syslog) 205 lsyslog(LOG_CRIT,"F_SETFL failed in rdchk(): %s", 206 strerror(errno)); 207 #endif 208 zpfatal("rdchk: F_SETFL failed\n"); /* lose */ 209 /* there is really no way to recover. And we can't tell 210 * the other side what's going on if we can't write to 211 * fd, but we try. 212 */ 213 canit(fd); 214 exit(1); 215 } 216 #else 217 fcntl(fd, F_SETFL, savestat | O_NDELAY); 218 lf = read(fd, &checked, 1) ; 219 fcntl(fd, F_SETFL, savestat); 220 #endif 221 return(lf == -1 && errno==EWOULDBLOCK ? 0 : lf) ; 222 } 223 #endif 224 225 226 227 228 229 #ifdef USE_TERMIOS 230 struct termios oldtty, tty; 231 #else 232 # if defined(USE_TERMIO) 233 struct termio oldtty, tty; 234 # else 235 //struct sgttyb oldtty, tty; 236 //struct tchars oldtch, tch; 237 # endif 238 #endif 239 240 241 /* 242 * mode(n) 243 * 3: save old tty stat, set raw mode with flow control 244 * 2: set XON/XOFF for sb/sz with ZMODEM or YMODEM-g 245 * 1: save old tty stat, set raw mode 246 * 0: restore original tty mode 247 */ 248 int 249 io_mode(int fd, int n) 250 { 251 #if 1 252 static int did0 = FALSE; 253 254 vfile("mode:%d", n); 255 256 switch(n) { 257 258 #ifdef USE_TERMIOS 259 case 2: /* Un-raw mode used by sz, sb when -g detected */ 260 if(!did0) { 261 did0 = TRUE; 262 tcgetattr(fd,&oldtty); 263 } 264 tty = oldtty; 265 266 tty.c_iflag = BRKINT|IXON; 267 268 tty.c_oflag = 0; /* Transparent output */ 269 270 tty.c_cflag &= ~PARENB; /* Disable parity */ 271 tty.c_cflag |= CS8; /* Set character size = 8 */ 272 if (Twostop) 273 tty.c_cflag |= CSTOPB; /* Set two stop bits */ 274 275 #ifdef READCHECK 276 tty.c_lflag = protocol==ZM_ZMODEM ? 0 : ISIG; 277 tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? -1 : 030; /* Interrupt char */ 278 #else 279 tty.c_lflag = 0; 280 tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? 03 : 030; /* Interrupt char */ 281 #endif 282 #ifdef _POSIX_VDISABLE 283 if (((int) _POSIX_VDISABLE)!=(-1)) { 284 tty.c_cc[VQUIT] = _POSIX_VDISABLE; /* Quit char */ 285 } else { 286 tty.c_cc[VQUIT] = -1; /* Quit char */ 287 } 288 #else 289 tty.c_cc[VQUIT] = -1; /* Quit char */ 290 #endif 291 #ifdef NFGVMIN 292 tty.c_cc[VMIN] = 1; 293 #else 294 tty.c_cc[VMIN] = 3; /* This many chars satisfies reads */ 295 #endif 296 tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */ 297 298 tcsetattr(fd,TCSADRAIN,&tty); 299 300 return OK; 301 case 1: 302 case 3: 303 if(!did0) { 304 did0 = TRUE; 305 tcgetattr(fd,&oldtty); 306 } 307 tty = oldtty; 308 309 tty.c_iflag = IGNBRK; 310 if (n==3) /* with flow control */ 311 tty.c_iflag |= IXOFF; 312 313 /* No echo, crlf mapping, INTR, QUIT, delays, no erase/kill */ 314 tty.c_lflag &= ~(ECHO | ICANON | ISIG); 315 tty.c_oflag = 0; /* Transparent output */ 316 317 tty.c_cflag &= ~(PARENB); /* Same baud rate, disable parity */ 318 /* Set character size = 8 */ 319 tty.c_cflag &= ~(CSIZE); 320 tty.c_cflag |= CS8; 321 if (Twostop) 322 tty.c_cflag |= CSTOPB; /* Set two stop bits */ 323 #ifdef NFGVMIN 324 tty.c_cc[VMIN] = 1; /* This many chars satisfies reads */ 325 #else 326 tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */ 327 #endif 328 tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */ 329 tcsetattr(fd,TCSADRAIN,&tty); 330 Baudrate = getspeed(cfgetospeed(&tty)); 331 return OK; 332 case 0: 333 if(!did0) 334 return ERROR; 335 tcdrain (fd); /* wait until everything is sent */ 336 tcflush (fd,TCIOFLUSH); /* flush input queue */ 337 tcsetattr (fd,TCSADRAIN,&oldtty); 338 tcflow (fd,TCOON); /* restart output */ 339 340 return OK; 341 #endif 342 343 #ifdef USE_TERMIO 344 case 2: /* Un-raw mode used by sz, sb when -g detected */ 345 if(!did0) 346 (void) ioctl(fd, TCGETA, &oldtty); 347 tty = oldtty; 348 349 tty.c_iflag = BRKINT|IXON; 350 351 tty.c_oflag = 0; /* Transparent output */ 352 353 tty.c_cflag &= ~PARENB; /* Disable parity */ 354 tty.c_cflag |= CS8; /* Set character size = 8 */ 355 if (Twostop) 356 tty.c_cflag |= CSTOPB; /* Set two stop bits */ 357 358 359 #ifdef READCHECK 360 tty.c_lflag = protocol==ZM_ZMODEM ? 0 : ISIG; 361 tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? -1 : 030; /* Interrupt char */ 362 #else 363 tty.c_lflag = 0; 364 tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? 03 : 030; /* Interrupt char */ 365 #endif 366 tty.c_cc[VQUIT] = -1; /* Quit char */ 367 #ifdef NFGVMIN 368 tty.c_cc[VMIN] = 1; 369 #else 370 tty.c_cc[VMIN] = 3; /* This many chars satisfies reads */ 371 #endif 372 tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */ 373 374 (void) ioctl(fd, TCSETAW, &tty); 375 did0 = TRUE; 376 return OK; 377 case 1: 378 case 3: 379 if(!did0) 380 (void) ioctl(fd, TCGETA, &oldtty); 381 tty = oldtty; 382 383 tty.c_iflag = n==3 ? (IGNBRK|IXOFF) : IGNBRK; 384 385 /* No echo, crlf mapping, delays, no erase/kill */ 386 tty.c_lflag &= ~(ECHO | ICANON | ISIG); 387 388 tty.c_oflag = 0; /* Transparent output */ 389 390 tty.c_cflag &= ~PARENB; /* Same baud rate, disable parity */ 391 tty.c_cflag |= CS8; /* Set character size = 8 */ 392 if (Twostop) 393 tty.c_cflag |= CSTOPB; /* Set two stop bits */ 394 #ifdef NFGVMIN 395 tty.c_cc[VMIN] = 1; /* This many chars satisfies reads */ 396 #else 397 tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */ 398 #endif 399 tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */ 400 (void) ioctl(fd, TCSETAW, &tty); 401 did0 = TRUE; 402 Baudrate = getspeed(tty.c_cflag & CBAUD); 403 return OK; 404 case 0: 405 if(!did0) 406 return ERROR; 407 (void) ioctl(fd, TCSBRK, 1); /* Wait for output to drain */ 408 (void) ioctl(fd, TCFLSH, 0); /* Flush input queue */ 409 (void) ioctl(fd, TCSETAW, &oldtty); /* Restore modes */ 410 (void) ioctl(fd, TCXONC,1); /* Restart output */ 411 return OK; 412 #endif 413 414 415 #ifdef USE_SGTTY 416 /* 417 * NOTE: this should transmit all 8 bits and at the same time 418 * respond to XOFF/XON flow control. If no FIONREAD or other 419 * READCHECK alternative, also must respond to INTRRUPT char 420 * This doesn't work with V7. It should work with LLITOUT, 421 * but LLITOUT was broken on the machine I tried it on. 422 */ 423 case 2: /* Un-raw mode used by sz, sb when -g detected */ 424 if(!did0) { 425 ioctl(fd, TIOCEXCL, 0); 426 ioctl(fd, TIOCGETP, &oldtty); 427 ioctl(fd, TIOCGETC, &oldtch); 428 #ifdef LLITOUT 429 ioctl(fd, TIOCLGET, &Locmode); 430 #endif 431 } 432 tty = oldtty; 433 tch = oldtch; 434 #ifdef READCHECK 435 tch.t_intrc = Zmodem ? -1:030; /* Interrupt char */ 436 #else 437 tch.t_intrc = Zmodem ? 03:030; /* Interrupt char */ 438 #endif 439 tty.sg_flags |= (ODDP|EVENP|CBREAK); 440 tty.sg_flags &= ~(ALLDELAY|CRMOD|ECHO|LCASE); 441 ioctl(fd, TIOCSETP, &tty); 442 ioctl(fd, TIOCSETC, &tch); 443 #ifdef LLITOUT 444 ioctl(fd, TIOCLBIS, &Locbit); 445 #else 446 bibi(99); /* un-raw doesn't work w/o lit out */ 447 #endif 448 did0 = TRUE; 449 return OK; 450 case 1: 451 case 3: 452 if(!did0) { 453 ioctl(fd, TIOCEXCL, 0); 454 ioctl(fd, TIOCGETP, &oldtty); 455 ioctl(fd, TIOCGETC, &oldtch); 456 #ifdef LLITOUT 457 ioctl(fd, TIOCLGET, &Locmode); 458 #endif 459 } 460 tty = oldtty; 461 tty.sg_flags |= RAW; 462 tty.sg_flags &= ~ECHO; 463 ioctl(fd, TIOCSETP, &tty); 464 did0 = TRUE; 465 Baudrate = getspeed(tty.sg_ospeed); 466 return OK; 467 case 0: 468 if(!did0) 469 return ERROR; 470 ioctl(fd, TIOCSETP, &oldtty); 471 ioctl(fd, TIOCSETC, &oldtch); 472 ioctl(fd, TIOCNXCL, 0); 473 #ifdef LLITOUT 474 ioctl(fd, TIOCLSET, &Locmode); 475 #endif 476 #ifdef TIOCFLUSH 477 { int x=1; ioctl(fd,TIOCFLUSH,&x); } 478 #endif 479 #endif 480 481 return OK; 482 default: 483 return ERROR; 484 } 485 #endif 486 } 487 488 void 489 sendbrk(int fd) 490 { 491 #if 0 492 #ifdef USE_TERMIOS 493 tcsendbreak(fd,0); 494 #endif 495 #ifdef USE_TERMIO 496 ioctl(fd, TCSBRK, 0); 497 #endif 498 #ifdef USE_SGTTY 499 #ifdef TIOCSBRK 500 sleep(1); 501 ioctl(fd, TIOCSBRK, 0); 502 sleep(1); 503 ioctl(fd, TIOCCBRK, 0); 504 #endif 505 #endif 506 #endif 507 } 508 509 void 510 purgeline(int fd) 511 { 512 readline_purge(); 513 #if 0 514 #ifdef TCFLSH 515 ioctl(fd, TCFLSH, 0); 516 #else 517 lseek(fd, 0L, 2); 518 #endif 519 #endif 520 } 521 522 /* End of rbsb.c */ 523