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