home *** CD-ROM | disk | FTP | other *** search
/ Boot Disc 8 / boot-disc-1997-04.iso / PDA_Soft / Psion / comms / p3nfs / nfsc / xymodem.c < prev   
C/C++ Source or Header  |  1996-05-26  |  7KB  |  314 lines

  1. /*
  2.  * In this file lines end with CR/LF, as our psion C-compiler lives in the 
  3.  * DOS-WORLD
  4.  * Copyright GNU Public License
  5.  */
  6.  
  7. #include <plib.h> 
  8. #include <p_xmodem.h>
  9. #include <p_serial.h>
  10. #include <hwif.h>
  11. #include "nfsc.h"
  12.  
  13. #ifdef HAVE_XYMODEM
  14. TEXT *XYEnv="NFSC_XY";
  15.  
  16.  
  17. static void 
  18. xy_configure(void)
  19. {
  20.   UWORD  xymodem = set.xymodem;
  21.  
  22.   if (   uOpenDialog ("Choose the protocol")
  23.       || uAddChoiceList ("Protocol: ", &xymodem, 
  24.              "Xmodem, 1 Byte Checksum",
  25.              "Xmodem, 2 Byte CRC",
  26.              "Xmodem, 2 Byte CRC (1K)",
  27.              "Ymodem, 2 Byte CRC",
  28.              "Ymodem, 2 Byte CRC (1K)",
  29.              "Ymodem-G, 2 Byte CRC",
  30.              "Ymodem-G, 2 Byte CRC (1K)", NULL)
  31.       || uRunDialog() <= 0)
  32.       return;
  33.  
  34.   set.xymodem = xymodem;
  35.   return;
  36. }
  37.  
  38. static UWORD
  39. setmode(void)
  40. {
  41.   UWORD ret = 0;
  42.  
  43.   switch(set.xymodem)
  44.     {
  45.     case XY_XMODEM:
  46.       ret = P_XMDM_CHECKSUMMODE;
  47.       break;
  48.     case XY_XMODEMCRC:
  49.       ret = P_XMDM_CRCMODE;
  50.       break;
  51.     case XY_XMODEMCRC1K:
  52.       ret = P_XMDM_CRCMODE | P_XMDM_ONE_K;
  53.       break;
  54.     case XY_YMODEM:
  55.       ret = P_YMODEM_MODE;
  56.       break;
  57.     case XY_YMODEM1K:
  58.       ret = P_YMODEM_MODE | P_XMDM_ONE_K;
  59.       break;
  60.     case XY_YMODEMG:
  61.       ret = P_YMODEM_G_MODE;
  62.       break;
  63.     case XY_YMODEMG1K:
  64.       ret = P_YMODEM_G_MODE | P_XMDM_ONE_K;
  65.       break;
  66.     }
  67.   return ret;
  68. }
  69.  
  70. static void *fp;
  71. static char *buf;
  72. static char fname[129];            /* Damn OPL string semantic */
  73.  
  74. static void
  75. errmsg(char *txt)
  76. {
  77.   wInfoMsgCorner(txt, W_CORNER_BOTTOM_RIGHT);
  78.   if(buf) p_free(buf);
  79.   if(fp)  p_close(fp);
  80.   p_close(serial);
  81.   Sw_Serial(ON);
  82. }
  83.  
  84. static char c_cancel[]   = "Cancel";
  85. static char c_cantopen[] = "Can't open XMD:";
  86. static char c_filename[] = "Filename: ";
  87. static char c_aborting[] = "XYmodem: Aborting";
  88. static char c_done[]     = "XYmodem: Done";
  89. static char c_timedout[] = "Connection timed out";
  90. char c_nomem[] = "Not enough memory";
  91.  
  92. static void
  93. xy_sendfile(void)
  94. {
  95.   H_DI_FSEL line1 = {fname, 0}; 
  96.   WORD len, l, ret;
  97.   UWORD type, mode;
  98.   P_INFO p_info;
  99.   char *s;
  100.  
  101.   if((len = p_getenviron (XYEnv, p_slen(XYEnv), fname+1)) > 0)
  102.     *fname = len;
  103.   if (   uOpenDialog ("Select file to send")
  104.       || uAddDialogItem (H_DIALOG_FSEL, c_filename, &line1)
  105.       || (uAddButtonList (c_cancel,W_KEY_ESCAPE,"Send file",W_KEY_RETURN,NULL))
  106.       || uRunDialog() <= 0)
  107.          return;
  108.   p_setenviron(XYEnv, p_slen(XYEnv), fname+1, p_slen(fname+1)+1);
  109.  
  110.   /* ---------------------------------------- Let's open the XYmodem device */
  111.   Sw_Serial(OFF);             /* Cancel outstanding events */
  112.   if(p_open(&serial, "XMD:",-1))
  113.     {
  114.       wInfoMsgCorner(c_cantopen, W_CORNER_BOTTOM_RIGHT);
  115.       Sw_Serial(ON); /* Re-enable input */
  116.       return;
  117.     }
  118.  
  119.   type = P_XMDM_ACCP;
  120.   mode = setmode();
  121.   len = (mode & P_XMDM_ONE_K) ? 1024 : 128;
  122.   buf = 0;
  123.   fp = 0;
  124.  
  125.   if(p_open(&fp, fname+1, P_FOPEN|P_FSTREAM|P_FSHARE))
  126.     {
  127.       errmsg("Can't read the file");
  128.       return;
  129.     }
  130.   if(!(buf = p_alloc(len)))
  131.     {
  132.       errmsg(c_nomem);
  133.       return;
  134.     }
  135.  
  136.   AddToHistory('>');
  137.   if(p_iow(serial, P_FCONNECT, &type, &mode))
  138.     {
  139.       errmsg(c_timedout);
  140.       return;
  141.     }
  142.   AddToHistory('s');
  143.  
  144.   /* ---------------------------------------------- Transmit the whole file */
  145.   ret = 0;
  146.   if(set.xymodem >= XY_YMODEM) /* Ymode protocol must send the filename */
  147.     {
  148.       /* Transmit only the filename, not the whole path */
  149.       if((l = p_slocr(fname+1, '\\')) >= 0 ||
  150.          (l = p_slocr(fname+1, ':' )) >= 0)
  151.         l++;
  152.       else
  153.         l = 0;
  154.         
  155.       /* Filename + length(decimal) + date(octal) */
  156.       p_bfil(buf, 128, 0);
  157.       p_finfo(fname+1, &p_info);
  158.       s = p_scpy(buf, fname+1+l) + 1;
  159.       s += p_gltob(s, p_info.size, 10);
  160.       *s++ = ' ';
  161.       s += p_gltob(s, p_info.modst, 8);
  162.  
  163.       l = 128;
  164.       ret = p_iow(serial, P_FWRITE, buf, &l);
  165.       AddToHistory(ret ? 'F' : 'f');
  166.     }
  167.  
  168.   l = 0;
  169.   while(ret == 0 && (l = p_read(fp, buf, len)) > 0)
  170.     {
  171.       ret = p_iow(serial, P_FWRITE, buf, &l);
  172.       AddToHistory(ret ? 'S' : 's');
  173.     }
  174.  
  175.   if(!ret && (!l || l == E_FILE_EOF))  /* Send EOT */
  176.     {
  177.       l = 0;
  178.       ret = p_iow(serial, P_FWRITE, buf, &l);
  179.       if(set.xymodem >= XY_YMODEM)
  180.     p_iow(serial, P_FCONNECT, &type, &mode);
  181.     }
  182.  
  183.  
  184.   if(l)
  185.     AddToHistory(l < 0 ? 'L' : 'l');
  186.   else
  187.     AddToHistory(ret ? 'C' : 'c');
  188.  
  189.   /* --------------------------------------------- Close the XYmodem device */
  190.   p_iow(serial, P_FDISCONNECT);
  191.   errmsg((ret || l) ? c_aborting : c_done);
  192. }
  193.  
  194. static void
  195. xy_receivefile(void)
  196. {
  197.   H_DI_FSEL line1 = {fname, 0}; 
  198.   WORD len, l, ret;
  199.   UWORD type, mode;
  200.   char xname[128];
  201.  
  202.   mode = setmode();
  203.   len = (mode & P_XMDM_ONE_K) ? 1024 : 128;
  204.  
  205.   /*
  206.   p_bfil(fname, sizeof(fname), 0);
  207.   */
  208.   if(mode >= XY_YMODEM)
  209.     line1.flags = H_FILE_JUST_DIRS;
  210.   if (   uOpenDialog ("XYmodem receive")
  211.       || uAddDialogItem (H_DIALOG_FSEL, 
  212.                          mode >= XY_YMODEM? "Directory: ":c_filename, &line1)
  213.       || (uAddButtonList (c_cancel,W_KEY_ESCAPE,"Receive",W_KEY_RETURN,NULL))
  214.       || uRunDialog() <= 0)
  215.          return;
  216.  
  217.   /* ---------------------------------------- Let's open the XYmodem device */
  218.   Sw_Serial(OFF);             /* Cancel outstanding events */
  219.   if(p_open(&serial, "XMD:",-1))
  220.     {
  221.       wInfoMsgCorner(c_cantopen, W_CORNER_BOTTOM_RIGHT);
  222.       Sw_Serial(ON); /* Re-enable input */
  223.       return;
  224.     }
  225.  
  226.   type = P_XMDM_INIT;
  227.   buf = 0;
  228.   fp = 0;
  229.  
  230.   if(!(buf = p_alloc(len)))
  231.     {
  232.       errmsg(c_nomem);
  233.       return;
  234.     }
  235.  
  236.   for(;;)
  237.     {
  238.       AddToHistory('>');
  239.       if(p_iow(serial, P_FCONNECT, &type, &mode))
  240.     {
  241.       errmsg(c_timedout);
  242.       return;
  243.     }
  244.       if(set.xymodem >= XY_YMODEM) /* Ymodem: the first frame is filename */
  245.     {
  246.       l = len;
  247.       if((ret = p_iow(serial, P_FREAD, buf, &l)) != 0)
  248.         {
  249.           errmsg(c_timedout);
  250.           return;
  251.         }
  252.       if(p_slen(buf) == 0)
  253.         {
  254.           p_iow(serial, P_FDISCONNECT);
  255.           errmsg(c_done);
  256.           return;
  257.         }
  258.       if((l = p_slocr(buf, '\\')) >= 0 || (l = p_slocr(buf, '/')) >= 0)
  259.         l++;
  260.       else
  261.         l = 0;
  262.       p_scpy(xname, fname+1);
  263.       p_scat(xname, buf+l);
  264.     }
  265.       else
  266.     p_scpy(xname, fname+1);
  267.  
  268.       if(p_open(&fp, xname, P_FUPDATE|P_FSTREAM|P_FREPLACE))
  269.     {
  270.       p_iow(serial, P_FDISCONNECT);
  271.       /*
  272.       errmsg("Can't write the file");
  273.       */
  274.       errmsg(xname);
  275.       return;
  276.     }
  277.       AddToHistory('f');
  278.  
  279.       /* ------------------------------------------ Transmit the whole file */
  280.       ret = 0;
  281.       while(ret == 0)
  282.     {
  283.       l = len;
  284.       if((ret = p_iow(serial, P_FREAD, buf, &l)) != 0)
  285.         break;
  286.       ret = p_write(fp, buf, l);
  287.       AddToHistory(ret ? 'R' : 'r');
  288.     }
  289.       p_close(fp); fp = 0;
  290.       if(set.xymodem < XY_YMODEM)
  291.         break;
  292.       if(ret != E_FILE_EOF)
  293.         break;
  294.     }
  295.  
  296.   AddToHistory(ret == E_FILE_EOF ? 'c' : 'C');
  297.  
  298.   /* --------------------------------------------- Close the XYmodem device */
  299.   p_iow(serial, P_FDISCONNECT);
  300.   errmsg((ret || l) ? c_aborting : c_done);
  301. }
  302.  
  303. void 
  304. DoXYmodem(char key)
  305. {
  306.   if(key == 'C')
  307.     xy_configure();
  308.   if(key == 'S')
  309.     xy_sendfile();
  310.   if(key == 'R')
  311.     xy_receivefile();
  312. }
  313. #endif /* HAVE_XYMODEM */
  314.