diff options
author | Bernhard Rosenkraenzer <Bernhard.Rosenkranzer@linaro.org> | 2011-10-10 11:48:48 +0159 |
---|---|---|
committer | Bernhard Rosenkraenzer <Bernhard.Rosenkranzer@linaro.org> | 2011-10-10 11:55:55 +0159 |
commit | 2cbcbec2a3530c1e947a23e9497f0bfefb453278 (patch) | |
tree | 3223c7336c0602155addcba81a9d348fb455e650 /rbsb.c | |
download | lrzsz-2cbcbec2a3530c1e947a23e9497f0bfefb453278.tar.gz |
Diffstat (limited to 'rbsb.c')
-rw-r--r-- | rbsb.c | 506 |
1 files changed, 506 insertions, 0 deletions
@@ -0,0 +1,506 @@ +/* + rbsb.c - terminal handling stuff for lrzsz + Copyright (C) until 1988 Chuck Forsberg (Omen Technology INC) + Copyright (C) 1994 Matt Porter, Michael D. Black + Copyright (C) 1996, 1997 Uwe Ohse + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. + + originally written by Chuck Forsberg +*/ + +/* + * Rev 05-05-1988 + * ============== (not quite, but originated there :-). -- uwe + */ +#include "zglobal.h" + +#include <stdio.h> +#include <errno.h> + +#ifndef HAVE_ERRNO_DECLARATION +extern int errno; +#endif + +#ifdef USE_SGTTY +# ifdef LLITOUT +long Locmode; /* Saved "local mode" for 4.x BSD "new driver" */ +long Locbit = LLITOUT; /* Bit SUPPOSED to disable output translations */ +# endif +#endif + +#ifdef HAVE_SYS_IOCTL_H +#include <sys/ioctl.h> +#endif + +#ifdef MAJOR_IN_MKDEV +#include <sys/mkdev.h> +#else +# ifdef MAJOR_IN_SYSMACROS +# include <sys/sysmacros.h> +# endif +#endif + +#if defined(HOWMANY) && HOWMANY > 255 +#ifndef NFGVMIN +Howmany must be 255 or less +#endif +#endif + +static struct { + unsigned baudr; + speed_t speedcode; +} speeds[] = { + {110, B110}, + {300, B300}, + {600, B600}, + {1200, B1200}, + {2400, B2400}, + {4800, B4800}, + {9600, B9600}, +#ifdef B19200 + {19200, B19200}, +#endif +#ifdef B38400 + {38400, B38400}, +#endif +#ifdef B57600 + {57600, B57600}, +#endif +#ifdef B115200 + {115200, B115200}, +#endif +#ifdef B230400 + {230400, B230400}, +#endif +#ifdef B460800 + {460800, B460800}, +#endif +#ifdef EXTA + {19200, EXTA}, +#endif +#ifdef EXTB + {38400, EXTB}, +#endif + {0, 0} +}; + +static unsigned getspeed __P((speed_t)); + +static unsigned +getspeed(speed_t code) +{ + int n; + for (n=0; speeds[n].baudr; ++n) + if (speeds[n].speedcode == code) + return speeds[n].baudr; + return 38400; /* Assume fifo if ioctl failed */ +} + +/* + * return 1 if stdout and stderr are different devices + * indicating this program operating with a modem on a + * different line + */ +int Fromcu; /* Were called from cu or yam */ +int +from_cu(void) +{ +#ifdef HAVE_ST_RDEV + struct stat a, b; +#if defined(makedev) + dev_t help=makedev(0,0); +#else + int help=0; +#endif + + /* in case fstat fails */ + a.st_rdev=b.st_rdev=a.st_dev=b.st_dev=help; + + fstat(1, &a); fstat(2, &b); + +#if defined(major) && defined(minor) + if (major(a.st_rdev) != major(b.st_rdev) + || minor(a.st_rdev) != minor(b.st_rdev)) + Fromcu=1; + else if (major(a.st_dev) != major(b.st_dev) + || minor(a.st_dev) != minor(b.st_dev)) + Fromcu=1; + else + Fromcu=0; +#else + Fromcu = (a.st_rdev != b.st_rdev) || (a.st_dev != b.st_dev); +#endif +#else + Fromcu = 1; /* a bad guess .. */ +#endif + return Fromcu; +} + + + +int Twostop; /* Use two stop bits */ + + +#ifdef READCHECK_FIONREAD +/* + * Return non 0 if something to read from io descriptor f + */ +int +rdchk(int fd) +{ + static long lf; + + ioctl(fd, FIONREAD, &lf); + return ((int) lf); +} +#endif + +#ifdef READCHECK_GETFL +unsigned char checked = '\0' ; +/* + * Nonblocking I/O is a bit different in System V, Release 2 + */ +int +rdchk(int fd) +{ + int lf, savestat; + + savestat = fcntl(fd, F_GETFL) ; + if (savestat == -1) + return 0; +#ifdef OVERLY_PARANOID + if (-1==fcntl(fd, F_SETFL, savestat | O_NDELAY)) + return 0; + lf = read(fd, &checked, 1) ; + if (-1==fcntl(fd, F_SETFL, savestat)) { +#ifdef ENABLE_SYSLOG + if (enable_syslog) + lsyslog(LOG_CRIT,"F_SETFL failed in rdchk(): %s", + strerror(errno)); +#endif + zpfatal("rdchk: F_SETFL failed\n"); /* lose */ + /* there is really no way to recover. And we can't tell + * the other side what's going on if we can't write to + * fd, but we try. + */ + canit(fd); + exit(1); + } +#else + fcntl(fd, F_SETFL, savestat | O_NDELAY); + lf = read(fd, &checked, 1) ; + fcntl(fd, F_SETFL, savestat); +#endif + return(lf == -1 && errno==EWOULDBLOCK ? 0 : lf) ; +} +#endif + + + + + +#ifdef USE_TERMIOS +struct termios oldtty, tty; +#else +# if defined(USE_TERMIO) +struct termio oldtty, tty; +# else +struct sgttyb oldtty, tty; +struct tchars oldtch, tch; +# endif +#endif + + +/* + * mode(n) + * 3: save old tty stat, set raw mode with flow control + * 2: set XON/XOFF for sb/sz with ZMODEM or YMODEM-g + * 1: save old tty stat, set raw mode + * 0: restore original tty mode + */ +int +io_mode(int fd, int n) +{ + static int did0 = FALSE; + + vfile("mode:%d", n); + + switch(n) { + +#ifdef USE_TERMIOS + case 2: /* Un-raw mode used by sz, sb when -g detected */ + if(!did0) { + did0 = TRUE; + tcgetattr(fd,&oldtty); + } + tty = oldtty; + + tty.c_iflag = BRKINT|IXON; + + tty.c_oflag = 0; /* Transparent output */ + + tty.c_cflag &= ~PARENB; /* Disable parity */ + tty.c_cflag |= CS8; /* Set character size = 8 */ + if (Twostop) + tty.c_cflag |= CSTOPB; /* Set two stop bits */ + +#ifdef READCHECK + tty.c_lflag = protocol==ZM_ZMODEM ? 0 : ISIG; + tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? -1 : 030; /* Interrupt char */ +#else + tty.c_lflag = 0; + tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? 03 : 030; /* Interrupt char */ +#endif +#ifdef _POSIX_VDISABLE + if (((int) _POSIX_VDISABLE)!=(-1)) { + tty.c_cc[VQUIT] = _POSIX_VDISABLE; /* Quit char */ + } else { + tty.c_cc[VQUIT] = -1; /* Quit char */ + } +#else + tty.c_cc[VQUIT] = -1; /* Quit char */ +#endif +#ifdef NFGVMIN + tty.c_cc[VMIN] = 1; +#else + tty.c_cc[VMIN] = 3; /* This many chars satisfies reads */ +#endif + tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */ + + tcsetattr(fd,TCSADRAIN,&tty); + + return OK; + case 1: + case 3: + if(!did0) { + did0 = TRUE; + tcgetattr(fd,&oldtty); + } + tty = oldtty; + + tty.c_iflag = IGNBRK; + if (n==3) /* with flow control */ + tty.c_iflag |= IXOFF; + + /* Setup raw mode: no echo, noncanonical (no edit chars), + * no signal generating chars, and no extended chars (^V, + * ^O, ^R, ^W). + */ + tty.c_lflag &= ~(ECHO | ICANON | ISIG | IEXTEN); + tty.c_oflag = 0; /* Transparent output */ + + tty.c_cflag &= ~(PARENB); /* Same baud rate, disable parity */ + /* Set character size = 8 */ + tty.c_cflag &= ~(CSIZE); + tty.c_cflag |= CS8; + if (Twostop) + tty.c_cflag |= CSTOPB; /* Set two stop bits */ +#ifdef NFGVMIN + tty.c_cc[VMIN] = 1; /* This many chars satisfies reads */ +#else + tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */ +#endif + tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */ + tcsetattr(fd,TCSADRAIN,&tty); + Baudrate = getspeed(cfgetospeed(&tty)); + return OK; + case 0: + if(!did0) + return ERROR; + tcdrain (fd); /* wait until everything is sent */ + tcflush (fd,TCIOFLUSH); /* flush input queue */ + tcsetattr (fd,TCSADRAIN,&oldtty); + tcflow (fd,TCOON); /* restart output */ + + return OK; +#endif + +#ifdef USE_TERMIO + case 2: /* Un-raw mode used by sz, sb when -g detected */ + if(!did0) + (void) ioctl(fd, TCGETA, &oldtty); + tty = oldtty; + + tty.c_iflag = BRKINT|IXON; + + tty.c_oflag = 0; /* Transparent output */ + + tty.c_cflag &= ~PARENB; /* Disable parity */ + tty.c_cflag |= CS8; /* Set character size = 8 */ + if (Twostop) + tty.c_cflag |= CSTOPB; /* Set two stop bits */ + + +#ifdef READCHECK + tty.c_lflag = protocol==ZM_ZMODEM ? 0 : ISIG; + tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? -1 : 030; /* Interrupt char */ +#else + tty.c_lflag = 0; + tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? 03 : 030; /* Interrupt char */ +#endif + tty.c_cc[VQUIT] = -1; /* Quit char */ +#ifdef NFGVMIN + tty.c_cc[VMIN] = 1; +#else + tty.c_cc[VMIN] = 3; /* This many chars satisfies reads */ +#endif + tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */ + + (void) ioctl(fd, TCSETAW, &tty); + did0 = TRUE; + return OK; + case 1: + case 3: + if(!did0) + (void) ioctl(fd, TCGETA, &oldtty); + tty = oldtty; + + tty.c_iflag = n==3 ? (IGNBRK|IXOFF) : IGNBRK; + + /* No echo, crlf mapping, delays, no erase/kill */ + tty.c_lflag &= ~(ECHO | ICANON | ISIG); + + tty.c_oflag = 0; /* Transparent output */ + + tty.c_cflag &= ~PARENB; /* Same baud rate, disable parity */ + tty.c_cflag |= CS8; /* Set character size = 8 */ + if (Twostop) + tty.c_cflag |= CSTOPB; /* Set two stop bits */ +#ifdef NFGVMIN + tty.c_cc[VMIN] = 1; /* This many chars satisfies reads */ +#else + tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */ +#endif + tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */ + (void) ioctl(fd, TCSETAW, &tty); + did0 = TRUE; + Baudrate = getspeed(tty.c_cflag & CBAUD); + return OK; + case 0: + if(!did0) + return ERROR; + (void) ioctl(fd, TCSBRK, 1); /* Wait for output to drain */ + (void) ioctl(fd, TCFLSH, 0); /* Flush input queue */ + (void) ioctl(fd, TCSETAW, &oldtty); /* Restore modes */ + (void) ioctl(fd, TCXONC,1); /* Restart output */ + return OK; +#endif + + +#ifdef USE_SGTTY + /* + * NOTE: this should transmit all 8 bits and at the same time + * respond to XOFF/XON flow control. If no FIONREAD or other + * READCHECK alternative, also must respond to INTRRUPT char + * This doesn't work with V7. It should work with LLITOUT, + * but LLITOUT was broken on the machine I tried it on. + */ + case 2: /* Un-raw mode used by sz, sb when -g detected */ + if(!did0) { + ioctl(fd, TIOCEXCL, 0); + ioctl(fd, TIOCGETP, &oldtty); + ioctl(fd, TIOCGETC, &oldtch); +#ifdef LLITOUT + ioctl(fd, TIOCLGET, &Locmode); +#endif + } + tty = oldtty; + tch = oldtch; +#ifdef READCHECK + tch.t_intrc = Zmodem ? -1:030; /* Interrupt char */ +#else + tch.t_intrc = Zmodem ? 03:030; /* Interrupt char */ +#endif + tty.sg_flags |= (ODDP|EVENP|CBREAK); + tty.sg_flags &= ~(ALLDELAY|CRMOD|ECHO|LCASE); + ioctl(fd, TIOCSETP, &tty); + ioctl(fd, TIOCSETC, &tch); +#ifdef LLITOUT + ioctl(fd, TIOCLBIS, &Locbit); +#else + bibi(99); /* un-raw doesn't work w/o lit out */ +#endif + did0 = TRUE; + return OK; + case 1: + case 3: + if(!did0) { + ioctl(fd, TIOCEXCL, 0); + ioctl(fd, TIOCGETP, &oldtty); + ioctl(fd, TIOCGETC, &oldtch); +#ifdef LLITOUT + ioctl(fd, TIOCLGET, &Locmode); +#endif + } + tty = oldtty; + tty.sg_flags |= RAW; + tty.sg_flags &= ~ECHO; + ioctl(fd, TIOCSETP, &tty); + did0 = TRUE; + Baudrate = getspeed(tty.sg_ospeed); + return OK; + case 0: + if(!did0) + return ERROR; + ioctl(fd, TIOCSETP, &oldtty); + ioctl(fd, TIOCSETC, &oldtch); + ioctl(fd, TIOCNXCL, 0); +#ifdef LLITOUT + ioctl(fd, TIOCLSET, &Locmode); +#endif +#ifdef TIOCFLUSH + { int x=1; ioctl(fd,TIOCFLUSH,&x); } +#endif +#endif + + return OK; + default: + return ERROR; + } +} + +void +sendbrk(int fd) +{ +#ifdef USE_TERMIOS + tcsendbreak(fd,0); +#endif +#ifdef USE_TERMIO + ioctl(fd, TCSBRK, 0); +#endif +#ifdef USE_SGTTY +#ifdef TIOCSBRK + sleep(1); + ioctl(fd, TIOCSBRK, 0); + sleep(1); + ioctl(fd, TIOCCBRK, 0); +#endif +#endif +} + +void +purgeline(int fd) +{ + readline_purge(); +#ifdef TCFLSH + ioctl(fd, TCFLSH, 0); +#else + lseek(fd, 0L, 2); +#endif +} + +/* End of rbsb.c */ |