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 extern int CYGACC_COMM_IF_GETC_TIMEOUT (char chan, char *c); 113 extern void CYGACC_COMM_IF_PUTC (char x, char y); 114 extern int CYGACC_COMM_IF_GETC_TIMEOUT (char chan, char *c); 115 116 unsigned 117 getspeed(int code) 118 { 119 int n; 120 121 for (n=0; speeds[n].baudr; ++n) 122 if (speeds[n].speedcode == code) 123 return speeds[n].baudr; 124 return 38400; /* Assume fifo if ioctl failed */ 125 } 126 127 /* 128 * return 1 if stdout and stderr are different devices 129 * indicating this program operating with a modem on a 130 * different line 131 */ 132 int Fromcu; /* Were called from cu or yam */ 133 int 134 from_cu(void) 135 { 136 #if 0 137 #ifdef HAVE_ST_RDEV 138 struct stat a, b; 139 #if defined(makedev) 140 dev_t help=makedev(0,0); 141 #else 142 int help=0; 143 #endif 144 145 /* in case fstat fails */ 146 a.st_rdev=b.st_rdev=a.st_dev=b.st_dev=help; 147 148 fstat(1, &a); fstat(2, &b); 149 150 #if defined(major) && defined(minor) 151 if (major(a.st_rdev) != major(b.st_rdev) 152 || minor(a.st_rdev) != minor(b.st_rdev)) 153 Fromcu=1; 154 else if (major(a.st_dev) != major(b.st_dev) 155 || minor(a.st_dev) != minor(b.st_dev)) 156 Fromcu=1; 157 else 158 Fromcu=0; 159 #else 160 Fromcu = (a.st_rdev != b.st_rdev) || (a.st_dev != b.st_dev); 161 #endif 162 #else 163 Fromcu = 1; /* a bad guess .. */ 164 #endif 165 return Fromcu; 166 #endif 167 return 0; 168 } 169 170 171 172 int Twostop; /* Use two stop bits */ 173 174 175 #ifdef READCHECK_FIONREAD 176 /* 177 * Return non 0 if something to read from io descriptor f 178 */ 179 int 180 rdchk(int fd) 181 { 182 static long lf; 183 184 ioctl(fd, FIONREAD, &lf); 185 return ((int) lf); 186 } 187 #endif 188 189 #ifdef READCHECK_GETFL 190 unsigned char checked = '\0' ; 191 /* 192 * Nonblocking I/O is a bit different in System V, Release 2 193 */ 194 int 195 rdchk(int fd) 196 { 197 int lf, savestat; 198 199 savestat = fcntl(fd, F_GETFL) ; 200 if (savestat == -1) 201 return 0; 202 #ifdef OVERLY_PARANOID 203 if (-1==fcntl(fd, F_SETFL, savestat | O_NDELAY)) 204 return 0; 205 lf = read(fd, &checked, 1) ; 206 if (-1==fcntl(fd, F_SETFL, savestat)) { 207 #ifdef ENABLE_SYSLOG 208 if (enable_syslog) 209 lsyslog(LOG_CRIT,"F_SETFL failed in rdchk(): %s", 210 strerror(errno)); 211 #endif 212 zpfatal("rdchk: F_SETFL failed\n"); /* lose */ 213 /* there is really no way to recover. And we can't tell 214 * the other side what's going on if we can't write to 215 * fd, but we try. 216 */ 217 canit(fd); 218 exit(1); 219 } 220 #else 221 fcntl(fd, F_SETFL, savestat | O_NDELAY); 222 lf = read(fd, &checked, 1) ; 223 fcntl(fd, F_SETFL, savestat); 224 #endif 225 return(lf == -1 && errno==EWOULDBLOCK ? 0 : lf) ; 226 } 227 #endif 228 229 230 231 232 233 #ifdef USE_TERMIOS 234 struct termios oldtty, tty; 235 #else 236 # if defined(USE_TERMIO) 237 struct termio oldtty, tty; 238 # else 239 //struct sgttyb oldtty, tty; 240 //struct tchars oldtch, tch; 241 # endif 242 #endif 243 244 245 /* 246 * mode(n) 247 * 3: save old tty stat, set raw mode with flow control 248 * 2: set XON/XOFF for sb/sz with ZMODEM or YMODEM-g 249 * 1: save old tty stat, set raw mode 250 * 0: restore original tty mode 251 */ 252 int 253 io_mode(int fd, int n) 254 { 255 #if 1 256 __maybe_unused static int did0 = FALSE; 257 258 vfile("mode:%d", n); 259 260 switch(n) { 261 262 #ifdef USE_TERMIOS 263 case 2: /* Un-raw mode used by sz, sb when -g detected */ 264 if(!did0) { 265 did0 = TRUE; 266 tcgetattr(fd,&oldtty); 267 } 268 tty = oldtty; 269 270 tty.c_iflag = BRKINT|IXON; 271 272 tty.c_oflag = 0; /* Transparent output */ 273 274 tty.c_cflag &= ~PARENB; /* Disable parity */ 275 tty.c_cflag |= CS8; /* Set character size = 8 */ 276 if (Twostop) 277 tty.c_cflag |= CSTOPB; /* Set two stop bits */ 278 279 #ifdef READCHECK 280 tty.c_lflag = protocol==ZM_ZMODEM ? 0 : ISIG; 281 tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? -1 : 030; /* Interrupt char */ 282 #else 283 tty.c_lflag = 0; 284 tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? 03 : 030; /* Interrupt char */ 285 #endif 286 #ifdef _POSIX_VDISABLE 287 if (((int) _POSIX_VDISABLE)!=(-1)) { 288 tty.c_cc[VQUIT] = _POSIX_VDISABLE; /* Quit char */ 289 } else { 290 tty.c_cc[VQUIT] = -1; /* Quit char */ 291 } 292 #else 293 tty.c_cc[VQUIT] = -1; /* Quit char */ 294 #endif 295 #ifdef NFGVMIN 296 tty.c_cc[VMIN] = 1; 297 #else 298 tty.c_cc[VMIN] = 3; /* This many chars satisfies reads */ 299 #endif 300 tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */ 301 302 tcsetattr(fd,TCSADRAIN,&tty); 303 304 return OK; 305 case 1: 306 case 3: 307 if(!did0) { 308 did0 = TRUE; 309 tcgetattr(fd,&oldtty); 310 } 311 tty = oldtty; 312 313 tty.c_iflag = IGNBRK; 314 if (n==3) /* with flow control */ 315 tty.c_iflag |= IXOFF; 316 317 /* No echo, crlf mapping, INTR, QUIT, delays, no erase/kill */ 318 tty.c_lflag &= ~(ECHO | ICANON | ISIG); 319 tty.c_oflag = 0; /* Transparent output */ 320 321 tty.c_cflag &= ~(PARENB); /* Same baud rate, disable parity */ 322 /* Set character size = 8 */ 323 tty.c_cflag &= ~(CSIZE); 324 tty.c_cflag |= CS8; 325 if (Twostop) 326 tty.c_cflag |= CSTOPB; /* Set two stop bits */ 327 #ifdef NFGVMIN 328 tty.c_cc[VMIN] = 1; /* This many chars satisfies reads */ 329 #else 330 tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */ 331 #endif 332 tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */ 333 tcsetattr(fd,TCSADRAIN,&tty); 334 Baudrate = getspeed(cfgetospeed(&tty)); 335 return OK; 336 case 0: 337 if(!did0) 338 return ERROR; 339 tcdrain (fd); /* wait until everything is sent */ 340 tcflush (fd,TCIOFLUSH); /* flush input queue */ 341 tcsetattr (fd,TCSADRAIN,&oldtty); 342 tcflow (fd,TCOON); /* restart output */ 343 344 return OK; 345 #endif 346 347 #ifdef USE_TERMIO 348 case 2: /* Un-raw mode used by sz, sb when -g detected */ 349 if(!did0) 350 (void) ioctl(fd, TCGETA, &oldtty); 351 tty = oldtty; 352 353 tty.c_iflag = BRKINT|IXON; 354 355 tty.c_oflag = 0; /* Transparent output */ 356 357 tty.c_cflag &= ~PARENB; /* Disable parity */ 358 tty.c_cflag |= CS8; /* Set character size = 8 */ 359 if (Twostop) 360 tty.c_cflag |= CSTOPB; /* Set two stop bits */ 361 362 363 #ifdef READCHECK 364 tty.c_lflag = protocol==ZM_ZMODEM ? 0 : ISIG; 365 tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? -1 : 030; /* Interrupt char */ 366 #else 367 tty.c_lflag = 0; 368 tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? 03 : 030; /* Interrupt char */ 369 #endif 370 tty.c_cc[VQUIT] = -1; /* Quit char */ 371 #ifdef NFGVMIN 372 tty.c_cc[VMIN] = 1; 373 #else 374 tty.c_cc[VMIN] = 3; /* This many chars satisfies reads */ 375 #endif 376 tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */ 377 378 (void) ioctl(fd, TCSETAW, &tty); 379 did0 = TRUE; 380 return OK; 381 case 1: 382 case 3: 383 if(!did0) 384 (void) ioctl(fd, TCGETA, &oldtty); 385 tty = oldtty; 386 387 tty.c_iflag = n==3 ? (IGNBRK|IXOFF) : IGNBRK; 388 389 /* No echo, crlf mapping, delays, no erase/kill */ 390 tty.c_lflag &= ~(ECHO | ICANON | ISIG); 391 392 tty.c_oflag = 0; /* Transparent output */ 393 394 tty.c_cflag &= ~PARENB; /* Same baud rate, disable parity */ 395 tty.c_cflag |= CS8; /* Set character size = 8 */ 396 if (Twostop) 397 tty.c_cflag |= CSTOPB; /* Set two stop bits */ 398 #ifdef NFGVMIN 399 tty.c_cc[VMIN] = 1; /* This many chars satisfies reads */ 400 #else 401 tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */ 402 #endif 403 tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */ 404 (void) ioctl(fd, TCSETAW, &tty); 405 did0 = TRUE; 406 Baudrate = getspeed(tty.c_cflag & CBAUD); 407 return OK; 408 case 0: 409 if(!did0) 410 return ERROR; 411 (void) ioctl(fd, TCSBRK, 1); /* Wait for output to drain */ 412 (void) ioctl(fd, TCFLSH, 0); /* Flush input queue */ 413 (void) ioctl(fd, TCSETAW, &oldtty); /* Restore modes */ 414 (void) ioctl(fd, TCXONC,1); /* Restart output */ 415 return OK; 416 #endif 417 418 419 #ifdef USE_SGTTY 420 /* 421 * NOTE: this should transmit all 8 bits and at the same time 422 * respond to XOFF/XON flow control. If no FIONREAD or other 423 * READCHECK alternative, also must respond to INTRRUPT char 424 * This doesn't work with V7. It should work with LLITOUT, 425 * but LLITOUT was broken on the machine I tried it on. 426 */ 427 case 2: /* Un-raw mode used by sz, sb when -g detected */ 428 if(!did0) { 429 ioctl(fd, TIOCEXCL, 0); 430 ioctl(fd, TIOCGETP, &oldtty); 431 ioctl(fd, TIOCGETC, &oldtch); 432 #ifdef LLITOUT 433 ioctl(fd, TIOCLGET, &Locmode); 434 #endif 435 } 436 tty = oldtty; 437 tch = oldtch; 438 #ifdef READCHECK 439 tch.t_intrc = Zmodem ? -1:030; /* Interrupt char */ 440 #else 441 tch.t_intrc = Zmodem ? 03:030; /* Interrupt char */ 442 #endif 443 tty.sg_flags |= (ODDP|EVENP|CBREAK); 444 tty.sg_flags &= ~(ALLDELAY|CRMOD|ECHO|LCASE); 445 ioctl(fd, TIOCSETP, &tty); 446 ioctl(fd, TIOCSETC, &tch); 447 #ifdef LLITOUT 448 ioctl(fd, TIOCLBIS, &Locbit); 449 #else 450 bibi(99); /* un-raw doesn't work w/o lit out */ 451 #endif 452 did0 = TRUE; 453 return OK; 454 case 1: 455 case 3: 456 if(!did0) { 457 ioctl(fd, TIOCEXCL, 0); 458 ioctl(fd, TIOCGETP, &oldtty); 459 ioctl(fd, TIOCGETC, &oldtch); 460 #ifdef LLITOUT 461 ioctl(fd, TIOCLGET, &Locmode); 462 #endif 463 } 464 tty = oldtty; 465 tty.sg_flags |= RAW; 466 tty.sg_flags &= ~ECHO; 467 ioctl(fd, TIOCSETP, &tty); 468 did0 = TRUE; 469 Baudrate = getspeed(tty.sg_ospeed); 470 return OK; 471 case 0: 472 if(!did0) 473 return ERROR; 474 ioctl(fd, TIOCSETP, &oldtty); 475 ioctl(fd, TIOCSETC, &oldtch); 476 ioctl(fd, TIOCNXCL, 0); 477 #ifdef LLITOUT 478 ioctl(fd, TIOCLSET, &Locmode); 479 #endif 480 #ifdef TIOCFLUSH 481 { int x=1; ioctl(fd,TIOCFLUSH,&x); } 482 #endif 483 #endif 484 485 return OK; 486 default: 487 return ERROR; 488 } 489 #endif 490 } 491 492 void 493 sendbrk(int fd) 494 { 495 #if 0 496 #ifdef USE_TERMIOS 497 tcsendbreak(fd,0); 498 #endif 499 #ifdef USE_TERMIO 500 ioctl(fd, TCSBRK, 0); 501 #endif 502 #ifdef USE_SGTTY 503 #ifdef TIOCSBRK 504 sleep(1); 505 ioctl(fd, TIOCSBRK, 0); 506 sleep(1); 507 ioctl(fd, TIOCCBRK, 0); 508 #endif 509 #endif 510 #endif 511 } 512 513 void 514 purgeline(int fd) 515 { 516 readline_purge(); 517 #if 0 518 #ifdef TCFLSH 519 ioctl(fd, TCFLSH, 0); 520 #else 521 lseek(fd, 0L, 2); 522 #endif 523 #endif 524 } 525 526 /* End of rbsb.c */ 527