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