home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume23 / xmodem3.9 / part02 / send.c < prev    next >
C/C++ Source or Header  |  1991-01-08  |  12KB  |  430 lines

  1. /**  send a file  **/
  2.  
  3. /*
  4.  * Operation of this routine depends on on MDM7BAT and YMDMBAT flags.
  5.  *
  6.  * If "name" is NULL; close out the BATCH send.
  7.  */
  8.  
  9. #include "xmodem.h"
  10.  
  11. sfile(name)
  12. char *name;
  13.     {
  14.  
  15.     char *sectdisp();
  16.     time_t time();
  17.     char *strcpy();
  18.     char *unix_cpm();
  19.     char *cpmify();
  20.     long countnl();
  21.  
  22.     extern unsigned short crctab[1<<B];    /* CRC-16 constant values, see getput.c */
  23.  
  24.     register int bufctr,         /* array index for data buffer */
  25.     sectnum;            /* packet number for packet header */
  26.  
  27.     register unsigned short checksum;     /* checksum/crc */
  28.  
  29.     char blockbuf[BBUFSIZ+6];    /* holds packet as it is constructed */
  30.  
  31.     struct stat filestatbuf;    /* file status info */
  32.  
  33.     int fd,         /* file descriptor for file being transmitted */
  34.     attempts,        /* number of attempts made to transmit a packet */
  35.     nlflag,         /* flag that we have to send a LF in next packet */
  36.     sendfin,         /* flag that we are sending the last packet */
  37.     closeout,        /* flag that we are closing out batch send */
  38.     startup,        /* flag that we are starting batch send */
  39.     tmode,            /* TRUE for text mode */
  40.     amode,            /* TRUE for apple mode */
  41.     filepack,        /* TRUE when sending first packet */
  42.     buf1024,        /* TRUE when sending 1K packets */
  43.     bbufcnt,        /* array index for packet */
  44.     firstchar,        /* first character in protocol transaction */
  45.     bufsize,        /* packet size (128 or 1024) */
  46.     sendresp;          /* response char to sent block received from remote*/
  47.     long sentsect;        /* count of 128 byte sectors actually sent */
  48.     long expsect;        /* count of 128 byte sectors expected to be sent */
  49.     time_t start;        /* starting time of transfer */
  50.     char c;
  51.  
  52.     nbchr = 0;  /* clear buffered read char count */
  53.  
  54.     CRCMODE = FALSE;    /* Receiver determines use of crc or checksum */
  55.     YMODEMG = FALSE;    /* Receiver determines use YMODEM-G */
  56.  
  57.     buf1024 = LONGPACK;    /* set packet size flag to command line switch */
  58.  
  59.     closeout = FALSE; startup = TRUE; filepack = FALSE;    /* indicate state of batch transfer */
  60.  
  61.     tmode = (XMITTYPE == 't') ? TRUE : FALSE;    /* set text mode */
  62.     amode = (XMITTYPE == 'a') ? TRUE : FALSE;    /* set apple mode */
  63.  
  64.     /* Check on NULL file name */
  65.     if (strcmp(name,"") == 0)
  66.         {
  67.         if (BATCH)
  68.             closeout = TRUE;
  69.         else
  70.             {
  71.             sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
  72.             error("NULL file name in send", TRUE);
  73.             }
  74.         }
  75.  
  76.     if (!closeout)        /* Are we closing down batch? */
  77.         {            /* no; let's send a file */
  78.         logit("----\nXMODEM Send Function\n");
  79.         tlogit("----\nXMODEM Send Function\n");
  80.  
  81.         if ((fd = open(name, 0)) < 0)    
  82.             {  
  83.             sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
  84.                     error("Can't open file for send", TRUE);
  85.             }
  86.     
  87.         stat(name, &filestatbuf);  /* get file status bytes */
  88.         if (tmode)           /* count up NLs */
  89.             filestatbuf.st_size += countnl(fd);
  90.         expsect = (filestatbuf.st_size/128) + 1;
  91.     
  92.         if (LOGFLAG)
  93.             {   
  94.                 fprintf(LOGFP, "File Name: %s\n", name);
  95.               fprintf(LOGFP,"File Size %ldK, %ld Records, %ld Bytes\n",
  96.                 (filestatbuf.st_size/1024)+1, expsect, filestatbuf.st_size);
  97.             projtime(expsect, LOGFP);
  98.             }
  99.         if (TIPFLAG)
  100.             {
  101.                 fprintf(stderr, "File Name: %s\n", name);
  102.               fprintf(stderr,"File Size %ldK, %ld Records, %ld Bytes\n",
  103.               (filestatbuf.st_size/1024)+1, expsect, filestatbuf.st_size);
  104.             projtime(expsect, stderr);
  105.             }
  106.         }
  107.     else
  108.         {
  109.         logit("----\nXMODEM Send Function\n");
  110.         logit("Closing down Batch Transmission\n");
  111.         tlogit("Closing down Batch Transmission\n");
  112.         }
  113.  
  114.  
  115.     bufsize = buf1024 ? 1024 : 128;        /* set sector size */
  116.     if (buf1024 && !closeout)
  117.         {
  118.         logit("1K packet mode chosen on command line\n");
  119.         tlogit("1K packet mode chosen on command line\n");
  120.         }
  121.  
  122.         sendfin = nlflag = FALSE;
  123.       attempts = 0;
  124.  
  125.     /* wait for and read startup character */
  126. restart:
  127.     do
  128.         {
  129.         while (((firstchar=readbyte(1)) != NAK) && (firstchar != CRCCHR) && (firstchar != GCHR) && (firstchar != CAN))
  130.             if (++attempts > NAKMAX)
  131.                 {
  132.                 if (MDM7BAT && startup)
  133.                     {
  134.                     sendbyte(ACK); sendbyte(EOT);
  135.                     }
  136.                 error("Remote System Not Responding", TRUE);
  137.                 }
  138.  
  139.         if ((firstchar & 0x7f) == CAN)
  140.             if (readbyte(3) == CAN)
  141.                 error("Send Canceled by CAN-CAN",TRUE);
  142.  
  143.         if (firstchar == GCHR)
  144.             {
  145.             CRCMODE = TRUE;
  146.             YMODEMG = TRUE;
  147.             CANCAN = TRUE;
  148.             if (!closeout)
  149.                 {
  150.                 logit("Receiver invoked YMODEM-G and CRC modes\n");
  151.                 tlogit("Receiver invoked YMODEM-G and CRC modes\n");
  152.                 }
  153.             }
  154.         if (firstchar == CRCCHR)
  155.             {
  156.             CRCMODE = TRUE;
  157.             if (!closeout)
  158.                 {
  159.                 logit("Receiver invoked CRC mode\n");
  160.                 tlogit("Receiver invoked CRC mode\n");
  161.                 }
  162.             if (readbyte(1) == KCHR)
  163.                 {
  164.                 buf1024 = TRUE;
  165.                 logit("Receiver invoked 1K packet mode\n");
  166.                 tlogit("Receiver invoked 1K packet mode\n");
  167.                 }
  168.             }
  169.         }
  170.     while (firstchar != NAK && firstchar != CRCCHR && firstchar != GCHR);
  171.  
  172.     if (MDM7BAT && closeout)    /* close out MODEM7 batch */
  173.         {
  174.         sendbyte(ACK); sendbyte (EOT);
  175.         flushin(); readbyte(2);     /* flush junk */
  176.         return;
  177.         }
  178.  
  179.     if (MDM7BAT && startup)        /* send MODEM7 file name */
  180.         {
  181.         if (send_name(unix_cpm(name)) == -1)
  182.             {
  183.             attempts = 0;
  184.             goto restart;
  185.             }
  186.         startup = FALSE;
  187.         attempts = 0;
  188.         goto restart;
  189.         }
  190.  
  191.     sectnum = 1;
  192.  
  193.     if (YMDMBAT)    /* Fudge for YMODEM transfer (to send name packet) */
  194.         {
  195.         sectnum = 0;
  196.         bufsize = 128;
  197.         filepack = TRUE;
  198.         }
  199.  
  200.     attempts = sentsect = 0;
  201.     start = time((time_t *) 0);
  202.  
  203.         do             /* outer packet building/sending loop; loop till whole file is sent */
  204.         {   
  205.  
  206.         if (closeout && YMDMBAT && sectnum == 1)    /* close out YMODEM */
  207.             return;
  208.  
  209.         if (YMDMBAT && sectnum == 1)            /* get set to send YMODEM data packets */
  210.             {
  211.             bufsize = buf1024 ? 1024 : 128;
  212.  
  213.             do        /* establish handshaking again */
  214.                 {
  215.                 while (((firstchar=readbyte(2)) != CRCCHR) && (firstchar != GCHR) && (firstchar != NAK) && (firstchar != CAN))
  216.                     if (++attempts > ERRORMAX)
  217.                         error("YMODEM protocol botch, C or G expected", TRUE);
  218.                 if ((firstchar&0x7f) == CAN)
  219.                     if (readbyte(3) == CAN)
  220.                         error("Send Canceled by CAN-CAN", TRUE);
  221.                 }
  222.             while ((firstchar != CRCCHR) &&  (firstchar != GCHR) && (firstchar != NAK));
  223.  
  224.             attempts = 0;
  225.             }
  226.  
  227.         if ((bufsize == 1024) && (attempts > KSWMAX))
  228.             {
  229.             logit("Reducing packet size to 128 due to excessive errors\n");
  230.             tlogit("Reducing packet size to 128 due to excessive errors\n");
  231.             bufsize = 128;
  232.             }
  233.  
  234.         if ((bufsize == 1024) && ((expsect - sentsect) < 8))
  235.             {
  236.             logit("Reducing packet size to 128 for tail end of file\n");
  237.             tlogit("Reducing packet size to 128 for tail end of file\n");
  238.             bufsize = 128;
  239.             }
  240.  
  241.         if (sectnum > 0)    /* data packet */
  242.             {
  243.             for (bufctr=0; bufctr < bufsize;)
  244.                     {
  245.                 if (nlflag)
  246.                             {  
  247.                     buff[bufctr++] = LF;  /* leftover newline */
  248.                                nlflag = FALSE;
  249.                         }
  250.                 if (getbyte(fd, &c) == EOF)
  251.                     { 
  252.                     sendfin = TRUE;  /* this is the last sector */
  253.                        if (!bufctr)  /* if EOF on sector boundary */
  254.                               break;  /* avoid sending extra sector */
  255.                           buff[bufctr++] = CTRLZ;  /* pad with Ctrl-Z for CP/M EOF (even do for binary files) */
  256.                        continue;
  257.                           }
  258.     
  259.                 if (tmode && c == LF)  /* text mode & Unix newline? */
  260.                         {
  261.                     buff[bufctr++] = CR;  /* insert carriage return */
  262.                          if (bufctr < bufsize)
  263.                                 buff[bufctr++] = LF;  /* insert LF */
  264.                            else
  265.                             nlflag = TRUE;  /* insert on next sector */
  266.                        }    
  267.                 else if (amode && c == LF)   /* Apple mode & Unix newline? */
  268.                     buff[bufctr++] = CR; /* substitute CR */
  269.                 else
  270.                     buff[bufctr++] = c;  /* copy the char without change */
  271.                     }
  272.  
  273.                 if (!bufctr)  /* if EOF on sector boundary */
  274.                           break;  /* avoid sending empty sector */
  275.             }    
  276.  
  277.         else        /* YMODEM filename packet */
  278.             {
  279.             for (bufctr=0; bufctr<1024; bufctr++)  /* zero packet */
  280.                 buff[bufctr]=0;
  281.             if (!closeout)
  282.                 {
  283.                 strcpy((char *)buff, cpmify(name));
  284.                 
  285.                     /* put in file name, length, mode, */
  286.                     /* dummy SN, files, bytes remaining and file type */
  287.                     {
  288.                     register char *p;
  289.                     p = (char *)buff + strlen(buff) + 1;
  290.                     sprintf(p, "%lu %lo %o 0 %d %ld 0", filestatbuf.st_size, 
  291.                       filestatbuf.st_mtime, filestatbuf.st_mode,
  292.                       yfilesleft, ytotleft);
  293.                     if (DEBUG)
  294.                         fprintf(LOGFP, "DEBUG: YMODEM header information: %s %s\n", buff, p);
  295.                     }
  296.                 if (buff[125])        /* need to have long packet? */
  297.                     {
  298.                     bufsize = 1024;
  299.                     if (DEBUG)
  300.                         fprintf(LOGFP, "DEBUG: YMODEM header sent in 1024 byte packet\n");
  301.                     }
  302.                 buff[bufsize-2]    = (expsect & 0xff);        /* put in KMD kludge information */
  303.                 buff[bufsize-1] = ((expsect >> 8) & 0xff);
  304.  
  305.                 /* update totals */
  306.                 ytotleft -= filestatbuf.st_size;
  307.                 if (--yfilesleft <= 0)
  308.                     ytotleft = 0;
  309.                 if (ytotleft < 0)
  310.                     ytotleft = 0;
  311.                 }
  312.             }
  313.  
  314.         bbufcnt = 0;        /* start building block to be sent */
  315.         blockbuf[bbufcnt++] = (bufsize == 1024) ? STX : SOH;    /* start of packet char */
  316.         blockbuf[bbufcnt++] = sectnum;        /* current sector # */
  317.         blockbuf[bbufcnt++] = ~sectnum;   /* and its complement */
  318.  
  319.                    checksum = 0;  /* initialize checksum */
  320.                    for (bufctr=0; bufctr < bufsize; bufctr++)
  321.                    {
  322.             blockbuf[bbufcnt++] = buff[bufctr];
  323.  
  324.             if (CRCMODE)
  325.                 checksum = (checksum<<B) ^ crctab[(checksum>>(W-B)) ^ buff[bufctr]];
  326.  
  327.             else
  328.                            checksum = ((checksum+buff[bufctr]) & 0xff);
  329.                  }
  330.  
  331.         if (CRCMODE)        /* put in CRC */
  332.             {
  333.             checksum &= 0xffff;
  334.             blockbuf[bbufcnt++] = ((checksum >> 8) & 0xff);
  335.             blockbuf[bbufcnt++] = (checksum & 0xff);
  336.             }
  337.         else            /* put in checksum */
  338.             blockbuf[bbufcnt++] = checksum;
  339.  
  340.                 attempts = 0;
  341.     
  342.                 do                /* inner packet loop */
  343.                     {
  344.  
  345.             writebuf(blockbuf, bbufcnt);    /* write the block */
  346.             if (!YMODEMG)
  347.                 flushin();              /* purge anything in input queue */
  348.  
  349.             if (DEBUG)
  350.                 fprintf (LOGFP, "DEBUG: %d byte Packet %02xh (%02xh) sent, checksum %02xh %02xh\n", 
  351.                 bbufcnt, blockbuf[1]&0xff, blockbuf[2]&0xff, blockbuf[bufsize+3]&0xff, blockbuf[bufsize+4]&0xff);
  352.  
  353.                     attempts++;
  354.             sendresp = (YMODEMG) ? ACK : readbyte(10);    /* get response from remote  (or fake it for YMODEM-G) */
  355.  
  356.             if (sendresp != ACK)
  357.                    {
  358.                 if (sendresp == TIMEOUT)
  359.                     {
  360.                        logitarg("Timeout on sector %s\n",sectdisp(sentsect,bufsize,1));
  361.                        tlogitarg("Timeout on sector %s\n",sectdisp(sentsect,bufsize,1));
  362.                     }
  363.                 if (sendresp == CAN)
  364.                     {
  365.                     if (CANCAN)
  366.                         {
  367.                         if (readbyte(3) == CAN)
  368.                             error("Send Canceled by CAN-CAN",TRUE);
  369.                         }
  370.                     else
  371.                         {
  372.                        logitarg("ignored CAN on sector %s\n",sectdisp(sentsect,bufsize,1));
  373.                        tlogitarg("ignored CAN on sector %s\n",sectdisp(sentsect,bufsize,1));
  374.                         }
  375.                     }
  376.                 else if (sendresp == NAK)
  377.                     {
  378.                        logitarg("NAK on sector %s\n",sectdisp(sentsect,bufsize,1));
  379.                        tlogitarg("NAK on sector %s\n",sectdisp(sentsect,bufsize,1));
  380.                     }
  381.                 else
  382.                     {
  383.                        logitarg("Non-ACK on sector %s\n",sectdisp(sentsect,bufsize,1));
  384.                        tlogitarg("Non-ACK on sector %s\n",sectdisp(sentsect,bufsize,1));
  385.                     }
  386.                    }
  387.                     }
  388.             while((sendresp != ACK) && (attempts < ERRORMAX));    /* close of inner loop */
  389.  
  390.                sectnum++;  /* increment to next sector number */
  391.         if (!filepack)
  392.             sentsect += (bufsize == 128) ? 1 : 8;
  393.         filepack = FALSE;
  394.         if (TIPFLAG && sentsect % 32 == 0)
  395.             tlogitarg("Sector %s sent\n", sectdisp(sentsect,bufsize,0));
  396.             }
  397.         while (!sendfin && ( attempts < ERRORMAX));    /* end of outer loop */
  398.  
  399.     if (attempts >= ERRORMAX)
  400.         {
  401.         sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
  402.         error ("Too many errors in transmission", TRUE);
  403.         }
  404.  
  405.         sendbyte(EOT);  /* send 1st EOT to close down transfer */
  406.         attempts = 0;
  407.     
  408.         while ((readbyte(15) != ACK) && (attempts++ < EOTMAX))     /* wait for ACK of EOT */
  409.         {
  410.         if (attempts > 1)
  411.             {
  412.             logitarg("EOT not ACKed, try %d\n", attempts);
  413.             tlogitarg("EOT not ACKed, try %d\n", attempts);
  414.             }
  415.            sendbyte(EOT);
  416.         }
  417.  
  418.         if (attempts >= RETRYMAX)
  419.            error("Remote System Not Responding on Completion", TRUE);
  420.  
  421.         close(fd);
  422.  
  423.         logit("Send Complete\n");
  424.         tlogit("Send Complete\n");
  425.     if (LOGFLAG)
  426.         prtime(sentsect, time((time_t *) 0) - start, LOGFP);
  427.     if (TIPFLAG)
  428.         prtime(sentsect, time((time_t *) 0) - start, stderr);
  429.     }
  430.