summaryrefslogtreecommitdiff
path: root/rbsb.c
diff options
context:
space:
mode:
authorBernhard Rosenkraenzer <Bernhard.Rosenkranzer@linaro.org>2011-10-10 11:48:48 +0159
committerBernhard Rosenkraenzer <Bernhard.Rosenkranzer@linaro.org>2011-10-10 11:55:55 +0159
commit2cbcbec2a3530c1e947a23e9497f0bfefb453278 (patch)
tree3223c7336c0602155addcba81a9d348fb455e650 /rbsb.c
downloadlrzsz-2cbcbec2a3530c1e947a23e9497f0bfefb453278.tar.gz
Import upstream sources from lrzsz 0.12.21HEADmaster
Diffstat (limited to 'rbsb.c')
-rw-r--r--rbsb.c506
1 files changed, 506 insertions, 0 deletions
diff --git a/rbsb.c b/rbsb.c
new file mode 100644
index 0000000..88b977c
--- /dev/null
+++ b/rbsb.c
@@ -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 */