Annotation of embedaddon/lrzsz/src/rbsb.c, revision 1.1.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>