Annotation of embedaddon/lrzsz/src/lsz.c, revision 1.1

1.1     ! misho       1: /*
        !             2:   lsz - send files with x/y/zmodem
        !             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: #include "zglobal.h"
        !            25: 
        !            26: /* char *getenv(); */
        !            27: 
        !            28: #define SS_NORMAL 0
        !            29: #include <stdio.h>
        !            30: #include <stdlib.h>
        !            31: #include <signal.h>
        !            32: #include <setjmp.h>
        !            33: #include <ctype.h>
        !            34: #include <errno.h>
        !            35: #include <getopt.h>
        !            36: 
        !            37: #ifndef R_OK
        !            38: #  define R_OK 4
        !            39: #endif
        !            40: 
        !            41: #if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MMAP)
        !            42: #  include <sys/mman.h>
        !            43: size_t mm_size;
        !            44: void *mm_addr=NULL;
        !            45: #else
        !            46: #  undef HAVE_MMAP
        !            47: #endif
        !            48: #include "timing.h"
        !            49: #include "long-options.h"
        !            50: #include "xstrtoul.h"
        !            51: #include "error.h"
        !            52: 
        !            53: #ifndef STRICT_PROTOTYPES
        !            54: extern time_t time();
        !            55: extern char *strerror();
        !            56: extern char *strstr();
        !            57: #endif
        !            58: 
        !            59: #ifndef HAVE_ERRNO_DECLARATION
        !            60: extern int errno;
        !            61: #endif
        !            62: 
        !            63: unsigned Baudrate=2400;        /* Default, should be set by first mode() call */
        !            64: unsigned Txwindow;     /* Control the size of the transmitted window */
        !            65: unsigned Txwspac;      /* Spacing between zcrcq requests */
        !            66: unsigned Txwcnt;       /* Counter used to space ack requests */
        !            67: size_t Lrxpos;         /* Receiver's last reported offset */
        !            68: int errors;
        !            69: enum zm_type_enum protocol;
        !            70: int under_rsh=FALSE;
        !            71: extern int turbo_escape;
        !            72: static int no_unixmode;
        !            73: 
        !            74: int Canseek=1; /* 1: can; 0: only rewind, -1: neither */
        !            75: 
        !            76: static int zsendfile __P ((struct zm_fileinfo *zi, const char *buf, size_t blen));
        !            77: static int getnak __P ((void));
        !            78: static int wctxpn __P ((struct zm_fileinfo *));
        !            79: static int wcs __P ((const char *oname, const char *remotename));
        !            80: static size_t zfilbuf __P ((struct zm_fileinfo *zi));
        !            81: static size_t filbuf __P ((char *buf, size_t count));
        !            82: static int getzrxinit __P ((void));
        !            83: static int calc_blklen __P ((long total_sent));
        !            84: static int sendzsinit __P ((void));
        !            85: static int wctx __P ((struct zm_fileinfo *));
        !            86: static int zsendfdata __P ((struct zm_fileinfo *));
        !            87: static int getinsync __P ((struct zm_fileinfo *, int flag));
        !            88: static void countem __P ((int argc, char **argv));
        !            89: static void chkinvok __P ((const char *s));
        !            90: static void usage __P ((int exitcode, const char *what));
        !            91: static int zsendcmd __P ((const char *buf, size_t blen));
        !            92: static void saybibi __P ((void));
        !            93: static int wcsend __P ((int argc, char *argp[]));
        !            94: static int wcputsec __P ((char *buf, int sectnum, size_t cseclen));
        !            95: static void usage1 __P ((int exitcode));
        !            96: 
        !            97: #ifdef ENABLE_SYSLOG
        !            98: #define DO_SYSLOG(message) do { \
        !            99:     if (enable_syslog) { \
        !           100:         const char *shortname; \
        !           101:         if (!zi->fname) \
        !           102:             shortname="no.name"; \
        !           103:                else { \
        !           104:             shortname=strrchr(zi->fname,'/'); \
        !           105:             if (!shortname) \
        !           106:                 shortname=zi->fname; \
        !           107:             else \
        !           108:                 shortname++; \
        !           109:                } \
        !           110:         lsyslog message ; \
        !           111:         } \
        !           112:   } while(0)
        !           113: #else
        !           114: #define DO_SYSLOG(message) do { } while(0)
        !           115: #endif
        !           116: 
        !           117: #define ZSDATA(x,y,z) \
        !           118:        do { if (Crc32t) {zsda32(x,y,z); } else {zsdata(x,y,z);}} while(0)
        !           119: #ifdef HAVE_MMAP
        !           120: #define DATAADR (mm_addr ? ((char *)mm_addr)+zi->bytes_sent : txbuf)
        !           121: #else
        !           122: #define DATAADR (txbuf)
        !           123: #endif
        !           124: 
        !           125: int Filesleft;
        !           126: long Totalleft;
        !           127: size_t buffersize=16384;
        !           128: #ifdef HAVE_MMAP
        !           129: int use_mmap=1;
        !           130: #endif
        !           131: 
        !           132: /*
        !           133:  * Attention string to be executed by receiver to interrupt streaming data
        !           134:  *  when an error is detected.  A pause (0336) may be needed before the
        !           135:  *  ^C (03) or after it.
        !           136:  */
        !           137: #ifdef READCHECK
        !           138: char Myattn[] = { 0 };
        !           139: #else
        !           140: char Myattn[] = { 03, 0336, 0 };
        !           141: #endif
        !           142: 
        !           143: FILE *input_f;
        !           144: 
        !           145: #define MAX_BLOCK 8192
        !           146: char txbuf[MAX_BLOCK];
        !           147: 
        !           148: long vpos = 0;                 /* Number of bytes read from file */
        !           149: 
        !           150: char Lastrx;
        !           151: char Crcflg;
        !           152: int Verbose=0;
        !           153: int Restricted=0;      /* restricted; no /.. or ../ in filenames */
        !           154: int Quiet=0;           /* overrides logic that would otherwise set verbose */
        !           155: int Ascii=0;           /* Add CR's for brain damaged programs */
        !           156: int Fullname=0;                /* transmit full pathname */
        !           157: int Unlinkafter=0;     /* Unlink file after it is sent */
        !           158: int Dottoslash=0;      /* Change foo.bar.baz to foo/bar/baz */
        !           159: int firstsec;
        !           160: int errcnt=0;          /* number of files unreadable */
        !           161: size_t blklen=128;             /* length of transmitted records */
        !           162: int Optiong;           /* Let it rip no wait for sector ACK's */
        !           163: int Totsecs;           /* total number of sectors this file */
        !           164: int Filcnt=0;          /* count of number of files opened */
        !           165: int Lfseen=0;
        !           166: unsigned Rxbuflen = 16384;     /* Receiver's max buffer length */
        !           167: unsigned Tframlen = 0; /* Override for tx frame length */
        !           168: unsigned blkopt=0;             /* Override value for zmodem blklen */
        !           169: int Rxflags = 0;
        !           170: int Rxflags2 = 0;
        !           171: size_t bytcnt;
        !           172: int Wantfcs32 = TRUE;  /* want to send 32 bit FCS */
        !           173: char Lzconv;   /* Local ZMODEM file conversion request */
        !           174: char Lzmanag;  /* Local ZMODEM file management request */
        !           175: int Lskipnocor;
        !           176: char Lztrans;
        !           177: char zconv;            /* ZMODEM file conversion request */
        !           178: char zmanag;           /* ZMODEM file management request */
        !           179: char ztrans;           /* ZMODEM file transport request */
        !           180: int command_mode;              /* Send a command, then exit. */
        !           181: int Cmdtries = 11;
        !           182: int Cmdack1;           /* Rx ACKs command, then do it */
        !           183: int Exitcode;
        !           184: int enable_timesync=0;
        !           185: size_t Lastsync;               /* Last offset to which we got a ZRPOS */
        !           186: int Beenhereb4;                /* How many times we've been ZRPOS'd same place */
        !           187: 
        !           188: int no_timeout=FALSE;
        !           189: size_t max_blklen=1024;
        !           190: size_t start_blklen=0;
        !           191: int zmodem_requested;
        !           192: time_t stop_time=0;
        !           193: int tcp_flag=0;
        !           194: char *tcp_server_address=0;
        !           195: int tcp_socket=-1;
        !           196: 
        !           197: int error_count;
        !           198: #define OVERHEAD 18
        !           199: #define OVER_ERR 20
        !           200: 
        !           201: #define MK_STRING(x) #x
        !           202: 
        !           203: #ifdef ENABLE_SYSLOG
        !           204: #  if defined(ENABLE_SYSLOG_FORCE) || defined(ENABLE_SYSLOG_DEFAULT)
        !           205: int enable_syslog=TRUE;
        !           206: #  else
        !           207: int enable_syslog=FALSE;
        !           208: #  endif
        !           209: #endif
        !           210: 
        !           211: jmp_buf intrjmp;       /* For the interrupt on RX CAN */
        !           212: 
        !           213: static long min_bps;
        !           214: static long min_bps_time;
        !           215: 
        !           216: static int io_mode_fd=0;
        !           217: static int zrqinits_sent=0;
        !           218: static int play_with_sigint=0;
        !           219: 
        !           220: /* called by signal interrupt or terminate to clean things up */
        !           221: RETSIGTYPE
        !           222: bibi (int n)
        !           223: {
        !           224:        canit(STDOUT_FILENO);
        !           225:        fflush (stdout);
        !           226:        io_mode (io_mode_fd,0);
        !           227:        if (n == 99)
        !           228:                error (0, 0, _ ("io_mode(,2) in rbsb.c not implemented\n"));
        !           229:        else
        !           230:                error (0, 0, _ ("caught signal %d; exiting"), n);
        !           231:        if (n == SIGQUIT)
        !           232:                abort ();
        !           233:        exit (128 + n);
        !           234: }
        !           235: 
        !           236: /* Called when ZMODEM gets an interrupt (^C) */
        !           237: static RETSIGTYPE
        !           238: onintr(int n LRZSZ_ATTRIB_UNUSED)
        !           239: {
        !           240:        signal(SIGINT, SIG_IGN);
        !           241:        longjmp(intrjmp, -1);
        !           242: }
        !           243: 
        !           244: int Zctlesc;   /* Encode control characters */
        !           245: const char *program_name = "sz";
        !           246: int Zrwindow = 1400;   /* RX window size (controls garbage count) */
        !           247: 
        !           248: static struct option const long_options[] =
        !           249: {
        !           250:   {"append", no_argument, NULL, '+'},
        !           251:   {"twostop", no_argument, NULL, '2'},
        !           252:   {"try-8k", no_argument, NULL, '8'},
        !           253:   {"start-8k", no_argument, NULL, '9'},
        !           254:   {"try-4k", no_argument, NULL, '4'},
        !           255:   {"start-4k", no_argument, NULL, '5'},
        !           256:   {"ascii", no_argument, NULL, 'a'},
        !           257:   {"binary", no_argument, NULL, 'b'},
        !           258:   {"bufsize", required_argument, NULL, 'B'},
        !           259:   {"cmdtries", required_argument, NULL, 'C'},
        !           260:   {"command", required_argument, NULL, 'c'},
        !           261:   {"immediate-command", required_argument, NULL, 'i'},
        !           262:   {"dot-to-slash", no_argument, NULL, 'd'},
        !           263:   {"full-path", no_argument, NULL, 'f'},
        !           264:   {"escape", no_argument, NULL, 'e'},
        !           265:   {"rename", no_argument, NULL, 'E'},
        !           266:   {"help", no_argument, NULL, 'h'},
        !           267:   {"crc-check", no_argument, NULL, 'H'},
        !           268:   {"1024", no_argument, NULL, 'k'},
        !           269:   {"1k", no_argument, NULL, 'k'},
        !           270:   {"packetlen", required_argument, NULL, 'L'},
        !           271:   {"framelen", required_argument, NULL, 'l'},
        !           272:   {"min-bps", required_argument, NULL, 'm'},
        !           273:   {"min-bps-time", required_argument, NULL, 'M'},
        !           274:   {"newer", no_argument, NULL, 'n'},
        !           275:   {"newer-or-longer", no_argument, NULL, 'N'},
        !           276:   {"16-bit-crc", no_argument, NULL, 'o'},
        !           277:   {"disable-timeouts", no_argument, NULL, 'O'},
        !           278:   {"disable-timeout", no_argument, NULL, 'O'}, /* i can't get it right */
        !           279:   {"protect", no_argument, NULL, 'p'},
        !           280:   {"resume", no_argument, NULL, 'r'},
        !           281:   {"restricted", no_argument, NULL, 'R'},
        !           282:   {"quiet", no_argument, NULL, 'q'},
        !           283:   {"stop-at", required_argument, NULL, 's'},
        !           284:   {"syslog", optional_argument, NULL , 2},
        !           285:   {"timesync", no_argument, NULL, 'S'},
        !           286:   {"timeout", required_argument, NULL, 't'},
        !           287:   {"turbo", no_argument, NULL, 'T'},
        !           288:   {"unlink", no_argument, NULL, 'u'},
        !           289:   {"unrestrict", no_argument, NULL, 'U'},
        !           290:   {"verbose", no_argument, NULL, 'v'},
        !           291:   {"windowsize", required_argument, NULL, 'w'},
        !           292:   {"xmodem", no_argument, NULL, 'X'},
        !           293:   {"ymodem", no_argument, NULL, 1},
        !           294:   {"zmodem", no_argument, NULL, 'Z'},
        !           295:   {"overwrite", no_argument, NULL, 'y'},
        !           296:   {"overwrite-or-skip", no_argument, NULL, 'Y'},
        !           297: 
        !           298:   {"delay-startup", required_argument, NULL, 4},
        !           299:   {"tcp", no_argument, NULL, 5},
        !           300:   {"tcp-server", no_argument, NULL, 6},
        !           301:   {"tcp-client", required_argument, NULL, 7},
        !           302:   {"no-unixmode", no_argument, NULL, 8},
        !           303:   {NULL, 0, NULL, 0}
        !           304: };
        !           305: 
        !           306: static void
        !           307: show_version(void)
        !           308: {
        !           309:        printf ("%s (%s) %s\n", program_name, PACKAGE, VERSION);
        !           310: }
        !           311: 
        !           312: 
        !           313: int 
        !           314: main(int argc, char **argv)
        !           315: {
        !           316:        char *cp;
        !           317:        int npats;
        !           318:        int dm;
        !           319:        int i;
        !           320:        int stdin_files;
        !           321:        char **patts;
        !           322:        int c;
        !           323:        const char *Cmdstr=NULL;                /* Pointer to the command string */
        !           324:        unsigned int startup_delay=0;
        !           325: 
        !           326:        if (((cp = getenv("ZNULLS")) != NULL) && *cp)
        !           327:                Znulls = atoi(cp);
        !           328:        if (((cp=getenv("SHELL"))!=NULL) && (strstr(cp, "rsh") || strstr(cp, "rksh")
        !           329:                || strstr(cp, "rbash") || strstr(cp,"rshell")))
        !           330:        {
        !           331:                under_rsh=TRUE;
        !           332:                Restricted=1;
        !           333:        }
        !           334:        if ((cp=getenv("ZMODEM_RESTRICTED"))!=NULL)
        !           335:                Restricted=1;
        !           336:        from_cu();
        !           337:        chkinvok(argv[0]);
        !           338: 
        !           339: #ifdef ENABLE_SYSLOG
        !           340:        openlog(program_name,LOG_PID,ENABLE_SYSLOG);
        !           341: #endif
        !           342: 
        !           343:        setlocale (LC_ALL, "");
        !           344:        bindtextdomain (PACKAGE, LOCALEDIR);
        !           345:        textdomain (PACKAGE);
        !           346: 
        !           347:        parse_long_options (argc, argv, show_version, usage1);
        !           348: 
        !           349:        Rxtimeout = 600;
        !           350: 
        !           351:        while ((c = getopt_long (argc, argv, 
        !           352:                "2+48abB:C:c:dfeEghHi:kL:l:m:M:NnOopRrqsSt:TUuvw:XYy",
        !           353:                long_options, (int *) 0))!=EOF)
        !           354:        {
        !           355:                unsigned long int tmp;
        !           356:                char *tmpptr;
        !           357:                enum strtol_error s_err;
        !           358: 
        !           359:                switch (c)
        !           360:                {
        !           361:                case 0:
        !           362:                        break;
        !           363:                case '+': Lzmanag = ZF1_ZMAPND; break;
        !           364:                case '2': Twostop = TRUE; break;
        !           365:                case '8':
        !           366:                        if (max_blklen==8192)
        !           367:                                start_blklen=8192;
        !           368:                        else
        !           369:                                max_blklen=8192;
        !           370:                        break;
        !           371:                case '9': /* this is a longopt .. */
        !           372:                        start_blklen=8192;
        !           373:                        max_blklen=8192;
        !           374:                        break;
        !           375:                case '4':
        !           376:                        if (max_blklen==4096)
        !           377:                                start_blklen=4096;
        !           378:                        else
        !           379:                                max_blklen=4096;
        !           380:                        break;
        !           381:                case '5': /* this is a longopt .. */
        !           382:                        start_blklen=4096;
        !           383:                        max_blklen=4096;
        !           384:                        break;
        !           385:                case 'a': Lzconv = ZCNL; Ascii = TRUE; break;
        !           386:                case 'b': Lzconv = ZCBIN; break;
        !           387:                case 'B':
        !           388:                        if (0==strcmp(optarg,"auto"))
        !           389:                                buffersize= (size_t) -1;
        !           390:                        else
        !           391:                                buffersize=strtol(optarg,NULL,10);
        !           392: #ifdef HAVE_MMAP
        !           393:                        use_mmap=0;
        !           394: #endif
        !           395:                        break;
        !           396:                case 'C': 
        !           397:                        s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL);
        !           398:                        Cmdtries = tmp;
        !           399:                        if (s_err != LONGINT_OK)
        !           400:                                STRTOL_FATAL_ERROR (optarg, _("command tries"), s_err);
        !           401:                        break;
        !           402:                case 'i':
        !           403:                        Cmdack1 = ZCACK1;
        !           404:                        /* **** FALL THROUGH TO **** */
        !           405:                case 'c':
        !           406:                        command_mode = TRUE;
        !           407:                        Cmdstr = optarg;
        !           408:                        break;
        !           409:                case 'd':
        !           410:                        ++Dottoslash;
        !           411:                        /* **** FALL THROUGH TO **** */
        !           412:                case 'f': Fullname=TRUE; break;
        !           413:                case 'e': Zctlesc = 1; break;
        !           414:                case 'E': Lzmanag = ZF1_ZMCHNG; break;
        !           415:                case 'h': usage(0,NULL); break;
        !           416:                case 'H': Lzmanag = ZF1_ZMCRC; break;
        !           417:                case 'k': start_blklen=1024; break;
        !           418:                case 'L':
        !           419:                        s_err = xstrtoul (optarg, NULL, 0, &tmp, "ck");
        !           420:                        blkopt = tmp;
        !           421:                        if (s_err != LONGINT_OK)
        !           422:                                STRTOL_FATAL_ERROR (optarg, _("packetlength"), s_err);
        !           423:                        if (blkopt<24 || blkopt>MAX_BLOCK)
        !           424:                        {
        !           425:                                char meld[256];
        !           426:                                sprintf(meld,
        !           427:                                        _("packetlength out of range 24..%ld"),
        !           428:                                        (long) MAX_BLOCK);
        !           429:                                usage(2,meld);
        !           430:                        }
        !           431:                        break;
        !           432:                case 'l':
        !           433:                        s_err = xstrtoul (optarg, NULL, 0, &tmp, "ck");
        !           434:                        Tframlen = tmp;
        !           435:                        if (s_err != LONGINT_OK)
        !           436:                                STRTOL_FATAL_ERROR (optarg, _("framelength"), s_err);
        !           437:                        if (Tframlen<32 || Tframlen>MAX_BLOCK)
        !           438:                        {
        !           439:                                char meld[256];
        !           440:                                sprintf(meld,
        !           441:                                        _("framelength out of range 32..%ld"),
        !           442:                                        (long) MAX_BLOCK);
        !           443:                                usage(2,meld);
        !           444:                        }
        !           445:                        break;
        !           446:         case 'm':
        !           447:                        s_err = xstrtoul (optarg, &tmpptr, 0, &tmp, "km");
        !           448:                        min_bps = tmp;
        !           449:                        if (s_err != LONGINT_OK)
        !           450:                                STRTOL_FATAL_ERROR (optarg, _("min_bps"), s_err);
        !           451:                        if (min_bps<0)
        !           452:                                usage(2,_("min_bps must be >= 0"));
        !           453:                        break;
        !           454:         case 'M':
        !           455:                        s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL);
        !           456:                        min_bps_time = tmp;
        !           457:                        if (s_err != LONGINT_OK)
        !           458:                                STRTOL_FATAL_ERROR (optarg, _("min_bps_time"), s_err);
        !           459:                        if (min_bps_time<=1)
        !           460:                                usage(2,_("min_bps_time must be > 1"));
        !           461:                        break;
        !           462:                case 'N': Lzmanag = ZF1_ZMNEWL;  break;
        !           463:                case 'n': Lzmanag = ZF1_ZMNEW;  break;
        !           464:                case 'o': Wantfcs32 = FALSE; break;
        !           465:                case 'O': no_timeout = TRUE; break;
        !           466:                case 'p': Lzmanag = ZF1_ZMPROT;  break;
        !           467:                case 'r': 
        !           468:                        if (Lzconv == ZCRESUM) 
        !           469:                                Lzmanag = ZF1_ZMCRC;
        !           470:                        else
        !           471:                                Lzconv = ZCRESUM; 
        !           472:                        break;
        !           473:                case 'R': Restricted = TRUE; break;
        !           474:                case 'q': Quiet=TRUE; Verbose=0; break;
        !           475:                case 's':
        !           476:                        if (isdigit((unsigned char) (*optarg))) {
        !           477:                                struct tm *tm;
        !           478:                                time_t t;
        !           479:                                int hh,mm;
        !           480:                                char *nex;
        !           481: 
        !           482:                                hh = strtoul (optarg, &nex, 10);
        !           483:                                if (hh>23)
        !           484:                                        usage(2,_("hour to large (0..23)"));
        !           485:                                if (*nex!=':')
        !           486:                                        usage(2, _("unparsable stop time\n"));
        !           487:                                nex++;
        !           488:                                mm = strtoul (optarg, &nex, 10);
        !           489:                                if (mm>59)
        !           490:                                        usage(2,_("minute to large (0..59)"));
        !           491: 
        !           492:                                t=time(NULL);
        !           493:                                tm=localtime(&t);
        !           494:                                tm->tm_hour=hh;
        !           495:                                tm->tm_min=hh;
        !           496:                                stop_time=mktime(tm);
        !           497:                                if (stop_time<t)
        !           498:                                        stop_time+=86400L; /* one day more */
        !           499:                                if (stop_time - t <10) 
        !           500:                                        usage(2,_("stop time to small"));
        !           501:                        } else {
        !           502:                                s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL);
        !           503:                                stop_time = tmp + time(0);
        !           504:                                if (s_err != LONGINT_OK)
        !           505:                                        STRTOL_FATAL_ERROR (optarg, _("stop-at"), s_err);
        !           506:                                if (tmp<10)
        !           507:                                        usage(2,_("stop time to small"));
        !           508:                        }
        !           509:                        break;
        !           510:                case 'S': enable_timesync=1; break;
        !           511:                case 'T': turbo_escape=1; break;
        !           512:                case 't':
        !           513:                        s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL);
        !           514:                        Rxtimeout = tmp;
        !           515:                        if (s_err != LONGINT_OK)
        !           516:                                STRTOL_FATAL_ERROR (optarg, _("timeout"), s_err);
        !           517:                        if (Rxtimeout<10 || Rxtimeout>1000)
        !           518:                                usage(2,_("timeout out of range 10..1000"));
        !           519:                        break;
        !           520:                case 'u': ++Unlinkafter; break;
        !           521:                case 'U':
        !           522:                        if (!under_rsh)
        !           523:                                Restricted=0;
        !           524:                        else
        !           525:                                error(1,0,
        !           526:                _("security violation: can't do that under restricted shell\n"));
        !           527:                        break;
        !           528:                case 'v': ++Verbose; break;
        !           529:                case 'w':
        !           530:                        s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL);
        !           531:                        Txwindow = tmp;
        !           532:                        if (s_err != LONGINT_OK)
        !           533:                                STRTOL_FATAL_ERROR (optarg, _("window size"), s_err);
        !           534:                        if (Txwindow < 256)
        !           535:                                Txwindow = 256;
        !           536:                        Txwindow = (Txwindow/64) * 64;
        !           537:                        Txwspac = Txwindow/4;
        !           538:                        if (blkopt > Txwspac
        !           539:                         || (!blkopt && Txwspac < MAX_BLOCK))
        !           540:                                blkopt = Txwspac;
        !           541:                        break;
        !           542:                case 'X': protocol=ZM_XMODEM; break;
        !           543:                case 1:   protocol=ZM_YMODEM; break;
        !           544:                case 'Z': protocol=ZM_ZMODEM; break;
        !           545:                case 'Y':
        !           546:                        Lskipnocor = TRUE;
        !           547:                        /* **** FALLL THROUGH TO **** */
        !           548:                case 'y':
        !           549:                        Lzmanag = ZF1_ZMCLOB; break;
        !           550:                case 2:
        !           551: #ifdef ENABLE_SYSLOG
        !           552: #  ifndef ENABLE_SYSLOG_FORCE
        !           553:                        if (optarg && (!strcmp(optarg,"off") || !strcmp(optarg,"no")))
        !           554:                        {
        !           555:                                if (under_rsh)
        !           556:                                        error(0,0, _("cannot turnoff syslog"));
        !           557:                                else
        !           558:                                        enable_syslog=FALSE;
        !           559:                        }
        !           560:                        else
        !           561:                                enable_syslog=TRUE;
        !           562: #  else
        !           563:                        error(0,0, _("cannot turnoff syslog"));
        !           564: #  endif
        !           565: #endif
        !           566:                        break;
        !           567:                case 4:
        !           568:                        s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL);
        !           569:                        startup_delay = tmp;
        !           570:                        if (s_err != LONGINT_OK)
        !           571:                                STRTOL_FATAL_ERROR (optarg, _("startup delay"), s_err);
        !           572:                        break;
        !           573:                case 5:
        !           574:                        tcp_flag=1;
        !           575:                        break;
        !           576:                case 6:
        !           577:                        tcp_flag=2;
        !           578:                        break;
        !           579:                case 7:
        !           580:                        tcp_flag=3;
        !           581:                        tcp_server_address=(char *)strdup(optarg);
        !           582:                        if (!tcp_server_address) {
        !           583:                                error(1,0,_("out of memory"));
        !           584:                        }
        !           585:                        break;
        !           586:                case 8: no_unixmode=1; break;
        !           587:                default:
        !           588:                        usage (2,NULL);
        !           589:                        break;
        !           590:                }
        !           591:        }
        !           592: 
        !           593:        if (getuid()!=geteuid()) {
        !           594:                error(1,0,
        !           595:                _("this program was never intended to be used setuid\n"));
        !           596:        }
        !           597:        zsendline_init();
        !           598: 
        !           599:        if (start_blklen==0) {
        !           600:                if (protocol == ZM_ZMODEM) {
        !           601:                        start_blklen=1024;
        !           602:                        if (Tframlen) {
        !           603:                                start_blklen=max_blklen=Tframlen;
        !           604:                        }
        !           605:                }
        !           606:                else
        !           607:                        start_blklen=128;
        !           608:        }
        !           609: 
        !           610:        if (argc<2)
        !           611:                usage(2,_("need at least one file to send"));
        !           612: 
        !           613:        if (startup_delay)
        !           614:                sleep(startup_delay);
        !           615: 
        !           616: #ifdef HAVE_SIGINTERRUPT
        !           617:        /* we want interrupted system calls to fail and not to be restarted. */
        !           618:        siginterrupt(SIGALRM,1);
        !           619: #endif
        !           620: 
        !           621: 
        !           622:        npats = argc - optind;
        !           623:        patts=&argv[optind];
        !           624: 
        !           625:        if (npats < 1 && !command_mode) 
        !           626:                usage(2,_("need at least one file to send"));
        !           627:        if (command_mode && Restricted) {
        !           628:                printf(_("Can't send command in restricted mode\n"));
        !           629:                exit(1);
        !           630:        }
        !           631: 
        !           632:        if (Fromcu && !Quiet) {
        !           633:                if (Verbose == 0)
        !           634:                        Verbose = 2;
        !           635:        }
        !           636:        vfile("%s %s\n", program_name, VERSION);
        !           637: 
        !           638:        if (tcp_flag==2) {
        !           639:                char buf[256];
        !           640: #ifdef MAXHOSTNAMELEN
        !           641:                char hn[MAXHOSTNAMELEN];
        !           642: #else
        !           643:                char hn[256];
        !           644: #endif
        !           645:                char *p,*q;
        !           646:                int d;
        !           647: 
        !           648:                /* tell receiver to receive via tcp */
        !           649:                d=tcp_server(buf);
        !           650:                p=strchr(buf+1,'<');
        !           651:                p++;
        !           652:                q=strchr(p,'>');
        !           653:                *q=0;
        !           654:                if (gethostname(hn,sizeof(hn))==-1) {
        !           655:                        error(1,0, _("hostname too long\n"));
        !           656:                }
        !           657:                fprintf(stdout,"connect with lrz --tcp-client \"%s:%s\"\n",hn,p);
        !           658:                fflush(stdout);
        !           659:                /* ok, now that this file is sent we can switch to tcp */
        !           660: 
        !           661:                tcp_socket=tcp_accept(d);
        !           662:                dup2(tcp_socket,0);
        !           663:                dup2(tcp_socket,1);
        !           664:        }
        !           665:        if (tcp_flag==3) {
        !           666:                char buf[256];
        !           667:                char *p;
        !           668:                p=strchr(tcp_server_address,':');
        !           669:                if (!p)
        !           670:                        error(1,0, _("illegal server address\n"));
        !           671:                *p++=0;
        !           672:                sprintf(buf,"[%s] <%s>\n",tcp_server_address,p);
        !           673: 
        !           674:                fprintf(stdout,"connecting to %s\n",buf);
        !           675:                fflush(stdout);
        !           676: 
        !           677:                /* we need to switch to tcp mode */
        !           678:                tcp_socket=tcp_connect(buf);
        !           679:                dup2(tcp_socket,0);
        !           680:                dup2(tcp_socket,1);
        !           681:        }
        !           682: 
        !           683: 
        !           684:        {
        !           685:                /* we write max_blocklen (data) + 18 (ZModem protocol overhead)
        !           686:                 * + escape overhead (about 4 %), so buffer has to be
        !           687:                 * somewhat larger than max_blklen 
        !           688:                 */
        !           689:                char *s=malloc(max_blklen+1024);
        !           690:                if (!s)
        !           691:                {
        !           692:                        zperr(_("out of memory"));
        !           693:                        exit(1);
        !           694:                }
        !           695: #ifdef SETVBUF_REVERSED
        !           696:                setvbuf(stdout,_IOFBF,s,max_blklen+1024);
        !           697: #else
        !           698:                setvbuf(stdout,s,_IOFBF,max_blklen+1024);
        !           699: #endif
        !           700:        }
        !           701:        blklen=start_blklen;
        !           702: 
        !           703:        for (i=optind,stdin_files=0;i<argc;i++) {
        !           704:                if (0==strcmp(argv[i],"-"))
        !           705:                        stdin_files++;
        !           706:        }
        !           707: 
        !           708:        if (stdin_files>1) {
        !           709:                usage(1,_("can read only one file from stdin"));
        !           710:        } else if (stdin_files==1) {
        !           711:                io_mode_fd=1;
        !           712:        }
        !           713:        io_mode(io_mode_fd,1);
        !           714:        readline_setup(io_mode_fd, 128, 256);
        !           715: 
        !           716:        if (signal(SIGINT, bibi) == SIG_IGN)
        !           717:                signal(SIGINT, SIG_IGN);
        !           718:        else {
        !           719:                signal(SIGINT, bibi); 
        !           720:                play_with_sigint=1;
        !           721:        }
        !           722:        signal(SIGTERM, bibi);
        !           723:        signal(SIGPIPE, bibi);
        !           724:        signal(SIGHUP, bibi);
        !           725: 
        !           726:        if ( protocol!=ZM_XMODEM) {
        !           727:                if (protocol==ZM_ZMODEM) {
        !           728:                        printf("rz\r");
        !           729:                        fflush(stdout);
        !           730:                }
        !           731:                countem(npats, patts);
        !           732:                if (protocol == ZM_ZMODEM) {
        !           733:                        /* throw away any input already received. This doesn't harm
        !           734:                         * as we invite the receiver to send it's data again, and
        !           735:                         * might be useful if the receiver has already died or
        !           736:                         * if there is dirt left if the line 
        !           737:                         */
        !           738: #ifdef HAVE_SELECT
        !           739:                        struct timeval t;
        !           740:                        unsigned char throwaway;
        !           741:                        fd_set f;
        !           742: #endif
        !           743: 
        !           744:                        purgeline(io_mode_fd);
        !           745:                                
        !           746: #ifdef HAVE_SELECT
        !           747:                        t.tv_sec = 0;
        !           748:                        t.tv_usec = 0;
        !           749:                                
        !           750:                        FD_ZERO(&f);
        !           751:                        FD_SET(io_mode_fd,&f);
        !           752:                                
        !           753:                        while (select(1,&f,NULL,NULL,&t)) {
        !           754:                                if (0==read(io_mode_fd,&throwaway,1)) /* EOF ... */
        !           755:                                        break;
        !           756:                        }
        !           757: #endif
        !           758: 
        !           759:                        purgeline(io_mode_fd);
        !           760:                        stohdr(0L);
        !           761:                        if (command_mode)
        !           762:                                Txhdr[ZF0] = ZCOMMAND;
        !           763:                        zshhdr(ZRQINIT, Txhdr);
        !           764:                        zrqinits_sent++;
        !           765: #if defined(ENABLE_TIMESYNC)
        !           766:                        if (Rxflags2 != ZF1_TIMESYNC)
        !           767:                                /* disable timesync if there are any flags we don't know.
        !           768:                                 * dsz/gsz seems to use some other flags! */
        !           769:                                enable_timesync=FALSE;
        !           770:                        if (Rxflags2 & ZF1_TIMESYNC && enable_timesync) {
        !           771:                                Totalleft+=6; /* TIMESYNC never needs more */
        !           772:                                Filesleft++;
        !           773:                        }
        !           774: #endif
        !           775:                        if (tcp_flag==1) {
        !           776:                                Totalleft+=256; /* tcp never needs more */
        !           777:                                Filesleft++;
        !           778:                        }
        !           779:                }
        !           780:        }
        !           781:        fflush(stdout);
        !           782: 
        !           783:        if (Cmdstr) {
        !           784:                if (getzrxinit()) {
        !           785:                        Exitcode=0200; canit(STDOUT_FILENO);
        !           786:                }
        !           787:                else if (zsendcmd(Cmdstr, strlen(Cmdstr)+1)) {
        !           788:                        Exitcode=0200; canit(STDOUT_FILENO);
        !           789:                }
        !           790:        } else if (wcsend(npats, patts)==ERROR) {
        !           791:                Exitcode=0200;
        !           792:                canit(STDOUT_FILENO);
        !           793:        }
        !           794:        fflush(stdout);
        !           795:        io_mode(io_mode_fd,0);
        !           796:        if (Exitcode)
        !           797:                dm=Exitcode;
        !           798:        else if (errcnt)
        !           799:                dm=1;
        !           800:        else
        !           801:                dm=0;
        !           802:        if (Verbose)
        !           803:        {
        !           804:                fputs("\r\n",stderr);
        !           805:                if (dm)
        !           806:                        fputs(_("Transfer incomplete\n"),stderr);
        !           807:                else
        !           808:                        fputs(_("Transfer complete\n"),stderr);
        !           809:        }
        !           810:        exit(dm);
        !           811:        /*NOTREACHED*/
        !           812: }
        !           813: 
        !           814: static int 
        !           815: send_pseudo(const char *name, const char *data)
        !           816: {
        !           817:        char *tmp;
        !           818:        const char *p;
        !           819:        int ret=0; /* ok */
        !           820:        size_t plen;
        !           821:        int fd;
        !           822:        int lfd;
        !           823:        
        !           824:        p = getenv ("TMPDIR");
        !           825:        if (!p)
        !           826:                p = getenv ("TMP");
        !           827:        if (!p)
        !           828:                p = "/tmp";
        !           829:        tmp=malloc(PATH_MAX+1);
        !           830:        if (!tmp)
        !           831:                error(1,0,_("out of memory"));
        !           832:        
        !           833:        plen=strlen(p);
        !           834:        memcpy(tmp,p,plen);     
        !           835:        tmp[plen++]='/';
        !           836: 
        !           837:        lfd=0;
        !           838:        do {
        !           839:                if (lfd++==10) {
        !           840:                        free(tmp);
        !           841:                        vstringf (_ ("send_pseudo %s: cannot open tmpfile %s: %s"),
        !           842:                                         name, tmp, strerror (errno));
        !           843:                        vstring ("\r\n");
        !           844:                        return 1;
        !           845:                }
        !           846:                sprintf(tmp+plen,"%s.%lu.%d",name,(unsigned long) getpid(),lfd);
        !           847:                fd=open(tmp,O_WRONLY|O_CREAT|O_EXCL,0700);
        !           848:                /* is O_EXCL guaranted to not follow symlinks? 
        !           849:                 * I don`t know ... so be careful
        !           850:                 */
        !           851:                if (fd!=-1) {
        !           852:                        struct stat st;
        !           853:                        if (0!=lstat(tmp,&st)) {
        !           854:                                vstringf (_ ("send_pseudo %s: cannot lstat tmpfile %s: %s"),
        !           855:                                                 name, tmp, strerror (errno));
        !           856:                                vstring ("\r\n");
        !           857:                                unlink(tmp);
        !           858:                                close(fd);
        !           859:                                fd=-1;
        !           860:                        } else {
        !           861:                                if (S_ISLNK(st.st_mode)) {
        !           862:                                        vstringf (_ ("send_pseudo %s: avoiding symlink trap"),name);
        !           863:                                        vstring ("\r\n");
        !           864:                                        unlink(tmp);
        !           865:                                        close(fd);
        !           866:                                        fd=-1;
        !           867:                                }
        !           868:                        }
        !           869:                }
        !           870:        } while (fd==-1);
        !           871:        if (write(fd,data,strlen(data))!=(signed long) strlen(data)
        !           872:                || close(fd)!=0) {
        !           873:                vstringf (_ ("send_pseudo %s: cannot write to tmpfile %s: %s"),
        !           874:                                 name, tmp, strerror (errno));
        !           875:                vstring ("\r\n");
        !           876:                free(tmp);
        !           877:                return 1;
        !           878:        }
        !           879: 
        !           880:        if (wcs (tmp,name) == ERROR) {
        !           881:                if (Verbose)
        !           882:                        vstringf (_ ("send_pseudo %s: failed"),name);
        !           883:                else {
        !           884:                        if (Verbose)
        !           885:                                vstringf (_ ("send_pseudo %s: ok"),name);
        !           886:                        Filcnt--;
        !           887:                }
        !           888:                vstring ("\r\n");
        !           889:                ret=1;
        !           890:        }
        !           891:        unlink (tmp);
        !           892:        free(tmp);
        !           893:        return ret;
        !           894: }
        !           895: 
        !           896: static int
        !           897: wcsend (int argc, char *argp[])
        !           898: {
        !           899:        int n;
        !           900: 
        !           901:        Crcflg = FALSE;
        !           902:        firstsec = TRUE;
        !           903:        bytcnt = (size_t) -1;
        !           904: 
        !           905:        if (tcp_flag==1) {
        !           906:                char buf[256];
        !           907:                int d;
        !           908: 
        !           909:                /* tell receiver to receive via tcp */
        !           910:                d=tcp_server(buf);
        !           911:                if (send_pseudo("/$tcp$.t",buf)) {
        !           912:                        error(1,0,_("tcp protocol init failed\n"));
        !           913:                }
        !           914:                /* ok, now that this file is sent we can switch to tcp */
        !           915: 
        !           916:                tcp_socket=tcp_accept(d);
        !           917:                dup2(tcp_socket,0);
        !           918:                dup2(tcp_socket,1);
        !           919:        }
        !           920: 
        !           921:        for (n = 0; n < argc; ++n) {
        !           922:                Totsecs = 0;
        !           923:                if (wcs (argp[n],NULL) == ERROR)
        !           924:                        return ERROR;
        !           925:        }
        !           926: #if defined(ENABLE_TIMESYNC)
        !           927:        if (Rxflags2 & ZF1_TIMESYNC && enable_timesync) {
        !           928:                /* implement Peter Mandrellas extension */
        !           929:                char buf[60];
        !           930:                time_t t = time (NULL);
        !           931:                struct tm *tm = localtime (&t);         /* sets timezone */
        !           932:                strftime (buf, sizeof (buf) - 1, "%H:%M:%S", tm);
        !           933:                if (Verbose) {
        !           934:                        vstring ("\r\n");
        !           935:                        vstringf (_("Answering TIMESYNC at %s"),buf);
        !           936:                }
        !           937: #if defined(HAVE_TIMEZONE_VAR)
        !           938:                sprintf(buf+strlen(buf),"%ld\r\n", timezone / 60);
        !           939:                if (Verbose)
        !           940:                        vstringf (" (%s %ld)\r\n", _ ("timezone"), timezone / 60);
        !           941: #else
        !           942:                if (Verbose)
        !           943:                        vstringf (" (%s)\r\n", _ ("timezone unknown"));
        !           944: #endif
        !           945:                send_pseudo("/$time$.t",buf);
        !           946:        }
        !           947: #endif
        !           948:        Totsecs = 0;
        !           949:        if (Filcnt == 0) {                      /* bitch if we couldn't open ANY files */
        !           950: #if 0
        !           951:        /* i *really* do not like this */
        !           952:                if (protocol != ZM_XMODEM) {
        !           953:                        const char *Cmdstr;             /* Pointer to the command string */
        !           954:                        command_mode = TRUE;
        !           955:                        Cmdstr = "echo \"lsz: Can't open any requested files\"";
        !           956:                        if (getnak ()) {
        !           957:                                Exitcode = 0200;
        !           958:                                canit(STDOUT_FILENO);
        !           959:                        }
        !           960:                        if (!zmodem_requested)
        !           961:                                canit(STDOUT_FILENO);
        !           962:                        else if (zsendcmd (Cmdstr, 1 + strlen (Cmdstr))) {
        !           963:                                Exitcode = 0200;
        !           964:                                canit(STDOUT_FILENO);
        !           965:                        }
        !           966:                        Exitcode = 1;
        !           967:                        return OK;
        !           968:                }
        !           969: #endif
        !           970:                canit(STDOUT_FILENO);
        !           971:                vstring ("\r\n");
        !           972:                vstringf (_ ("Can't open any requested files."));
        !           973:                vstring ("\r\n");
        !           974:                return ERROR;
        !           975:        }
        !           976:        if (zmodem_requested)
        !           977:                saybibi ();
        !           978:        else if (protocol != ZM_XMODEM) {
        !           979:                struct zm_fileinfo zi;
        !           980:                char *pa;
        !           981:                pa=alloca(PATH_MAX+1);
        !           982:                *pa='\0';
        !           983:                zi.fname = pa;
        !           984:                zi.modtime = 0;
        !           985:                zi.mode = 0;
        !           986:                zi.bytes_total = 0;
        !           987:                zi.bytes_sent = 0;
        !           988:                zi.bytes_received = 0;
        !           989:                zi.bytes_skipped = 0;
        !           990:                wctxpn (&zi);
        !           991:        }
        !           992:        return OK;
        !           993: }
        !           994: 
        !           995: static int
        !           996: wcs(const char *oname, const char *remotename)
        !           997: {
        !           998: #if !defined(S_ISDIR)
        !           999:        int c;
        !          1000: #endif
        !          1001:        struct stat f;
        !          1002:        char *name;
        !          1003:        struct zm_fileinfo zi;
        !          1004: #ifdef HAVE_MMAP
        !          1005:        int dont_mmap_this=0;
        !          1006: #endif
        !          1007: #ifdef ENABLE_SYSLOG
        !          1008:        const char *shortname;
        !          1009:        shortname=strrchr(oname,'/');
        !          1010:        if (shortname)
        !          1011:                shortname++;
        !          1012:        else
        !          1013:                shortname=oname;
        !          1014: #endif
        !          1015: 
        !          1016: 
        !          1017:        if (Restricted) {
        !          1018:                /* restrict pathnames to current tree or uucppublic */
        !          1019:                if ( strstr(oname, "../")
        !          1020: #ifdef PUBDIR
        !          1021:                 || (oname[0]== '/' && strncmp(oname, MK_STRING(PUBDIR),
        !          1022:                        strlen(MK_STRING(PUBDIR))))
        !          1023: #endif
        !          1024:                ) {
        !          1025:                        canit(STDOUT_FILENO);
        !          1026:                        vchar('\r');
        !          1027:                        error(1,0,
        !          1028:                                _("security violation: not allowed to upload from %s"),oname);
        !          1029:                }
        !          1030:        }
        !          1031:        
        !          1032:        if (0==strcmp(oname,"-")) {
        !          1033:                char *p=getenv("ONAME");
        !          1034:                name=alloca(PATH_MAX+1);
        !          1035:                if (p) {
        !          1036:                        strcpy(name, p);
        !          1037:                } else {
        !          1038:                        sprintf(name, "s%lu.lsz", (unsigned long) getpid());
        !          1039:                }
        !          1040:                input_f=stdin;
        !          1041: #ifdef HAVE_MMAP
        !          1042:                dont_mmap_this=1;
        !          1043: #endif
        !          1044:        } else if ((input_f=fopen(oname, "r"))==NULL) {
        !          1045:                int e=errno;
        !          1046:                error(0,e, _("cannot open %s"),oname);
        !          1047:                ++errcnt;
        !          1048:                return OK;      /* pass over it, there may be others */
        !          1049:        } else {
        !          1050:                name=alloca(PATH_MAX+1);
        !          1051:                strcpy(name, oname);
        !          1052:        }
        !          1053: #ifdef HAVE_MMAP
        !          1054:        if (!use_mmap || dont_mmap_this)
        !          1055: #endif
        !          1056:        {
        !          1057:                static char *s=NULL;
        !          1058:                static size_t last_length=0;
        !          1059:                struct stat st;
        !          1060:                if (fstat(fileno(input_f),&st)==-1)
        !          1061:                        st.st_size=1024*1024;
        !          1062:                if (buffersize==(size_t) -1 && s) {
        !          1063:                        if ((size_t) st.st_size > last_length) {
        !          1064:                                free(s);
        !          1065:                                s=NULL;
        !          1066:                                last_length=0;
        !          1067:                        }
        !          1068:                }
        !          1069:                if (!s && buffersize) {
        !          1070:                        last_length=16384;
        !          1071:                        if (buffersize==(size_t) -1) {
        !          1072:                                if (st.st_size>0)
        !          1073:                                        last_length=st.st_size;
        !          1074:                        } else
        !          1075:                                last_length=buffersize;
        !          1076:                        /* buffer whole pages */
        !          1077:                        last_length=(last_length+4095)&0xfffff000;
        !          1078:                        s=malloc(last_length);
        !          1079:                        if (!s) {
        !          1080:                                zpfatal(_("out of memory"));
        !          1081:                                exit(1);
        !          1082:                        }
        !          1083:                }
        !          1084:                if (s) {
        !          1085: #ifdef SETVBUF_REVERSED
        !          1086:                        setvbuf(input_f,_IOFBF,s,last_length);
        !          1087: #else
        !          1088:                        setvbuf(input_f,s,_IOFBF,last_length);
        !          1089: #endif
        !          1090:                }
        !          1091:        }
        !          1092:        vpos = 0;
        !          1093:        /* Check for directory or block special files */
        !          1094:        fstat(fileno(input_f), &f);
        !          1095: #if defined(S_ISDIR)
        !          1096:        if (S_ISDIR(f.st_mode) || S_ISBLK(f.st_mode)) {
        !          1097: #else
        !          1098:        c = f.st_mode & S_IFMT;
        !          1099:        if (c == S_IFDIR || c == S_IFBLK) {
        !          1100: #endif
        !          1101:                error(0,0, _("is not a file: %s"),name);
        !          1102:                fclose(input_f);
        !          1103:                return OK;
        !          1104:        }
        !          1105: 
        !          1106:        if (remotename) {
        !          1107:                /* disqualify const */
        !          1108:                union {
        !          1109:                        const char *c;
        !          1110:                        char *s;
        !          1111:                } cheat;
        !          1112:                cheat.c=remotename;
        !          1113:                zi.fname=cheat.s;
        !          1114:        } else
        !          1115:                zi.fname=name;
        !          1116:        zi.modtime=f.st_mtime;
        !          1117:        zi.mode=f.st_mode;
        !          1118: #if defined(S_ISFIFO)
        !          1119:        zi.bytes_total= (S_ISFIFO(f.st_mode)) ? DEFBYTL : f.st_size;
        !          1120: #else
        !          1121:        zi.bytes_total= c == S_IFIFO ? DEFBYTL : f.st_size;
        !          1122: #endif
        !          1123:        zi.bytes_sent=0;
        !          1124:        zi.bytes_received=0;
        !          1125:        zi.bytes_skipped=0;
        !          1126:        zi.eof_seen=0;
        !          1127:        timing(1,NULL);
        !          1128: 
        !          1129:        ++Filcnt;
        !          1130:        switch (wctxpn(&zi)) {
        !          1131:        case ERROR:
        !          1132: #ifdef ENABLE_SYSLOG
        !          1133:                if (enable_syslog)
        !          1134:                        lsyslog(LOG_INFO, _("%s/%s: error occured"),protname(),shortname);
        !          1135: #endif
        !          1136:                return ERROR;
        !          1137:        case ZSKIP:
        !          1138:                error(0,0, _("skipped: %s"),name);
        !          1139: #ifdef ENABLE_SYSLOG
        !          1140:                if (enable_syslog)
        !          1141:                        lsyslog(LOG_INFO, _("%s/%s: skipped"),protname(),shortname);
        !          1142: #endif
        !          1143:                return OK;
        !          1144:        }
        !          1145:        if (!zmodem_requested && wctx(&zi)==ERROR)
        !          1146:        {
        !          1147: #ifdef ENABLE_SYSLOG
        !          1148:                if (enable_syslog)
        !          1149:                        lsyslog(LOG_INFO, _("%s/%s: error occured"),protname(),shortname);
        !          1150: #endif
        !          1151:                return ERROR;
        !          1152:        }
        !          1153:        if (Unlinkafter)
        !          1154:                unlink(oname);
        !          1155: 
        !          1156:        if (Verbose > 1
        !          1157: #ifdef ENABLE_SYSLOG
        !          1158:                || enable_syslog
        !          1159: #endif
        !          1160:                ) {
        !          1161:                long bps;
        !          1162:                double d=timing(0,NULL);
        !          1163:                if (d==0) /* can happen if timing() uses time() */
        !          1164:                        d=0.5;
        !          1165:                bps=zi.bytes_sent/d;
        !          1166:                vchar('\r');
        !          1167:                if (Verbose > 1) 
        !          1168:                        vstringf(_("Bytes Sent:%7ld   BPS:%-8ld                        \n"),
        !          1169:                                (long) zi.bytes_sent,bps);
        !          1170: #ifdef ENABLE_SYSLOG
        !          1171:                if (enable_syslog)
        !          1172:                        lsyslog(LOG_INFO, "%s/%s: %ld Bytes, %ld BPS",shortname,
        !          1173:                                protname(), (long) zi.bytes_sent,bps);
        !          1174: #endif
        !          1175:        }
        !          1176:        return 0;
        !          1177: }
        !          1178: 
        !          1179: /*
        !          1180:  * generate and transmit pathname block consisting of
        !          1181:  *  pathname (null terminated),
        !          1182:  *  file length, mode time and file mode in octal
        !          1183:  *  as provided by the Unix fstat call.
        !          1184:  *  N.B.: modifies the passed name, may extend it!
        !          1185:  */
        !          1186: static int
        !          1187: wctxpn(struct zm_fileinfo *zi)
        !          1188: {
        !          1189:        register char *p, *q;
        !          1190:        char *name2;
        !          1191:        struct stat f;
        !          1192: 
        !          1193:        name2=alloca(PATH_MAX+1);
        !          1194:        f.st_size = 0;
        !          1195: 
        !          1196:        if (protocol==ZM_XMODEM) {
        !          1197:                if (Verbose && *zi->fname && fstat(fileno(input_f), &f)!= -1) {
        !          1198:                        vstringf(_("Sending %s, %ld blocks: "),
        !          1199:                          zi->fname, (long) (f.st_size>>7));
        !          1200:                }
        !          1201:                vstringf(_("Give your local XMODEM receive command now."));
        !          1202:                vstring("\r\n");
        !          1203:                return OK;
        !          1204:        }
        !          1205:        if (!zmodem_requested)
        !          1206:                if (getnak()) {
        !          1207:                        vfile("getnak failed");
        !          1208:                        DO_SYSLOG((LOG_INFO, "%s/%s: getnak failed",
        !          1209:                                           shortname,protname()));
        !          1210:                        return ERROR;
        !          1211:                }
        !          1212: 
        !          1213:        q = (char *) 0;
        !          1214:        if (Dottoslash) {               /* change . to . */
        !          1215:                for (p=zi->fname; *p; ++p) {
        !          1216:                        if (*p == '/')
        !          1217:                                q = p;
        !          1218:                        else if (*p == '.')
        !          1219:                                *(q=p) = '/';
        !          1220:                }
        !          1221:                if (q && strlen(++q) > 8) {     /* If name>8 chars */
        !          1222:                        q += 8;                 /*   make it .ext */
        !          1223:                        strcpy(name2, q);       /* save excess of name */
        !          1224:                        *q = '.';
        !          1225:                        strcpy(++q, name2);     /* add it back */
        !          1226:                }
        !          1227:        }
        !          1228: 
        !          1229:        for (p=zi->fname, q=txbuf ; *p; )
        !          1230:                if ((*q++ = *p++) == '/' && !Fullname)
        !          1231:                        q = txbuf;
        !          1232:        *q++ = 0;
        !          1233:        p=q;
        !          1234:        while (q < (txbuf + MAX_BLOCK))
        !          1235:                *q++ = 0;
        !          1236:        /* note that we may lose some information here in case mode_t is wider than an 
        !          1237:         * int. But i believe sending %lo instead of %o _could_ break compatability
        !          1238:         */
        !          1239:        if (!Ascii && (input_f!=stdin) && *zi->fname && fstat(fileno(input_f), &f)!= -1)
        !          1240:                sprintf(p, "%lu %lo %o 0 %d %ld", (long) f.st_size, f.st_mtime,
        !          1241:                  (unsigned int)((no_unixmode) ? 0 : f.st_mode), 
        !          1242:                  Filesleft, Totalleft);
        !          1243:        if (Verbose)
        !          1244:                vstringf(_("Sending: %s\n"),txbuf);
        !          1245:        Totalleft -= f.st_size;
        !          1246:        if (--Filesleft <= 0)
        !          1247:                Totalleft = 0;
        !          1248:        if (Totalleft < 0)
        !          1249:                Totalleft = 0;
        !          1250: 
        !          1251:        /* force 1k blocks if name won't fit in 128 byte block */
        !          1252:        if (txbuf[125])
        !          1253:                blklen=1024;
        !          1254:        else {          /* A little goodie for IMP/KMD */
        !          1255:                txbuf[127] = (f.st_size + 127) >>7;
        !          1256:                txbuf[126] = (f.st_size + 127) >>15;
        !          1257:        }
        !          1258:        if (zmodem_requested)
        !          1259:                return zsendfile(zi,txbuf, 1+strlen(p)+(p-txbuf));
        !          1260:        if (wcputsec(txbuf, 0, 128)==ERROR) {
        !          1261:                vfile("wcputsec failed");
        !          1262:                DO_SYSLOG((LOG_INFO, "%s/%s: wcputsec failed",
        !          1263:                                   shortname,protname()));
        !          1264:                return ERROR;
        !          1265:        }
        !          1266:        return OK;
        !          1267: }
        !          1268: 
        !          1269: static int 
        !          1270: getnak(void)
        !          1271: {
        !          1272:        int firstch;
        !          1273:        int tries=0;
        !          1274: 
        !          1275:        Lastrx = 0;
        !          1276:        for (;;) {
        !          1277:                tries++;
        !          1278:                switch (firstch = READLINE_PF(100)) {
        !          1279:                case ZPAD:
        !          1280:                        if (getzrxinit())
        !          1281:                                return ERROR;
        !          1282:                        Ascii = 0;      /* Receiver does the conversion */
        !          1283:                        return FALSE;
        !          1284:                case TIMEOUT:
        !          1285:                        /* 30 seconds are enough */
        !          1286:                        if (tries==3) {
        !          1287:                                zperr(_("Timeout on pathname"));
        !          1288:                                return TRUE;
        !          1289:                        }
        !          1290:                        /* don't send a second ZRQINIT _directly_ after the
        !          1291:                         * first one. Never send more then 4 ZRQINIT, because
        !          1292:                         * omen rz stops if it saw 5 of them */
        !          1293:                        if ((zrqinits_sent>1 || tries>1) && zrqinits_sent<4) {
        !          1294:                                /* if we already sent a ZRQINIT we are using zmodem
        !          1295:                                 * protocol and may send further ZRQINITs 
        !          1296:                                 */
        !          1297:                                stohdr(0L);
        !          1298:                                zshhdr(ZRQINIT, Txhdr);
        !          1299:                                zrqinits_sent++;
        !          1300:                        }
        !          1301:                        continue;
        !          1302:                case WANTG:
        !          1303:                        io_mode(io_mode_fd,2);  /* Set cbreak, XON/XOFF, etc. */
        !          1304:                        Optiong = TRUE;
        !          1305:                        blklen=1024;
        !          1306:                case WANTCRC:
        !          1307:                        Crcflg = TRUE;
        !          1308:                case NAK:
        !          1309:                        return FALSE;
        !          1310:                case CAN:
        !          1311:                        if ((firstch = READLINE_PF(20)) == CAN && Lastrx == CAN)
        !          1312:                                return TRUE;
        !          1313:                default:
        !          1314:                        break;
        !          1315:                }
        !          1316:                Lastrx = firstch;
        !          1317:        }
        !          1318: }
        !          1319: 
        !          1320: 
        !          1321: static int 
        !          1322: wctx(struct zm_fileinfo *zi)
        !          1323: {
        !          1324:        register size_t thisblklen;
        !          1325:        register int sectnum, attempts, firstch;
        !          1326: 
        !          1327:        firstsec=TRUE;  thisblklen = blklen;
        !          1328:        vfile("wctx:file length=%ld", (long) zi->bytes_total);
        !          1329: 
        !          1330:        while ((firstch=READLINE_PF(Rxtimeout))!=NAK && firstch != WANTCRC
        !          1331:          && firstch != WANTG && firstch!=TIMEOUT && firstch!=CAN)
        !          1332:                ;
        !          1333:        if (firstch==CAN) {
        !          1334:                zperr(_("Receiver Cancelled"));
        !          1335:                return ERROR;
        !          1336:        }
        !          1337:        if (firstch==WANTCRC)
        !          1338:                Crcflg=TRUE;
        !          1339:        if (firstch==WANTG)
        !          1340:                Crcflg=TRUE;
        !          1341:        sectnum=0;
        !          1342:        for (;;) {
        !          1343:                if (zi->bytes_total <= (zi->bytes_sent + 896L))
        !          1344:                        thisblklen = 128;
        !          1345:                if ( !filbuf(txbuf, thisblklen))
        !          1346:                        break;
        !          1347:                if (wcputsec(txbuf, ++sectnum, thisblklen)==ERROR)
        !          1348:                        return ERROR;
        !          1349:                zi->bytes_sent += thisblklen;
        !          1350:        }
        !          1351:        fclose(input_f);
        !          1352:        attempts=0;
        !          1353:        do {
        !          1354:                purgeline(io_mode_fd);
        !          1355:                sendline(EOT);
        !          1356:                flushmo();
        !          1357:                ++attempts;
        !          1358:        } while ((firstch=(READLINE_PF(Rxtimeout)) != ACK) && attempts < RETRYMAX);
        !          1359:        if (attempts == RETRYMAX) {
        !          1360:                zperr(_("No ACK on EOT"));
        !          1361:                return ERROR;
        !          1362:        }
        !          1363:        else
        !          1364:                return OK;
        !          1365: }
        !          1366: 
        !          1367: static int 
        !          1368: wcputsec(char *buf, int sectnum, size_t cseclen)
        !          1369: {
        !          1370:        int checksum, wcj;
        !          1371:        char *cp;
        !          1372:        unsigned oldcrc;
        !          1373:        int firstch;
        !          1374:        int attempts;
        !          1375: 
        !          1376:        firstch=0;      /* part of logic to detect CAN CAN */
        !          1377: 
        !          1378:        if (Verbose>1) {
        !          1379:                vchar('\r');
        !          1380:                if (protocol==ZM_XMODEM) {
        !          1381:                        vstringf(_("Xmodem sectors/kbytes sent: %3d/%2dk"), Totsecs, Totsecs/8 );
        !          1382:                } else {
        !          1383:                        vstringf(_("Ymodem sectors/kbytes sent: %3d/%2dk"), Totsecs, Totsecs/8 );
        !          1384:                }
        !          1385:        }
        !          1386:        for (attempts=0; attempts <= RETRYMAX; attempts++) {
        !          1387:                Lastrx= firstch;
        !          1388:                sendline(cseclen==1024?STX:SOH);
        !          1389:                sendline(sectnum);
        !          1390:                sendline(-sectnum -1);
        !          1391:                oldcrc=checksum=0;
        !          1392:                for (wcj=cseclen,cp=buf; --wcj>=0; ) {
        !          1393:                        sendline(*cp);
        !          1394:                        oldcrc=updcrc((0377& *cp), oldcrc);
        !          1395:                        checksum += *cp++;
        !          1396:                }
        !          1397:                if (Crcflg) {
        !          1398:                        oldcrc=updcrc(0,updcrc(0,oldcrc));
        !          1399:                        sendline((int)oldcrc>>8);
        !          1400:                        sendline((int)oldcrc);
        !          1401:                }
        !          1402:                else
        !          1403:                        sendline(checksum);
        !          1404: 
        !          1405:                flushmo();
        !          1406:                if (Optiong) {
        !          1407:                        firstsec = FALSE; return OK;
        !          1408:                }
        !          1409:                firstch = READLINE_PF(Rxtimeout);
        !          1410: gotnak:
        !          1411:                switch (firstch) {
        !          1412:                case CAN:
        !          1413:                        if(Lastrx == CAN) {
        !          1414: cancan:
        !          1415:                                zperr(_("Cancelled"));  return ERROR;
        !          1416:                        }
        !          1417:                        break;
        !          1418:                case TIMEOUT:
        !          1419:                        zperr(_("Timeout on sector ACK")); continue;
        !          1420:                case WANTCRC:
        !          1421:                        if (firstsec)
        !          1422:                                Crcflg = TRUE;
        !          1423:                case NAK:
        !          1424:                        zperr(_("NAK on sector")); continue;
        !          1425:                case ACK: 
        !          1426:                        firstsec=FALSE;
        !          1427:                        Totsecs += (cseclen>>7);
        !          1428:                        return OK;
        !          1429:                case ERROR:
        !          1430:                        zperr(_("Got burst for sector ACK")); break;
        !          1431:                default:
        !          1432:                        zperr(_("Got %02x for sector ACK"), firstch); break;
        !          1433:                }
        !          1434:                for (;;) {
        !          1435:                        Lastrx = firstch;
        !          1436:                        if ((firstch = READLINE_PF(Rxtimeout)) == TIMEOUT)
        !          1437:                                break;
        !          1438:                        if (firstch == NAK || firstch == WANTCRC)
        !          1439:                                goto gotnak;
        !          1440:                        if (firstch == CAN && Lastrx == CAN)
        !          1441:                                goto cancan;
        !          1442:                }
        !          1443:        }
        !          1444:        zperr(_("Retry Count Exceeded"));
        !          1445:        return ERROR;
        !          1446: }
        !          1447: 
        !          1448: /* fill buf with count chars padding with ^Z for CPM */
        !          1449: static size_t 
        !          1450: filbuf(char *buf, size_t count)
        !          1451: {
        !          1452:        int c;
        !          1453:        size_t m;
        !          1454: 
        !          1455:        if ( !Ascii) {
        !          1456:                m = read(fileno(input_f), buf, count);
        !          1457:                if (m <= 0)
        !          1458:                        return 0;
        !          1459:                while (m < count)
        !          1460:                        buf[m++] = 032;
        !          1461:                return count;
        !          1462:        }
        !          1463:        m=count;
        !          1464:        if (Lfseen) {
        !          1465:                *buf++ = 012; --m; Lfseen = 0;
        !          1466:        }
        !          1467:        while ((c=getc(input_f))!=EOF) {
        !          1468:                if (c == 012) {
        !          1469:                        *buf++ = 015;
        !          1470:                        if (--m == 0) {
        !          1471:                                Lfseen = TRUE; break;
        !          1472:                        }
        !          1473:                }
        !          1474:                *buf++ =c;
        !          1475:                if (--m == 0)
        !          1476:                        break;
        !          1477:        }
        !          1478:        if (m==count)
        !          1479:                return 0;
        !          1480:        else
        !          1481:                while (m--!=0)
        !          1482:                        *buf++ = CPMEOF;
        !          1483:        return count;
        !          1484: }
        !          1485: 
        !          1486: /* Fill buffer with blklen chars */
        !          1487: static size_t
        !          1488: zfilbuf (struct zm_fileinfo *zi)
        !          1489: {
        !          1490:        size_t n;
        !          1491: 
        !          1492:        n = fread (txbuf, 1, blklen, input_f);
        !          1493:        if (n < blklen)
        !          1494:                zi->eof_seen = 1;
        !          1495:        else {
        !          1496:                /* save one empty paket in case file ends ob blklen boundary */
        !          1497:                int c = getc(input_f);
        !          1498: 
        !          1499:                if (c != EOF || !feof(input_f))
        !          1500:                        ungetc(c, input_f);
        !          1501:                else
        !          1502:                        zi->eof_seen = 1;
        !          1503:        }
        !          1504:        return n;
        !          1505: }
        !          1506: 
        !          1507: static void
        !          1508: usage1 (int exitcode)
        !          1509: {
        !          1510:        usage (exitcode, NULL);
        !          1511: }
        !          1512: 
        !          1513: static void
        !          1514: usage(int exitcode, const char *what)
        !          1515: {
        !          1516:        FILE *f=stdout;
        !          1517: 
        !          1518:        if (exitcode)
        !          1519:        {
        !          1520:                if (what)
        !          1521:                        fprintf(stderr, "%s: %s\n",program_name,what);
        !          1522:            fprintf (stderr, _("Try `%s --help' for more information.\n"),
        !          1523:             program_name);
        !          1524:                exit(exitcode);
        !          1525:        }
        !          1526: 
        !          1527:        fprintf(f, _("%s version %s\n"), program_name,
        !          1528:                VERSION);
        !          1529: 
        !          1530:        fprintf(f,_("Usage: %s [options] file ...\n"),
        !          1531:                program_name);
        !          1532:        fprintf(f,_("   or: %s [options] -{c|i} COMMAND\n"),program_name);
        !          1533:        fputs(_("Send file(s) with ZMODEM/YMODEM/XMODEM protocol\n"),f);
        !          1534:        fputs(_(
        !          1535:                "    (X) = option applies to XMODEM only\n"
        !          1536:                "    (Y) = option applies to YMODEM only\n"
        !          1537:                "    (Z) = option applies to ZMODEM only\n"
        !          1538:                ),f);
        !          1539:        /* splitted into two halves for really bad compilers */
        !          1540:        fputs(_(
        !          1541: "  -+, --append                append to existing destination file (Z)\n"
        !          1542: "  -2, --twostop               use 2 stop bits\n"
        !          1543: "  -4, --try-4k                go up to 4K blocksize\n"
        !          1544: "      --start-4k              start with 4K blocksize (doesn't try 8)\n"
        !          1545: "  -8, --try-8k                go up to 8K blocksize\n"
        !          1546: "      --start-8k              start with 8K blocksize\n"
        !          1547: "  -a, --ascii                 ASCII transfer (change CR/LF to LF)\n"
        !          1548: "  -b, --binary                binary transfer\n"
        !          1549: "  -B, --bufsize N             buffer N bytes (N==auto: buffer whole file)\n"
        !          1550: "  -c, --command COMMAND       execute remote command COMMAND (Z)\n"
        !          1551: "  -C, --command-tries N       try N times to execute a command (Z)\n"
        !          1552: "  -d, --dot-to-slash          change '.' to '/' in pathnames (Y/Z)\n"
        !          1553: "      --delay-startup N       sleep N seconds before doing anything\n"
        !          1554: "  -e, --escape                escape all control characters (Z)\n"
        !          1555: "  -E, --rename                force receiver to rename files it already has\n"
        !          1556: "  -f, --full-path             send full pathname (Y/Z)\n"
        !          1557: "  -i, --immediate-command CMD send remote CMD, return immediately (Z)\n"
        !          1558: "  -h, --help                  print this usage message\n"
        !          1559: "  -k, --1k                    send 1024 byte packets (X)\n"
        !          1560: "  -L, --packetlen N           limit subpacket length to N bytes (Z)\n"
        !          1561: "  -l, --framelen N            limit frame length to N bytes (l>=L) (Z)\n"
        !          1562: "  -m, --min-bps N             stop transmission if BPS below N\n"
        !          1563: "  -M, --min-bps-time N          for at least N seconds (default: 120)\n"
        !          1564:                ),f);
        !          1565:        fputs(_(
        !          1566: "  -n, --newer                 send file if source newer (Z)\n"
        !          1567: "  -N, --newer-or-longer       send file if source newer or longer (Z)\n"
        !          1568: "  -o, --16-bit-crc            use 16 bit CRC instead of 32 bit CRC (Z)\n"
        !          1569: "  -O, --disable-timeouts      disable timeout code, wait forever\n"
        !          1570: "  -p, --protect               protect existing destination file (Z)\n"
        !          1571: "  -r, --resume                resume interrupted file transfer (Z)\n"
        !          1572: "  -R, --restricted            restricted, more secure mode\n"
        !          1573: "  -q, --quiet                 quiet (no progress reports)\n"
        !          1574: "  -s, --stop-at {HH:MM|+N}    stop transmission at HH:MM or in N seconds\n"
        !          1575: "      --tcp                   build a TCP connection to transmit files\n"
        !          1576: "      --tcp-server            open socket, wait for connection\n"
        !          1577: "  -u, --unlink                unlink file after transmission\n"
        !          1578: "  -U, --unrestrict            turn off restricted mode (if allowed to)\n"
        !          1579: "  -v, --verbose               be verbose, provide debugging information\n"
        !          1580: "  -w, --windowsize N          Window is N bytes (Z)\n"
        !          1581: "  -X, --xmodem                use XMODEM protocol\n"
        !          1582: "  -y, --overwrite             overwrite existing files\n"
        !          1583: "  -Y, --overwrite-or-skip     overwrite existing files, else skip\n"
        !          1584: "      --ymodem                use YMODEM protocol\n"
        !          1585: "  -Z, --zmodem                use ZMODEM protocol\n"
        !          1586: "\n"
        !          1587: "short options use the same arguments as the long ones\n"
        !          1588:        ),f);
        !          1589:        exit(exitcode);
        !          1590: }
        !          1591: 
        !          1592: /*
        !          1593:  * Get the receiver's init parameters
        !          1594:  */
        !          1595: static int 
        !          1596: getzrxinit(void)
        !          1597: {
        !          1598:        static int dont_send_zrqinit=1;
        !          1599:        int old_timeout=Rxtimeout;
        !          1600:        int n;
        !          1601:        struct stat f;
        !          1602:        size_t rxpos;
        !          1603:        int timeouts=0;
        !          1604: 
        !          1605:        Rxtimeout=100; /* 10 seconds */
        !          1606:        /* XXX purgeline(io_mode_fd); this makes _real_ trouble. why? -- uwe */
        !          1607: 
        !          1608:        for (n=10; --n>=0; ) {
        !          1609:                /* we might need to send another zrqinit in case the first is 
        !          1610:                 * lost. But *not* if getting here for the first time - in
        !          1611:                 * this case we might just get a ZRINIT for our first ZRQINIT.
        !          1612:                 * Never send more then 4 ZRQINIT, because
        !          1613:                 * omen rz stops if it saw 5 of them.
        !          1614:                 */
        !          1615:                if (zrqinits_sent<4 && n!=10 && !dont_send_zrqinit) {
        !          1616:                        zrqinits_sent++;
        !          1617:                        stohdr(0L);
        !          1618:                        zshhdr(ZRQINIT, Txhdr);
        !          1619:                }
        !          1620:                dont_send_zrqinit=0;
        !          1621:                
        !          1622:                switch (zgethdr(Rxhdr, 1,&rxpos)) {
        !          1623:                case ZCHALLENGE:        /* Echo receiver's challenge numbr */
        !          1624:                        stohdr(rxpos);
        !          1625:                        zshhdr(ZACK, Txhdr);
        !          1626:                        continue;
        !          1627:                case ZCOMMAND:          /* They didn't see our ZRQINIT */
        !          1628:                        /* ??? Since when does a receiver send ZCOMMAND?  -- uwe */
        !          1629:                        continue;
        !          1630:                case ZRINIT:
        !          1631:                        Rxflags = 0377 & Rxhdr[ZF0];
        !          1632:                        Rxflags2 = 0377 & Rxhdr[ZF1];
        !          1633:                        Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32));
        !          1634:                        {
        !          1635:                                int old=Zctlesc;
        !          1636:                                Zctlesc |= Rxflags & TESCCTL;
        !          1637:                                /* update table - was initialised to not escape */
        !          1638:                                if (Zctlesc && !old)
        !          1639:                                        zsendline_init();
        !          1640:                        }
        !          1641:                        Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8);
        !          1642:                        if ( !(Rxflags & CANFDX))
        !          1643:                                Txwindow = 0;
        !          1644:                        vfile("Rxbuflen=%d Tframlen=%d", Rxbuflen, Tframlen);
        !          1645:                        if ( play_with_sigint)
        !          1646:                                signal(SIGINT, SIG_IGN);
        !          1647:                        io_mode(io_mode_fd,2);  /* Set cbreak, XON/XOFF, etc. */
        !          1648: #ifndef READCHECK
        !          1649:                        /* Use MAX_BLOCK byte frames if no sample/interrupt */
        !          1650:                        if (Rxbuflen < 32 || Rxbuflen > MAX_BLOCK) {
        !          1651:                                Rxbuflen = MAX_BLOCK;
        !          1652:                                vfile("Rxbuflen=%d", Rxbuflen);
        !          1653:                        }
        !          1654: #endif
        !          1655:                        /* Override to force shorter frame length */
        !          1656:                        if (Tframlen && Rxbuflen > Tframlen)
        !          1657:                                Rxbuflen = Tframlen;
        !          1658:                        if ( !Rxbuflen)
        !          1659:                                Rxbuflen = 1024;
        !          1660:                        vfile("Rxbuflen=%d", Rxbuflen);
        !          1661: 
        !          1662:                        /* If using a pipe for testing set lower buf len */
        !          1663:                        fstat(0, &f);
        !          1664: #if defined(S_ISCHR)
        !          1665:                        if (! (S_ISCHR(f.st_mode))) {
        !          1666: #else
        !          1667:                        if ((f.st_mode & S_IFMT) != S_IFCHR) {
        !          1668: #endif
        !          1669:                                Rxbuflen = MAX_BLOCK;
        !          1670:                        }
        !          1671:                        /*
        !          1672:                         * If input is not a regular file, force ACK's to
        !          1673:                         *  prevent running beyond the buffer limits
        !          1674:                         */
        !          1675:                        if ( !command_mode) {
        !          1676:                                fstat(fileno(input_f), &f);
        !          1677: #if defined(S_ISREG)
        !          1678:                                if (!(S_ISREG(f.st_mode))) {
        !          1679: #else
        !          1680:                                if ((f.st_mode & S_IFMT) != S_IFREG) {
        !          1681: #endif
        !          1682:                                        Canseek = -1;
        !          1683:                                        /* return ERROR; */
        !          1684:                                }
        !          1685:                        }
        !          1686:                        /* Set initial subpacket length */
        !          1687:                        if (blklen < 1024) {    /* Command line override? */
        !          1688:                                if (Baudrate > 300)
        !          1689:                                        blklen = 256;
        !          1690:                                if (Baudrate > 1200)
        !          1691:                                        blklen = 512;
        !          1692:                                if (Baudrate > 2400)
        !          1693:                                        blklen = 1024;
        !          1694:                        }
        !          1695:                        if (Rxbuflen && blklen>Rxbuflen)
        !          1696:                                blklen = Rxbuflen;
        !          1697:                        if (blkopt && blklen > blkopt)
        !          1698:                                blklen = blkopt;
        !          1699:                        vfile("Rxbuflen=%d blklen=%d", Rxbuflen, blklen);
        !          1700:                        vfile("Txwindow = %u Txwspac = %d", Txwindow, Txwspac);
        !          1701:                        Rxtimeout=old_timeout;
        !          1702:                        return (sendzsinit());
        !          1703:                case ZCAN:
        !          1704:                case TIMEOUT:
        !          1705:                        if (timeouts++==0)
        !          1706:                                continue; /* force one other ZRQINIT to be sent */
        !          1707:                        return ERROR;
        !          1708:                case ZRQINIT:
        !          1709:                        if (Rxhdr[ZF0] == ZCOMMAND)
        !          1710:                                continue;
        !          1711:                default:
        !          1712:                        zshhdr(ZNAK, Txhdr);
        !          1713:                        continue;
        !          1714:                }
        !          1715:        }
        !          1716:        return ERROR;
        !          1717: }
        !          1718: 
        !          1719: /* Send send-init information */
        !          1720: static int 
        !          1721: sendzsinit(void)
        !          1722: {
        !          1723:        int c;
        !          1724: 
        !          1725:        if (Myattn[0] == '\0' && (!Zctlesc || (Rxflags & TESCCTL)))
        !          1726:                return OK;
        !          1727:        errors = 0;
        !          1728:        for (;;) {
        !          1729:                stohdr(0L);
        !          1730:                if (Zctlesc) {
        !          1731:                        Txhdr[ZF0] |= TESCCTL; zshhdr(ZSINIT, Txhdr);
        !          1732:                }
        !          1733:                else
        !          1734:                        zsbhdr(ZSINIT, Txhdr);
        !          1735:                ZSDATA(Myattn, 1+strlen(Myattn), ZCRCW);
        !          1736:                c = zgethdr(Rxhdr, 1,NULL);
        !          1737:                switch (c) {
        !          1738:                case ZCAN:
        !          1739:                        return ERROR;
        !          1740:                case ZACK:
        !          1741:                        return OK;
        !          1742:                default:
        !          1743:                        if (++errors > 19)
        !          1744:                                return ERROR;
        !          1745:                        continue;
        !          1746:                }
        !          1747:        }
        !          1748: }
        !          1749: 
        !          1750: /* Send file name and related info */
        !          1751: static int 
        !          1752: zsendfile(struct zm_fileinfo *zi, const char *buf, size_t blen)
        !          1753: {
        !          1754:        int c;
        !          1755:        unsigned long crc;
        !          1756:        size_t rxpos;
        !          1757: 
        !          1758:        /* we are going to send a ZFILE. There cannot be much useful
        !          1759:         * stuff in the line right now (*except* ZCAN?). 
        !          1760:         */
        !          1761: #if 0
        !          1762:        purgeline(io_mode_fd); /* might possibly fix stefan glasers problems */
        !          1763: #endif
        !          1764: 
        !          1765:        for (;;) {
        !          1766:                Txhdr[ZF0] = Lzconv;    /* file conversion request */
        !          1767:                Txhdr[ZF1] = Lzmanag;   /* file management request */
        !          1768:                if (Lskipnocor)
        !          1769:                        Txhdr[ZF1] |= ZF1_ZMSKNOLOC;
        !          1770:                Txhdr[ZF2] = Lztrans;   /* file transport request */
        !          1771:                Txhdr[ZF3] = 0;
        !          1772:                zsbhdr(ZFILE, Txhdr);
        !          1773:                ZSDATA(buf, blen, ZCRCW);
        !          1774: again:
        !          1775:                c = zgethdr(Rxhdr, 1, &rxpos);
        !          1776:                switch (c) {
        !          1777:                case ZRINIT:
        !          1778:                        while ((c = READLINE_PF(50)) > 0)
        !          1779:                                if (c == ZPAD) {
        !          1780:                                        goto again;
        !          1781:                                }
        !          1782:                        /* **** FALL THRU TO **** */
        !          1783:                default:
        !          1784:                        continue;
        !          1785:                case ZRQINIT:  /* remote site is sender! */
        !          1786:                        if (Verbose)
        !          1787:                                vstringf(_("got ZRQINIT"));
        !          1788:                        DO_SYSLOG((LOG_INFO, "%s/%s: got ZRQINIT - sz talks to sz",
        !          1789:                                           shortname,protname()));
        !          1790:                        return ERROR;
        !          1791:                case ZCAN:
        !          1792:                        if (Verbose)
        !          1793:                                vstringf(_("got ZCAN"));
        !          1794:                        DO_SYSLOG((LOG_INFO, "%s/%s: got ZCAN - receiver canceled",
        !          1795:                                           shortname,protname()));
        !          1796:                        return ERROR;
        !          1797:                case TIMEOUT:
        !          1798:                        DO_SYSLOG((LOG_INFO, "%s/%s: got TIMEOUT",
        !          1799:                                           shortname,protname()));
        !          1800:                        return ERROR;
        !          1801:                case ZABORT:
        !          1802:                        DO_SYSLOG((LOG_INFO, "%s/%s: got ZABORT",
        !          1803:                                           shortname,protname()));
        !          1804:                        return ERROR;
        !          1805:                case ZFIN:
        !          1806:                        DO_SYSLOG((LOG_INFO, "%s/%s: got ZFIN",
        !          1807:                                           shortname,protname()));
        !          1808:                        return ERROR;
        !          1809:                case ZCRC:
        !          1810:                        crc = 0xFFFFFFFFL;
        !          1811: #ifdef HAVE_MMAP
        !          1812:                        if (use_mmap && !mm_addr)
        !          1813:                        {
        !          1814:                                struct stat st;
        !          1815:                                if (fstat (fileno (input_f), &st) == 0) {
        !          1816:                                        mm_size = st.st_size;
        !          1817:                                        mm_addr = mmap (0, mm_size, PROT_READ,
        !          1818:                                                                        MAP_SHARED, fileno (input_f), 0);
        !          1819:                                        if ((caddr_t) mm_addr == (caddr_t) - 1)
        !          1820:                                                mm_addr = NULL;
        !          1821:                                        else {
        !          1822:                                                fclose (input_f);
        !          1823:                                                input_f = NULL;
        !          1824:                                        }
        !          1825:                                }
        !          1826:                        }
        !          1827:                        if (mm_addr) {
        !          1828:                                size_t i;
        !          1829:                                size_t count;
        !          1830:                                char *p=mm_addr;
        !          1831:                                count=(rxpos < mm_size && rxpos > 0)? rxpos: mm_size;
        !          1832:                                for (i=0;i<count;i++,p++) {
        !          1833:                                        crc = UPDC32(*p, crc);
        !          1834:                                }
        !          1835:                                crc = ~crc;
        !          1836:                        } else
        !          1837: #endif
        !          1838:                        if (Canseek >= 0) {
        !          1839:                                if (rxpos==0) {
        !          1840:                                        struct stat st;
        !          1841:                                        if (0==fstat(fileno(input_f),&st)) {
        !          1842:                                                rxpos=st.st_size;
        !          1843:                                        } else
        !          1844:                                                rxpos=-1;
        !          1845:                                }
        !          1846:                                while (rxpos-- && ((c = getc(input_f)) != EOF))
        !          1847:                                        crc = UPDC32(c, crc);
        !          1848:                                crc = ~crc;
        !          1849:                                clearerr(input_f);      /* Clear EOF */
        !          1850:                                fseek(input_f, 0L, 0);
        !          1851:                        }
        !          1852:                        stohdr(crc);
        !          1853:                        zsbhdr(ZCRC, Txhdr);
        !          1854:                        goto again;
        !          1855:                case ZSKIP:
        !          1856:                        if (input_f)
        !          1857:                                fclose(input_f);
        !          1858: #ifdef HAVE_MMAP
        !          1859:                        else if (mm_addr) {
        !          1860:                                munmap(mm_addr,mm_size);
        !          1861:                                mm_addr=NULL;
        !          1862:                        }
        !          1863: #endif
        !          1864: 
        !          1865:                        vfile("receiver skipped");
        !          1866:                        DO_SYSLOG((LOG_INFO, "%s/%s: receiver skipped",
        !          1867:                                           shortname, protname()));
        !          1868:                        return c;
        !          1869:                case ZRPOS:
        !          1870:                        /*
        !          1871:                         * Suppress zcrcw request otherwise triggered by
        !          1872:                         * lastsync==bytcnt
        !          1873:                         */
        !          1874: #ifdef HAVE_MMAP
        !          1875:                        if (!mm_addr)
        !          1876: #endif
        !          1877:                        if (rxpos && fseek(input_f, (long) rxpos, 0)) {
        !          1878:                                int er=errno;
        !          1879:                                vfile("fseek failed: %s", strerror(er));
        !          1880:                                DO_SYSLOG((LOG_INFO, "%s/%s: fseek failed: %s",
        !          1881:                                                   shortname, protname(), strerror(er)));
        !          1882:                                return ERROR;
        !          1883:                        }
        !          1884:                        if (rxpos)
        !          1885:                                zi->bytes_skipped=rxpos;
        !          1886:                        bytcnt = zi->bytes_sent = rxpos;
        !          1887:                        Lastsync = rxpos -1;
        !          1888:                        return zsendfdata(zi);
        !          1889:                }
        !          1890:        }
        !          1891: }
        !          1892: 
        !          1893: /* Send the data in the file */
        !          1894: static int
        !          1895: zsendfdata (struct zm_fileinfo *zi)
        !          1896: {
        !          1897:        static int c;
        !          1898:        int newcnt;
        !          1899:        static int junkcount;                           /* Counts garbage chars received by TX */
        !          1900:        static size_t last_txpos = 0;
        !          1901:        static long last_bps = 0;
        !          1902:        static long not_printed = 0;
        !          1903:        static long total_sent = 0;
        !          1904:        static time_t low_bps=0;
        !          1905: 
        !          1906: #ifdef HAVE_MMAP
        !          1907:        if (use_mmap && !mm_addr)
        !          1908:        {
        !          1909:                struct stat st;
        !          1910:                if (fstat (fileno (input_f), &st) == 0) {
        !          1911:                        mm_size = st.st_size;
        !          1912:                        mm_addr = mmap (0, mm_size, PROT_READ,
        !          1913:                                                        MAP_SHARED, fileno (input_f), 0);
        !          1914:                        if ((caddr_t) mm_addr == (caddr_t) - 1)
        !          1915:                                mm_addr = NULL;
        !          1916:                        else {
        !          1917:                                fclose (input_f);
        !          1918:                                input_f = NULL;
        !          1919:                        }
        !          1920:                }
        !          1921:        }
        !          1922: #endif
        !          1923: 
        !          1924:        if (play_with_sigint)
        !          1925:                signal (SIGINT, onintr);
        !          1926: 
        !          1927:        Lrxpos = 0;
        !          1928:        junkcount = 0;
        !          1929:        Beenhereb4 = 0;
        !          1930:   somemore:
        !          1931:        if (setjmp (intrjmp)) {
        !          1932:          if (play_with_sigint)
        !          1933:                  signal (SIGINT, onintr);
        !          1934:          waitack:
        !          1935:                junkcount = 0;
        !          1936:                c = getinsync (zi, 0);
        !          1937:          gotack:
        !          1938:                switch (c) {
        !          1939:                default:
        !          1940:                        if (input_f)
        !          1941:                                fclose (input_f);
        !          1942:                        DO_SYSLOG((LOG_INFO, "%s/%s: got %d",
        !          1943:                                           shortname, protname(), c));
        !          1944:                        return ERROR;
        !          1945:                case ZCAN:
        !          1946:                        if (input_f)
        !          1947:                                fclose (input_f);
        !          1948:                        DO_SYSLOG((LOG_INFO, "%s/%s: got ZCAN",
        !          1949:                                           shortname, protname(), c));
        !          1950:                        return ERROR;
        !          1951:                case ZSKIP:
        !          1952:                        if (input_f)
        !          1953:                                fclose (input_f);
        !          1954:                        DO_SYSLOG((LOG_INFO, "%s/%s: got ZSKIP",
        !          1955:                                           shortname, protname(), c));
        !          1956:                        return c;
        !          1957:                case ZACK:
        !          1958:                case ZRPOS:
        !          1959:                        break;
        !          1960:                case ZRINIT:
        !          1961:                        return OK;
        !          1962:                }
        !          1963: #ifdef READCHECK
        !          1964:                /*
        !          1965:                 * If the reverse channel can be tested for data,
        !          1966:                 *  this logic may be used to detect error packets
        !          1967:                 *  sent by the receiver, in place of setjmp/longjmp
        !          1968:                 *  rdchk(fdes) returns non 0 if a character is available
        !          1969:                 */
        !          1970:                while (rdchk (io_mode_fd)) {
        !          1971: #ifdef READCHECK_READS
        !          1972:                        switch (checked)
        !          1973: #else
        !          1974:                        switch (READLINE_PF (1))
        !          1975: #endif
        !          1976:                        {
        !          1977:                        case CAN:
        !          1978:                        case ZPAD:
        !          1979:                                c = getinsync (zi, 1);
        !          1980:                                goto gotack;
        !          1981:                        case XOFF:                      /* Wait a while for an XON */
        !          1982:                        case XOFF | 0200:
        !          1983:                                READLINE_PF (100);
        !          1984:                        }
        !          1985:                }
        !          1986: #endif
        !          1987:        }
        !          1988: 
        !          1989:        newcnt = Rxbuflen;
        !          1990:        Txwcnt = 0;
        !          1991:        stohdr (zi->bytes_sent);
        !          1992:        zsbhdr (ZDATA, Txhdr);
        !          1993: 
        !          1994:        do {
        !          1995:                size_t n;
        !          1996:                int e;
        !          1997:                unsigned old = blklen;
        !          1998:                blklen = calc_blklen (total_sent);
        !          1999:                total_sent += blklen + OVERHEAD;
        !          2000:                if (Verbose > 2 && blklen != old)
        !          2001:                        vstringf (_("blklen now %d\n"), blklen);
        !          2002: #ifdef HAVE_MMAP
        !          2003:                if (mm_addr) {
        !          2004:                        if (zi->bytes_sent + blklen < mm_size)
        !          2005:                                n = blklen;
        !          2006:                        else {
        !          2007:                                n = mm_size - zi->bytes_sent;
        !          2008:                                zi->eof_seen = 1;
        !          2009:                        }
        !          2010:                } else
        !          2011: #endif
        !          2012:                        n = zfilbuf (zi);
        !          2013:                if (zi->eof_seen) {
        !          2014:                        e = ZCRCE;
        !          2015:                        if (Verbose>3)
        !          2016:                                vstring("e=ZCRCE/eof seen");
        !          2017:                } else if (junkcount > 3) {
        !          2018:                        e = ZCRCW;
        !          2019:                        if (Verbose>3)
        !          2020:                                vstring("e=ZCRCW/junkcount > 3");
        !          2021:                } else if (bytcnt == Lastsync) {
        !          2022:                        e = ZCRCW;
        !          2023:                        if (Verbose>3)
        !          2024:                                vstringf("e=ZCRCW/bytcnt == Lastsync == %ld", 
        !          2025:                                        (unsigned long) Lastsync);
        !          2026: #if 0
        !          2027:                /* what is this good for? Rxbuflen/newcnt normally are short - so after
        !          2028:                 * a few KB ZCRCW will be used? (newcnt is never incremented)
        !          2029:                 */
        !          2030:                } else if (Rxbuflen && (newcnt -= n) <= 0) {
        !          2031:                        e = ZCRCW;
        !          2032:                        if (Verbose>3)
        !          2033:                                vstringf("e=ZCRCW/Rxbuflen(newcnt=%ld,n=%ld)", 
        !          2034:                                        (unsigned long) newcnt,(unsigned long) n);
        !          2035: #endif
        !          2036:                } else if (Txwindow && (Txwcnt += n) >= Txwspac) {
        !          2037:                        Txwcnt = 0;
        !          2038:                        e = ZCRCQ;
        !          2039:                        if (Verbose>3)
        !          2040:                                vstring("e=ZCRCQ/Window");
        !          2041:                } else {
        !          2042:                        e = ZCRCG;
        !          2043:                        if (Verbose>3)
        !          2044:                                vstring("e=ZCRCG");
        !          2045:                }
        !          2046:                if ((Verbose > 1 || min_bps || stop_time)
        !          2047:                        && (not_printed > (min_bps ? 3 : 7) 
        !          2048:                                || zi->bytes_sent > last_bps / 2 + last_txpos)) {
        !          2049:                        int minleft = 0;
        !          2050:                        int secleft = 0;
        !          2051:                        time_t now;
        !          2052:                        last_bps = (zi->bytes_sent / timing (0,&now));
        !          2053:                        if (last_bps > 0) {
        !          2054:                                minleft = (zi->bytes_total - zi->bytes_sent) / last_bps / 60;
        !          2055:                                secleft = ((zi->bytes_total - zi->bytes_sent) / last_bps) % 60;
        !          2056:                        }
        !          2057:                        if (min_bps) {
        !          2058:                                if (low_bps) {
        !          2059:                                        if (last_bps<min_bps) {
        !          2060:                                                if (now-low_bps>=min_bps_time) {
        !          2061:                                                        /* too bad */
        !          2062:                                                        if (Verbose) {
        !          2063:                                                                vstringf(_("zsendfdata: bps rate %ld below min %ld"),
        !          2064:                                                                  last_bps, min_bps);
        !          2065:                                                                vstring("\r\n");
        !          2066:                                                        }
        !          2067:                                                        DO_SYSLOG((LOG_INFO, "%s/%s: bps rate low: %ld <%ld",
        !          2068:                                                                           shortname, protname(), last_bps, min_bps));
        !          2069:                                                        return ERROR;
        !          2070:                                                }
        !          2071:                                        } else
        !          2072:                                                low_bps=0;
        !          2073:                                } else if (last_bps < min_bps) {
        !          2074:                                        low_bps=now;
        !          2075:                                }
        !          2076:                        }
        !          2077:                        if (stop_time && now>=stop_time) {
        !          2078:                                /* too bad */
        !          2079:                                if (Verbose) {
        !          2080:                                        vstring(_("zsendfdata: reached stop time"));
        !          2081:                                        vstring("\r\n");
        !          2082:                                }
        !          2083:                                DO_SYSLOG((LOG_INFO, "%s/%s: reached stop time",
        !          2084:                                                   shortname, protname()));
        !          2085:                                return ERROR;
        !          2086:                        }
        !          2087: 
        !          2088:                        if (Verbose > 1) {
        !          2089:                                vchar ('\r');
        !          2090:                                vstringf (_("Bytes Sent:%7ld/%7ld   BPS:%-8ld ETA %02d:%02d  "),
        !          2091:                                         (long) zi->bytes_sent, (long) zi->bytes_total, 
        !          2092:                                        last_bps, minleft, secleft);
        !          2093:                        }
        !          2094:                        last_txpos = zi->bytes_sent;
        !          2095:                } else if (Verbose)
        !          2096:                        not_printed++;
        !          2097:                ZSDATA (DATAADR, n, e);
        !          2098:                bytcnt = zi->bytes_sent += n;
        !          2099:                if (e == ZCRCW)
        !          2100:                        goto waitack;
        !          2101: #ifdef READCHECK
        !          2102:                /*
        !          2103:                 * If the reverse channel can be tested for data,
        !          2104:                 *  this logic may be used to detect error packets
        !          2105:                 *  sent by the receiver, in place of setjmp/longjmp
        !          2106:                 *  rdchk(fdes) returns non 0 if a character is available
        !          2107:                 */
        !          2108:                fflush (stdout);
        !          2109:                while (rdchk (io_mode_fd)) {
        !          2110: #ifdef READCHECK_READS
        !          2111:                        switch (checked)
        !          2112: #else
        !          2113:                        switch (READLINE_PF (1))
        !          2114: #endif
        !          2115:                        {
        !          2116:                        case CAN:
        !          2117:                        case ZPAD:
        !          2118:                                c = getinsync (zi, 1);
        !          2119:                                if (c == ZACK)
        !          2120:                                        break;
        !          2121:                                /* zcrce - dinna wanna starta ping-pong game */
        !          2122:                                ZSDATA (txbuf, 0, ZCRCE);
        !          2123:                                goto gotack;
        !          2124:                        case XOFF:                      /* Wait a while for an XON */
        !          2125:                        case XOFF | 0200:
        !          2126:                                READLINE_PF (100);
        !          2127:                        default:
        !          2128:                                ++junkcount;
        !          2129:                        }
        !          2130:                }
        !          2131: #endif                                                 /* READCHECK */
        !          2132:                if (Txwindow) {
        !          2133:                        size_t tcount = 0;
        !          2134:                        while ((tcount = zi->bytes_sent - Lrxpos) >= Txwindow) {
        !          2135:                                vfile ("%ld (%ld,%ld) window >= %u", tcount, 
        !          2136:                                        (long) zi->bytes_sent, (long) Lrxpos,
        !          2137:                                        Txwindow);
        !          2138:                                if (e != ZCRCQ)
        !          2139:                                        ZSDATA (txbuf, 0, e = ZCRCQ);
        !          2140:                                c = getinsync (zi, 1);
        !          2141:                                if (c != ZACK) {
        !          2142:                                        ZSDATA (txbuf, 0, ZCRCE);
        !          2143:                                        goto gotack;
        !          2144:                                }
        !          2145:                        }
        !          2146:                        vfile ("window = %ld", tcount);
        !          2147:                }
        !          2148:        } while (!zi->eof_seen);
        !          2149: 
        !          2150: 
        !          2151:        if (play_with_sigint)
        !          2152:                signal (SIGINT, SIG_IGN);
        !          2153: 
        !          2154:        for (;;) {
        !          2155:                stohdr (zi->bytes_sent);
        !          2156:                zsbhdr (ZEOF, Txhdr);
        !          2157:                switch (getinsync (zi, 0)) {
        !          2158:                case ZACK:
        !          2159:                        continue;
        !          2160:                case ZRPOS:
        !          2161:                        goto somemore;
        !          2162:                case ZRINIT:
        !          2163:                        return OK;
        !          2164:                case ZSKIP:
        !          2165:                        if (input_f)
        !          2166:                                fclose (input_f);
        !          2167:                        DO_SYSLOG((LOG_INFO, "%s/%s: got ZSKIP",
        !          2168:                                           shortname, protname()));
        !          2169:                        return c;
        !          2170:                default:
        !          2171:                        if (input_f)
        !          2172:                                fclose (input_f);
        !          2173:                        DO_SYSLOG((LOG_INFO, "%s/%s: got %d",
        !          2174:                                           shortname, protname(), c));
        !          2175:                        return ERROR;
        !          2176:                }
        !          2177:        }
        !          2178: }
        !          2179: 
        !          2180: static int
        !          2181: calc_blklen(long total_sent)
        !          2182: {
        !          2183:        static long total_bytes=0;
        !          2184:        static int calcs_done=0;
        !          2185:        static long last_error_count=0;
        !          2186:        static int last_blklen=0;
        !          2187:        static long last_bytes_per_error=0;
        !          2188:        unsigned long best_bytes=0;
        !          2189:        long best_size=0;
        !          2190:        long this_bytes_per_error;
        !          2191:        long d;
        !          2192:        unsigned int i;
        !          2193:        if (total_bytes==0)
        !          2194:        {
        !          2195:                /* called from countem */
        !          2196:                total_bytes=total_sent;
        !          2197:                return 0;
        !          2198:        }
        !          2199: 
        !          2200:        /* it's not good to calc blklen too early */
        !          2201:        if (calcs_done++ < 5) {
        !          2202:                if (error_count && start_blklen >1024)
        !          2203:                        return last_blklen=1024;
        !          2204:                else 
        !          2205:                        last_blklen/=2;
        !          2206:                return last_blklen=start_blklen;
        !          2207:        }
        !          2208: 
        !          2209:        if (!error_count) {
        !          2210:                /* that's fine */
        !          2211:                if (start_blklen==max_blklen)
        !          2212:                        return start_blklen;
        !          2213:                this_bytes_per_error=LONG_MAX;
        !          2214:                goto calcit;
        !          2215:        }
        !          2216: 
        !          2217:        if (error_count!=last_error_count) {
        !          2218:                /* the last block was bad. shorten blocks until one block is
        !          2219:                 * ok. this is because very often many errors come in an
        !          2220:                 * short period */
        !          2221:                if (error_count & 2)
        !          2222:                {
        !          2223:                        last_blklen/=2;
        !          2224:                        if (last_blklen < 32)
        !          2225:                                last_blklen = 32;
        !          2226:                        else if (last_blklen > 512)
        !          2227:                                last_blklen=512;
        !          2228:                        if (Verbose > 3)
        !          2229:                                vstringf(_("calc_blklen: reduced to %d due to error\n"),
        !          2230:                                        last_blklen);
        !          2231:                }
        !          2232:                last_error_count=error_count;
        !          2233:                last_bytes_per_error=0; /* force recalc */
        !          2234:                return last_blklen;
        !          2235:        }
        !          2236: 
        !          2237:        this_bytes_per_error=total_sent / error_count;
        !          2238:                /* we do not get told about every error, because
        !          2239:                 * there may be more than one error per failed block.
        !          2240:                 * but one the other hand some errors are reported more
        !          2241:                 * than once: If a modem buffers more than one block we
        !          2242:                 * get at least two ZRPOS for the same position in case
        !          2243:                 * *one* block has to be resent.
        !          2244:                 * so don't do this:
        !          2245:                 * this_bytes_per_error/=2;
        !          2246:                 */
        !          2247:        /* there has to be a margin */
        !          2248:        if (this_bytes_per_error<100)
        !          2249:                this_bytes_per_error=100;
        !          2250: 
        !          2251:        /* be nice to the poor machine and do the complicated things not
        !          2252:         * too often
        !          2253:         */
        !          2254:        if (last_bytes_per_error>this_bytes_per_error)
        !          2255:                d=last_bytes_per_error-this_bytes_per_error;
        !          2256:        else
        !          2257:                d=this_bytes_per_error-last_bytes_per_error;
        !          2258:        if (d<4)
        !          2259:        {
        !          2260:                if (Verbose > 3)
        !          2261:                {
        !          2262:                        vstringf(_("calc_blklen: returned old value %d due to low bpe diff\n"),
        !          2263:                                last_blklen);
        !          2264:                        vstringf(_("calc_blklen: old %ld, new %ld, d %ld\n"),
        !          2265:                                last_bytes_per_error,this_bytes_per_error,d );
        !          2266:                }
        !          2267:                return last_blklen;
        !          2268:        }
        !          2269:        last_bytes_per_error=this_bytes_per_error;
        !          2270: 
        !          2271: calcit:
        !          2272:        if (Verbose > 3)
        !          2273:                vstringf(_("calc_blklen: calc total_bytes=%ld, bpe=%ld, ec=%ld\n"),
        !          2274:                        total_bytes,this_bytes_per_error,(long) error_count);
        !          2275:        for (i=32;i<=max_blklen;i*=2) {
        !          2276:                long ok; /* some many ok blocks do we need */
        !          2277:                long failed; /* and that's the number of blocks not transmitted ok */
        !          2278:                unsigned long transmitted;
        !          2279:                ok=total_bytes / i + 1;
        !          2280:                failed=((long) i + OVERHEAD) * ok / this_bytes_per_error;
        !          2281:                transmitted=total_bytes + ok * OVERHEAD  
        !          2282:                        + failed * ((long) i+OVERHEAD+OVER_ERR);
        !          2283:                if (Verbose > 4)
        !          2284:                        vstringf(_("calc_blklen: blklen %d, ok %ld, failed %ld -> %lu\n"),
        !          2285:                                i,ok,failed,transmitted);
        !          2286:                if (transmitted < best_bytes || !best_bytes)
        !          2287:                {
        !          2288:                        best_bytes=transmitted;
        !          2289:                        best_size=i;
        !          2290:                }
        !          2291:        }
        !          2292:        if (best_size > 2*last_blklen)
        !          2293:                best_size=2*last_blklen;
        !          2294:        last_blklen=best_size;
        !          2295:        if (Verbose > 3)
        !          2296:                vstringf(_("calc_blklen: returned %d as best\n"),
        !          2297:                        last_blklen);
        !          2298:        return last_blklen;
        !          2299: }
        !          2300: 
        !          2301: /*
        !          2302:  * Respond to receiver's complaint, get back in sync with receiver
        !          2303:  */
        !          2304: static int 
        !          2305: getinsync(struct zm_fileinfo *zi, int flag)
        !          2306: {
        !          2307:        int c;
        !          2308:        size_t rxpos;
        !          2309: 
        !          2310:        for (;;) {
        !          2311:                c = zgethdr(Rxhdr, 0, &rxpos);
        !          2312:                switch (c) {
        !          2313:                case ZCAN:
        !          2314:                case ZABORT:
        !          2315:                case ZFIN:
        !          2316:                case TIMEOUT:
        !          2317:                        return ERROR;
        !          2318:                case ZRPOS:
        !          2319:                        /* ************************************* */
        !          2320:                        /*  If sending to a buffered modem, you  */
        !          2321:                        /*   might send a break at this point to */
        !          2322:                        /*   dump the modem's buffer.            */
        !          2323:                        if (input_f)
        !          2324:                                clearerr(input_f);      /* In case file EOF seen */
        !          2325: #ifdef HAVE_MMAP
        !          2326:                        if (!mm_addr)
        !          2327: #endif
        !          2328:                        if (fseek(input_f, (long) rxpos, 0))
        !          2329:                                return ERROR;
        !          2330:                        zi->eof_seen = 0;
        !          2331:                        bytcnt = Lrxpos = zi->bytes_sent = rxpos;
        !          2332:                        if (Lastsync == rxpos) {
        !          2333:                                error_count++;
        !          2334:                        }
        !          2335:                        Lastsync = rxpos;
        !          2336:                        return c;
        !          2337:                case ZACK:
        !          2338:                        Lrxpos = rxpos;
        !          2339:                        if (flag || zi->bytes_sent == rxpos)
        !          2340:                                return ZACK;
        !          2341:                        continue;
        !          2342:                case ZRINIT:
        !          2343:                case ZSKIP:
        !          2344:                        if (input_f)
        !          2345:                                fclose(input_f);
        !          2346: #ifdef HAVE_MMAP
        !          2347:                        else if (mm_addr) {
        !          2348:                                munmap(mm_addr,mm_size);
        !          2349:                                mm_addr=NULL;
        !          2350:                        }
        !          2351: #endif
        !          2352:                        return c;
        !          2353:                case ERROR:
        !          2354:                default:
        !          2355:                        error_count++;
        !          2356:                        zsbhdr(ZNAK, Txhdr);
        !          2357:                        continue;
        !          2358:                }
        !          2359:        }
        !          2360: }
        !          2361: 
        !          2362: 
        !          2363: /* Say "bibi" to the receiver, try to do it cleanly */
        !          2364: static void
        !          2365: saybibi(void)
        !          2366: {
        !          2367:        for (;;) {
        !          2368:                stohdr(0L);             /* CAF Was zsbhdr - minor change */
        !          2369:                zshhdr(ZFIN, Txhdr);    /*  to make debugging easier */
        !          2370:                switch (zgethdr(Rxhdr, 0,NULL)) {
        !          2371:                case ZFIN:
        !          2372:                        sendline('O');
        !          2373:                        sendline('O');
        !          2374:                        flushmo();
        !          2375:                case ZCAN:
        !          2376:                case TIMEOUT:
        !          2377:                        return;
        !          2378:                }
        !          2379:        }
        !          2380: }
        !          2381: 
        !          2382: /* Send command and related info */
        !          2383: static int 
        !          2384: zsendcmd(const char *buf, size_t blen)
        !          2385: {
        !          2386:        int c;
        !          2387:        pid_t cmdnum;
        !          2388:        size_t rxpos;
        !          2389: 
        !          2390:        cmdnum = getpid();
        !          2391:        errors = 0;
        !          2392:        for (;;) {
        !          2393:                stohdr((size_t) cmdnum);
        !          2394:                Txhdr[ZF0] = Cmdack1;
        !          2395:                zsbhdr(ZCOMMAND, Txhdr);
        !          2396:                ZSDATA(buf, blen, ZCRCW);
        !          2397: listen:
        !          2398:                Rxtimeout = 100;                /* Ten second wait for resp. */
        !          2399:                c = zgethdr(Rxhdr, 1, &rxpos);
        !          2400: 
        !          2401:                switch (c) {
        !          2402:                case ZRINIT:
        !          2403:                        goto listen;    /* CAF 8-21-87 */
        !          2404:                case ERROR:
        !          2405:                case TIMEOUT:
        !          2406:                        if (++errors > Cmdtries)
        !          2407:                                return ERROR;
        !          2408:                        continue;
        !          2409:                case ZCAN:
        !          2410:                case ZABORT:
        !          2411:                case ZFIN:
        !          2412:                case ZSKIP:
        !          2413:                case ZRPOS:
        !          2414:                        return ERROR;
        !          2415:                default:
        !          2416:                        if (++errors > 20)
        !          2417:                                return ERROR;
        !          2418:                        continue;
        !          2419:                case ZCOMPL:
        !          2420:                        Exitcode = rxpos;
        !          2421:                        saybibi();
        !          2422:                        return OK;
        !          2423:                case ZRQINIT:
        !          2424:                        vfile("******** RZ *******");
        !          2425:                        system("rz");
        !          2426:                        vfile("******** SZ *******");
        !          2427:                        goto listen;
        !          2428:                }
        !          2429:        }
        !          2430: }
        !          2431: 
        !          2432: /*
        !          2433:  * If called as lsb use YMODEM protocol
        !          2434:  */
        !          2435: static void
        !          2436: chkinvok (const char *s)
        !          2437: {
        !          2438:        const char *p;
        !          2439: 
        !          2440:        p = s;
        !          2441:        while (*p == '-')
        !          2442:                s = ++p;
        !          2443:        while (*p)
        !          2444:                if (*p++ == '/')
        !          2445:                        s = p;
        !          2446:        if (*s == 'v') {
        !          2447:                Verbose = 1;
        !          2448:                ++s;
        !          2449:        }
        !          2450:        program_name = s;
        !          2451:        if (*s == 'l')
        !          2452:                s++;                                    /* lsz -> sz */
        !          2453:        protocol = ZM_ZMODEM;
        !          2454:        if (s[0] == 's' && s[1] == 'x')
        !          2455:                protocol = ZM_XMODEM;
        !          2456:        if (s[0] == 's' && (s[1] == 'b' || s[1] == 'y')) {
        !          2457:                protocol = ZM_YMODEM;
        !          2458:        }
        !          2459: }
        !          2460: 
        !          2461: static void
        !          2462: countem (int argc, char **argv)
        !          2463: {
        !          2464:        struct stat f;
        !          2465: 
        !          2466:        for (Totalleft = 0, Filesleft = 0; --argc >= 0; ++argv) {
        !          2467:                f.st_size = -1;
        !          2468:                if (Verbose > 2) {
        !          2469:                        vstringf ("\nCountem: %03d %s ", argc, *argv);
        !          2470:                }
        !          2471:                if (access (*argv, R_OK) >= 0 && stat (*argv, &f) >= 0) {
        !          2472: #if defined(S_ISDIR)
        !          2473:                        if (!S_ISDIR(f.st_mode) && !S_ISBLK(f.st_mode)) {
        !          2474: #else
        !          2475:                        int c;
        !          2476:                        c = f.st_mode & S_IFMT;
        !          2477:                        if (c != S_IFDIR && c != S_IFBLK) {
        !          2478: #endif
        !          2479:                                ++Filesleft;
        !          2480:                                Totalleft += f.st_size;
        !          2481:                        }
        !          2482:                } else if (strcmp (*argv, "-") == 0) {
        !          2483:                        ++Filesleft;
        !          2484:                        Totalleft += DEFBYTL;
        !          2485:                }
        !          2486:                if (Verbose > 2)
        !          2487:                        vstringf (" %ld", (long) f.st_size);
        !          2488:        }
        !          2489:        if (Verbose > 2)
        !          2490:                vstringf (_("\ncountem: Total %d %ld\n"),
        !          2491:                                 Filesleft, Totalleft);
        !          2492:        calc_blklen (Totalleft);
        !          2493: }
        !          2494: 
        !          2495: /* End of lsz.c */
        !          2496: 
        !          2497: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>