Annotation of sbbs/stp/stp.c, revision 1.1.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.