home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / uniflex / ufsend.c < prev    next >
C/C++ Source or Header  |  1993-08-22  |  19KB  |  527 lines

  1. #include "ufk.h"
  2.  
  3. int offset,                      /* Offset in data buffer to start */
  4.     org_size;                    /* Original packet size */
  5. char size_lowered;               /* Flag if packet shortening has been done */
  6.  
  7. sendfile()
  8. {
  9.    if (numprm <= 1)                    /* check parameter */
  10.       prterr(ER_FSPCREQ);
  11.    else if (!get_file_spec(TRUE))      /* Get filespec for send */
  12.       prterr(ER_NOFILSEL);
  13.    else
  14.    {
  15.       if (!open_port(TRUE,FALSE))      /* Setup communication port */
  16.          prterr(ER_POPNERR);
  17.       else
  18.       {
  19.          if (alloc_pkt(SEND))          /* Allocate packet memory */
  20.          {
  21.             sflg++;
  22.             set_frame();
  23.             if (!sendsw())                /* Send the file(s) */
  24.                disp(0,18,"Send failed.\n"); /* Report failure */
  25.             beep();
  26.             while (get_file_spec(FALSE)); /* Flush directory buffer */
  27.          }
  28.          close_port(sflg,FALSE);
  29.       }
  30.    }
  31. }
  32.  
  33. /*
  34.  *  s e n d s w
  35.  *
  36.  *  Sendsw is the state table switcher for sending files.  It loops until
  37.  *  either it finishes, or an error is encountered.  The routines called
  38.  *  by sendsw are responsible for changing the state.
  39.  *
  40.  */
  41.  
  42. sendsw()
  43. {
  44.    char sinit(), sfile(), sattr(), sdata(), seof(), sbreak();
  45.  
  46.    init_xfer();                           /* Reset counters */
  47.    set_default_comm();                    /* Set communication parameters */
  48.    state = 'S';                           /* Send initiate is start state */
  49.    n = 0;                                 /* Initialize message number */
  50.    offset = 0;                            /* Offset in data buffer to start */
  51.    size_lowered = FALSE;                  /* No long packet error received */
  52.    numtry = 0;                            /* Say no tries yet */
  53.    if (remote && (sflg != 2))             /* Wait before sending if remote */
  54.       kdelay(send_delay);                 /* and if no server mode request */
  55.    purgeline(ttyfd);                      /* Eat old input */
  56.    while(TRUE)                            /* Do this as long as necessary */
  57.    {
  58.       if (debug)
  59.       {
  60.          prtdbgf("Send state: ");
  61.          if (!screen)
  62.             fputs("Send state: ",stdout);
  63.          disp_state(50,13,state);
  64.       }
  65.       switch(state)
  66.       {
  67.          case 'S':                        /* Send-init */
  68.                state = sinit();
  69.                break;
  70.  
  71.          case 'F':                        /* Send-file */
  72.                state = sfile();
  73.                break;
  74.  
  75.          case 'A':                        /* Send attributes */
  76.                state = sattr();
  77.                break;
  78.  
  79.          case 'D':                        /* Send-data */
  80.                state = sdata();
  81.                break;
  82.  
  83.          case 'Z':                        /* Send-End-of-File */
  84.                state = seof();
  85.                break;
  86.  
  87.          case 'B':                        /* Send-Break */
  88.                state = sbreak();
  89.                break;
  90.  
  91.          case 'C':                        /* Complete */
  92.                fin_xfer();
  93.                return (TRUE);
  94.  
  95.          case 'Q':
  96.          default:                         /* Unknown or abort, fail */
  97.                fin_xfer();
  98.                return (FALSE);
  99.       }
  100.    }
  101. }
  102.  
  103.  
  104. /*
  105.  *  s i n i t
  106.  *
  107.  *  Send Initiate: send this host's parameters and get other side's back.
  108.  */
  109.  
  110. char sinit()
  111. {
  112.    char  num;                             /* Packet number */
  113.    int len;                               /* length */
  114.  
  115.    if (numtry++ >= maxtry)                /* If too many tries, give up */
  116.       return('Q');
  117.    spar(sndpkt,&len);                     /* Fill up init info packet */
  118.  
  119.    spack('S',n,len,sndpkt,0,1);           /* Send an S packet */
  120.    switch(rpack(&len,&num,recpkt,1))      /* What was the reply? */
  121.    {
  122.       case 'N':                           /* NAK, try it again */
  123.             return(state);
  124.  
  125.       case 'Y':                           /* ACK */
  126.             if (n != num)                 /* If wrong ACK, stay in S state */
  127.                return(state);             /* and try again */
  128.             rpar(recpkt,len);             /* Get other side's init info */
  129.             numtry = 0;                   /* Reset try counter */
  130.             n = ( n + 1) % 64;            /* Bump packet count */
  131.             return('F');                  /* OK, switch state to F */
  132.  
  133.       case 'E':                           /* Error packet received */
  134.             prerrpkt(recpkt);             /* Print it out and */
  135.             return('Q');                  /* Abort */
  136.  
  137.       case 'T':                           /* Timeout */
  138.             if (aborted)
  139.                return('Q');               /* aborted by user */
  140.       case FALSE:                         /* Receive failure, try again */
  141.             return(state);
  142.  
  143.       default:                            /* Anything else, just "abort" */
  144.             return('Q');
  145.    }
  146. }
  147.  
  148.  
  149. /*
  150.  *  s f i l e
  151.  *
  152.  *  Send File Header.
  153.  */
  154.  
  155. char sfile()
  156. {
  157.    char  num,                             /* Packet number */
  158.          fnm[15];
  159.    int   i, len;                          /* length */
  160.  
  161.    if (numtry++ >= maxtry)                /* If too many tries, give up */
  162.       return('Q');
  163.  
  164.    aborted = FALSE;
  165.    if (fp != ERROR)                       /* If left open, close it */
  166.       fclose(fp);
  167.    fp = fopen(filnam,"r");                /* open the file to be sent */
  168.    if (fp == NULL)                        /* If bad file pointer, give up */
  169.    {
  170.       error(PER_OPEN,"%s",filnam);        /* Can't open file */
  171.       if (!get_file_spec(FALSE))
  172.          return('C');                     /* No more files to do */
  173.       else
  174.          return('S');                     /* Try next file */
  175.    }
  176.    for (i = strlen(filnam) - 1; i >= 0; --i)
  177.       if (filnam[i] == '/')               /* Skip directory specification */
  178.          break;
  179.    strcpy(fnm,&filnam[i+1]);
  180.    map_case(fnm,OUT);                     /* map to correct case */
  181.    if (!nooutput)
  182.    {
  183.       if (screen)
  184.       {
  185.          disp(0,2,"Sending: ");
  186.          posit(20,2);
  187.          printf("%s as %s", filnam, fnm);
  188.          clreol(-1,-1);
  189.       }
  190.       else
  191.          printf("\n\lSending: %s as %s\n\l",filnam,fnm);
  192.    }
  193.    fnm[strlen(fnm)] = EOF;                /* Terminate data */
  194.    len = bufill(sndpkt,TRUE,fnm);
  195.    spack('F',n,len,sndpkt,0,block_check_type); /* Send an F packet */
  196.    switch(rpack(&len,&num,recpkt,block_check_type))/* What was the reply? */
  197.    {
  198.       case 'N':                           /* NAK, just stay in this state, */
  199.             num = (--num < 0 ? 63 : num); /* unless it's NAK for next packet */
  200.             if (n != num)                 /* which is just like an ACK for */
  201.                return(state);             /* this packet so fall thru to... */
  202.  
  203.       case 'Y':                           /* ACK */
  204.             if (n != num)                 /* If wrong ACK, stay in F state */
  205.                return(state);
  206.             numtry = 0;                   /* Reset try counter */
  207.             n = (n + 1) % 64;             /* Bump packet count */
  208.             if (attribute)
  209.                return('A');               /* Switch to attribute state */
  210.             else
  211.             {
  212.                if ((size = bufill(sndpkt,TRUE,0)) == EOF)/* data from file */
  213.                   return('Z');            /* If EOF then empty data file */
  214.                org_size = size;           /* Remember original size */
  215.                   return('D');            /* Switch state to D */
  216.             }
  217.  
  218.       case 'E':                           /* Error packet received */
  219.             prerrpkt(recpkt);             /* Print it out and */
  220.             return('Q');                  /* abort */
  221.  
  222.       case 'T':                           /* Timeout */
  223.             if (aborted)
  224.             {
  225.                error(PER_ABORTED);        /* send error packet */
  226.                return('Q');               /* aborted by user */
  227.             }
  228.       case FALSE:                         /* Receive failure, stay in F */
  229.             return(state);
  230.  
  231.       default:                            /* Something else, just "abort" */
  232.             return('Q');
  233.    }
  234. }
  235.  
  236. /*
  237.  *  s a t t r
  238.  *
  239.  *  Send File Attributes
  240.  */
  241.  
  242. char sattr()
  243. {
  244.    char  num;                             /* Packet number */
  245.    int len;                               /* length */
  246.  
  247.    if (numtry++ >= maxtry)                /* If too many tries "abort" */
  248.       return('Q');
  249.  
  250.    snd_attributes();                      /* Prepare send attribute packet */
  251.    spack('A',n,size,sndpkt,0,block_check_type);/* Send an A packet */
  252.    switch (rpack(&len,&num,recpkt,block_check_type))/* What was the reply? */
  253.    {
  254.       case 'N':                           /* NAK, just stay in this state, */
  255.             num = (--num < 0 ? 63 : num); /* unless NAK for previous packet, */
  256.             if (n != num)                 /* which is just like an ACK for */
  257.                return(state);             /* this packet so fall thru to... */
  258.  
  259.       case 'Y':                           /* ACK */
  260.             if (n != num)                 /* If wrong ACK, fail */
  261.                return(state);
  262.             numtry = 0;                   /* Reset try counter */
  263.             n = (n + 1) % 64;             /* and bump packet count */
  264.             if ((size = bufill(sndpkt,TRUE,0)) == EOF)/* Get data from file */
  265.                return('Z');               /* If EOF then empty data file */
  266.             org_size = size;              /* Remember original size */
  267.             return('D');                  /* Switch state to data */
  268.  
  269.       case 'E':                           /* Error packet received */
  270.             prerrpkt(recpkt);             /* Print it out and */
  271.             return('Q');                  /* abort */
  272.  
  273.       case 'T':                           /* Timeout */
  274.             if (aborted)
  275.             {
  276.                error(PER_ABORTED);        /* send error packet */
  277.                return('Q');               /* aborted by user */
  278.             }
  279.       case FALSE:                         /* Receive failure, stay in B */
  280.             return(state);
  281.  
  282.       default:                            /* Other, "abort" */
  283.             return ('Q');
  284.    }
  285. }
  286.  
  287.  
  288. /*
  289.  *  s d a t a
  290.  *
  291.  *  Send File Data
  292.  */
  293.  
  294. char sdata()
  295. {
  296.    char  num,                             /* Packet number */
  297.          tmpc;
  298.    int   len;                             /* length */
  299.  
  300.    if (numtry++ >= maxtry)                /* If too many tries, give up */
  301.       return('Q');
  302.    spack('D',n,size,sndpkt,offset,block_check_type);/* Send a D packet */
  303.    switch(rpack(&len,&num,recpkt,block_check_type))/* What was the reply? */
  304.    {
  305.       case 'N':                           /* NAK, just stay in this state, */
  306.             num = (--num < 0 ? 63 : num); /* unless it's NAK for next packet */
  307.             if (n != num)                 /* which is just like an ACK for */
  308.             {                             /* this packet so fall thru to 'Y' */
  309.                if ((org_size > 91) && auto_recover)/* If extended length... */
  310.                   lower_size();           /* Lower packet size on error */
  311.                return(state);             /* Try again */
  312.             }
  313.  
  314.       case 'Y':                           /* ACK */
  315.             if (n != num)                 /* If wrong ACK, fail */
  316.                return(state);
  317.             numtry = 0;                   /* Reset try counter */
  318.             n = (n + 1) % 64;             /* Bump packet count */
  319.             if (size_lowered)
  320.                adjust_size();             /* Still data in buffer */
  321.             else
  322.             {
  323.                offset = 0;                /* No more old data in buffer */
  324.                if ((size = bufill(sndpkt,FALSE,0)) == EOF)/* Get new data */
  325.                   return('Z');            /* If EOF set state to that */
  326.                org_size = size;           /* Remember original size */
  327.             }
  328.             tmpc = *recpkt;
  329.             if (len == 1)                 /* Data on ack */
  330.             {
  331.                if (tmpc == 'Z')           /* Stop entire batch */
  332.                   filecount = 0;          /* No more files to send */
  333.                if ((tmpc == 'X') || (tmpc == 'Z'))
  334.                   aborted = tmpc - 64;    /* Make binary */
  335.             }
  336.             if ((aborted == ABORTX) || (aborted == ABORTZ))
  337.             {
  338.                if (screen)
  339.                   disp(0,19,"Transfer interrupted.");
  340.                else
  341.                   fputs("Transfer interrupted.\n\l",stdout);
  342.                beep();
  343.                return('Z');               /* Send abort */
  344.             }
  345.             return('D');                  /* Got data, stay in state D */
  346.  
  347.       case 'E':                           /* Error packet received */
  348.             prerrpkt(recpkt);             /* Print it out and */
  349.             return('Q');                  /* abort */
  350.  
  351.       case 'T':                           /* Timeout */
  352.             if (aborted)
  353.             {
  354.                error(PER_ABORTED);        /* send error packet */
  355.                return('Q');               /* aborted by user */
  356.             }
  357.             if ((org_size > 91) && auto_recover) /* If extended length... */
  358.                lower_size();              /* Lower packet size on error */
  359.  
  360.       case FALSE:                         /* Receive failure, stay in D */
  361.             return(state);
  362.  
  363.       default:                            /* Anything else, "abort" */
  364.             return('Q');
  365.    }
  366. }
  367.  
  368.  
  369. /*
  370.  *  s e o f
  371.  *
  372.  *  Send End-Of-File.
  373.  */
  374.  
  375. char seof()
  376. {
  377.    char  num;                             /* Packet number */
  378.    int len, tlen;                         /* length */
  379.  
  380.    if (numtry++ >= maxtry)                /* If too many tries, "abort" */
  381.       return('Q');
  382.  
  383.    tlen = 0;                              /* Assume no abort */
  384.    if ((aborted == ABORTX) || (aborted == ABORTZ))
  385.    {
  386.       *sndpkt = 'D';                      /* Discard file on abort */
  387.       tlen = 1;
  388.       *(sndpkt+sizeof(char)) = '\0';      /* For debug printout */
  389.    }
  390.    spack('Z',n,tlen,sndpkt,0,block_check_type); /* Send a 'Z' packet */
  391.    switch(rpack(&len,&num,recpkt,block_check_type))/* What was the reply? */
  392.    {
  393.       case 'N':                           /* NAK, just stay in this state, */
  394.             num = (--num < 0 ? 63 : num); /* unless it's NAK for next packet */
  395.             if (n != num)                 /* which is just like an ACK for */
  396.                return(state);             /* this packet so fall thru to... */
  397.  
  398.       case 'Y':                           /* ACK */
  399.             if (n != num)                 /* If wrong ACK, hold out */
  400.                return(state);
  401.             numtry = 0;                   /* Reset try counter */
  402.             n = (n + 1) % 64;             /* and bump packet count */
  403.             fclose(fp);                   /* Close the input file */
  404.             fp = ERROR;                   /* flag no file open */
  405.  
  406.             if (!get_file_spec(FALSE))
  407.                return ('B');              /* Stop if no more files */
  408.             if (aborted == ABORTZ)        /* Abort the rest ? */
  409.             {
  410.                while (get_file_spec(FALSE)); /* Flush directory buffer */
  411.                return ('B');
  412.             }
  413.             return('F');                  /* More files, switch state to F */
  414.  
  415.       case 'E':                           /* Error packet received */
  416.             prerrpkt(recpkt);             /* Print it out and */
  417.             return('Q');                  /* abort */
  418.  
  419.       case 'T':                           /* Timeout */
  420.             if (aborted)
  421.             {
  422.                error(PER_ABORTED);        /* send error packet */
  423.                return('Q');               /* aborted by user */
  424.             }
  425.       case FALSE:                         /* Receive failure, stay in Z */
  426.             return(state);
  427.  
  428.       default:                            /* Something else, "abort" */
  429.             return('Q');
  430.    }
  431. }
  432.  
  433.  
  434. /*
  435.  *  s b r e a k
  436.  *
  437.  *  Send Break (EOT)
  438.  */
  439.  
  440. char sbreak()
  441. {
  442.    char  num;                             /* Packet number */
  443.    int len;                               /* length */
  444.  
  445.    if (numtry++ >= maxtry)                /* If too many tries "abort" */
  446.       return('Q');
  447.  
  448.    spack('B',n,0,sndpkt,0,block_check_type);/* Send a B packet */
  449.    switch (rpack(&len,&num,recpkt,block_check_type))/* What was the reply? */
  450.    {
  451.       case 'N':                           /* NAK, just stay in this state, */
  452.             num = (--num < 0 ? 63 : num); /* unless NAK for previous packet, */
  453.             if (n != num)                 /* which is just like an ACK for */
  454.                return(state);             /* this packet so fall thru to... */
  455.  
  456.       case 'Y':                           /* ACK */
  457.             if (n != num)                 /* If wrong ACK, fail */
  458.                return(state);
  459.             numtry = 0;                   /* Reset try counter */
  460.             n = (n + 1) % 64;             /* and bump packet count */
  461.             return('C');                  /* Switch state to Complete */
  462.  
  463.       case 'E':                           /* Error packet received */
  464.             prerrpkt(recpkt);             /* Print it out and */
  465.             return('Q');                  /* abort */
  466.  
  467.       case 'T':                           /* Timeout */
  468.             if (aborted)
  469.             {
  470.                error(PER_ABORTED);        /* send error packet */
  471.                return('Q');               /* aborted by user */
  472.             }
  473.       case FALSE:                         /* Receive failure, stay in B */
  474.             return(state);
  475.  
  476.       default:                            /* Other, "abort" */
  477.             return ('Q');
  478.    }
  479. }
  480.  
  481. lower_size()
  482. {
  483.    int rest;
  484.  
  485.    if (size >= 80)                    /* Minimum size to cut packet size to */
  486.    {
  487.       rest = size % 2;                /* Find out if odd or even */
  488.       size /= 2;                      /* Half of it */
  489.       size += rest;                   /* Add rest if odd */
  490.       spsiz = size;                   /* Use the new size from now on */
  491.       size_lowered = TRUE;            /* Flag size has been modified */
  492.       check_prefix();         /* Make sure not in middle of prefix sequence */
  493.    }
  494. }
  495.  
  496. adjust_size()
  497. {
  498.    offset += size;             /* Increment offset to next unsend character */
  499.    if (offset + size >= org_size) /* Adjust size if past end of buffer */
  500.    {
  501.       size = org_size - offset;
  502.       size_lowered = FALSE;    /* Flag modification done */
  503.    }
  504.    else
  505.       check_prefix();         /* Make sure not in middle of prefix sequence */
  506. }
  507.  
  508. check_prefix()
  509. {
  510.    register char *p;
  511.    char *q;
  512.  
  513.    p = sndpkt + offset;              /* Start check at this place */
  514.    q = p + size;                     /* Until end of current window */
  515.    while (p < q)
  516.    {
  517.       if (*p == repeat_quote)        /* If it's a repeat quote character .. */
  518.          p += 2 * sizeof(char);      /* Skip count */
  519.       if (*p == eight_quote)         /* If it's an eight-bit quote */
  520.          p++;                        /* Skip it */
  521.       if (*p == quote)               /* Same for control quote character */
  522.          p++;
  523.       p++;                           /* Point to next data character */
  524.    }
  525.    size = p - (sndpkt + offset);     /* Calculate new size */
  526. }
  527.