Annotation of sbbs/stp/stp.c, revision 1.1

1.1     ! root        1: /* STP.C */
        !             2: 
        !             3: /* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
        !             4: 
        !             5: /* Synchronet Transfer Protocols */
        !             6: 
        !             7: #include <io.h>
        !             8: #include <dos.h>
        !             9: #include <dir.h>
        !            10: #include <time.h>
        !            11: #include <alloc.h>
        !            12: #include <stdio.h>
        !            13: #include <fcntl.h>
        !            14: #include <errno.h>
        !            15: #include <string.h>
        !            16: #include <stdlib.h>
        !            17: #include <stdarg.h>
        !            18: #include <sys/stat.h>
        !            19: 
        !            20: #define STP 1
        !            21: 
        !            22: #include "zmodem.h"
        !            23: 
        !            24: #define MAXERRORS      10
        !            25: 
        !            26: #define ERROR -1
        !            27:                                                        /* Various Character/Ctrl-Code Definitions      */
        !            28: #define SP                     32              /* Space bar                                                            */
        !            29: #define ESC                    27              /* ESC Char                                                             */
        !            30: #define        CR                      13              /* Carriage Return                                                      */
        !            31: #define FF          12      /* Form Feed                                                               */
        !            32: #define        LF                      10              /* Line Feed                                                            */
        !            33: #define TAB                    9               /* Horizontal Tabulation                                        */
        !            34: #define BS                     8               /* Back Space                                                           */
        !            35: #define SOH            1               /* Start of header                                                      */
        !            36: #define STX         2          /* Start of text                            */
        !            37: #define ETX         3       /* End of text                              */
        !            38: #define EOT            4               /* End of transmission                                          */
        !            39: #define ACK            6               /* Acknowledge                                                          */
        !            40: #define DLE            16              /* Data link escape                                             */
        !            41: #define XON            17              /* Ctrl-Q - resume transmission                         */
        !            42: #define XOFF           19              /* Ctrl-S - pause transmission                          */
        !            43: #define NAK            21              /* Negative Acknowledge                                         */
        !            44: #define CAN            24              /* Cancel                                                                       */
        !            45: #define CPMEOF         26              /* CP/M End of file (^Z)                                        */
        !            46: #define LOC_ABORT      0x2e03  /* Local abort key      (^C)                                    */
        !            47: 
        !            48: #define uchar  unsigned char
        !            49: #define uint   unsigned int
        !            50: #define ulong   unsigned long
        !            51: 
        !            52: #define SEND           (1<<0)  /* Sending file(s)                                                      */
        !            53: #define RECV           (1<<1)  /* Receiving file(s)                                            */
        !            54: #define XMODEM         (1<<2)  /* Use Xmodem                                                           */
        !            55: #define YMODEM         (1<<3)  /* Use Ymodem                                                           */
        !            56: #define ZMODEM         (1<<4)  /* Use Zmodem                                                           */
        !            57: #define CRC            (1<<5)  /* Use CRC error correction                             */
        !            58: #define GMODE          (1<<6)  /* For Qmodem-G and Ymodem-G                            */
        !            59: #define DIR            (1<<7)  /* Directory specified to download to           */
        !            60: #define DEBUG          (1<<8)  /* Debug output                                                         */
        !            61: #define OVERWRITE      (1<<9)  /* Overwrite receiving files                            */
        !            62: #define IGNORE_DCD     (1<<10) /* Ignore DCD                                                           */
        !            63: #define ALARM          (1<<11) /* Alarm when starting and stopping xfer        */
        !            64: #define NO_LOCAL       (1<<12) /* Don't check local keyboard               */
        !            65: 
        !            66:                                                        /* Zmodem mode bits                                             */
        !            67: #define CTRL_ESC       (1<<0)  /* Escape all control chars                             */
        !            68: #define VAR_HDRS       (1<<1)  /* Use variable headers                                         */
        !            69: 
        !            70: #define LOOP_NOPEN     50
        !            71: 
        !            72: #define MAX_FNAMES     100     /* Up to 100 filenames                                          */
        !            73: 
        !            74: /************************/
        !            75: /* Remote I/O Constants */
        !            76: /************************/
        !            77: 
        !            78:                                                        /* i/o mode and state flags */
        !            79: #define CTSCK 0x1000           /* check cts (mode only) */
        !            80: #define RTSCK 0x2000           /* check rts (mode only) */
        !            81: #define TXBOF 0x0800           /* transmit buffer overflow (outcom only) */
        !            82: #define ABORT 0x0400           /* check for ^C (mode), aborting (state) */
        !            83: #define PAUSE 0x0200           /* check for ^S (mode), pausing (state) */
        !            84: #define NOINP 0x0100           /* input buffer empty (incom only) */
        !            85: 
        !            86:                                                        /* status flags */
        !            87: #define DCD    0x80            /* DCD on */
        !            88: #define RI             0x40            /* Ring indicate */
        !            89: #define DSR    0x20            /* Dataset ready */
        !            90: #define CTS    0x10            /* CTS on */
        !            91: #define FERR   0x08            /* Frameing error */
        !            92: #define PERR   0x04            /* Parity error */
        !            93: #define OVRR   0x02            /* Overrun */
        !            94: #define RXLOST         0x01            /* Receive buffer overflow */
        !            95: 
        !            96: /* rioctl() arguments */
        !            97: /* returns mode or state flags in high 8 bits, status flags in low 8 bits */
        !            98: 
        !            99:                                                        /* the following return mode in high 8 bits */
        !           100: #define IOMODE 0               /* no operation */
        !           101: #define IOSM 1                 /* i/o set mode flags */
        !           102: #define IOCM 2                 /* i/o clear mode flags */
        !           103: 
        !           104: #define GVERS 0x007            /* get version */
        !           105: #define GUART 0x107            /* get uart */
        !           106: #define GIRQN 0x207            /* get IRQ number */
        !           107: #define GBAUD 0x307            /* get baud */
        !           108: 
        !           109:                                                        /* the following return state in high 8 bits */
        !           110: #define IOSTATE 4              /* no operation */
        !           111: #define IOSS 5                 /* i/o set state flags */
        !           112: #define IOCS 6                 /* i/o clear state flags */
        !           113: #define IOFB 0x308             /* i/o buffer flush */
        !           114: #define IOFI 0x208             /* input buffer flush */
        !           115: #define IOFO 0x108             /* output buffer flush */
        !           116: #define IOCE 9                 /* i/o clear error flags */
        !           117: 
        !           118: #define TS_INT28        1
        !           119: #define TS_WINOS2       2
        !           120: #define TS_NODV         4
        !           121: 
        !           122:                                                        /* return count (16bit) */
        !           123: #define RXBC   0x000a          /* get receive buffer count */
        !           124: #define RXBS   0x010a          /* get receive buffer size */
        !           125: #define TXBC   0x000b          /* get transmit buffer count */
        !           126: #define TXBS   0x010b          /* get transmit buffer size */
        !           127: #define TXBF   0x020b          /* get transmit buffer free space */
        !           128: #define TXSYNC 0x000c          /* sync transmition (seconds<<8|0x0c) */
        !           129: #define IDLE   0x000d          /* suspend communication routines */
        !           130: #define RESUME 0x010d          /* return from suspended state */
        !           131: #define RLERC  0x000e          /* read line error count and clear */
        !           132: #define CPTON  0x0110          /* set input translation flag for ctrl-p on */
        !           133: #define CPTOFF 0x0010          /* set input translation flag for ctrl-p off */
        !           134: #define GETCPT 0x8010          /* return the status of ctrl-p translation */
        !           135: #define MSR    0x0011          /* read modem status register */
        !           136: #define FIFOCTL 0x0012         /* FIFO UART control */
        !           137: #define TSTYPE 0x0013          /* Time-slice API type */
        !           138: #define GETTST 0x8013          /* Get Time-slice API type */
        !           139: 
        !           140:                                                        /* ivhctl() arguments */
        !           141: #define INT29R 1               /* copy int 29h output to remote */
        !           142: #define INT29L 2                       /* Use _putlc for int 29h */
        !           143: #define INT16  0x10            /* return remote chars to int 16h calls */
        !           144: #define INTCLR 0            /* release int 16h, int 29h */
        !           145: 
        !           146: #define DCDHIGH (rioctl(IOSTATE)&DCD || mode&IGNORE_DCD)
        !           147: 
        !           148: /**************/
        !           149: /* Prototypes */
        !           150: /**************/
        !           151: 
        !           152: /* LCLOLL.ASM */
        !           153: int     lclini(int);
        !           154: void lclxy(int,int);
        !           155: int  lclwx(void);
        !           156: int  lclwy(void);
        !           157: int  lclatr(int);
        !           158: int  lclaes(void);
        !           159: void lputc(int);
        !           160: long lputs(char far *);
        !           161: uint lkbrd(int);
        !           162: 
        !           163: /* RCIOLL.ASM */
        !           164: 
        !           165: int  rioini(int com,int irq);          /* initialize com,irq */
        !           166: int  setbaud(int rate);                /* set baud rate */
        !           167: int  rioctl(int action);               /* remote i/o control */
        !           168: int  dtr(char onoff);                  /* set/reset dtr */
        !           169: int  incom(void);                      /* receive character */
        !           170: int  ivhctl(int intcode);              /* local i/o redirection */
        !           171: 
        !           172: void riosync();
        !           173: void cancel();
        !           174: 
        !           175: extern mswtyp;
        !           176: extern uint riobp;
        !           177: 
        !           178: uint   asmrev;
        !           179: 
        !           180: /***************/
        !           181: /* Global Vars */
        !           182: /***************/
        !           183: long   mode=0L;                                                /* Program mode                                         */
        !           184: long   zmode=0L;                                               /* Zmodem mode                                          */
        !           185: uchar  hdr_block_num;                                  /* Block number received in header      */
        !           186: uchar  block[1024];                                    /* Block buffer                                         */
        !           187: uint   block_size;                                     /* Block size (128 or 1024)             */
        !           188: ulong  block_num;                                              /* Block number                                         */
        !           189: ulong  last_block_num;                                 /* Last block number sent                       */
        !           190: uint   flows=0;                                                /* Number of flow controls                      */
        !           191: 
        !           192: /**************************************/
        !           193: /* Zmodem specific, from Chuck's RZSZ */
        !           194: /**************************************/
        !           195: char   Txhdr[ZMAXHLEN];                                /* Zmodem transmit header                       */
        !           196: char   Rxhdr[ZMAXHLEN];                                /* Zmodem receive header                        */
        !           197: char   attn[ZATTNLEN];                                 /* Attention string for sender          */
        !           198: char   zconv;
        !           199: char   zmanag;
        !           200: char   ztrans;
        !           201: int    tryzhdrtype;
        !           202: int    Rxtimeout = 100;                /* Tenths of seconds to wait for something */
        !           203: int    Rxframeind;                     /* ZBIN ZBIN32, or ZHEX type of frame */
        !           204: int    Rxtype;                                 /* Type of header received */
        !           205: int    Rxhlen;                                 /* Length of header received */
        !           206: int    Rxcount;                                /* Count of data bytes received */
        !           207: 
        !           208: /********/
        !           209: /* Code */
        !           210: /********/
        !           211: 
        !           212: int cbreakh()
        !           213: {
        !           214: return(1);
        !           215: }
        !           216: 
        !           217: /****************************************************************************/
        !           218: /* Performs printf() through local assembly routines                        */
        !           219: /****************************************************************************/
        !           220: int lprintf(char *fmat, ...)
        !           221: {
        !           222:        va_list argptr;
        !           223:        char sbuf[2048];
        !           224:        int chcount;
        !           225: 
        !           226: va_start(argptr,fmat);
        !           227: chcount=vsprintf(sbuf,fmat,argptr);
        !           228: va_end(argptr);
        !           229: lputs(sbuf);
        !           230: return(chcount);
        !           231: }
        !           232: 
        !           233: void newline()
        !           234: {
        !           235: if(lclwx()>1)
        !           236:        lputs("\r\n");
        !           237: }
        !           238: 
        !           239: /****************************************************************************/
        !           240: /* Network open function. Opens all files DENYALL and retries LOOP_NOPEN    */
        !           241: /* number of times if the attempted file is already open or denying access  */
        !           242: /* for some other reason.      All files are opened in BINARY mode.                    */
        !           243: /****************************************************************************/
        !           244: int nopen(char *str, int access)
        !           245: {
        !           246:        char count=0,logstr[256];
        !           247:        int file,share;
        !           248: 
        !           249: if(access==O_RDONLY) share=O_DENYWRITE;
        !           250:        else share=O_DENYALL;
        !           251: while(((file=open(str,O_BINARY|share|access,S_IWRITE))==-1)
        !           252:        && errno==EACCES && count++<LOOP_NOPEN);
        !           253: if(file==-1 && errno==EACCES)
        !           254:        lprintf("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
        !           255: return(file);
        !           256: }
        !           257: 
        !           258: 
        !           259: /****************************************************************************/
        !           260: /* Converts an ASCII Hex string into an ulong                                                          */
        !           261: /****************************************************************************/
        !           262: ulong ahtoul(char *str)
        !           263: {
        !           264:        ulong l,val=0;
        !           265: 
        !           266: while((l=(*str++)|0x20)!=0x20)
        !           267:        val=(l&0xf)+(l>>6&1)*9+val*16;
        !           268: return(val);
        !           269: }
        !           270: 
        !           271: /****************************************************************************/
        !           272: /* Checks the disk drive for the existence of a file. Returns 1 if it       */
        !           273: /* exists, 0 if it doesn't.                                                 */
        !           274: /****************************************************************************/
        !           275: char fexist(char *filespec)
        !           276: {
        !           277:     struct ffblk f;
        !           278: 
        !           279: if(findfirst(filespec,&f,0)==NULL)
        !           280:     return(1);
        !           281: return(0);
        !           282: }
        !           283: 
        !           284: /****************************************************************************/
        !           285: /* Truncates white-space chars off end of 'str' and terminates at first tab */
        !           286: /****************************************************************************/
        !           287: void truncsp(char *str)
        !           288: {
        !           289:        char c;
        !           290: 
        !           291: str[strcspn(str,"\t")]=0;
        !           292: c=strlen(str);
        !           293: while(c && str[c-1]<=SP) c--;
        !           294: str[c]=0;
        !           295: }
        !           296: 
        !           297: /**************/
        !           298: /* Exit Point */
        !           299: /**************/
        !           300: void bail(int code)
        !           301: {
        !           302: 
        !           303: if(mode&ALARM) {
        !           304:        sound(2000);
        !           305:        mswait(500);
        !           306:        sound(1000);
        !           307:        mswait(500);
        !           308:        nosound(); }
        !           309: riosync();
        !           310: rioini(0,0);   /* uninstall com routines */
        !           311: newline();
        !           312: lprintf("Exiting - Error level: %d  Flow restraint count: %u\r\n",code,flows);
        !           313: fcloseall();
        !           314: exit(code);
        !           315: }
        !           316: 
        !           317: /************************************************************/
        !           318: /* Get a character from com port, time out after 10 seconds */
        !           319: /************************************************************/
        !           320: int getcom(char timeout)
        !           321: {
        !           322:        uint    i,ch;
        !           323:        time_t  start;
        !           324: 
        !           325: if((ch=incom())!=NOINP)
        !           326:        return(ch);
        !           327: for(i=0;i<10000;i++)                      /* ten consecutive re-tries */
        !           328:        if((ch=incom())!=NOINP)
        !           329:                return(ch);
        !           330: flows++;
        !           331: start=time(NULL);
        !           332: while(time(NULL)-start<(long)timeout) {   /* wait up to ten seconds */
        !           333:        if((ch=incom())!=NOINP)
        !           334:                return(ch);
        !           335:        if(!DCDHIGH) {
        !           336:                newline();
        !           337:                lprintf("No carrier\r\n");
        !           338:                bail(1); }
        !           339:        mswait(0);
        !           340:        if(!(mode&NO_LOCAL) && lkbrd(0)==LOC_ABORT) {
        !           341:                newline();
        !           342:                lprintf("Local abort\r\n");
        !           343:                cancel();
        !           344:                bail(1); } }
        !           345: newline();
        !           346: lprintf("Input timeout\r\n");
        !           347: return(NOINP);
        !           348: }
        !           349: 
        !           350: /**********************************/
        !           351: /* Output a character to COM port */
        !           352: /**********************************/
        !           353: void putcom(uchar ch)
        !           354: {
        !           355:        int i=0;
        !           356: 
        !           357: while(outcom(ch)&TXBOF && i<180) { /* 10 sec delay */
        !           358:        if(!i) lputc('F');
        !           359:        if(!DCDHIGH) {
        !           360:                newline();
        !           361:                lprintf("No carrier\r\n");
        !           362:                bail(1); }
        !           363:        i++;
        !           364:        mswait(1);
        !           365:        if(!(mode&NO_LOCAL) && lkbrd(0)==LOC_ABORT) {
        !           366:                newline();
        !           367:                lprintf("Local abort\r\n");
        !           368:                bail(1); } }
        !           369: if(i) {
        !           370:        lprintf("\b \b");
        !           371:        flows++;
        !           372:        if(i==180) {
        !           373:                newline();
        !           374:                lprintf("Output timeout\r\n");
        !           375:                bail(1); } }
        !           376: }
        !           377: 
        !           378: void put_nak()
        !           379: {
        !           380: while(getcom(1)!=NOINP && (mode&NO_LOCAL || lkbrd(0)!=LOC_ABORT))
        !           381:        ;                               /* wait for any trailing data */
        !           382: putcom(NAK);
        !           383: }
        !           384: 
        !           385: void cancel()
        !           386: {
        !           387:        int i;
        !           388: 
        !           389: for(i=0;i<10;i++)
        !           390:        putcom(CAN);
        !           391: for(i=0;i<10;i++)
        !           392:        putcom(BS);
        !           393: }
        !           394: 
        !           395: /********************************/
        !           396: /* Update the CRC bytes                */
        !           397: /********************************/
        !           398: /****
        !           399: void update_crc(uchar c, uchar *crc1, uchar *crc2)
        !           400: {
        !           401:        int i, temp;
        !           402:        uchar carry, c_crc1, c_crc2;
        !           403: 
        !           404: for (i=0; i < 8; i++) {
        !           405:        temp = c * 2;
        !           406:        c = temp;                       /* rotate left */
        !           407:        carry = ((temp > 255) ? 1 : 0);
        !           408:        temp = (*crc2) * 2;
        !           409:        (*crc2) = temp;
        !           410:        (*crc2) |= carry;                  /* rotate with carry */
        !           411:        c_crc2 = ((temp > 255) ? 1 : 0);
        !           412:        temp = (*crc1) * 2;
        !           413:        (*crc1) = temp;
        !           414:        (*crc1) |= c_crc2;
        !           415:        c_crc1 = ((temp > 255) ? 1 : 0);
        !           416:        if (c_crc1) {
        !           417:                (*crc2) ^= 0x21;
        !           418:                (*crc1) ^= 0x10; } }
        !           419: }
        !           420: ****/
        !           421: 
        !           422: void ucrc16(uchar ch, uint *rcrc) {
        !           423:     uint i, cy;
        !           424:     uchar nch=ch;
        !           425:  
        !           426: for (i=0; i<8; i++) {
        !           427:     cy=*rcrc & 0x8000;
        !           428:     *rcrc<<=1;
        !           429:     if (nch & 0x80) *rcrc |= 1;
        !           430:     nch<<=1;
        !           431:     if (cy) *rcrc ^= 0x1021; }
        !           432: }
        !           433: 
        !           434: 
        !           435: char *chr(uchar ch)
        !           436: {
        !           437:        static char str[25];
        !           438: 
        !           439: switch(ch) {
        !           440:        case SOH:
        !           441:                return("SOH");
        !           442:        case STX:
        !           443:                return("STX");
        !           444:        case ETX:
        !           445:                return("ETX");
        !           446:        case EOT:
        !           447:                return("EOT");
        !           448:        case ACK:
        !           449:                return("ACK");
        !           450:        case NAK:
        !           451:                return("NAK");
        !           452:        case CAN:
        !           453:                return("CAN");
        !           454:        default:
        !           455:                sprintf(str,"%02Xh",ch);
        !           456:                return(str); }
        !           457: }
        !           458: 
        !           459: /****************************************************************/
        !           460: /* Gets the filename from the filename and optional path in buf */
        !           461: /****************************************************************/
        !           462: char *justfname(char *buf, char *out)
        !           463: {
        !           464:        char *p1,*p2;
        !           465: 
        !           466: if(mode&DEBUG)
        !           467:        lprintf("justfname:  in: '%s'\r\n",buf);
        !           468: p1=buf;
        !           469: while(*p1) {
        !           470:        if((p2=strchr(p1,':'))!=NULL) {      /* Remove path */
        !           471:                p1=p2+1;
        !           472:                continue; }
        !           473:        if((p2=strchr(p1,'/'))!=NULL) {
        !           474:                p1=p2+1;
        !           475:                continue; }
        !           476:        if((p2=strchr(p1,'\\'))!=NULL) {
        !           477:                p1=p2+1;
        !           478:                continue; }
        !           479:        break; }
        !           480: if(!*p1) {
        !           481:        lprintf("Invalid filename\r\n");
        !           482:        strcpy(out,""); }
        !           483: else
        !           484:        strcpy(out,p1);                                            /* Use just the filename */
        !           485: if(mode&DEBUG)
        !           486:        lprintf("justfname: out: '%s'\r\n",out);
        !           487: return(out);
        !           488: }
        !           489: 
        !           490: /****************************************************************************/
        !           491: /* Receive a X/Y/Zmodem block (sector) from COM port                                           */
        !           492: /* hdrblock is 1 if attempting to get Ymodem header block, 0 if data block     */
        !           493: /* Returns 0 if all went well, -1 on error or CAN, and EOT if EOT                      */
        !           494: /****************************************************************************/
        !           495: int get_block(int hdrblock)
        !           496: {
        !           497:        uchar chksum,calc_chksum;
        !           498:        int i,b,errors,eot=0,can=0;
        !           499:        uint crc,calc_crc;
        !           500: 
        !           501: for(errors=0;errors<MAXERRORS;errors++) {
        !           502:        i=getcom(10);
        !           503:        if(eot && i!=EOT)
        !           504:                eot=0;
        !           505:        if(can && i!=CAN)
        !           506:                can=0;
        !           507:        switch(i) {
        !           508:                case SOH: /* 128 byte blocks */
        !           509:                        block_size=128;
        !           510:                        break;
        !           511:                case STX: /* 1024 byte blocks */
        !           512:                        block_size=1024;
        !           513:                        break;
        !           514:                case EOT:
        !           515:                        if((mode&(YMODEM|GMODE))==YMODEM && !eot) {
        !           516:                                eot=1;
        !           517:                                put_nak();              /* chuck's double EOT trick */
        !           518:                                continue; }
        !           519:                        return(EOT);
        !           520:                case CAN:
        !           521:                        newline();
        !           522:                        if(!can) {                      /* must get two CANs in a row */
        !           523:                                can=1;
        !           524:                                lprintf("Received CAN  Expected SOH, STX, or EOT\r\n");
        !           525:                                continue; }
        !           526:                        lprintf("Cancelled remotely\r\n");
        !           527:                        return(-1);
        !           528:                case NOINP:     /* Nothing came in */
        !           529:                        continue;
        !           530:                default:
        !           531:                        newline();
        !           532:                        lprintf("Received %s  Expected SOH, STX, or EOT\r\n",chr(i));
        !           533:                        if(hdrblock)  /* Trying to get Ymodem header block */
        !           534:                                return(-1);
        !           535:                        put_nak();
        !           536:                        continue; }
        !           537:        i=getcom(1);
        !           538:        if(i==NOINP) {
        !           539:                put_nak();
        !           540:                continue; }
        !           541:        hdr_block_num=i;
        !           542:        i=getcom(1);
        !           543:        if(i==NOINP) {
        !           544:                put_nak();
        !           545:                continue; }
        !           546:        if(hdr_block_num!=(uchar)~i) {
        !           547:                newline();
        !           548:                lprintf("Block number error\r\n");
        !           549:                put_nak();
        !           550:                continue; }
        !           551:        calc_crc=calc_chksum=0;
        !           552:        for(b=0;b<block_size;b++) {
        !           553:                i=getcom(1);
        !           554:                if(i==NOINP)
        !           555:                        break;
        !           556:                block[b]=i;
        !           557:                if(mode&CRC)
        !           558:                        ucrc16(block[b],&calc_crc);
        !           559:                else
        !           560:                        calc_chksum+=block[b]; }
        !           561: 
        !           562:        if(b<block_size) {
        !           563:                put_nak();
        !           564:                continue; }
        !           565: 
        !           566:        if(mode&CRC) {
        !           567:                crc=getcom(1)<<8;
        !           568:                crc|=getcom(1); }
        !           569:        else
        !           570:                chksum=getcom(1);
        !           571: 
        !           572:        if(mode&CRC) {
        !           573:                ucrc16(0,&calc_crc);
        !           574:                ucrc16(0,&calc_crc);
        !           575:                if(crc==calc_crc)
        !           576:                        break;
        !           577:                newline();
        !           578:                lprintf("CRC error\r\n"); }
        !           579: 
        !           580:        else {  /* CHKSUM */
        !           581:                if(chksum==calc_chksum)
        !           582:                        break;
        !           583:                newline();
        !           584:                lprintf("Checksum error\r\n"); }
        !           585: 
        !           586:        if(mode&GMODE) {        /* Don't bother sending a NAK. He's not listening */
        !           587:                cancel();
        !           588:                bail(1); }
        !           589:        put_nak(); }
        !           590: 
        !           591: if(errors>=MAXERRORS) {
        !           592:        newline();
        !           593:        lprintf("Too many errors\r\n");
        !           594:        return(-1); }
        !           595: return(0);
        !           596: }
        !           597: 
        !           598: /*****************/
        !           599: /* Sends a block */
        !           600: /*****************/
        !           601: void put_block()
        !           602: {
        !           603:        uchar ch,chksum;
        !           604:     int i;
        !           605:        uint crc;
        !           606: 
        !           607: if(block_size==128)
        !           608:        putcom(SOH);
        !           609: else                   /* 1024 */
        !           610:        putcom(STX);
        !           611: ch=(block_num&0xff);
        !           612: putcom(ch);
        !           613: putcom(~ch);
        !           614: chksum=crc=0;
        !           615: for(i=0;i<block_size;i++) {
        !           616:        putcom(block[i]);
        !           617:        if(mode&CRC)
        !           618:                ucrc16(block[i],&crc);
        !           619:        else
        !           620:                chksum+=block[i]; }
        !           621: 
        !           622: if(mode&CRC) {
        !           623:        ucrc16(0,&crc);
        !           624:        ucrc16(0,&crc);
        !           625:        putcom(crc>>8);
        !           626:        putcom(crc&0xff); }
        !           627: else
        !           628:        putcom(chksum);
        !           629: }
        !           630: 
        !           631: /************************************************************/
        !           632: /* Gets an acknowledgement - usually after sending a block     */
        !           633: /* Returns 1 if ack received, 0 otherwise.                                     */
        !           634: /************************************************************/
        !           635: int get_ack()
        !           636: {
        !           637:        int i,errors,can=0;
        !           638: 
        !           639: for(errors=0;errors<MAXERRORS;errors++) {
        !           640: 
        !           641:        if(mode&GMODE) {                /* Don't wait for ACK on Ymodem-G */
        !           642:                if(incom()==CAN) {
        !           643:                        newline();
        !           644:                        lprintf("Cancelled remotely\r\n");
        !           645:                        cancel();
        !           646:                        bail(1); }
        !           647:                return(1); }
        !           648: 
        !           649:        i=getcom(10);
        !           650:        if(can && i!=CAN)
        !           651:                can=0;
        !           652:        if(i==ACK)
        !           653:                return(1);
        !           654:        if(i==CAN) {
        !           655:                if(can) {
        !           656:                        newline();
        !           657:                        lprintf("Cancelled remotely\r\n");
        !           658:                        cancel();
        !           659:                        bail(1); }
        !           660:                can=1; }
        !           661:        if(i!=NOINP) {
        !           662:                newline();
        !           663:                lprintf("Received %s  Expected ACK\r\n",chr(i));
        !           664:                if(i!=CAN)
        !           665:                        return(0); } }
        !           666: 
        !           667: return(0);
        !           668: }
        !           669: 
        !           670: /****************************************************************************/
        !           671: /* Syncronizes the remote and local machines                                                           */
        !           672: /****************************************************************************/
        !           673: void riosync()
        !           674: {
        !           675:        int     i=0;
        !           676: 
        !           677: while(rioctl(TXBC) && i<180) { /* 10 sec */
        !           678:        if(!(mode&NO_LOCAL) && lkbrd(0)==LOC_ABORT) {
        !           679:                newline();
        !           680:                lprintf("Local abort\r\n");
        !           681:                cancel();
        !           682:                break; }
        !           683:        if(!DCDHIGH)
        !           684:                break;
        !           685:        mswait(1);
        !           686:        i++; }
        !           687: }
        !           688: 
        !           689: /*********************************************************/
        !           690: /* Returns the number of blocks required to send n bytes */
        !           691: /*********************************************************/
        !           692: long blocks(long n)
        !           693: {
        !           694:        long l;
        !           695: 
        !           696: l=n/(long)block_size;
        !           697: if(l*(long)block_size<n)
        !           698:        l++;
        !           699: return(l);
        !           700: }
        !           701: 
        !           702: /****************************************/
        !           703: /* Zmodem specific functions start here */
        !           704: /****************************************/
        !           705: 
        !           706: /**********************************************/
        !           707: /* Output single byte as two hex ASCII digits */
        !           708: /**********************************************/
        !           709: void putzhex(uchar val)
        !           710: {
        !           711:        char *digits="0123456789abcdef";
        !           712: 
        !           713: putcom(digits[(val&0xF0)>>4]);
        !           714: putcom(digits[val&0xF]);
        !           715: }
        !           716: 
        !           717: /***********************/
        !           718: /* Output a hex header */
        !           719: /***********************/
        !           720: void putzhhdr(char type)
        !           721: {
        !           722:        uint i,crc=0;
        !           723: 
        !           724: putcom(ZPAD);
        !           725: putcom(ZPAD);
        !           726: putcom(ZDLE);
        !           727: if(zmode&VAR_HDRS) {
        !           728:        putcom(ZVHEX);
        !           729:        putzhex(4); }
        !           730: else
        !           731:        putcom(ZHEX);
        !           732: putzhex(type);
        !           733: ucrc16(type,&crc);
        !           734: for(i=0;i<4;i++) {
        !           735:        putzhex(Txhdr[i]);
        !           736:        ucrc16(Txhdr[i],&crc); }
        !           737: ucrc16(0,&crc);
        !           738: ucrc16(0,&crc);
        !           739: putzhex(crc>>8);
        !           740: putzhex(crc&0xff);
        !           741: putcom(CR);
        !           742: putcom(LF);    /* Chuck's RZ.C sends LF|0x80 for some unknown reason */
        !           743: if(type!=ZFIN && type!=ZACK)
        !           744:        putcom(XON);
        !           745: }
        !           746: 
        !           747: /****************************************************************************/
        !           748: /* Stores a long in the Zmodem transmit header (usually position offset)       */
        !           749: /****************************************************************************/
        !           750: void ltohdr(long l)
        !           751: {
        !           752: 
        !           753: Txhdr[ZP0] = l;
        !           754: Txhdr[ZP1] = l>>8;
        !           755: Txhdr[ZP2] = l>>16;
        !           756: Txhdr[ZP3] = l>>24;
        !           757: }
        !           758: 
        !           759: /****************************************************************************/
        !           760: /* Outputs single Zmodem character, escaping with ZDLE when appropriate     */
        !           761: /****************************************************************************/
        !           762: void putzcom(uchar ch)
        !           763: {
        !           764:     static lastsent;
        !           765: 
        !           766: if(ch&0x60) /* not a control char */
        !           767:     putcom(lastsent=ch);
        !           768: else
        !           769:     switch(ch) {
        !           770:         case DLE:
        !           771:         case DLE|0x80:          /* even if high-bit set */
        !           772:         case XON:
        !           773:         case XON|0x80:
        !           774:         case XOFF:
        !           775:         case XOFF|0x80:
        !           776:         case ZDLE:
        !           777:             putcom(ZDLE);
        !           778:             ch^=0x40;
        !           779:             putcom(lastsent=ch);
        !           780:             break;
        !           781:         case CR:
        !           782:         case CR|0x80:
        !           783:             if(!(zmode&CTRL_ESC) && (lastsent&0x7f)!='@')
        !           784:                 putcom(lastsent=ch);
        !           785:             else {
        !           786:                 putcom(ZDLE);
        !           787:                 ch^=0x40;
        !           788:                 putcom(lastsent=ch); }
        !           789:             break;
        !           790:         default:
        !           791:             if(zmode&CTRL_ESC && !(ch&0x60)) {  /* it's a ctrl char */
        !           792:                 putcom(ZDLE);
        !           793:                 ch^=0x40; }
        !           794:             putcom(lastsent=ch);
        !           795:             break; }
        !           796: }
        !           797: 
        !           798: /*
        !           799:  * Read a byte, checking for ZMODEM escape encoding
        !           800:  *  including CAN*5 which represents a quick abort
        !           801:  */
        !           802: int getzcom()
        !           803: {
        !           804:        int i;
        !           805: 
        !           806: while(1) {
        !           807:        /* Quick check for non control characters */
        !           808:        if((i=getcom(Rxtimeout))&0x60)
        !           809:                return(i);
        !           810:        if(i==ZDLE)
        !           811:                break;
        !           812:        if((i&0x7f)==XOFF || (i&0x7f)==XON)
        !           813:                continue;
        !           814:        if(zmode&CTRL_ESC && !(i&0x60))
        !           815:                continue;
        !           816:        return(i); }
        !           817: 
        !           818: while(1) {     /* Escaped characters */
        !           819:        if((i=getcom(Rxtimeout))<0)
        !           820:                return(i);
        !           821:        if(i==CAN && (i=getcom(Rxtimeout))<0)
        !           822:                return(i);
        !           823:        if(i==CAN && (i=getcom(Rxtimeout))<0)
        !           824:         return(i);
        !           825:        if(i==CAN && (i=getcom(Rxtimeout))<0)
        !           826:         return(i);
        !           827:        switch (i) {
        !           828:                case CAN:
        !           829:                        return(GOTCAN);
        !           830:                case ZCRCE:
        !           831:                case ZCRCG:
        !           832:                case ZCRCQ:
        !           833:                case ZCRCW:
        !           834:                        return(i|GOTOR);
        !           835:                case ZRUB0:
        !           836:                        return(0x7f);
        !           837:                case ZRUB1:
        !           838:                        return(0xff);
        !           839:                case XON:
        !           840:                case XON|0x80:
        !           841:                case XOFF:
        !           842:                case XOFF|0x80:
        !           843:                        continue;
        !           844:                default:
        !           845:                        if (zmode&CTRL_ESC && !(i&0x60))
        !           846:                                continue;
        !           847:                        if ((i&0x60)==0x40)
        !           848:                                return(i^0x40);
        !           849:                        break; }
        !           850:        break; }
        !           851: return(ERROR);
        !           852: }
        !           853: 
        !           854: 
        !           855: 
        !           856: /*
        !           857:  * Read a character from the modem line with timeout.
        !           858:  *  Eat parity, XON and XOFF characters.
        !           859:  */
        !           860: int getcom7()
        !           861: {
        !           862:        int i;
        !           863: 
        !           864: while(1) {
        !           865:        i=getcom(10);
        !           866:        switch(i) {
        !           867:                case XON:
        !           868:                case XOFF:
        !           869:                        continue;
        !           870:                case CR:
        !           871:                case LF:
        !           872:                case NOINP:
        !           873:                case ZDLE:
        !           874:                        return(i);
        !           875:                default:
        !           876:                        if(!(i&0x60) && zmode&CTRL_ESC)
        !           877:                                continue;
        !           878:                        return(i); } }
        !           879: }
        !           880: 
        !           881: 
        !           882: #if 0
        !           883: 
        !           884: int getzhdr()
        !           885: {
        !           886:        int done=0;
        !           887: 
        !           888: while(!done) {
        !           889:        i=getcom(10);
        !           890:        switch(i) {
        !           891:                case NOINP:
        !           892:                        done=1;
        !           893:                        continue;
        !           894:                case XON:
        !           895:                case XON|0x80:
        !           896:                        continue;
        !           897:                case ZPAD|0x80:
        !           898:                case ZPAD:
        !           899:                        break;
        !           900:                case CAN:
        !           901:                        cancount++;
        !           902:                        if(cancount>=5) {
        !           903:                                i=ZCAN;
        !           904:                                done=1;
        !           905:                                break; }
        !           906:                        i=getcom(10);
        !           907:                        switch(i) {
        !           908:                                case NOINP:
        !           909:                                        continue;
        !           910:                                case ZCRCW:
        !           911:                                        switch(getcom(10)) {
        !           912:                                                case NOINP:
        !           913:                                                        i=ERROR
        !           914:                                                        done=1;
        !           915:                                                        break;
        !           916:                                                case RCDO:
        !           917:                                                        done=1;
        !           918:                                                        break;
        !           919:                                                default:
        !           920:                                                        continue; }
        !           921:                                        break;
        !           922:                                case RCDO:
        !           923:                                        done=1;
        !           924:                                        break;
        !           925:                                case CAN:
        !           926:                                        cancount++;
        !           927:                                        if(cancount>=5) {
        !           928:                                                i=ZCAN;
        !           929:                                                done=1;
        !           930:                                        continue;
        !           931:                                default:
        !           932:                                        break; }
        !           933:                        continue;
        !           934:                default:
        !           935:                        continue; }
        !           936: 
        !           937:        i=Rxframeind=getcom7();
        !           938:        switch (i) {
        !           939:                case ZVBIN32:
        !           940:                        if((Rxhlen=c=getzcom())<0)
        !           941:                                goto fifi;
        !           942:                        if(c>ZMAXHLEN)
        !           943:                                goto agn2;
        !           944:                        Crc32r=1;
        !           945:                        c=zrbhd32(hdr);
        !           946:                        break;
        !           947:                case ZBIN32:
        !           948:                        if(zmode&VAR_HDRS)
        !           949:                                goto agn2;
        !           950:                        Crc32r=1;
        !           951:                        c=zrbhd32(hdr);
        !           952:                        break;
        !           953:                case ZVBINR32:
        !           954:                        if((Rxhlen=c=getzcom())<0)
        !           955:                                goto fifi;
        !           956:                        if(c>ZMAXHLEN)
        !           957:                                goto agn2;
        !           958:                        Crc32r=2;
        !           959:                        c=zrbhd32(hdr);
        !           960:                        break;
        !           961:                case ZBINR32:
        !           962:                        if(zmode&VAR_HDRS)
        !           963:                                goto agn2;
        !           964:                        Crc32r=2;
        !           965:                        c=zrbhd32(hdr);
        !           966:                        break;
        !           967:                case RCDO:
        !           968:                case TIMEOUT:
        !           969:                        goto fifi;
        !           970:                case ZVBIN:
        !           971:                        if((Rxhlen=c=getzcom())<0)
        !           972:                                goto fifi;
        !           973:                        if(c>ZMAXHLEN)
        !           974:                                goto agn2;
        !           975:                        Crc32r=0;
        !           976:                        c=zrbhdr(hdr);
        !           977:                        break;
        !           978:                case ZBIN:
        !           979:                        if(zmode&VAR_HDRS)
        !           980:                                goto agn2;
        !           981:                        Crc32r=0;
        !           982:                        c=zrbhdr(hdr);
        !           983:                        break;
        !           984:                case ZVHEX:
        !           985:                        if((Rxhlen=c=zgethex()) < 0)
        !           986:                                goto fifi;
        !           987:                        if(c>ZMAXHLEN)
        !           988:                                goto agn2;
        !           989:                        Crc32r=0;
        !           990:                        c=zrhhdr(hdr);
        !           991:                        break;
        !           992:                case ZHEX:
        !           993:                        if(zmode&VAR_HDRS)
        !           994:                                goto agn2;
        !           995:                        Crc32r=0;
        !           996:                        c=zrhhdr(hdr);
        !           997:                        break;
        !           998:                case CAN:
        !           999:                        goto gotcan;
        !          1000:                default:
        !          1001:                        goto agn2;
        !          1002:                }
        !          1003: 
        !          1004: 
        !          1005: 
        !          1006: /****************************************************************************/
        !          1007: /* Get the receiver's init parameters                                       */
        !          1008: /****************************************************************************/
        !          1009: int getzrxinit()
        !          1010: {
        !          1011:        int i;
        !          1012:        struct stat f;
        !          1013: 
        !          1014: for(i=0;i<10;i++) {
        !          1015:        switch(zgethdr(Rxhdr,1)) {
        !          1016:                case ZCHALLENGE:        /* Echo receiver's challenge numbr */
        !          1017:                        ltohdr(Rxpos);
        !          1018:                        putzhhdr(ZACK);
        !          1019:                        continue;
        !          1020:                case ZCOMMAND:          /* They didn't see out ZRQINIT */
        !          1021:                        ltohdr(0L);
        !          1022:                        putzhhdr(ZRQINIT);
        !          1023:                        continue;
        !          1024:                case ZRINIT:
        !          1025:                        Rxflags=Rxhdr[ZF0]&0x7f;
        !          1026:                        if(Rxhdr[ZF1]&CANVHDR)
        !          1027:                 zmode|=VAR_HDRS;
        !          1028:                        Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32));
        !          1029:                        Zctlesc |= Rxflags & TESCCTL;
        !          1030:                        Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8);
        !          1031:                        if ( !(Rxflags & CANFDX))
        !          1032:                                Txwindow = 0;
        !          1033: 
        !          1034:                        /* Override to force shorter frame length */
        !          1035:                        if (Rxbuflen && (Rxbuflen>Tframlen) && (Tframlen>=32))
        !          1036:                                Rxbuflen = Tframlen;
        !          1037:                        if ( !Rxbuflen && (Tframlen>=32) && (Tframlen<=1024))
        !          1038:                                Rxbuflen = Tframlen;
        !          1039:                        vfile("Rxbuflen=%d", Rxbuflen);
        !          1040: 
        !          1041:                        /*
        !          1042:                         * If input is not a regular file, force ACK's to
        !          1043:                         *      prevent running beyond the buffer limits
        !          1044:                         */
        !          1045:                        if ( !Command) {
        !          1046:                                fstat(fileno(in), &f);
        !          1047:                                if ((f.st_mode & S_IFMT) != S_IFREG) {
        !          1048:                                        Canseek = -1;
        !          1049:        ef TXBSIZE
        !          1050:                                        Txwindow = TXBSIZE - 1024;
        !          1051:                                        Txwspac = TXBSIZE/4;
        !          1052:        e
        !          1053:                                        return ERROR;
        !          1054:        if
        !          1055:                                }
        !          1056:                        }
        !          1057: 
        !          1058:                        /* Set initial subpacket length */
        !          1059:                        if (blklen < 1024) {    /* Command line override? */
        !          1060:                                if (Effbaud > 300)
        !          1061:                                        blklen = 256;
        !          1062:                                if (Effbaud > 1200)
        !          1063:                                        blklen = 512;
        !          1064:                                if (Effbaud > 2400)
        !          1065:                                        blklen = 1024;
        !          1066:                        }
        !          1067:                        if (Rxbuflen && blklen>Rxbuflen)
        !          1068:                                blklen = Rxbuflen;
        !          1069:                        if (blkopt && blklen > blkopt)
        !          1070:                                blklen = blkopt;
        !          1071:                        vfile("Rxbuflen=%d blklen=%d", Rxbuflen, blklen);
        !          1072:                        vfile("Txwindow = %u Txwspac = %d", Txwindow, Txwspac);
        !          1073: 
        !          1074: 
        !          1075:                        if (Lztrans == ZTRLE && (Rxflags & CANRLE))
        !          1076:                                Txfcs32 = 2;
        !          1077:                        else
        !          1078:                                Lztrans = 0;
        !          1079: 
        !          1080:                        return (sendzsinit());
        !          1081:                case ZCAN:
        !          1082:                case TIMEOUT:
        !          1083:                        return ERROR;
        !          1084:                case ZRQINIT:
        !          1085:                        if (Rxhdr[ZF0] == ZCOMMAND)
        !          1086:                                continue;
        !          1087:                default:
        !          1088:                        putzhhdr(ZNAK);
        !          1089:                        continue; } }
        !          1090: return(ERROR);
        !          1091: }
        !          1092: 
        !          1093: 
        !          1094: getzdata(char *buf, int length)
        !          1095: {
        !          1096:        int c,d;
        !          1097:        uint crc;
        !          1098:        char *end;
        !          1099: 
        !          1100:        switch (Crc32r) {
        !          1101:        case 1:
        !          1102:                return zrdat32(buf, length);
        !          1103:        case 2:
        !          1104:                return zrdatr32(buf, length);
        !          1105:        }
        !          1106: 
        !          1107:        crc = Rxcount = 0;  end = buf + length;
        !          1108:        while (buf <= end) {
        !          1109:                if ((c = getzcom()) & ~0377) {
        !          1110: crcfoo:
        !          1111:                        switch (c) {
        !          1112:                        case GOTCRCE:
        !          1113:                        case GOTCRCG:
        !          1114:                        case GOTCRCQ:
        !          1115:                        case GOTCRCW:
        !          1116:                                crc = updcrc((d=c)&0377, crc);
        !          1117:                                if ((c = getzcom()) & ~0377)
        !          1118:                                        goto crcfoo;
        !          1119:                                crc = updcrc(c, crc);
        !          1120:                                if ((c = getzcom()) & ~0377)
        !          1121:                                        goto crcfoo;
        !          1122:                                crc = updcrc(c, crc);
        !          1123:                                if (crc & 0xFFFF) {
        !          1124:                                        zperr(badcrc);
        !          1125:                                        return ERROR;
        !          1126:                                }
        !          1127:                                Rxcount = length - (end - buf);
        !          1128: #ifndef DSZ
        !          1129:                                vfile("zrdata: %d  %s", Rxcount,
        !          1130:                                 Zendnames[d-GOTCRCE&3]);
        !          1131: #endif
        !          1132:                                return d;
        !          1133:                        case GOTCAN:
        !          1134:                                zperr("Sender Canceled");
        !          1135:                                return ZCAN;
        !          1136:                        case TIMEOUT:
        !          1137:                                zperr("TIMEOUT");
        !          1138:                                return c;
        !          1139:                        default:
        !          1140:                                garbitch(); return c;
        !          1141:                        }
        !          1142:                }
        !          1143:                *buf++ = c;
        !          1144:                crc = updcrc(c, crc);
        !          1145:        }
        !          1146: #ifdef DSZ
        !          1147:        garbitch(); 
        !          1148: #else
        !          1149:        zperr("Data subpacket too long");
        !          1150: #endif
        !          1151:        return ERROR;
        !          1152: }
        !          1153: 
        !          1154: #endif
        !          1155: 
        !          1156: /************************************************/
        !          1157: /* Dump the current blockm contents - for debug */
        !          1158: /************************************************/
        !          1159: void dump_block()
        !          1160: {
        !          1161:        long l;
        !          1162: 
        !          1163: for(l=0;l<block_size;l++)
        !          1164:        lprintf("%02X  ",block[l]);
        !          1165: lputs("\r\n");
        !          1166: }
        !          1167: 
        !          1168: char   *usage=
        !          1169: "usage: STP <port> [chan] [opts] <cmd> [file | path | +list]\r\n\r\n"
        !          1170: "where:\r\n\r\n"
        !          1171: "port   = COM port (1-4), D for DigiBoard, or UART I/O address (hex)\r\n"
        !          1172: "chan   = IRQ channel (2-15) or DigiBoard channel (4+)\r\n"
        !          1173: "opts   = b# to set DTE rate to #bps\r\n"
        !          1174: "         t# to set time-slice API type (default=1)\r\n"
        !          1175: "         o  to overwrite files when receiving\r\n"
        !          1176: "         d  to disable dropped carrier detection\r\n"
        !          1177: "         a  to sound alarm at start and stop of transfer\r\n"
        !          1178: "         l  to disable local keyboard (Ctrl-C) checking\r\n"
        !          1179: "cmd    = sx to send Xmodem     rx to recv Xmodem\r\n"
        !          1180: "         sX to send Xmodem-1k  rc to recv Xmodem-CRC\r\n"
        !          1181: "         sy to send Ymodem     ry to recv Ymodem\r\n"
        !          1182: "         sY to send Ymodem-1k  rg to recv Ymodem-G\r\n"
        !          1183: "         sz to send Zmodem     rz to recv Zmodem\r\n"
        !          1184: "file   = filename to send or receive\r\n"
        !          1185: "path   = path to receive files into\r\n"
        !          1186: "list   = name of text file with list of filenames to send or receive\r\n";
        !          1187: 
        !          1188: /***************/
        !          1189: /* Entry Point */
        !          1190: /***************/
        !          1191: int main(int argc, char **argv)
        !          1192: {
        !          1193:        char    str[256],tmp[256],tmp2[256],irq,errors,*p,*p2,first_block
        !          1194:                        ,*fname[MAX_FNAMES],fnames=0,fnum,success;
        !          1195:        int     ch,i,j,k,file,last,total_files=0,sent_files=0,can;
        !          1196:        uint    base=0,baud=0,cps;
        !          1197:        long    b,l,m,file_bytes_left,serial_num;
        !          1198:        ulong   file_bytes=0,total_bytes=0,sent_bytes=0;
        !          1199:        time_t  t,startall,startfile,ftime;
        !          1200:        struct  ffblk ff;
        !          1201:        struct  ftime ft;
        !          1202:        struct  date dosdate;
        !          1203:        struct  time dostime;
        !          1204:        FILE    *stream,*log=NULL;
        !          1205: 
        !          1206: mswtyp=TS_INT28;   /* default to int 28 only */
        !          1207: 
        !          1208: ctrlbrk(cbreakh);
        !          1209: 
        !          1210: if((asmrev=*(&riobp-1))!=19) {
        !          1211:        printf("Wrong rciol.obj\n");
        !          1212:     exit(1); }
        !          1213: 
        !          1214: lclini(0xd<<8);
        !          1215: 
        !          1216: lprintf("\r\nSynchronet Transfer Protocols v1.00"
        !          1217:        "  Developed 1993-1997 Rob Swindell\r\n\r\n");
        !          1218: 
        !          1219: lputs("Command line: ");
        !          1220: for(i=1;i<argc;i++)
        !          1221:        lprintf("%s ",argv[i]);
        !          1222: lputs("\r\n");
        !          1223: 
        !          1224: if(argc<3) {
        !          1225:        lprintf(usage);
        !          1226:        exit(1); }
        !          1227: 
        !          1228: i=1;
        !          1229: 
        !          1230: base=ahtoul(argv[i]);
        !          1231: if(base>4 && base<0x100)       /* 'D' and 'FFFF' are the same */
        !          1232:        base=0xffff;
        !          1233: if(base!=0xffff && base<5)
        !          1234:        switch(atoi(argv[i])) {
        !          1235:                case 1:
        !          1236:                        base=0x3f8;
        !          1237:                        irq=4;
        !          1238:                        break;
        !          1239:                case 2:
        !          1240:                        base=0x2f8;
        !          1241:                        irq=3;
        !          1242:                        break;
        !          1243:                case 3:
        !          1244:                        base=0x3e8;
        !          1245:                        irq=4;
        !          1246:                        break;
        !          1247:                case 4:
        !          1248:                        base=0x2e8;
        !          1249:                        irq=3;
        !          1250:                        break;
        !          1251:                default:
        !          1252:                        lprintf("Invalid COM Port (%s)\r\n",argv[1]);
        !          1253:                        lprintf(usage);
        !          1254:                        exit(1); }
        !          1255: 
        !          1256: if(base>4 || isdigit(argv[i+1][0]))
        !          1257:        irq=atoi(argv[++i]);
        !          1258: 
        !          1259: for(i++;i<argc;i++) {
        !          1260: 
        !          1261:        if(!(mode&(SEND|RECV))) {
        !          1262:                if(toupper(argv[i][0])=='S' || toupper(argv[i][0])=='R') { /* cmd */
        !          1263:                        if(toupper(argv[i][0])=='R')
        !          1264:                                mode|=RECV;
        !          1265:                        else
        !          1266:                                mode|=SEND;
        !          1267: 
        !          1268:                        block_size=1024;
        !          1269: 
        !          1270:                        switch(argv[i][1]) {
        !          1271:                                case 'c':
        !          1272:                                case 'C':
        !          1273:                                        mode|=CRC;
        !          1274:                                case 'x':
        !          1275:                                        block_size=128;
        !          1276:                                case 'X':
        !          1277:                                        mode|=XMODEM;
        !          1278:                                        break;
        !          1279:                                case 'y':
        !          1280:                                        block_size=128;
        !          1281:                                case 'Y':
        !          1282:                                        mode|=(YMODEM|CRC);
        !          1283:                                        break;
        !          1284:                                case 'g':
        !          1285:                                case 'G':
        !          1286:                                        mode|=(YMODEM|CRC|GMODE);
        !          1287:                                        break;
        !          1288:                                case 'z':
        !          1289:                                case 'Z':
        !          1290:                                        mode|=(ZMODEM|CRC);
        !          1291:                                        break;
        !          1292:                                default:
        !          1293:                                        lprintf("Unrecognized command '%s'\r\n\r\n",argv[i]);
        !          1294:                                        lprintf(usage);
        !          1295:                                        exit(1); } }
        !          1296: 
        !          1297:                else if(toupper(argv[i][0])=='B')
        !          1298:                        baud=atoi(argv[i]+1);
        !          1299: 
        !          1300:                else if(toupper(argv[i][0])=='T')
        !          1301:                        mswtyp=atoi(argv[i]+1);
        !          1302: 
        !          1303:                else if(toupper(argv[i][0])=='O')
        !          1304:                        mode|=OVERWRITE;
        !          1305: 
        !          1306:                else if(toupper(argv[i][0])=='D')
        !          1307:                        mode|=IGNORE_DCD;
        !          1308: 
        !          1309:                else if(toupper(argv[i][0])=='A')
        !          1310:                        mode|=ALARM;
        !          1311: 
        !          1312:                else if(toupper(argv[i][0])=='L')
        !          1313:                        mode|=NO_LOCAL;
        !          1314: 
        !          1315:                else if(argv[i][0]=='*')
        !          1316:                        mode|=DEBUG; }
        !          1317: 
        !          1318:        else if(argv[i][0]=='+') {
        !          1319:                if(mode&DIR) {
        !          1320:                        lprintf("Cannot specify both directory and filename\r\n");
        !          1321:                        exit(1); }
        !          1322:                sprintf(str,"%s",argv[i]+1);
        !          1323:                if((file=nopen(str,O_RDONLY))==-1
        !          1324:                        || (stream=fdopen(file,"rb"))==NULL) {
        !          1325:                        lprintf("Error opening filelist %s\r\n",str);
        !          1326:                        exit(1); }
        !          1327:                while(!feof(stream) && !ferror(stream) && fnames<MAX_FNAMES) {
        !          1328:                        if(!fgets(str,128,stream))
        !          1329:                                break;
        !          1330:                        truncsp(str);
        !          1331:                        strupr(str);
        !          1332:                        if((fname[fnames]=(char *)malloc(strlen(str)+1))==NULL) {
        !          1333:                                lprintf("Error allocating memory for filename\r\n");
        !          1334:                                exit(1); }
        !          1335:                        strcpy(fname[fnames++],str); }
        !          1336:                fclose(stream); }
        !          1337: 
        !          1338:        else if(mode&(SEND|RECV)){
        !          1339:                if((fname[fnames]=(char *)malloc(128))==NULL) {
        !          1340:                        lprintf("Error allocating memory for filename\r\n");
        !          1341:                        exit(1); }
        !          1342:                strcpy(fname[fnames],argv[i]);
        !          1343:                strupr(fname[fnames]);
        !          1344:                j=strlen(fname[fnames]);
        !          1345:                if(fname[fnames][j-1]=='\\'                 /* Ends in \ */
        !          1346:                        || !strcmp(fname[fnames]+1,":")) {      /* Drive letter only */
        !          1347: /*                       || !findfirst(fname[fnames],&ff,FA_DIREC)) {    is a directory */
        !          1348:                        if(mode&DIR) {
        !          1349:                                lprintf("Only one directory can be specified\r\n");
        !          1350:                                exit(1); }
        !          1351:                        if(fnames) {
        !          1352:                                lprintf("Cannot specify both directory and filename\r\n");
        !          1353:                                exit(1); }
        !          1354:                        if(mode&SEND) {
        !          1355:                                lprintf("Cannot send directory '%s'\r\n",fname[fnames]);
        !          1356:                                exit(1);}
        !          1357:                        mode|=DIR; }
        !          1358:                fnames++; } }
        !          1359: 
        !          1360: if(!(mode&(SEND|RECV))) {
        !          1361:        lprintf("No command specified\r\n");
        !          1362:        lprintf(usage);
        !          1363:        exit(1); }
        !          1364: 
        !          1365: if(mode&(SEND|XMODEM) && !fnames) { /* Sending with any or recv w/Xmodem */
        !          1366:        lprintf("Must specify filename or filelist\r\n");
        !          1367:        lprintf(usage);
        !          1368:        exit(1); }
        !          1369: 
        !          1370: i=strlen(fname[0]);    /* Make sure the directory ends in \ or : */
        !          1371: if(mode&DIR && fname[0][i-1]!='\\' && fname[0][i-1]!=':')
        !          1372:        strcat(fname[0],"\\");
        !          1373: 
        !          1374: i=rioini(base,irq);
        !          1375: if(i) {
        !          1376:        lprintf("STP: Error (%d) initializing COM port base %x irq %d\r\n"
        !          1377:                ,i,base,irq);
        !          1378:        exit(1); }
        !          1379: 
        !          1380: if(mode&ALARM) {
        !          1381:        sound(1000);
        !          1382:        mswait(500);
        !          1383:        sound(2000);
        !          1384:        mswait(500);
        !          1385:        nosound(); }
        !          1386: 
        !          1387: if(baud) {
        !          1388:        i=setbaud(baud);
        !          1389:        if(i) {
        !          1390:                lprintf("STP: Error setting baud rate to %u\r\n",baud);
        !          1391:                bail(1); } }
        !          1392: else
        !          1393:        baud=rioctl(GBAUD);
        !          1394: 
        !          1395: rioctl(IOSM|CTSCK|RTSCK);
        !          1396: 
        !          1397: rioctl(TSTYPE|mswtyp);                 /* set time-slice API type */
        !          1398: 
        !          1399: if(!DCDHIGH) {
        !          1400:        newline();
        !          1401:        lprintf("No carrier\r\n");
        !          1402:        bail(1); }
        !          1403: 
        !          1404: p=getenv("DSZLOG");
        !          1405: if(p) {
        !          1406:        if((file=open(p,O_WRONLY|O_BINARY|O_CREAT,S_IWRITE|S_IREAD))==-1
        !          1407:                || (log=fdopen(file,"wb"))==NULL) {
        !          1408:                lprintf("Error opening DSZLOG file '%s'\r\n",p);
        !          1409:                bail(1); }
        !          1410:        setvbuf(log,NULL,_IOFBF,16*1024); }
        !          1411: 
        !          1412: startall=time(NULL);
        !          1413: 
        !          1414: if(mode&RECV) {
        !          1415:        if(fnames>1)
        !          1416:                lprintf("Receiving %u files\r\n",fnames);
        !          1417:        fnum=0;
        !          1418:        while(1) {
        !          1419:                if(mode&XMODEM) {
        !          1420:                        strcpy(str,fname[0]);
        !          1421:                        file_bytes=file_bytes_left=0x7fffffff;
        !          1422:                        serial_num=-1; }
        !          1423: 
        !          1424:                else if(mode&YMODEM) {
        !          1425:                        lprintf("Fetching Ymodem header block\r\n");
        !          1426:                        for(errors=0;errors<MAXERRORS;errors++) {
        !          1427:                                if(errors>3 && mode&CRC && !(mode&GMODE))
        !          1428:                                        mode&=~CRC;
        !          1429:                                if(mode&GMODE)          /* G for Ymodem-G */
        !          1430:                                        putcom('G');
        !          1431:                                else if(mode&CRC)       /* C for CRC */
        !          1432:                                        putcom('C');
        !          1433:                                else                            /* NAK for checksum */
        !          1434:                                        putcom(NAK);
        !          1435:                                for(i=60;i;i--) {
        !          1436:                                        if(rioctl(RXBC))        /* no chars in-bound */
        !          1437:                                                break;
        !          1438:                                        mswait(100); }          /* so wait */
        !          1439: 
        !          1440:                                if(!i) {                                /* none after 6 secs */
        !          1441:                                        if(errors)
        !          1442:                                                lprintf("Ymodem header timeout (%d)\r\n",errors);
        !          1443:                                        continue; }
        !          1444:                                if(!get_block(1)) {      /* block received successfully */
        !          1445:                                        putcom(ACK);
        !          1446:                                        break; } }
        !          1447:                        if(errors==MAXERRORS) {
        !          1448:                                lprintf("Error fetching Ymodem header block\r\n");
        !          1449:                                cancel();
        !          1450:                                bail(1); }
        !          1451:                        if(!block[0]) {
        !          1452:                                lputs("Received Ymodem termination block\r\n");
        !          1453:                                bail(0); }
        !          1454:                        p=block+strlen(block)+1;
        !          1455:                        sscanf(p,"%ld %lo %lo %lo %d %ld"
        !          1456:                                ,&file_bytes                    /* file size (decimal) */
        !          1457:                                ,&ftime                                 /* file time (octal unix format) */
        !          1458:                                ,&m                                     /* file mode (not used) */
        !          1459:                                ,&serial_num                    /* program serial number */
        !          1460:                                ,&total_files                   /* remaining files to be sent */
        !          1461:                                ,&total_bytes                   /* remaining bytes to be sent */
        !          1462:                                );
        !          1463:                        if(!file_bytes)
        !          1464:                                file_bytes=0x7fffffff;
        !          1465:                        file_bytes_left=file_bytes;
        !          1466:                        if(!total_files)
        !          1467:                                total_files=fnames-fnum;
        !          1468:                        if(!total_files)
        !          1469:                                total_files=1;
        !          1470:                        if(total_bytes<file_bytes)
        !          1471:                                total_bytes=file_bytes;
        !          1472:                        if(!serial_num)
        !          1473:                                serial_num=-1;
        !          1474:                        strupr(block);
        !          1475:                        lprintf("Incoming filename: %.64s ",block);
        !          1476:                        if(mode&DIR)
        !          1477:                                sprintf(str,"%s%s",fname[0],justfname(block,tmp));
        !          1478:                        else {
        !          1479:                                justfname(block,str);
        !          1480:                                for(i=0;i<fnames;i++) {
        !          1481:                                        if(!fname[i][0])        /* name blank or already used */
        !          1482:                                                continue;
        !          1483:                                        justfname(fname[i],tmp);
        !          1484:                                        if(!stricmp(tmp,str)) {
        !          1485:                                                strcpy(str,fname[i]);
        !          1486:                                                fname[i][0]=0;
        !          1487:                                                break; } }
        !          1488:                                if(i==fnames) {                                 /* Not found in list */
        !          1489:                                        if(fnames)
        !          1490:                                                lputs(" - Not in receive list!");
        !          1491:                                        if(!fnames || fnum>=fnames || !fname[fnum][0])
        !          1492:                                                justfname(block,str);   /* worst case */
        !          1493:                                        else {
        !          1494:                                                strcpy(str,fname[fnum]);
        !          1495:                                                fname[fnum][0]=0; } } }
        !          1496:                        lputs("\r\n"); }
        !          1497: 
        !          1498:                else {  /* Zmodem */
        !          1499: #if 0
        !          1500:                        tryzhdrtype=ZRINIT;
        !          1501:                        while(1) {
        !          1502:                                Txhdr[ZF0]=(CANFC32|CANFDX|CANOVIO|CANRLE);
        !          1503:                                /* add CANBRK if we can send break signal */
        !          1504:                                if(zmode&CTRL_ESC)
        !          1505:                                        Txhdr[ZF0]|=TESCCTL;
        !          1506:                                Txhdr[ZF1]=CANVHDR;
        !          1507:                                Txhdr[ZP0]=0;
        !          1508:                                Txhdr[ZP1]=0;
        !          1509:                                putzhhdr(tryzhdrtype);
        !          1510:                                done=0;
        !          1511:                                while(!done) {
        !          1512:                                        done=1;
        !          1513:                                        switch(getzhdr()) {
        !          1514:                                                case ZRQINIT:
        !          1515:                                                        if(Rxhdr[ZF3]&0x80)
        !          1516:                                                                zmode|=VAR_HDRS;   /* we can var header */
        !          1517:                                                        break;
        !          1518:                                                case ZFILE:
        !          1519:                                                        zconv=Rxhdr[ZF0];
        !          1520:                                                        zmanag=Rxhdr[ZF1];
        !          1521:                                                        ztrans=Rxhdr[ZF2];
        !          1522:                                                        if(Rxhdr[ZF3]&ZCANVHDR)
        !          1523:                                                                zmode|=VAR_HDRS;
        !          1524:                                                        tryzhdrtype=ZRINIT;
        !          1525:                                                        if(getzdata(block, 1024)==GOTCRCW) {
        !          1526:                                                                /* something */
        !          1527:                                                                done=1; }
        !          1528:                                                        putzhhdr(ZNAK);
        !          1529:                                                        done=0;
        !          1530:                                                        break;
        !          1531:                                                case ZSINIT:
        !          1532:                                                        if(Rxhdr[ZF0]&TESCCTL)
        !          1533:                                                                zmode|=CTRL_ESC;
        !          1534:                                                        if (getzdata(attn,ZATTNLEN)==GOTCRCW) {
        !          1535:                                                                ltohdr(1L);
        !          1536:                                                                putzhhdr(ZACK); }
        !          1537:                                                        else
        !          1538:                                                                putzhhdr(ZNAK);
        !          1539:                                                        done=0;
        !          1540:                                                        break;
        !          1541:                                                case ZFREECNT:
        !          1542:                                                        ltohdr(0);                      /* should be free disk space */
        !          1543:                                                        putzhhdr(ZACK);
        !          1544:                                                        done=0;
        !          1545:                                                        break;
        !          1546:                                                case ZCOMMAND:
        !          1547: /***
        !          1548:                                                        cmdzack1flg = Rxhdr[ZF0];
        !          1549:                                                        if(getzdata(block,1024)==GOTCRCW) {
        !          1550:                                                                if (cmdzack1flg & ZCACK1)
        !          1551:                                                                        ltohdr(0L);
        !          1552:                                                                else
        !          1553:                                                                        ltohdr((long)sys2(block));
        !          1554:                                                                purgeline();    /* dump impatient questions */
        !          1555:                                                                do {
        !          1556:                                                                        zshhdr(4,ZCOMPL, Txhdr);
        !          1557:                                                                }
        !          1558:                                                                while (++errors<20 && zgethdr(Rxhdr,1)!=ZFIN);
        !          1559:                                                                ackbibi();
        !          1560:                                                                if (cmdzack1flg & ZCACK1)
        !          1561:                                                                        exec2(block);
        !          1562:                                                                return ZCOMPL;
        !          1563:                                                        }
        !          1564: ***/
        !          1565:                                                        putzhhdr(ZNAK);
        !          1566:                                                        done=0;
        !          1567:                                                        break;
        !          1568:                                                case ZCOMPL:
        !          1569:                                                        done=0;
        !          1570:                                                        break;
        !          1571:                                                case ZFIN:
        !          1572:                                                        ackbibi();
        !          1573:                                                        return ZCOMPL;
        !          1574:                                                case ZCAN:
        !          1575:                                                        return ERROR; } }
        !          1576: #endif
        !          1577:                        }
        !          1578: 
        !          1579:                fnum++;
        !          1580: 
        !          1581:                if(!(mode&DIR) && fnames && fnum>fnames) {
        !          1582:                        newline();
        !          1583:                        lprintf("Attempt to send more files than specified\r\n");
        !          1584:                        cancel();
        !          1585:                        break; }
        !          1586: 
        !          1587:                k=strlen(str);  /* strip out control characters and high ASCII */
        !          1588:                for(i=j=0;i<k;i++)
        !          1589:                        if(str[i]>SP && (uchar)str[i]<0x7f)
        !          1590:                                str[j++]=str[i];
        !          1591:                str[j]=0;
        !          1592:                strupr(str);
        !          1593:                if(fexist(str) && !(mode&OVERWRITE)) {
        !          1594:                        lprintf("%s already exists\r\n",str);
        !          1595:                        cancel();
        !          1596:                        bail(1); }
        !          1597:                if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1
        !          1598:                        || (stream=fdopen(file,"wb"))==NULL) {
        !          1599:                        lprintf("Error creating %s\r\n",str);
        !          1600:                        cancel();
        !          1601:                        bail(1); }
        !          1602:                setvbuf(stream,NULL,_IOFBF,8*1024);
        !          1603:                startfile=time(NULL);
        !          1604:                lprintf("Receiving %s (%lu bytes) via %s %s\r\n"
        !          1605:                        ,str
        !          1606:                        ,mode&XMODEM ? 0 : file_bytes
        !          1607:                        ,mode&XMODEM ? "Xmodem" : mode&YMODEM ? mode&GMODE ? "Ymodem-G"
        !          1608:                        : "Ymodem" :"Zmodem"
        !          1609:                        ,mode&CRC ? "CRC-16":"Checksum");
        !          1610: 
        !          1611:                errors=0;
        !          1612:                block_num=0;
        !          1613:                if(mode&GMODE)          /* G for Ymodem-G */
        !          1614:                        putcom('G');
        !          1615:                else if(mode&CRC)       /* C for CRC */
        !          1616:                        putcom('C');
        !          1617:                else                            /* NAK for checksum */
        !          1618:                        putcom(NAK);
        !          1619:                while(errors<MAXERRORS) {
        !          1620:                        if(block_num && !(mode&GMODE))
        !          1621:                                putcom(ACK);
        !          1622:                        i=get_block(0);         /* returns 0 if block okay */
        !          1623:                        if(i==EOT)                      /* end of transfer */
        !          1624:                                break;
        !          1625:                        if(i) {                         /* other error */
        !          1626:                                cancel();
        !          1627:                                bail(1); }
        !          1628:                        if(file_bytes_left<=0L)  { /* No more bytes to send */
        !          1629:                                newline();
        !          1630:                                lputs("Attempt to send more than header specified\r\n");
        !          1631:                                break; }
        !          1632:                        if(hdr_block_num==((block_num+1)&0xff)) {       /* correct block */
        !          1633:                                block_num++;
        !          1634:                                if(file_bytes_left<block_size) {
        !          1635:                                        if(fwrite(block,1,file_bytes_left,stream)
        !          1636:                                                !=file_bytes_left) {
        !          1637:                                                newline();
        !          1638:                                                lprintf("Error writing to file\r\n");
        !          1639:                                                cancel();
        !          1640:                                                bail(1); } }
        !          1641:                                else {
        !          1642:                                        if(fwrite(block,1,block_size,stream)
        !          1643:                                                !=block_size) {
        !          1644:                                                newline();
        !          1645:                                                lprintf("Error writing to file\r\n");
        !          1646:                                                cancel();
        !          1647:                                                bail(1); } }
        !          1648:                                file_bytes_left-=block_size; }
        !          1649:                        else {
        !          1650:                                newline();
        !          1651:                                lprintf("Block number %u instead of %u\r\n"
        !          1652:                                        ,hdr_block_num,(block_num+1)&0xff);
        !          1653:                                // dump_block();
        !          1654:                                errors++; }
        !          1655:                        t=time(NULL)-startfile;
        !          1656:                        if(!t) t=1;
        !          1657:                        cps=(uint)((block_num*(long)block_size)/t);     /* cps so far */
        !          1658:                        if(!cps) cps=1;
        !          1659:                        l=file_bytes/cps;  /* total transfer est time */
        !          1660:                        l-=t;                           /* now, it's est time left */
        !          1661:             if(l<0) l=0;
        !          1662:                        b=blocks(file_bytes);
        !          1663:                        if(mode&YMODEM)
        !          1664:                                lprintf("\rBlock (%lu%s): %lu/%lu  Byte: %lu  Time: %lu:%02lu  "
        !          1665:                                        "Left: %lu:%02lu  CPS: %u  %lu%% "
        !          1666:                                        ,block_size%1024L ? block_size: block_size/1024L
        !          1667:                                        ,block_size%1024L ? "" : "k"
        !          1668:                                        ,block_num
        !          1669:                                        ,b
        !          1670:                                        ,block_num*(long)block_size
        !          1671:                                        ,t/60L
        !          1672:                                        ,t%60L
        !          1673:                                        ,l/60L
        !          1674:                                        ,l%60L
        !          1675:                                        ,cps
        !          1676:                                        ,(long)(((float)block_num/(float)b)*100.0)
        !          1677:                                        );
        !          1678:                        else    /* Xmodem */
        !          1679:                                lprintf("\rBlock (%lu%s): %lu  Byte: %lu  Time: %lu:%02lu  "
        !          1680:                                        "CPS: %u "
        !          1681:                                        ,block_size%1024L ? block_size: block_size/1024L
        !          1682:                                        ,block_size%1024L ? "" : "k"
        !          1683:                                        ,block_num
        !          1684:                                        ,block_num*(long)block_size
        !          1685:                                        ,t/60L
        !          1686:                                        ,t%60L
        !          1687:                                        ,cps
        !          1688:                     );
        !          1689:                }
        !          1690: 
        !          1691:                putcom(ACK);
        !          1692:                if(!(mode&XMODEM) && ftime) {
        !          1693:                        unixtodos(ftime,&dosdate,&dostime);
        !          1694:                        if(dosdate.da_year>=1980) {
        !          1695:                                ft.ft_min=dostime.ti_min;
        !          1696:                                ft.ft_hour=dostime.ti_hour;
        !          1697:                                ft.ft_tsec=dostime.ti_sec/2;
        !          1698:                                ft.ft_year=dosdate.da_year-1980;
        !          1699:                                ft.ft_day=dosdate.da_day;
        !          1700:                                ft.ft_month=dosdate.da_mon;
        !          1701:                                setftime(file,&ft); } }
        !          1702:                fclose(stream);
        !          1703:                t=time(NULL)-startfile;
        !          1704:                if(!t) t=1;
        !          1705:                l=(block_num-1)*(long)block_size;
        !          1706:                if(l>file_bytes)
        !          1707:                        l=file_bytes;
        !          1708:                newline();
        !          1709:                lprintf("Successsful - Time: %lu:%02lu  CPS: %lu\r\n"
        !          1710:                        ,t/60,t%60,l/t);
        !          1711:                if(log) {
        !          1712:                        fprintf(log,"%c %6lu %5u bps %4lu cps %3u errors %5u %4u "
        !          1713:                                "%s %d\r\n"
        !          1714:                                ,mode&ZMODEM ? 'Z' : 'R'
        !          1715:                                ,l
        !          1716:                                ,baud
        !          1717:                                ,l/t
        !          1718:                                ,errors
        !          1719:                                ,flows
        !          1720:                                ,block_size
        !          1721:                                ,str
        !          1722:                                ,serial_num); }
        !          1723:                if(mode&XMODEM)
        !          1724:                        break;
        !          1725:                total_files--;
        !          1726:                total_bytes-=file_bytes;
        !          1727:                if(total_files>1 && total_bytes)
        !          1728:                        lprintf("Remaining - Time: %lu:%02lu  Files: %u  Bytes: %lu\r\n"
        !          1729:                                ,(total_bytes/cps)/60
        !          1730:                                ,(total_bytes/cps)%60
        !          1731:                                ,total_files
        !          1732:                                ,total_bytes
        !          1733:                 );
        !          1734:                }
        !          1735:        bail(0); }
        !          1736: 
        !          1737: /********/
        !          1738: /* SEND */
        !          1739: /********/
        !          1740: 
        !          1741: /****************************************************/
        !          1742: /* Search through all to find total files and bytes */
        !          1743: /****************************************************/
        !          1744: for(fnum=0;fnum<fnames;fnum++) {
        !          1745:        last=findfirst(fname[fnum],&ff,0);      /* incase wildcards are used */
        !          1746:        if(last)
        !          1747:                lprintf("%s not found\r\n",fname[fnum]);
        !          1748:        while(!last) {
        !          1749:                total_files++;
        !          1750:                total_bytes+=ff.ff_fsize;
        !          1751:                last=findnext(&ff); } }
        !          1752: 
        !          1753: if(fnames>1)
        !          1754:        lprintf("Sending %u files (%lu bytes total)\r\n"
        !          1755:                ,total_files,total_bytes);
        !          1756: 
        !          1757: rioctl(IOFB);
        !          1758: 
        !          1759: /***********************************************/
        !          1760: /* Send every file matching names or filespecs */
        !          1761: /***********************************************/
        !          1762: for(fnum=0;fnum<fnames;fnum++) {
        !          1763:        last=findfirst(fname[fnum],&ff,0);
        !          1764:        while(!last) {
        !          1765:                if(mode&ZMODEM) {
        !          1766: #if 0
        !          1767:                        putcom('r'); putcom('z'); putcom(CR);       /* send rz\r */
        !          1768:                        ltohdr(0L);     /* Zero the header */
        !          1769:                        putzhhdr(ZRQINIT);
        !          1770:                        getzrxinit();
        !          1771: #endif
        !          1772:                        } /* Zmodem */
        !          1773:                else {
        !          1774:                        mode&=~GMODE;
        !          1775:                        flows=0;
        !          1776:                        for(errors=can=0;errors<MAXERRORS;errors++) {
        !          1777:                                i=getcom(10);
        !          1778:                                if(can && i!=CAN)
        !          1779:                                        can=0;
        !          1780:                                if(i==NAK) {            /* csum */
        !          1781:                                        mode&=~CRC;
        !          1782:                                        break; }
        !          1783:                                if(i=='C') {
        !          1784:                                        mode|=CRC;
        !          1785:                                        break; }
        !          1786:                                if(i=='G') {
        !          1787:                                        mode|=(GMODE|CRC);
        !          1788:                                        break; }
        !          1789:                                if(i==CAN) {
        !          1790:                                        if(can) {
        !          1791:                                                newline();
        !          1792:                                                lprintf("Cancelled remotely\r\n");
        !          1793:                                                bail(1); }
        !          1794:                                        can=1; }
        !          1795:                                rioctl(IOFB);   /* flush buffers cause we have crap-o-la */
        !          1796:                                if(i!=NOINP) {
        !          1797:                                        newline();
        !          1798:                                        lprintf("Received %s  Expected NAK, C, or G\r\n"
        !          1799:                                                ,chr(i)); } }
        !          1800:                        if(errors==MAXERRORS) {
        !          1801:                                lprintf("Timeout starting transfer\r\n");
        !          1802:                                cancel();
        !          1803:                                bail(1); } } /* X/Ymodem */
        !          1804: 
        !          1805:                strcpy(str,fname[fnum]);
        !          1806:                if(strchr(str,'*') || strchr(str,'?')) {    /* wildcards used */
        !          1807:                        p=strrchr(str,'\\');
        !          1808:                        if(!p)
        !          1809:                                p=strchr(str,':');
        !          1810:                        if(p)
        !          1811:                                *(p+1)=NULL;
        !          1812:                        else
        !          1813:                                str[0]=0;
        !          1814:                        strcat(str,ff.ff_name); }
        !          1815: 
        !          1816:                lprintf("Sending %s (%lu bytes) via %s %s\r\n"
        !          1817:                        ,str,ff.ff_fsize
        !          1818:                        ,mode&XMODEM ? "Xmodem" : mode&YMODEM ? mode&GMODE ? "Ymodem-G"
        !          1819:                        : "Ymodem" :"Zmodem"
        !          1820:             ,mode&CRC ? "CRC-16":"Checksum");
        !          1821: 
        !          1822:                if((file=nopen(str,O_RDONLY))==-1
        !          1823:                        || (stream=fdopen(file,"rb"))==NULL) {
        !          1824:                        lprintf("Error opening %s for read\r\n",str);
        !          1825:                        cancel();
        !          1826:                        bail(1); }
        !          1827:                setvbuf(stream,NULL,_IOFBF,8*1024);
        !          1828:                rioctl(IOFB);   /* flush buffers cause extra 'G', 'C', or NAKs */
        !          1829:                if(!(mode&XMODEM)) {
        !          1830:                        getftime(file,&ft);
        !          1831:                        dostime.ti_min=ft.ft_min;
        !          1832:                        dostime.ti_hour=ft.ft_hour;
        !          1833:                        dostime.ti_hund=0;
        !          1834:                        dostime.ti_sec=ft.ft_tsec*2;
        !          1835:                        dosdate.da_year=1980+ft.ft_year;
        !          1836:                        dosdate.da_day=ft.ft_day;
        !          1837:                        dosdate.da_mon=ft.ft_month;
        !          1838:                        t=dostounix(&dosdate,&dostime);
        !          1839:                        memset(block,NULL,128);
        !          1840:                        strcpy(block,ff.ff_name);
        !          1841:                        strlwr(block);
        !          1842:                        sprintf(block+strlen(block)+1,"%lu %lo 0 0 %d %ld"
        !          1843:                                ,ff.ff_fsize,t,total_files-sent_files,total_bytes-sent_bytes);
        !          1844:                        /*
        !          1845:                        lprintf("Sending Ymodem block '%s'\r\n",block+strlen(block)+1);
        !          1846:                        */
        !          1847:                        block_num=0;
        !          1848:                        i=block_size;
        !          1849:                        block_size=128;         /* Always use 128 for first block */
        !          1850:                        for(errors=0;errors<MAXERRORS;errors++) {
        !          1851:                                put_block();
        !          1852:                                if(get_ack())
        !          1853:                                        break; }
        !          1854:                        if(errors==MAXERRORS) {
        !          1855:                                newline();
        !          1856:                                lprintf("Failed to send header block\r\n");
        !          1857:                                cancel();
        !          1858:                                bail(1); }
        !          1859:                        block_size=i;           /* Restore block size */
        !          1860:                        mode&=~GMODE;
        !          1861:                        for(errors=can=0;errors<MAXERRORS;errors++) {
        !          1862:                                i=getcom(10);
        !          1863:                                if(can && i!=CAN)
        !          1864:                                        can=0;
        !          1865:                                if(i==NAK) {            /* csum */
        !          1866:                                        mode&=~CRC;
        !          1867:                                        break; }
        !          1868:                                if(i=='C') {
        !          1869:                                        mode|=CRC;
        !          1870:                                        break; }
        !          1871:                                if(i=='G') {
        !          1872:                                        mode|=(GMODE|CRC);
        !          1873:                                        break; }
        !          1874:                                if(i==CAN) {
        !          1875:                                        if(can) {
        !          1876:                                                newline();
        !          1877:                                                lprintf("Cancelled remotely\r\n");
        !          1878:                                                bail(1); }
        !          1879:                                        can=1; }
        !          1880:                                rioctl(IOFB);
        !          1881:                                if(i!=NOINP) {
        !          1882:                                        newline();
        !          1883:                                        lprintf("Received %s  Expected NAK, C, or G\r\n"
        !          1884:                                                ,chr(i)); } }
        !          1885:                        if(errors==MAXERRORS) {
        !          1886:                                newline();
        !          1887:                                lprintf("Too many errors waiting for receiver\r\n");
        !          1888:                                cancel();
        !          1889:                                bail(1); } }
        !          1890:                last_block_num=block_num=1;
        !          1891:                startfile=time(NULL);
        !          1892:                errors=0;
        !          1893:                while((block_num-1)*(long)block_size<ff.ff_fsize && errors<MAXERRORS) {
        !          1894:                        if(last_block_num==block_num) {  /* block_num didn't increment */
        !          1895:                                fseek(stream,(block_num-1)*(long)block_size,SEEK_SET);
        !          1896:                                i=fread(block,1,block_size,stream);
        !          1897:                                while(i<block_size)
        !          1898:                                        block[i++]=CPMEOF; }
        !          1899:                        last_block_num=block_num;
        !          1900:                        put_block();
        !          1901:                        i=fread(block,1,block_size,stream); /* read next block from disk */
        !          1902:                        while(i<block_size)
        !          1903:                                block[i++]=CPMEOF;
        !          1904:                        t=time(NULL)-startfile;
        !          1905:                        if(!t) t=1;             /* t is time so far */
        !          1906:                        cps=(uint)((block_num*(long)block_size)/t);     /* cps so far */
        !          1907:                        if(!cps) cps=1;
        !          1908:                        l=ff.ff_fsize/cps;      /* total transfer est time */
        !          1909:                        l-=t;                           /* now, it's est time left */
        !          1910:                        if(l<0) l=0;
        !          1911:                        b=blocks(ff.ff_fsize);
        !          1912:                        lprintf("\rBlock (%lu%s): %lu/%lu  Byte: %lu  "
        !          1913:                                "Time: %lu:%02lu  Left: %lu:%02lu  CPS: %u  %lu%% "
        !          1914:                                ,block_size%1024L ? block_size: block_size/1024L
        !          1915:                                ,block_size%1024L ? "" : "k"
        !          1916:                                ,block_num
        !          1917:                                ,b
        !          1918:                                ,block_num*(long)block_size
        !          1919:                                ,t/60L
        !          1920:                                ,t%60L
        !          1921:                                ,l/60L
        !          1922:                                ,l%60L
        !          1923:                                ,cps
        !          1924:                                ,(long)(((float)block_num/(float)b)*100.0)
        !          1925:                                );
        !          1926:                        if(!get_ack())
        !          1927:                                errors++;
        !          1928:                        else
        !          1929:                                block_num++; }
        !          1930:                fclose(stream);
        !          1931:                success=0;
        !          1932:                if((block_num-1)*(long)block_size>=ff.ff_fsize) {
        !          1933:                        sent_files++;
        !          1934:                        sent_bytes+=ff.ff_fsize;
        !          1935:                        riosync();
        !          1936:                        lprintf("\n");
        !          1937: 
        !          1938:                        for(i=0;i<10;i++) {
        !          1939:                                lprintf("\rSending EOT (%d)",i+1);
        !          1940:                                rioctl(IOFI);
        !          1941:                                putcom(EOT);
        !          1942:                                ch=getcom(10);
        !          1943:                                if(ch==ACK)
        !          1944:                                        break;
        !          1945:                                if(ch==NAK && i==0 && (mode&(YMODEM|GMODE))==YMODEM)
        !          1946:                                        continue;  /* chuck's double EOT trick so don't complain */
        !          1947:                                if(ch!=NOINP) {
        !          1948:                                        newline();
        !          1949:                                        lprintf("Received %s  Expected ACK\r\n"
        !          1950:                                                ,chr(ch)); } }
        !          1951:                        if(i==3)
        !          1952:                                lprintf("\rNo ACK on EOT   \n");
        !          1953:                        t=time(NULL)-startfile;
        !          1954:                        if(!t) t=1;
        !          1955:                        lprintf("\rSuccesssful - Time: %lu:%02lu  CPS: %lu\r\n"
        !          1956:                                ,t/60,t%60,ff.ff_fsize/t);
        !          1957:                        success=1; }
        !          1958:                else {
        !          1959:                        newline();
        !          1960:                        lputs("Unsuccessful!\r\n");
        !          1961:                        t=time(NULL)-startfile;
        !          1962:                        if(!t) t=1; }
        !          1963: 
        !          1964:                if(total_files>1 && total_files-sent_files>1)
        !          1965:                        lprintf("Remaining - Time: %lu:%02lu  Files: %u  Bytes: %lu\r\n"
        !          1966:                                ,((total_bytes-sent_bytes)/cps)/60
        !          1967:                                ,((total_bytes-sent_bytes)/cps)%60
        !          1968:                                ,total_files-sent_files
        !          1969:                                ,total_bytes-sent_bytes
        !          1970:                                );
        !          1971:                if(log) {
        !          1972:                        l=(block_num-1)*(long)block_size;
        !          1973:                        if(l>ff.ff_fsize)
        !          1974:                                l=ff.ff_fsize;
        !          1975:                        fprintf(log,"%c %6lu %5u bps %4lu cps %3u errors %5u %4u "
        !          1976:                                "%s -1\r\n"
        !          1977:                                ,success ? (mode&ZMODEM ? 'z':'S') : 'E'
        !          1978:                                ,l
        !          1979:                                ,baud
        !          1980:                                ,l/t
        !          1981:                                ,errors
        !          1982:                                ,flows
        !          1983:                                ,block_size
        !          1984:                                ,fname[fnum]); }
        !          1985: 
        !          1986:                last=findnext(&ff); } }
        !          1987: if(mode&XMODEM)
        !          1988:        bail(0);
        !          1989: mode&=~GMODE;
        !          1990: i=getcom(10);
        !          1991: if(i==NAK)
        !          1992:        mode&=~CRC;
        !          1993: else if(i=='C')
        !          1994:        mode|=CRC;
        !          1995: else if(i=='G')
        !          1996:        mode|=(GMODE|CRC);
        !          1997: if(i!=NOINP && i!=NAK && i!='C' && i!='G') {
        !          1998:        newline();
        !          1999:        lprintf("Received %s  Expected NAK, C, or G\r\n",chr(i)); }
        !          2000: else if(i!=NOINP) {
        !          2001:        block_num=0;
        !          2002:        block[0]=0;
        !          2003:        block_size=128;
        !          2004:        put_block();
        !          2005:        if(!get_ack()) {
        !          2006:                newline();
        !          2007:                lprintf("Failed to receive ACK after terminating block\r\n"); } }
        !          2008: if(total_files>1) {
        !          2009:        t=time(NULL)-startall;
        !          2010:        if(!t) t=1;
        !          2011:        newline();
        !          2012:        lprintf("Overall - Time %02lu:%02lu  Bytes: %lu  CPS: %lu\r\n"
        !          2013:                ,t/60,t%60,sent_bytes,sent_bytes/t); }
        !          2014: bail(0);
        !          2015: return(0);
        !          2016: }
        !          2017: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.