home *** CD-ROM | disk | FTP | other *** search
/ Transactor / Transactor_26_1988_Transactor_Publishing.d64 / xmodem.c < prev    next >
Text File  |  2023-02-26  |  8KB  |  493 lines

  1. /* xmodem.c - xmodem protocol */
  2. /* W Mat Waites - Sept 1988 */
  3.  
  4. #include <stdio.h>
  5.  
  6. /* number of retries, timeouts */
  7. #define RETRY 5
  8. #define TOUT 2
  9. #define BTOUT 10
  10.  
  11. /* protocol characters */
  12. #define SOH 0x01
  13. #define EOT 0x04
  14. #define ACK 0x06
  15. #define NAK 0x15
  16. #define CAN 0x18
  17.  
  18. #define RECSIZE 128
  19.  
  20. char *diskerr();
  21.  
  22. int rec;
  23. int tries;
  24. int timeout;
  25.  
  26. /* buffer for data in/out */
  27. char buffer[132];
  28.  
  29. /* sendfile() - send file via xmodem */
  30. sendfile(fname, disk)
  31. char *fname;
  32. int disk;
  33. {SHIFT-+}
  34.   int st;
  35.   int ch;
  36.   char errbuf[41];
  37.   char locname[21];
  38.   char *status = 0x0090;
  39.   FILE dfile;
  40.  
  41.   rec = 1;
  42.  
  43.   strcpy(locname, fname);
  44.   strcat(locname, ",r");
  45.  
  46.   /* attempt to open file for read */
  47.   device(disk);
  48.   dfile = fopen(locname);
  49.  
  50.   /* check for disk error */
  51.   strcpy(errbuf, diskerr(disk));
  52.   st = atoi(errbuf);
  53.   if(st >= 20)
  54.     {SHIFT-+}
  55.     close(dfile);
  56.     showerr(fname, errbuf);
  57.     return(0);
  58.     {SHIFT--}
  59.  
  60.   printf("%s opened\n", fname);
  61.  
  62.   /* clear input buffer */
  63.   while(getserial() >= 0)
  64.     {SHIFT-+}
  65.     {SHIFT--}
  66.  
  67.   tries = RETRY;
  68.  
  69.   for(;;)
  70.     {SHIFT-+}
  71.     printf("Synching...\n");
  72.     if(chkstop())
  73.       {SHIFT-+}
  74.       close(dfile);
  75.       return(0);
  76.       {SHIFT--}
  77.     ch = getchtmo(BTOUT);
  78.     if(timeout)
  79.       {SHIFT-+}
  80.       printf("Timeout\n");
  81.       tries--;
  82.       if(tries > 0)
  83.         {SHIFT-+}
  84.         continue;
  85.         {SHIFT--}
  86.       close(dfile);
  87.       return(0);
  88.       {SHIFT--}
  89.     if(ch == NAK)
  90.       {SHIFT-+}
  91.       break;
  92.       {SHIFT--}
  93.     printf("Strange char [%02x]\n", ch);
  94.     {SHIFT--}
  95.  
  96.   printf("Synched\n");
  97.  
  98.   /* send the file */
  99.   while(fillbuf(dfile, buffer))
  100.     {SHIFT-+}
  101.     if(chkstop())
  102.       {SHIFT-+}
  103.       close(dfile);
  104.       return(0);
  105.       {SHIFT--}
  106.     if(!txrec(buffer))
  107.       {SHIFT-+}
  108.       close(dfile);
  109.       return(0);
  110.       {SHIFT--}
  111.     {SHIFT--}
  112.  
  113.   /* tell 'em we're done */
  114.   putserial(EOT);
  115.   for(;;)
  116.     {SHIFT-+}
  117.     ch = getchtmo(TOUT);
  118.     if(timeout)
  119.       {SHIFT-+}
  120.       putserial(EOT);
  121.       {SHIFT--}
  122.     else
  123.       {SHIFT-+}
  124.       if(ch == ACK)
  125.         {SHIFT-+}
  126.         printf("sent EOT\n\n");
  127.         break;
  128.         {SHIFT--}
  129.       {SHIFT--}
  130.     {SHIFT--}
  131.  
  132.   close(dfile);
  133.   printf("%s transferred\n\n", fname);
  134.   return(1);
  135. {SHIFT--}
  136.  
  137. /* recvfile() - recv file via xmodem */
  138. recvfile(fname, disk)
  139. char *fname;
  140. int disk;
  141. {SHIFT-+}
  142.   int st;
  143.   int ch;
  144.   int i;
  145.   char r1, r2, dt;
  146.   int response;
  147.   char rchk;
  148.   char locname[21];
  149.   char errbuf[41];
  150.   unsigned chksum;
  151.   FILE dfile;
  152.  
  153.   rec = 1;
  154.  
  155.   strcpy(locname, fname);
  156.   strcat(locname, ",w");
  157.  
  158.   /* attempt to open file for write */
  159.   device(disk);
  160.   dfile = fopen(locname);
  161.  
  162.   /* check for disk error */
  163.   strcpy(errbuf, diskerr(disk));
  164.   st = atoi(errbuf);
  165.   if(st >= 20)
  166.     {SHIFT-+}
  167.     close(dfile);
  168.     showerr(fname, errbuf);
  169.     return(0);
  170.     {SHIFT--}
  171.  
  172.   printf("%s opened\n", fname);
  173.  
  174.   /* clear input queue */
  175.   while(getserial() >= 0)
  176.     {SHIFT-+}
  177.     {SHIFT--}
  178.  
  179.   /* transfer file */
  180.   response = NAK;
  181.   for(;;)
  182.     {SHIFT-+}
  183.     /* get a record */
  184.     printf("Record %3d ", rec);
  185.     tries = RETRY;
  186.     for(;;)
  187.       {SHIFT-+}
  188.       if(chkstop())
  189.         {SHIFT-+}
  190.         close(dfile);
  191.         return(0);
  192.         {SHIFT--}
  193.       /* shake hands */
  194.       putserial(response);
  195.       /* get 1st char */
  196.       ch = getchtmo(TOUT);
  197.       if(timeout)
  198.         {SHIFT-+}
  199.         tries--;
  200.         if(tries > 0)
  201.           {SHIFT-+}
  202.           continue;  /* try again */
  203.           {SHIFT--}
  204.         printf("Can't sync w/sender\n");
  205.  
  206.         close(dfile);
  207.         return(0);
  208.         {SHIFT--}
  209.       if(ch == SOH)  /* beg of data */
  210.         {SHIFT-+}
  211.         break;
  212.         {SHIFT--}
  213.       else if(ch == EOT) /* done */
  214.         {SHIFT-+}
  215.         printf("got EOT\n\n");
  216.         close(dfile);
  217.         putserial(ACK);
  218.         printf("%s transferred\n\n",
  219.           fname);
  220.         return(1);
  221.         {SHIFT--}
  222.       else if(ch == CAN)  /* cancelled */
  223.         {SHIFT-+}
  224.         close(dfile);
  225.         printf("Transfer cancelled!\n");
  226.         return(0);
  227.         {SHIFT--}
  228.       else
  229.         {SHIFT-+}
  230.         printf("Strange char [%02x]\n", ch);
  231.         gobble();  /* clear any weirdness */
  232.         response = NAK;  /* and try again */
  233.         {SHIFT--}
  234.       {SHIFT--}
  235.  
  236.     response = NAK;
  237.     r1 = getchtmo(TOUT);  /* record number */
  238.     if(timeout)
  239.       {SHIFT-+}
  240.       printf("TMO on recnum\n");
  241.       continue;
  242.       {SHIFT--}
  243.     /* get 1's comp record number */
  244.     r2 = getchtmo(TOUT);
  245.     if(timeout)
  246.       {SHIFT-+}
  247.       printf("TMO on comp recnum\n");
  248.       continue;
  249.       {SHIFT--}
  250.  
  251.     /* get data */
  252.     chksum = 0;
  253.     for(i=0; i<RECSIZE; i++)
  254.       {SHIFT-+}
  255.       dt = getchtmo(TOUT);
  256.       if(timeout)
  257.         {SHIFT-+}
  258.         break;
  259.         {SHIFT--}
  260.       buffer[i] = dt;
  261.       chksum += dt;
  262.       chksum &= 0xff;
  263.       {SHIFT--}
  264.     /* check for data timeout */
  265.     if(timeout)
  266.       {SHIFT-+}
  267.       printf("TMO on data\n");
  268.       continue;
  269.       {SHIFT--}
  270.  
  271.     /* get checksum */
  272.     rchk = getchtmo(TOUT);
  273.     if(timeout)
  274.       {SHIFT-+}
  275.       printf("TMO on checksum\n");
  276.       continue;
  277.       {SHIFT--}
  278.  
  279.     /* compare rec num and 1's comp */
  280.     if(({CBM-P}r1 & 0xff) != (r2 & 0xff))
  281.       {SHIFT-+}
  282.       printf("Bad recnum's\n");
  283.       continue;
  284.       {SHIFT--}
  285.  
  286.     /* compare checksum and local one */
  287.     if(rchk != chksum)
  288.       {SHIFT-+}
  289.       printf("Bad checksum\n");
  290.       response = NAK;
  291.       continue;
  292.       {SHIFT--}
  293.  
  294.     if((r1 ==(rec-1) & 0xff)) /* dupe */
  295.       {SHIFT-+}
  296.       printf("Duplicate record\n");
  297.       response = ACK;
  298.       continue;
  299.       {SHIFT--}
  300.  
  301.     if(r1 != (rec & 0xff))
  302.       {SHIFT-+}
  303.       printf("Record numbering error\n");
  304.       close(dfile);
  305.       return(0);
  306.       {SHIFT--}
  307.  
  308.     rec++;
  309.  
  310.     /* write data to file */
  311.     for(i=0; i<RECSIZE; i++)
  312.       {SHIFT-+}
  313.       putc(buffer[i], dfile);
  314.       {SHIFT--}
  315.  
  316.     printf("OK\n");
  317.     response = ACK;
  318.     {SHIFT--}
  319. {SHIFT--}
  320.  
  321. /* showerr() - display disk error */
  322. showerr(fname, errmsg)
  323. char *fname;
  324. char *errmsg;
  325. {SHIFT-+}
  326.   erase();
  327.   move(11, 5);
  328.   printf("Error accessing %s", fname);
  329.   move(13, 5);
  330.   printf("[%s]", errmsg);
  331.   move(20, 5);
  332. {SHIFT--}
  333.  
  334. /* getchtmo() - get char w/timeout */
  335. getchtmo(timlen)
  336. int timlen;
  337. {SHIFT-+}
  338.   int serchar;
  339.  
  340.   timeout = 0;
  341.   setclock((unsigned)0); /* start timer */
  342.  
  343.   for(;;)
  344.     {SHIFT-+}
  345.  
  346.     serchar = getserial();
  347.     if(serchar >= 0)
  348.       {SHIFT-+}
  349.       return(serchar);
  350.       {SHIFT--}
  351.  
  352.     if(getclock() >= timlen)
  353.       {SHIFT-+}
  354.       timeout = 1;
  355.       return 0;
  356.       {SHIFT--}
  357.     {SHIFT--}
  358. {SHIFT--}
  359.  
  360. /* fillbuf() - get buffer of data */
  361. fillbuf(filnum, buf)
  362. int filnum;
  363. char buf[];
  364. {SHIFT-+}
  365.   int i;
  366.   int echk;
  367.   char *status = 0x0090;
  368.  
  369.   for(i=0; i<RECSIZE; i++)
  370.     {SHIFT-+}
  371.     /* get a char from file */
  372.     if((echk=fgetc(filnum)) == EOF)
  373.       {SHIFT-+}
  374.       break;
  375.       {SHIFT--}
  376.     buf[i] = echk;
  377.     {SHIFT--}
  378.  
  379.   if(i == 0) return 0;
  380.  
  381.   /* set rest of buffer to CTRL-Z */
  382.   for(; i<RECSIZE; i++)
  383.     {SHIFT-+}
  384.     buf[i] = (char)26;
  385.     {SHIFT--}
  386.   return(1);
  387. {SHIFT--}
  388.  
  389. /* txrec() - send rec, get response */
  390. txrec(buf)
  391. char buf[];
  392. {SHIFT-+}
  393.   int i;
  394.   int ch;
  395.   unsigned chksum;
  396.  
  397.   tries = RETRY;
  398.  
  399.   for(;;)
  400.     {SHIFT-+}
  401.     /* send record */
  402.  
  403.     printf("Record %3d ", rec);
  404.     putserial(SOH);
  405.     putserial(rec);
  406.     putserial({CBM-P}rec);
  407.     chksum = 0;
  408.     for(i=0; i<RECSIZE; i++)
  409.       {SHIFT-+}
  410.       putserial(buf[i]);
  411.       chksum += buf[i];
  412.       chksum &= 0xff;
  413.       {SHIFT--}
  414.     putserial(chksum);
  415.  
  416.     /* get response */
  417.     ch = getchtmo(BTOUT);
  418.     if(timeout)
  419.       {SHIFT-+}
  420.       tries--;
  421.       if(tries > 0)
  422.         {SHIFT-+}
  423.         printf("Retrying...\n");
  424.         continue;
  425.         {SHIFT--}
  426.       printf("Timeout\n");
  427.       return(0);
  428.       {SHIFT--}
  429.  
  430.     /* analyze response */
  431.     if(ch == CAN)
  432.       {SHIFT-+}
  433.       printf("Cancelled\n");
  434.       return(0);
  435.       {SHIFT--}
  436.     else if(ch == ACK)
  437.       {SHIFT-+}
  438.       printf("ACKed\n", rec);
  439.       break;
  440.       {SHIFT--}
  441.     else
  442.       {SHIFT-+}
  443.       if(ch == NAK)
  444.         {SHIFT-+}
  445.         printf("NAKed\n", rec);
  446.         {SHIFT--}
  447.       else
  448.         {SHIFT-+}
  449.         printf("Strange response\n");
  450.         {SHIFT--}
  451.       tries--;
  452.       if(tries > 0)
  453.         {SHIFT-+}
  454.         continue;
  455.         {SHIFT--}
  456.       printf("No more retries!\n");
  457.       return(0);
  458.       {SHIFT--}
  459.     {SHIFT--}
  460.   rec++;
  461.   return(1);
  462. {SHIFT--}
  463.  
  464. /* gobble() - gobble up stray chars */
  465. gobble()
  466. {SHIFT-+}
  467.   unsigned gotone;
  468.  
  469.   printf("\ngobbling\n");
  470.  
  471.   sleep(2);
  472.  
  473.   for(;;)
  474.     {SHIFT-+}
  475.     gotone = 0;
  476.     /* clear input queue */
  477.     while(getserial() >= 0)
  478.       {SHIFT-+}
  479.       gotone = 1;
  480.       {SHIFT--}
  481.     if(gotone)
  482.       {SHIFT-+}
  483.       sleep(1);
  484.       {SHIFT--}
  485.     else
  486.       {SHIFT-+}
  487.       return;
  488.       {SHIFT--}
  489.     {SHIFT--}
  490. {SHIFT--}
  491.  
  492. /* end of file */
  493.