home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / zip / telecomm / zmdm.zoo / sz.c < prev    next >
C/C++ Source or Header  |  1991-04-27  |  33KB  |  1,712 lines

  1. /*
  2.  *                ACKNOWLEDGEMENTS
  3.  *
  4.  *    ZMDM was derived from rz/sz for Unix  posted by 
  5.  *    Chuck Forsberg (...!tektronix!reed!omen!caf ). We
  6.  *    thank him for his excellent code, and for giving
  7.  *    us permission to use and distribute his code and
  8.  *    documentation.
  9.  *
  10.  *    Atari St version by:
  11.  *    Jwahar Bammi
  12.  *     bang:   {any internet host}!dsrgsun.ces.CWRU.edu!bammi
  13.  *     domain: bammi@dsrgsun.ces.CWRU.edu
  14.  *    GEnie:    J.Bammi
  15.  */
  16.  
  17. #include "config.h"
  18. #define SVERSION "sz 3.03 5-09-89"
  19. #define SSTVERSION "$Revision: 1.77 $ $Date: 1991/04/27 22:12:49 $"
  20. #define OS    "Unix V7/BSD"
  21.  
  22. #ifndef STANDALONE
  23. #define RETURN return
  24. #else
  25. static void RETURN();
  26. void bibi(n) int n; {} /* dummy */
  27. #endif 
  28.  
  29. /* #define SDEBUG */
  30.  
  31. #include "zmdm.h"
  32. #include "common.h"
  33. #include "zmodem.h"
  34.  
  35. #ifndef Vsync             /* Atari forgot these in osbind.h */
  36. #define Vsync()    xbios(37)
  37. #endif
  38.  
  39. #ifndef Supexec
  40.         /* Some versions of osbind don't define Supexec */
  41. #define Supexec(X) xbios(38,X)
  42. #endif
  43.  
  44. #define SLOGFILE "szlog"
  45.  
  46. #define purgeline()    while(Bconstat(1)) Bconin(1)
  47. #define S_IFDIR 0x0010
  48.  
  49. /*
  50.  * Attention string to be executed by receiver to interrupt streaming data
  51.  *  when an error is detected.  A pause (0336) may be needed before the
  52.  *  ^C (03) or after it.
  53.  */
  54. #ifdef READCHECK
  55. char Myattn[] = { 0 };
  56. #else
  57. #ifdef USG
  58. char Myattn[] = { 03, 0336, 0 };
  59. #else
  60. char Myattn[] = { 0 };
  61. #endif
  62. #endif
  63.  
  64. #define TXBMASK (TXBSIZE-1)
  65. static char *txbuf = secbuf;        /* Pointer to current file segment */
  66.  
  67. #if (MWC || MANX || __GNUC__)
  68. FILE *fopen();
  69. #else
  70. FILE *fopen(), *fopenb();
  71. #endif
  72. static long bytcnt, Lastsync;
  73. static unsigned long SaveIntr;
  74. static int Resuming, ForceBin;
  75. static int in;
  76. static int Filesleft;
  77. static long Totalleft;
  78. static long vpos;
  79. static void countem();
  80.  
  81. #ifndef __GNUC__
  82. extern long stread();
  83. #else
  84. long stread(int, unsigned char *, long);
  85. #endif
  86.  
  87. /* called by signal interrupt or terminate to clean things up */
  88. #ifndef STANDALONE
  89. void bibis(n)
  90. int n;
  91. {
  92.     canit(); flush_modem(); mode(0);
  93.     fprintf(STDERR, "\r\nsz: caught signal %d; exiting\n", n);
  94.  
  95.     aexit(128+n);
  96. }
  97. #endif
  98.  
  99. /* Called when Zmodem gets an interrupt (^X) */
  100. #ifdef ONINTR
  101. void onintr()
  102. {
  103.     siggi = 0;
  104.     longjmp(intrjmp, -1);
  105. }
  106. #endif
  107.  
  108. #define ZKER
  109.  
  110. #ifdef STANDALONE
  111. int main(argc, argv)
  112. #else
  113. int dosz(argc, argv)
  114. #endif
  115. int argc;
  116. char **argv;
  117. {
  118.     register char *cp;
  119.     register int npats;
  120.     int agcnt; char **agcv;
  121.     char **patts;
  122.  
  123. #ifdef STANDALONE
  124. #if (MWC || __GNUC__)
  125. #ifdef MWC
  126.     extern char *lmalloc();
  127. #else
  128. #define lmalloc malloc
  129.     extern void *lmalloc(unsigned long);
  130. #endif    
  131. #endif
  132.  
  133.     /* Set up Dta */
  134.     Fsetdta(&statbuf);
  135.  
  136.     /* Get screen rez */
  137.     rez = Getrez();
  138.     drv_map = Drvmap();
  139.  
  140. #if (MWC || MANX || __GNUC__)
  141. #ifndef DYNABUF
  142. #if (MWC || __GNUC__)
  143.     if((bufr = (unsigned char *)lmalloc((unsigned long)BBUFSIZ))
  144.                      == (unsigned char *)NULL)
  145. #else
  146.     if((bufr = (unsigned char *)Malloc((unsigned long)BBUFSIZ))
  147.                      == (unsigned char *)NULL)
  148. #endif
  149. #else
  150.     if((bufr = dalloc()) == (unsigned char *)NULL)
  151. #endif /* DYNABUF */
  152.     {
  153. #ifdef REMOTE
  154.         Bauxws("Sorry, could not allocate enough memory\r\n");
  155. #else
  156.         Bconws("Sorry, could not allocate enough memory\r\n");
  157. #endif
  158.  
  159.         Pterm(4);
  160.     }
  161. #else /* MWC || MANX */
  162. #ifdef DYNABUF
  163.     if((bufr = dalloc()) == (unsigned char *)NULL)
  164.     {
  165. #ifdef REMOTE
  166.         Bauxws("Sorry, could not allocate enough memory\r\n");
  167. #else
  168.         Bconws("Sorry, could not allocate enough memory\r\n");
  169. #endif
  170.         Pterm(5);
  171.     }
  172. #endif /* DYNABUF */
  173. #endif /* MWC || MANX */
  174.  
  175. #ifndef REMOTE
  176.     STDERR = stderr;
  177. #else
  178. #ifndef DLIBS
  179.     if((STDERR = fopen("aux:", "rw")) == (FILE *)NULL)
  180.     {
  181.         Bauxws("Could not Open Aux Stream for Stderr\r\n");
  182.         finish();
  183.     }
  184.     setbuf(STDERR, (char *)NULL);
  185. #else
  186.     STDERR = stdaux;
  187. #endif /* DLIBS */
  188.     
  189. #endif /* REMOTE */
  190.     {
  191.         int speed;
  192.         speed = getbaud();
  193.         Baudrate = BAUD_RATE(speed);
  194.         SetIoBuf();
  195.         Rsconf(speed, 0,-1,-1,-1,-1);
  196.         Vsync(); Vsync();
  197.     }
  198. #endif /* STANDALONE */
  199.  
  200.     SendType = 1;
  201.     Rxtimeout = 600;
  202.     npats=0;
  203.     Filesleft = 0;
  204.     Totalleft = 0L;
  205.     txbuf = secbuf;
  206.     vpos = 0;
  207.     bytcnt = 0;
  208.     
  209.     if (argc<2)
  210.     {
  211.         susage();
  212.         RETURN(1);
  213.     }
  214.  
  215.     initz();
  216. #ifndef STANDALONE
  217.     schkinvok(argv[0]);
  218. #else
  219.     Progname = "sz";
  220. #endif
  221.  
  222.     SaveIntr = Setexc(0x0102, -1L);
  223.     BusErr   = Setexc(2, -1L);
  224.     AddrErr  = Setexc(3, -1L);
  225.  
  226.     Verbose = 0;
  227.     Resuming = FALSE;
  228.     ForceBin = FALSE;
  229.     in = (-1);
  230.     vdebug = 0;
  231.  
  232. #ifdef SDEBUG
  233.     logf = (FILE *)NULL;
  234. #endif
  235.     while (--argc) {
  236.         cp = *++argv;
  237.         if (*cp++ == '-' && *cp) {
  238.             while ( *cp) {
  239.                 switch(*cp++) {
  240.                 case '+':
  241.                     Lzmanag = ZMAPND; break;
  242. #ifdef CSTOPB
  243.                 case '2':
  244.                     Twostop = TRUE; break;
  245. #endif
  246.                 case '7':
  247.                     Wcsmask=0177; break;
  248.  
  249. /*
  250.     On the St we look up the ext and decide. For Xmodem
  251.     transfers, the file is always sent in binary mode
  252.     and it is the responsibility of the receiver to
  253.     strip CR if so desired.
  254.                 case 'a':
  255.                     Lzconv = ZCNL;
  256.                     Ascii = TRUE; break;
  257.                 case 'b':
  258.                     Lzconv = ZCBIN; break;
  259. */
  260.  
  261. /*  ST extention, force binary, useful to back up every thing
  262.  *  in image mode, see -B option of rz too +jrb
  263.  */
  264.                 case 'B':
  265.                     ForceBin = TRUE;
  266.                     Lzconv = ZCBIN;
  267.                     break;
  268.                 case 'C':
  269.                     if (--argc < 1) {
  270.                         susage();
  271.                         RETURN(1);
  272.                     }
  273.                     Cmdtries = atoi(*++argv);
  274.                     break;
  275.                 case 'i':
  276.                     Cmdack1 = ZCACK1;
  277.                     /* **** FALL THROUGH TO **** */
  278.                 case 'c':
  279.                     if (--argc != 1) {
  280.                         susage();
  281.                         RETURN(1);
  282.                     }
  283.                     Command = TRUE;
  284.                     Cmdstr = *++argv;
  285.                     break;
  286.                 case 'd':
  287.                     ++Dottoslash;
  288.                     /* **** FALL THROUGH TO **** */
  289.                 case 'f':
  290.                     Fullname=TRUE; break;
  291.                 case 'e':
  292.                     Zctlesc = 1; break;
  293.                 case 'k':
  294.                     Blklen=KSIZE; break;
  295.                 case 'L':
  296.                     if (--argc < 1) {
  297.                         susage();
  298.                         RETURN(1);
  299.                     }
  300.                     blkopt = atoi(*++argv);
  301.                     if (blkopt<24 || blkopt>1024)
  302.                     {
  303.                         susage();
  304.                         RETURN(1);
  305.                     }
  306.                     break;
  307.                 case 'l':
  308.                     if (--argc < 1) {
  309.                         susage();
  310.                         RETURN(1);
  311.                     }
  312.                     Tframlen = atoi(*++argv);
  313.                     if (Tframlen<32 || Tframlen>1024)
  314.                     {
  315.                         susage();
  316.                         RETURN(1);
  317.                     }
  318.                     break;
  319.                 case 'N':
  320.                     Lzmanag = ZMNEWL;  break;
  321.                 case 'n':
  322.                     Lzmanag = ZMNEW;  break;
  323.                 case 'o':
  324.                     Wantfcs32 = FALSE; break;
  325.                 case 'p':
  326.                     Lzmanag = ZMPROT;  break;
  327.                 case 'r':
  328.                     if (Lzconv == ZCRESUM)
  329.                         Lzmanag = (Lzmanag & ZMMASK) |
  330.                             ZMCRC; 
  331.                     Lzconv = ZCRESUM; Resuming = TRUE;
  332.                     break; 
  333.                 case 'q':
  334.                     Quiet=TRUE; Verbose=0; break;
  335.                 case 't':
  336.                     if (--argc < 1) {
  337.                         susage();
  338.                         RETURN(1);
  339.                     }
  340.                     Rxtimeout = atoi(*++argv);
  341.                     if (Rxtimeout<10 || Rxtimeout>1000)
  342.                     {
  343.                         susage();
  344.                         RETURN(1);
  345.                     }
  346.                     break;
  347.                 case 'u':
  348.                     ++Unlinkafter; break;
  349.                 case 'v':
  350.                     ++Verbose; break;
  351.                 case 'w':
  352.                     if (--argc < 1) {
  353.                         susage();
  354.                         RETURN(1);
  355.                     }
  356.                     Txwindow = atoi(*++argv);
  357.                     if (Txwindow < 256)
  358.                         Txwindow = 256;
  359.                     Txwindow = (Txwindow/64) * 64;
  360.                     Txwspac = Txwindow/4;
  361.                     if (blkopt > Txwspac
  362.                      || (!blkopt && Txwspac < 1024))
  363.                         blkopt = Txwspac;
  364.                     break;
  365.                 case 'X':
  366.                     ++Modem; break;
  367.                 case 'Y':
  368.                     Lskipnocor = TRUE;
  369.                     /* **** FALLL THROUGH TO **** */
  370.                 case 'y':
  371.                     Lzmanag = ZMCLOB; break;
  372.                 case 'Z':
  373.                 case 'z':
  374.                     Lztrans = ZTRLE;  break;
  375.                 default:
  376.                     susage();
  377.                     RETURN(1);
  378.                 }
  379.             }
  380.         }
  381.         else if ( !npats && argc>0) {
  382.             if (argv[0][0]) {
  383.                 npats=argc;
  384.                 patts=argv;
  385.             }
  386.         }
  387.     }
  388.     if (npats < 1 && !Command) 
  389.     {
  390.         susage();
  391.         RETURN(1);
  392.     }
  393.  
  394. #ifdef SDEBUG
  395.     if (Verbose > 2)
  396.     {
  397.         if ((logf = fopen(SLOGFILE, "a"))== (FILE *)NULL)
  398.         {
  399.             fprintf(STDERR, "Can't open log file %s\n",SLOGFILE);
  400.             RETURN(0200);
  401.         }
  402.         fprintf(logf, "Progname=%s\n", Progname);
  403.         vdebug = 1;
  404.         fflush(logf);
  405.     }
  406. #endif
  407.  
  408.     if ( !Quiet)
  409.     {
  410.         if (Verbose < 2)
  411.             Verbose = 2;
  412.     }
  413.  
  414.  
  415.     Setexc(0x0102, bibis);
  416.     Setexc(2, buserr);
  417.     Setexc(3, addrerr);
  418.  
  419.     if(setjmp(busjmp))
  420.     {
  421.         /* On a bus error - instead of 2 bombs */
  422.         fprintf(STDERR,"\r\nFATAL: Bus Error\n\n");
  423. #ifdef SDEBUG
  424.         if(logf != (FILE *)NULL)
  425.             fclose(logf);
  426. #endif
  427.         if(in != -1)
  428.         {
  429.             stfclose(in);
  430.             in = (-1);
  431.         }
  432.         canit();
  433.         Setexc(2, BusErr);
  434.         Setexc(3, AddrErr);
  435.         Setexc(0x0102, SaveIntr);
  436.         RETURN(2);
  437.     }
  438.  
  439.     if(setjmp(addrjmp))
  440.     {
  441.         /* On address error - instead of 3 bombs */
  442.         fprintf(STDERR,"\r\nFATAL: Address Error\n\n");
  443. #ifdef SDEBUG
  444.         if(logf != (FILE *)NULL)
  445.             fclose(logf);
  446. #endif
  447.         if(in != -1)
  448.         {
  449.             stfclose(in);
  450.             in = (-1);
  451.         }
  452.         canit();
  453.         Setexc(2, BusErr);
  454.         Setexc(3, AddrErr);
  455.         Setexc(0x0102, SaveIntr);
  456.         RETURN(3);
  457.     }
  458.  
  459.     if((Exitcode = setjmp(abrtjmp)))
  460.     {
  461.         fprintf(STDERR,"\nTransfer ABORT\n\n");
  462. #ifdef SDEBUG
  463.     if(logf != (FILE *)NULL)
  464.         fclose(logf);
  465. #endif
  466.         if(in != -1)
  467.         {
  468.             stfclose(in);
  469.             in = (-1);
  470.         }
  471.         Setexc(2, BusErr);
  472.         Setexc(3, AddrErr);
  473.         Setexc(0x0102, SaveIntr);
  474.         RETURN(Exitcode);
  475.     }
  476.  
  477.     mode(1);
  478.  
  479.  
  480.     if ( !Modem) {
  481.         if (!Command && !Quiet && Verbose != 1)
  482.         {
  483.             fprintf(STDERR, "sz: %d file%s requested:\n",
  484.                 npats, npats>1?"s":"");
  485.             for ( agcnt=npats, agcv=patts; --agcnt>=0; )
  486.             {
  487.                 fprintf(STDERR, "%s ", *agcv++);
  488.             }
  489.             fprintf(STDERR, "\n\n");
  490.  
  491. #ifdef SDEBUG
  492.             if(Verbose > 2)
  493.             {
  494.                 fprintf(logf, "sz: %d file%s requested:\n",
  495.                     npats, npats>1?"s":"");
  496.                 for ( agcnt=npats, agcv=patts; --agcnt>=0; )
  497.                 {
  498.                     fprintf(logf, "%s ", *agcv++);
  499.                 }
  500.                 fprintf(logf, "\n");
  501.                 fflush(logf);
  502.             }
  503. #endif
  504.         }
  505.  
  506.         countem(npats, patts);
  507.         if (!Nozmodem) {
  508.             stohdr(0L);
  509.             if (Command)
  510.                 Txhdr[ZF0] = ZCOMMAND;
  511.             zshhdr(4, ZRQINIT, Txhdr);
  512.         }
  513.     }
  514.     flush_modem();
  515.  
  516.     if (Command) {
  517.         if (getzrxinit()) {
  518.             Exitcode=0200; canit();
  519.         }
  520.         else if (zsendcmd(Cmdstr, (int)(1+strlen(Cmdstr)))) {
  521.             Exitcode=0200; canit();
  522.         }
  523.     } else if (wcsend(npats, patts)==ERROR) {
  524.         Exitcode=0200;
  525.         canit();
  526.     }
  527.     flush_modem();
  528.     mode(0);
  529.  
  530. #ifdef SDEBUG
  531.     if(logf != (FILE *)NULL)
  532.         fclose(logf);
  533. #endif
  534.     if(in != -1)
  535.     {
  536.         stfclose(in);
  537.         in = (-1);
  538.     }
  539.  
  540.     putc('\n', STDERR);
  541.     Setexc(2, BusErr);
  542.     Setexc(3, AddrErr);
  543.     Setexc(0x0102, SaveIntr);
  544.     RETURN((errcnt != 0) | Exitcode);
  545.  
  546. }
  547.  
  548. #ifdef STANDALONE
  549. static void RETURN(n)
  550. int n;
  551. {
  552.     ResetIoBuf();
  553. #if (MWC || MANX || __GNUC__)
  554. #ifndef DYNABUF
  555.     free(bufr);
  556. #else
  557.     Mfree(bufr);
  558. #endif
  559. #else
  560. #ifdef DYNABUF
  561.     Mfree(bufr);
  562. #endif
  563. #endif
  564.     exit(n);
  565. }
  566. #endif /* STANDALONE */
  567.  
  568. int wcsend(argc, argp)
  569. int argc;
  570. char *argp[];
  571. {
  572.     register int n;
  573.  
  574.     Crcflg=FALSE;
  575.     Firstsec=TRUE;
  576.     bytcnt = -1;
  577.     
  578.     for (n=0; n<argc; ++n) {
  579.         Totsecs = 0;
  580.         if (wcs(argp[n])==ERROR)
  581.             return ERROR;
  582.     }
  583.     Totsecs = 0;
  584.     if (Filcnt==0) {    /* bitch if we couldn't open ANY files */
  585.         if (!Modem && !Nozmodem) {
  586.             Command = TRUE;
  587.             Cmdstr = "echo \"sz: Can't open any requested files\"";
  588.             if (getnak()) {
  589.                 Exitcode=0200; canit();
  590.             }
  591.             if (!Zmodem)
  592.                 canit();
  593.             else if (zsendcmd(Cmdstr, (int)(1+strlen(Cmdstr)))) {
  594.                 Exitcode=0200; canit();
  595.             }
  596.             Exitcode = 1; return OK;
  597.         }
  598.         canit();
  599.         fprintf(STDERR,"\n\nCan't open any requested files.\n\n");
  600.         return ERROR;
  601.     }
  602.     if (Zmodem)
  603.         saybibi();
  604.     else if(!Modem)
  605.         wctxpn("");
  606.     return OK;
  607. }
  608.  
  609. int wcs(oname)
  610. char *oname;
  611. {
  612.     extern struct stat statbuf;
  613.     char name[PATHLEN];
  614.  
  615.     strcpy(name, oname);
  616.  
  617.     /* Check for directory or block special files */
  618.     if(Fsfirst(name,(int)(0x01 | 0x010 | 0x020)) != 0)
  619.     {
  620.         ++errcnt;
  621.         return OK;    /* may be others */
  622.     }
  623.  
  624.     if (statbuf.st_mode & S_IFDIR ) {
  625.         return OK;
  626.     }
  627.  
  628.     if((in = stfopen(oname,"r")) <= 0){
  629.         ++errcnt;
  630.         return OK;    /* pass over it, there may be others */
  631.     }
  632.     BEofseen = Eofseen = 0;  vpos = 0;
  633.  
  634.     ++Filcnt;
  635.     switch (wctxpn(name)) {
  636.     case ERROR:
  637.         return ERROR;
  638.     case ZSKIP:
  639.         return OK;
  640.     }
  641.     if (!Zmodem && wctx(statbuf.st_size)==ERROR)
  642.         return ERROR;
  643.     if (Unlinkafter)
  644.         unlink(oname);
  645.     return 0;
  646. }
  647.  
  648. #define ISDRIVE(X) ( (((X >= 'a') && (X <= 'n'))) || ((X >= 'A') && (X <= 'N')))
  649. /*
  650.  * generate and transmit pathname block consisting of
  651.  *  pathname (null terminated),
  652.  *  file length, mode time and file mode in octal
  653.  *  as provided by the St's Fsfirst() call.
  654.  *  N.B.: modifies the passed name, may extend it!
  655.  */
  656. static long start_time;
  657.  
  658. int wctxpn(name)
  659. char *name;
  660. {
  661.     register char *p, *q;
  662.     char name2[PATHLEN];
  663.     unsigned long unixtime;
  664.     extern struct stat statbuf;
  665.     extern unsigned long st2unix();    /* Convert St's date and time to unix
  666.                    time (seconds since Jan 1 1970 00:00:00) */
  667.     extern void rd_time();
  668.  
  669.     if(*name)
  670.         if(Fsfirst(name,(int)(0x01 | 0x020)) != 0)
  671.             return ERROR;
  672.  
  673.     if (Modem) {
  674. #ifndef REMOTE
  675.         if (*name) {
  676.             fprintf(STDERR,
  677.             "Outgoing:\n\t Name: %s\n\t Size: %ld Bytes\n\
  678. \tBlocks: %ld\n\tBufSize: %ld\n\n",
  679.               name, statbuf.st_size, statbuf.st_size>>7, (long)BBUFSIZ);
  680.         }
  681. #endif /* REMOTE */
  682.         return OK;
  683.     }
  684.  
  685.     vfile2("\r\nAwaiting pathname nak for %s\r\n", *name?name:"<END>");
  686.  
  687.     if ( !Zmodem)
  688.         if (getnak())
  689.             return ERROR;
  690.  
  691.     /* convert to Unix style path names */
  692.     /* skip any device identifier */
  693.     if(ISDRIVE(name[0]) && (name[1] == ':'))
  694.         name = &name[2];
  695.  
  696.     for(p = name; *p != '\0'; p++)
  697.     {
  698.         if(*p == '\\')
  699.             *p = '/';
  700.     }
  701.  
  702.     if(!Resuming)
  703.     {
  704.         if(ForceBin)
  705.         {
  706.             Lzconv = ZCBIN;
  707.             Ascii = FALSE;
  708.         }
  709.         else
  710.         {
  711.             if(!isbinary(name))
  712.             {
  713.                 /* We indicate to the other side */
  714.                 Lzconv = ZCNL;
  715.                 Ascii = TRUE;
  716.             }
  717.             else
  718.             {
  719.                 Lzconv = ZCBIN;
  720.                 Ascii = FALSE;
  721.             }
  722.         }
  723.     }
  724.  
  725.     q = (char *) 0;
  726.     if (Dottoslash) {        /* change . to . */
  727.         for (p=name; *p; ++p) {
  728.             if (*p == '/')
  729.                 q = p;
  730.             else if (*p == '.')
  731.                 *(q=p) = '/';
  732.         }
  733.         if (q && (int)strlen(++q) > 8) {    /* If name>8 chars */
  734.             q += 8;            /*   make it .ext */
  735.             strcpy(name2, q);    /* save excess of name */
  736.             *q = '.';
  737.             strcpy(++q, name2);    /* add it back */
  738.         }
  739.     }
  740.  
  741.     for (p=name, q=txbuf ; *p; )
  742.         if ((*q++ = *p++) == '/' && !Fullname)
  743.             q = txbuf;
  744.     *q++ = 0;
  745.     p=q;
  746.     while (q < (txbuf + KSIZE))
  747.         *q++ = 0;
  748.     if (*name)
  749.     {
  750.         unixtime = st2unix(statbuf.st_time, statbuf.st_date);
  751.         sprintf(p, "%lu %lo %o %d %ld", statbuf.st_size,
  752.             unixtime,
  753.              ((statbuf.st_mode & 0x01)?0444:0644),
  754.             Filesleft, Totalleft);
  755.         Totalleft -= statbuf.st_size;
  756.     }
  757.  
  758.     if(Zmodem)
  759.     {
  760.         Supexec(rd_time);
  761.         start_time = pr_time;
  762.     }
  763.  
  764.     if(Verbose)
  765. #ifndef REMOTE
  766.         fprintf(STDERR,
  767. "Outgoing: [Hit CTRL-C to Cancel]\n\tName: %s\n\tSize: %ld Bytes\n\tBufSize:\
  768.  %ld\n",
  769.             name, statbuf.st_size, (long)BBUFSIZ);
  770.     if(!Resuming)
  771.     {
  772.         fprintf(STDERR,"\tMode: %s\n\n", (Ascii)?"ASCII":"BINARY");
  773.     }
  774.     else
  775.     {
  776.         fprintf(STDERR,"\tMode: Resume Transfer Mode\n\n");
  777.     }
  778. #endif
  779.  
  780. #ifdef SDEBUG
  781.     if(Verbose > 2)
  782.     {
  783.         fprintf(STDERR,"File: %s (%s)\n", name, p);
  784.         fprintf(logf,"File: %s (%s)\n", name, p);
  785.         fflush(logf);
  786.     }
  787. #endif
  788.  
  789.     if (--Filesleft <= 0)
  790.         Totalleft = 0;
  791.     if (Totalleft < 0)
  792.         Totalleft = 0;
  793.  
  794.     /* force 1k blocks if name won't fit in 128 byte block */
  795.     if (txbuf[125])
  796.         Blklen=KSIZE;
  797.     else {        /* A little goodie for IMP/KMD */
  798.         txbuf[127] = (statbuf.st_size + 127) >>7;
  799.         txbuf[126] = (statbuf.st_size + 127) >>15;
  800.     }
  801.  
  802.     if (Zmodem)
  803.         return zsendfile(txbuf, (int)(1+strlen(p)+ 
  804.                 (int)((long)p-(long)txbuf)), statbuf.st_size);
  805.     if (wcputsec(txbuf, 0, SECSIZ)==ERROR)
  806.         return ERROR;
  807.     return OK;
  808. }
  809.  
  810. int getnak()
  811. {
  812.     register int firstch;
  813.  
  814.     Lastrx = 0;
  815.     for (;;) {
  816.         switch (firstch = readock(800)) {
  817.         case ZPAD:
  818.             if (getzrxinit())
  819.                 return ERROR;
  820.             Ascii = 0;
  821.             return FALSE;
  822.         case TIMEOUT:
  823.             vfile("Timeout on pathname\n");
  824.             return TRUE;
  825.         case WANTG:
  826. #ifdef USG
  827.             mode(2);    /* Set cbreak, XON/XOFF, etc. */
  828. #endif
  829.             Optiong = TRUE;
  830.             Blklen=KSIZE;
  831.         case WANTCRC:
  832.             Crcflg = TRUE;
  833.         case NAK:
  834.             return FALSE;
  835.         case CAN:
  836.             if ((firstch = readock(20)) == CAN && Lastrx == CAN)
  837.                 return TRUE;
  838.         default:
  839.             break;
  840.         }
  841.         Lastrx = firstch;
  842.     }
  843. }
  844.  
  845.  
  846. int wctx(flen)
  847. long flen;
  848. {
  849.         int thisblklen;
  850.     register int sectnum, attempts, firstch;
  851.     long charssent;
  852.  
  853.     charssent = 0;
  854.     Firstsec=TRUE;
  855.     thisblklen = Blklen;
  856.     
  857.     while ((firstch=readock(Rxtimeout))!=NAK && firstch != WANTCRC
  858.       && firstch != WANTG && firstch!=TIMEOUT && firstch!=CAN)
  859.         ;
  860.     if (firstch==CAN) {
  861.         fprintf(STDERR, "\r\nReceiver CANcelled\n");
  862.         return ERROR;
  863.     }
  864.     if (firstch==WANTCRC)
  865.         Crcflg=TRUE;
  866.     if (firstch==WANTG)
  867.         Crcflg=TRUE;
  868.     sectnum=0;
  869.     for (;;) {
  870.         if (flen <= (charssent + 896L))
  871.             thisblklen = 128;
  872.         if ( !filbuf(txbuf, thisblklen))
  873.             break;
  874.         if (wcputsec(txbuf, ++sectnum, thisblklen)==ERROR)
  875.             return ERROR;
  876.         charssent += thisblklen;
  877.     }
  878.  
  879. #ifndef REMOTE
  880.     if (Verbose>1)
  881.     {
  882.         fprintf(STDERR, "\nClosing\n\n");
  883. #ifdef SDEBUG
  884.         if(Verbose > 2)
  885.         {
  886.             fprintf(logf, " Closing\n");
  887.             fflush(logf);
  888.         }
  889. #endif
  890.     }
  891. #endif /* REMOTE */
  892.  
  893.     stfclose(in);
  894.     in = (-1);
  895.  
  896.     attempts=0;
  897.     do {
  898.         vfile(" EOT ");
  899.         purgeline();
  900.         sendline(EOT);
  901.         flush_modem();
  902.         ++attempts;
  903.     }
  904.         while ((firstch=(readock(Rxtimeout)) != ACK) && attempts < RETRYMAX);
  905.     if (attempts == RETRYMAX) {
  906.         fprintf(STDERR, "\r\nNo ACK on EOT\n");
  907.         return ERROR;
  908.     }
  909.     else
  910.         return OK;
  911. }
  912.  
  913. int wcputsec(buf, sectnum, cseclen)
  914. char *buf;
  915. int sectnum;
  916. int cseclen;    /* data length of this sector to send */
  917. {
  918.     register int checksum, wcj;
  919.     register char *cp;
  920.     unsigned int oldcrc;
  921.     int firstch;
  922.     int attempts;
  923.  
  924.     firstch=0;    /* part of logic to detect CAN CAN */
  925.  
  926. #ifndef REMOTE
  927.     if (Verbose>1)
  928.     {
  929.         fprintf(STDERR, "\rBlock %06d  %04dK ", Totsecs, (Totsecs>>3));
  930. #ifdef SDEBUG
  931.         if(Verbose > 2)
  932.         {
  933.             fprintf(logf, "\rBlock %d %dK ", Totsecs, (Totsecs>>3) );
  934.             fflush(logf);
  935.         }
  936. #endif
  937.     }
  938. #endif /* REMOTE */
  939.  
  940.     for (attempts=0; attempts <= RETRYMAX; attempts++) {
  941.         Lastrx= firstch;
  942.         sendline(cseclen==KSIZE?STX:SOH);
  943.         sendline(sectnum);
  944.         sendline(-sectnum -1);
  945.         oldcrc=checksum=0;
  946.         for (wcj=cseclen,cp=buf; --wcj>=0; ) {
  947.             sendline(*cp);
  948.             oldcrc=updcrc((0377& *cp), oldcrc);
  949.             checksum += *cp++;
  950.         }
  951.         if (Crcflg) {
  952.             oldcrc=updcrc(0,updcrc(0,oldcrc));
  953.             sendline((int)oldcrc>>8);
  954.             sendline((int)oldcrc);
  955.         }
  956.         else
  957.             sendline(checksum);
  958.         flush_modem();
  959.         
  960.         if (Optiong) {
  961.             Firstsec = FALSE; return OK;
  962.         }
  963.         firstch = readock(Rxtimeout);
  964. gotnak:
  965.         switch (firstch) {
  966.         case CAN:
  967.             if(Lastrx == CAN) {
  968. cancan:
  969.                 fprintf(STDERR, "\r\nCancelled\n");  return ERROR;
  970.             }
  971.             break;
  972.         case TIMEOUT:
  973.             vfile("Timeout on sector ACK\n"); continue;
  974.         case WANTCRC:
  975.             if (Firstsec)
  976.                 Crcflg = TRUE;
  977.         case NAK:
  978.             vfile("NAK on sector\n"); continue;
  979.         case ACK: 
  980.             Firstsec=FALSE;
  981.             Totsecs += (cseclen>>7);
  982.             return OK;
  983.         case ERROR:
  984.             vfile("Got burst for sector ACK\n"); break;
  985.         default:
  986.             vfile("Got %02x for sector ACK\n", firstch); break;
  987.         }
  988.         for (;;) {
  989.             Lastrx = firstch;
  990.             if ((firstch = readock(Rxtimeout)) == TIMEOUT)
  991.                 break;
  992.             if (firstch == NAK || firstch == WANTCRC)
  993.                 goto gotnak;
  994.             if (firstch == CAN && Lastrx == CAN)
  995.                 goto cancan;
  996.         }
  997.     }
  998.     fprintf(STDERR, "\r\nRetry Count Exceeded\n");
  999.     return ERROR;
  1000. }
  1001.  
  1002. /* fill buf with count chars padding with ^Z for CPM */
  1003. int filbuf(buf, count)
  1004. register unsigned char *buf;
  1005. register int count;
  1006. {
  1007.     register int m, c;
  1008.  
  1009.     if(!Ascii)
  1010.     {
  1011.         m = (int)stread(in, buf, (long)count);
  1012.         if(m <= 0)
  1013.         return 0;
  1014.         while (m < count)
  1015.         buf[m++] = 032;
  1016.         return count;
  1017.     }
  1018.     m=count;
  1019.     if (Lfseen) {
  1020.         *buf++ = 012; --m; Lfseen = 0;
  1021.     }
  1022.     while ((c=stgetc(in))!=EOF) {
  1023.         if (c == 012) {
  1024.             *buf++ = 015;
  1025.             if (--m == 0) {
  1026.                 Lfseen = TRUE; break;
  1027.             }
  1028.         }
  1029.         *buf++ =c;
  1030.         if (--m == 0)
  1031.             break;
  1032.     }
  1033.     if (m==count)
  1034.         return 0;
  1035.     else
  1036.         while (--m>=0)
  1037.             *buf++ = CPMEOF;
  1038.     return count;
  1039. }
  1040.  
  1041. /* fill buf with count chars */
  1042. int zfilbuf()
  1043. {
  1044.     int n, c;
  1045.  
  1046. #ifdef SDEBUG
  1047.     vfile("zfilbuf: bytcnt =%lu vpos=%lu blklen=%d", bytcnt, vpos, Blklen);
  1048. #endif
  1049.     /* We assume request is within buffer, or just beyond */
  1050.     txbuf = secbuf + (bytcnt & TXBMASK);
  1051.     if (vpos <= bytcnt) {
  1052.         for (n=0; n<Blklen; n++)
  1053.         if ((c = stgetc(in)) == EOF)
  1054.             break;
  1055.         else
  1056.             txbuf[n] = c;
  1057.         vpos += n;
  1058.         if (n < Blklen)
  1059.         Eofseen = 1;
  1060. #ifdef SDEBUG
  1061.         vfile("zfilbuf: n=%d vpos=%lu Eofseen=%d", n, vpos, Eofseen);
  1062. #endif
  1063.         return n;
  1064.     }
  1065.     if (vpos >= (bytcnt+Blklen))
  1066.         return Blklen;
  1067.     /* May be a short block if crash recovery etc. */
  1068.     Eofseen = BEofseen;
  1069.     return (vpos - bytcnt);
  1070. }
  1071.  
  1072. int fooseek(fptr, pos, whence)
  1073. int fptr;
  1074. long pos;
  1075. int whence;
  1076. {
  1077.     long m, n;
  1078.  
  1079. #ifdef SDEBUG
  1080.     vfile("fooseek: pos =%lu vpos=%lu Canseek=1", pos, vpos);
  1081. #endif
  1082.     /* Seek offset < current buffer */
  1083.     if (pos < (vpos -TXBSIZE +1024)) {
  1084.         BEofseen = 0;
  1085.         if (1) {
  1086.             vpos = pos & ~TXBMASK;
  1087.             if (vpos >= pos)
  1088.                 vpos -= TXBSIZE;
  1089.             if (stfseek(fptr, vpos, 0))
  1090.                 return 1;
  1091.         }
  1092.         while (vpos < pos) {
  1093.             n = (int)stread(fptr, secbuf, (long)TXBSIZE);
  1094.             vpos += n;
  1095. #ifdef SDEBUG
  1096.             vfile("n=%d vpos=%ld", n, vpos);
  1097. #endif
  1098.             if (n < TXBSIZE) {
  1099.             BEofseen = 1;
  1100.             break;
  1101.             }
  1102.         }
  1103.         return 0;
  1104.     }
  1105.     /* Seek offset > current buffer (Crash Recovery, etc.) */
  1106.     if (pos > vpos) {
  1107.         if (1)
  1108.             if (stfseek(fptr, vpos = (pos & ~TXBMASK), 0))
  1109.                 return 1;
  1110.         while (vpos <= pos) {
  1111.             txbuf = secbuf + (vpos & TXBMASK);
  1112.             m = TXBSIZE - (vpos & TXBMASK);
  1113.             n = (int)stread(fptr, txbuf, (long)m);
  1114.             vpos += n;
  1115.             if (n < m) {
  1116.                 BEofseen = 1;
  1117.                 break;
  1118.             }
  1119.         }
  1120.         return 0;
  1121.     }
  1122.     /* Seek offset is within current buffer */
  1123.     return 0;
  1124. }
  1125. #define fseek fooseek
  1126.  
  1127. /*
  1128.  * readock(timeout) reads character(s) from file descriptor 0
  1129.  * timeout is in tenths of seconds
  1130.  */
  1131. readock(timeout)
  1132. int timeout;
  1133. {
  1134.     register int c;
  1135.     static char byt;
  1136.  
  1137.     if (setjmp(tohere)) {
  1138.         vfile("TIMEOUT\n");
  1139.         return TIMEOUT;
  1140.     }
  1141.     c = timeout >> 3;
  1142.     if (c<2)
  1143.         c=2;
  1144. #ifdef SDEBUG
  1145.     if (Verbose>3) {
  1146.         fprintf(STDERR, "Timeout=%d Calling alarm(%d) ", timeout, c);
  1147.         byt[1] = 0;
  1148.         fprintf(logf, "Timeout=%d Calling alarm(%d) ", timeout, c);
  1149.         fflush(logf);
  1150.  
  1151.     }
  1152. #endif
  1153.     stalarm(c);
  1154.     c=read_modem(&byt, 1);
  1155.  
  1156.     stalarm(0);
  1157. #ifdef SDEBUG
  1158.     if (Verbose>5)
  1159.     {
  1160.         fprintf(STDERR, "ret cnt=%d %x\n", c, byt);
  1161.         fprintf(logf, "ret cnt=%d %x\n", c, byt);
  1162.         fflush(logf);
  1163.     }
  1164. #endif
  1165.  
  1166.     if (c<1)
  1167.         return TIMEOUT;
  1168.     return (byt&0377);
  1169. }
  1170.  
  1171. int susage()
  1172. {
  1173.     fprintf(STDERR,"\nSend file(s) with ZMODEM/YMODEM/XMODEM Protocol\n");
  1174.     fprintf(STDERR,"    (Y) = Option applies to YMODEM only\n");
  1175.     fprintf(STDERR,"    (Z) = Option applies to ZMODEM only\n");
  1176.     fprintf(STDERR,
  1177.     "%s for %s by ST Enthusiasts at Case Western Reserve University\n",
  1178.        SSTVERSION, STOS);
  1179.     fprintf(STDERR,"\tBased on %s for %s by Chuck Forsberg\n\n", SVERSION, OS);
  1180. /*    fprintf(STDERR,"Usage:    sz [-12+adefknquvXy] [-] file ...\n"); */
  1181.     fprintf(STDERR,"Usage:    sz [-+defknquvXyBwZ] file ...\n");
  1182. /*    fprintf(STDERR,"    sz [-1eqv] -c COMMAND\n"); */
  1183.     fprintf(STDERR,"    sz [-eqv] -c COMMAND\n");
  1184.     fprintf(STDERR,"    sb [-dfkquv] [-] file ...\n");
  1185.     fprintf(STDERR,"    sx [-kquv] [-] file\n");
  1186.  
  1187. /*    fprintf(STDERR,"    1 Use stdout for modem input\n"); */
  1188. #ifdef CSTOPB
  1189.     fprintf(STDERR,"    2 Use 2 stop bits\n");
  1190. #endif
  1191.     fprintf(STDERR,"    + Append to existing destination file (Z)\n");
  1192. /*    fprintf(STDERR,"    a (ASCII) change NL to CR/LF\n"); */
  1193.     fprintf(STDERR,"    c send COMMAND (Z)\n");
  1194.     fprintf(STDERR,"    d Change '.' to '/' in pathnames (Y/Z)\n");
  1195.     fprintf(STDERR,"    e Escape control characters (Z)\n");
  1196.     fprintf(STDERR,"    f send Full pathname (Y/Z)\n");
  1197.     fprintf(STDERR,"    i send COMMAND, ack Immediately (Z)\n");
  1198.     fprintf(STDERR,"    k Send 1024 byte packets (Y)\n");
  1199.     fprintf(STDERR,"    L N Limit packet length to N bytes (Z)\n");
  1200.     fprintf(STDERR,"    l N Limit frame length to N bytes (l>=L) (Z)\n");
  1201.     fprintf(STDERR,"    n send file if Newer (Z)\n");
  1202.     fprintf(STDERR,"    N send file if Newer or Longer (Z)\n");
  1203.     fprintf(STDERR, "    o Use 16 bit CRC instead of 32 bit CRC (Z)\n");
  1204.     fprintf(STDERR,"    p Protect existing destination file (Z)\n");
  1205.     fprintf(STDERR,"    r Resume/Recover interrupted file transfer (Z)\n");
  1206.     fprintf(STDERR,"    q Quiet (no progress reports)\n");
  1207.     fprintf(STDERR,"    u Unlink file after transmission\n");
  1208.     fprintf(STDERR,"    v Verbose - debugging information\n");
  1209.     fprintf(STDERR,"    X XMODEM protocol - send no pathnames\n");
  1210.     fprintf(STDERR,"    y Yes, overwrite existing file (Z)\n");
  1211.     fprintf(STDERR,"    B Force Binary mode transfers (Z)\n");
  1212.     fprintf(STDERR,"    w N Window is N bytes (Z)\n");
  1213.     fprintf(STDERR,"    Z   Activate ZMODEM compression(Z)\n");
  1214. /*    fprintf(STDERR,
  1215. "- as pathname sends standard input as sPID.sz or environment ONAME\n"); */
  1216.     return(1);
  1217. }
  1218.  
  1219. /*
  1220.  * Get the receiver's init parameters
  1221.  */
  1222. int getzrxinit()
  1223. {
  1224.     register int n;
  1225.  
  1226.     for (n=10; --n>=0; ) {
  1227.         
  1228.         switch (zgethdr(Rxhdr, 1)) {
  1229.         case ZCHALLENGE:    /* Echo receiver's challenge numbr */
  1230.             stohdr(Rxpos);
  1231.             zshhdr(4, ZACK, Txhdr);
  1232.             continue;
  1233.         case ZCOMMAND:        /* They didn't see out ZRQINIT */
  1234.             stohdr(0L);
  1235.             zshhdr(4, ZRQINIT, Txhdr);
  1236.             continue;
  1237.         case ZRINIT:
  1238.             Rxflags = 0377 & Rxhdr[ZF0];
  1239.             Usevhdrs = Rxhdr[ZF1] & CANVHDR;
  1240.              Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32));
  1241.  
  1242.             Zctlesc |= Rxflags & TESCCTL;
  1243.             Rxbuflen = 
  1244.                 ((unsigned)0337 & (unsigned)Rxhdr[ZP0])+
  1245.                 (((unsigned)0377 & (unsigned)Rxhdr[ZP1])<<8); 
  1246.             if ( !(Rxflags & CANFDX))
  1247.                 Txwindow = 0;
  1248.             vfile("Rxbuflen=%d Tframlen=%d", Rxbuflen, Tframlen);
  1249.             siggi = 0;
  1250. #ifndef READCHECK
  1251. #ifdef USG
  1252.             mode(2);    /* Set cbreak, XON/XOFF, etc. */
  1253. #else
  1254. #if 0
  1255.             /* Use 1024 byte frames if no sample/interrupt */
  1256.             if (Rxbuflen < 32 || Rxbuflen > 1024) {
  1257.                 Rxbuflen = 1024;
  1258.                 vfile("Rxbuflen=%d", Rxbuflen);
  1259.             }
  1260. #endif
  1261. #endif
  1262. #endif
  1263.             /* Override to force shorter frame length */
  1264.             if (Rxbuflen && (Rxbuflen>Tframlen) && (Tframlen>=32))
  1265.                 Rxbuflen = Tframlen;
  1266.             if ( !Rxbuflen && (Tframlen>=32) && (Tframlen<=1024))
  1267.                 Rxbuflen = Tframlen;
  1268.             vfile("Rxbuflen=%d", Rxbuflen);
  1269. #if 0
  1270.             /*
  1271.              * If input is not a regular file, force ACK's each 1024
  1272.              *  (A smarter strategey could be used here ...)
  1273.              */
  1274.             if (Rxbuflen && (Rxbuflen > 1024))
  1275.                 Rxbuflen = 1024;
  1276.             vfile("Rxbuflen=%d", Rxbuflen);
  1277. #endif
  1278.             /* Set initial subpacket length */
  1279.             if (Blklen < 1024) {    /* Command line override? */
  1280.                 if (Baudrate > 110)
  1281.                     Blklen = 256;
  1282.                 if (Baudrate > 1200)
  1283.                     Blklen = 1024;
  1284.             }
  1285.             if (Rxbuflen && Blklen>Rxbuflen)
  1286.                 Blklen = Rxbuflen;
  1287.             if (blkopt && Blklen > blkopt)
  1288.                 Blklen = blkopt;
  1289.  
  1290.             if (Lztrans == ZTRLE && (Rxflags & CANRLE))
  1291.                 Txfcs32 = 2;
  1292.             else
  1293.                 Lztrans = 0;
  1294.  
  1295.             return (sendzsinit());
  1296.         case ZCAN:
  1297.         case TIMEOUT:
  1298.             return ERROR;
  1299.         case ZRQINIT:
  1300.             if (Rxhdr[ZF0] == ZCOMMAND)
  1301.                 continue;
  1302.         default:
  1303.             zshhdr(4, ZNAK, Txhdr);
  1304.             continue;
  1305.         }
  1306.     }
  1307.     return ERROR;
  1308. }
  1309.  
  1310. /* Send send-init information */
  1311. int sendzsinit()
  1312. {
  1313.     register int c;
  1314.     register int errors;
  1315.     
  1316.     if (Myattn[0] == '\0' && (!Zctlesc || (Rxflags & TESCCTL)))
  1317.         return OK;
  1318.  
  1319.     errors = 0;
  1320.     for (;;) {
  1321.         stohdr(0L);
  1322. #ifdef ALTCANOFF
  1323.         Txhdr[ALTCOFF] = ALTCANOFF;
  1324. #endif
  1325.         if (Zctlesc) {
  1326.             Txhdr[ZF0] |= TESCCTL; zshhdr(4, ZSINIT, Txhdr);
  1327.         }
  1328.         else
  1329.             zsbhdr(4, ZSINIT, Txhdr);
  1330.         zsdata(Myattn, (int)(1+strlen(Myattn)), ZCRCW);
  1331.         c = zgethdr(Rxhdr, 1);
  1332.         switch (c) {
  1333.         case ZCAN:
  1334.             return ERROR;
  1335.         case ZACK:
  1336.             return OK;
  1337.         default:
  1338.             if (++errors > 19)
  1339.                 return ERROR;
  1340.             continue;
  1341.         }
  1342.     }
  1343. }
  1344.  
  1345. /* Send file name and related info */
  1346. int zsendfile(buf, blen, szbytes)
  1347. char *buf;
  1348. int blen;
  1349. long szbytes;
  1350. {
  1351.     register int c, szstat;
  1352.     long end_time;
  1353.     register unsigned long crc;
  1354.     extern void rd_time();
  1355.     long lastcrcrq = -1L;
  1356.  
  1357.     Supexec(rd_time);
  1358.     start_time = pr_time;
  1359.     
  1360.     for (;;) {
  1361.         Txhdr[ZF0] = Lzconv;    /* file conversion request */
  1362.         Txhdr[ZF1] = Lzmanag;    /* file management request */
  1363.         if (Lskipnocor)
  1364.             Txhdr[ZF1] |= ZMSKNOLOC;
  1365.         Txhdr[ZF2] = Lztrans;    /* file transport request */
  1366.         Txhdr[ZF3] = 0;
  1367.         zsbhdr(4, ZFILE, Txhdr);
  1368.         zsdata(buf, blen, ZCRCW);
  1369. again:
  1370.         c = zgethdr(Rxhdr, 1);
  1371.         switch (c) {
  1372.         case ZRINIT:
  1373.             while ((c = readock(50)) > 0)
  1374.                 if (c == ZPAD) {
  1375.                     goto again;
  1376.                 }
  1377.             /* **** FALL THRU TO **** */
  1378.         default:
  1379.             continue;
  1380.  
  1381.         case ZCAN:
  1382.         case TIMEOUT:
  1383.         case ZABORT:
  1384.         case ZFIN:
  1385.             return ERROR;
  1386.         case ZCRC:
  1387.             if (Rxpos != lastcrcrq) {
  1388.                 lastcrcrq = Rxpos;
  1389.                 crc = 0xFFFFFFFFL;
  1390.                 if (1) {
  1391.                     fseek(in, 0L, 0);
  1392.                     while (((c = stgetc(in)) != EOF) && --lastcrcrq)
  1393.                         crc = UPDC32(c, crc);
  1394.                     crc = ~crc;
  1395. /*                    clearerr(in);    /* Clear possible EOF */
  1396.                     lastcrcrq = Rxpos;
  1397.                 }
  1398.             }
  1399.             stohdr(crc);
  1400.             zsbhdr(4, ZCRC, Txhdr);
  1401.             goto again;
  1402.         case ZSKIP:
  1403. #ifndef REMOTE
  1404.             fprintf(STDERR,"\n\n");
  1405. #endif
  1406.             stfclose(in); in = (-1); return c;
  1407.         case ZRPOS:
  1408.             if(fseek(in, Rxpos, 0))
  1409.             {
  1410.                 fprintf(STDERR,"\r\nError While Seeking file\n");
  1411.                 return ERROR;
  1412.             }
  1413.             Lastsync = (bytcnt = Txpos = Lrxpos = Rxpos) -1;
  1414.             if((szstat =  zsendfdata()) == OK)
  1415.             {
  1416. #ifndef REMOTE
  1417.                 Supexec(rd_time);
  1418.                 end_time = pr_time;
  1419.                 fprintf(STDERR,"%ld Bytes Sent\t\
  1420. Transfer Time %ld secs.\tApprox %ld cps\n\n", szbytes, (end_time - start_time)/200L,
  1421. szbytes/((end_time - start_time)/200L));
  1422. #endif
  1423.             }
  1424.             return szstat;
  1425.         }
  1426.     }
  1427. }
  1428.  
  1429. static int Beenhereb4;
  1430.  
  1431. /* Send the data in the file */
  1432. int zsendfdata()
  1433. {
  1434.     register int c1, e;
  1435.     register long newcnt;
  1436. #ifdef __GNUC__
  1437.     volatile long tcount = 0;
  1438.     volatile int n;
  1439. #else
  1440.     register int n;
  1441.     register long tcount = 0;
  1442. #endif
  1443.     long ttcount = 0;
  1444.     static int tleft = 6;    /* Counter for test mode */
  1445.     int junkcount;
  1446.     
  1447.     Lrxpos = 0;
  1448.     junkcount = 0;
  1449.     Beenhereb4 = FALSE;
  1450.     
  1451. somemore:
  1452.     if (setjmp(intrjmp)) {
  1453. waitack:
  1454.         junkcount = 0;
  1455.         c1 = getinsync(0);
  1456. gotack:        
  1457.         switch (c1) {
  1458.         default:
  1459.         case ZCAN:
  1460.             fprintf(STDERR,"\r\nReceiver Cancelled Transfer\n\n");
  1461.             stfclose(in);
  1462.             in = (-1);
  1463.             return ERROR;
  1464.         case ZSKIP:
  1465. #ifndef REMOTE
  1466.             fprintf(STDERR,"\r\nReceiver forced SKIP Transfer(1)\n\n");
  1467. #endif
  1468.             stfclose(in);
  1469.             in = (-1);
  1470.             return c1;
  1471.         case ZACK:
  1472.             /* fall thru */
  1473.         case ZRPOS:
  1474.             break;
  1475.         case ZRINIT:
  1476.             return OK;
  1477.         }
  1478.     }
  1479.  
  1480.     siggi = 1;
  1481.     newcnt = Rxbuflen;
  1482.     Txwcnt = 0;
  1483.     stohdr(Txpos);
  1484.     zsbhdr(4, ZDATA, Txhdr);
  1485.  
  1486.     do {
  1487.         n = zfilbuf();
  1488.         tcount += n;
  1489.         lreport(tcount);
  1490.         if (Eofseen)
  1491.             e = ZCRCE;
  1492.         else if (junkcount > 3)
  1493.             e = ZCRCW;
  1494.         else if (bytcnt == Lastsync)
  1495.             e = ZCRCW;
  1496.         else if (Rxbuflen && (newcnt -= n) <= 0)
  1497.                 e = ZCRCW;
  1498.         else if (Txwindow && (Txwcnt += n) >= Txwspac) {
  1499.             Txwcnt = 0;  e = ZCRCQ;
  1500.         } else
  1501.             e = ZCRCG;
  1502.         zsdata(txbuf, n, e);
  1503.         bytcnt = (Txpos += n);
  1504.  
  1505.         if (e == ZCRCW)
  1506.             goto waitack;
  1507.         if (Txwindow) {
  1508.             while ((ttcount = (Txpos - Lrxpos)) >= Txwindow) {
  1509.                 vfile("%ld window >= %u", ttcount, Txwindow);
  1510.                 if (e != ZCRCQ)
  1511.                     zsdata(txbuf, 0, e = ZCRCQ);
  1512.                 c1 = getinsync(1);
  1513.                 if (c1 != ZACK) {
  1514.                     zsdata(txbuf, 0, ZCRCE);
  1515.                     goto gotack;
  1516.                 }
  1517.             }
  1518. /*            vfile("window = %ld", ttcount); */
  1519.         }
  1520.     } while (!Eofseen);
  1521.  
  1522.     siggi = 0;
  1523.     lsct = 1;
  1524.  
  1525.     for (;;) {
  1526.         stohdr(Txpos);
  1527.         zsbhdr(4, ZEOF, Txhdr);
  1528.         switch (getinsync(0)) {
  1529.         case ZACK:
  1530.             continue;
  1531.         case ZRPOS:
  1532.             goto somemore;
  1533.         case ZRINIT:
  1534.             return OK;
  1535.         case ZSKIP:
  1536. #ifndef REMOTE
  1537.             fprintf(STDERR,"\r\nReceiver forced SKIP Transfer(2)\n\n");
  1538. #endif
  1539.             stfclose(in);
  1540.             in = (-1);
  1541.             return c1;
  1542.         default:
  1543.             fprintf(STDERR,"\r\nErrors while Send Data\n\n");
  1544.             stfclose(in);
  1545.             in = (-1);
  1546.             return ERROR;
  1547.         }
  1548.     }
  1549. }
  1550.  
  1551. /*
  1552.  * Respond to receiver's complaint, get back in sync with receiver
  1553.  */
  1554. int getinsync(flag)
  1555. int flag;
  1556. {
  1557.     register int c;
  1558.  
  1559.     for (;;) {
  1560. #ifdef TESTATTN
  1561.         if (Testattn) {
  1562.             wr_modem("\r\n\n\n***** Signal Caught *****\r\n");
  1563.             Rxpos = 0; c = ZRPOS;
  1564.         } else
  1565. #endif
  1566.             c = zgethdr(Rxhdr, 0);
  1567.         switch (c) {
  1568.         case ZCAN:
  1569.         case ZABORT:
  1570.         case ZFIN:
  1571.         case TIMEOUT:
  1572.             return ERROR;
  1573.         case ZRPOS:
  1574.             if (fseek(in, Rxpos, 0))
  1575.                 return ERROR;
  1576.             Eofseen = 0;
  1577.             bytcnt = Lrxpos = Txpos = Rxpos;
  1578.             if (Lastsync == Rxpos) {
  1579.                 if (++Beenhereb4 > 4)
  1580.                     if (Blklen > 32)
  1581.                         Blklen /= 2;
  1582.             }
  1583.             Lastsync = Rxpos;
  1584.             return c;
  1585.         case ZACK:
  1586.             Lrxpos = Rxpos;
  1587.             if (flag || Txpos == Rxpos)
  1588.                 return ZACK;
  1589.             continue;
  1590.         case ZRINIT:
  1591.         case ZSKIP:
  1592. #ifndef REMOTE
  1593.             fprintf(STDERR,"\033K\n\n");
  1594. #endif
  1595.             stfclose(in);
  1596.             in = (-1);
  1597.             return c;
  1598.         case ERROR:
  1599.         default:
  1600.             zsbhdr(4, ZNAK, Txhdr);
  1601.             continue;
  1602.         }
  1603.     }
  1604. }
  1605. /* Say "bibi" to the receiver, try to do it cleanly */
  1606. void  saybibi()
  1607. {
  1608.     for (;;) {
  1609.         stohdr(0L);
  1610.         zsbhdr(4, ZFIN, Txhdr);
  1611.         switch (zgethdr(Rxhdr, 0)) {
  1612.         case ZFIN:
  1613.             sendline('O'); sendline('O'); flush_modem();
  1614.         case ZCAN:
  1615.         case TIMEOUT:
  1616.             return;
  1617.         }
  1618.     }
  1619. }
  1620.  
  1621. /* Send command and related info */
  1622. int zsendcmd(buf, blen)
  1623. char *buf;
  1624. int blen;
  1625. {
  1626.     register int c, errors;
  1627.     long cmdnum;
  1628.  
  1629. /*    cmdnum = getpid(); */
  1630.     cmdnum = 1;    /* A random # */
  1631.     errors = 0;
  1632.     for (;;) {
  1633.         stohdr(cmdnum);
  1634.         Txhdr[ZF0] = Cmdack1;
  1635.         zsbhdr(4, ZCOMMAND, Txhdr);
  1636.         zsdata(buf, blen, ZCRCW);
  1637. listen:
  1638.         Rxtimeout = 100;        /* Ten second wait for resp. */
  1639.         Usevhdrs = 0;        /* Allow rx to send fixed len headers */
  1640.         c = zgethdr(Rxhdr, 1);
  1641.  
  1642.         switch (c) {
  1643.         case ZRINIT:
  1644.             goto listen;
  1645.         case ERROR:
  1646.         case GCOUNT:
  1647.         case TIMEOUT:
  1648.             if (++errors > Cmdtries)
  1649.                 return ERROR;
  1650.             continue;
  1651.         case ZCAN:
  1652.         case ZABORT:
  1653.         case ZFIN:
  1654.         case ZSKIP:
  1655.         case ZRPOS:
  1656.             return ERROR;
  1657.         default:
  1658.             if (++errors > 20)
  1659.                 return ERROR;
  1660.             continue;
  1661.         case ZCOMPL:
  1662.             Exitcode = Rxpos;
  1663.             saybibi();
  1664.             return OK;
  1665.         case ZRQINIT:
  1666.             vfile("******** RZ *******");
  1667. /*            stsystem("rz"); */
  1668.             vfile("******** SZ *******");
  1669.             goto listen;
  1670.         }
  1671.     }
  1672. }
  1673.  
  1674.  
  1675. #ifndef STANDALONE
  1676. /*
  1677.  * If called as sb use YMODEM protocol
  1678.  */
  1679. void schkinvok(s)
  1680. char *s;
  1681. {
  1682.     if (s[0]=='s' && s[1]=='b') {
  1683.         Nozmodem = TRUE; Blklen=KSIZE;
  1684.     }
  1685.     if (s[0]=='s' && s[1]=='x') {
  1686.         Modem = TRUE;
  1687.     }
  1688. }
  1689. #endif
  1690.  
  1691. static void countem(argc, argv)
  1692. int argc;
  1693. char **argv;
  1694. {
  1695.     register c;
  1696.     extern struct stat statbuf;
  1697.     
  1698.     for (Totalleft = 0, Filesleft = 0; --argc >=0; ++argv)
  1699.     {
  1700.     /* Check for directory or block special files */
  1701.     if(Fsfirst(*argv,(int)(0x01 | 0x010 | 0x020)) != 0)
  1702.         continue;
  1703.     
  1704.     if (statbuf.st_mode & S_IFDIR )
  1705.         continue;
  1706.     
  1707.     ++Filesleft;  Totalleft += statbuf.st_size;
  1708.     }
  1709. }
  1710.  
  1711. /* -eof- */
  1712.