File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / lrzsz / src / rbsb.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Thu Oct 24 15:49:50 2019 UTC (4 years, 11 months ago) by misho
Branches: lrzsz, MAIN
CVS tags: v0_12_20p5, HEAD
lrzsz ver 0.12.20

    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>