home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff330.lzh / Vt100 / Src.lzh / Src / newkermit.c < prev    next >
C/C++ Source or Header  |  1990-03-01  |  8KB  |  343 lines

  1. /*            :ts=8                        */
  2.  
  3. /*
  4.  * These are the new interfaces between vt100 and the new Kermit protocol
  5.  * module.
  6.  */
  7.  
  8. #include "vt100.h"            /* Get defines and so on    */
  9. /*
  10.  * Here are the declarations for our communication with kermitproto.c
  11.  */
  12.  
  13. extern int    cx, cz;            /* Abort flags            */
  14.  
  15. extern char    start;            /* Start state for Kermit    */
  16. char        *cmarg;            /* Command argument for server    */ 
  17.  
  18. /*
  19.  * The below variables have to do with the status of the communcation
  20.  * so far.  They should be maintained over in kermitproto.w so that
  21.  * things like the number of bytes sent and the packet type can be
  22.  * printed as status.
  23.  */
  24. static int    npackets,        /* Number of packets sent so far */
  25.         naks;            /* Number of naks        */
  26.  
  27.  
  28. static char message[80];        /* Message line to output    */
  29.  
  30. /*
  31.  * Do Kermit sending.  This expands wild cards into local variables for
  32.  * gnfile() below.
  33.  */
  34.  
  35. static int nfiles, wild;
  36. static char **lp, **list;
  37.  
  38. doksend(file,more)
  39. char *file;
  40. int more;
  41. {
  42.     char *p;
  43.  
  44.     list = NULL;
  45.     p = file;
  46.     while(*p && *p != '*' && *p != '?') p++;
  47.     if (*p) {
  48.     wild = 1;
  49.     list = expand(file, &nfiles);
  50.     if (list == NULL) {
  51.         InfoMsg1Line("KERMIT: No wild card match");
  52.         return FALSE;
  53.     }
  54.     }
  55.     else {
  56.     nfiles = 1;
  57.     wild = 0;
  58.     list = (char **) malloc(sizeof(char *));
  59.     *list = (char *) malloc(strlen(file) + 1);
  60.     strcpy(*list, file);
  61.     }
  62.     lp = list;
  63.     start = 's';            /* Set start state to send    */
  64.     npackets = naks = 0;
  65.     message[0] = '\0';
  66.     proto();                /* Call protocol        */
  67.     if (wild == 1)
  68.     free_expand(list);
  69.     else {
  70.     free((void *) *list);
  71.     free((void *) list);
  72.     }
  73.     return TRUE;
  74. }
  75.  
  76. /*
  77.  * gnfile(s, n)  char *s; int n;
  78.  *
  79.  * Returns in string s the name of the next file for Kermit to process,
  80.  * which can be up to n characters in length.  Returns a positive value
  81.  * if there are more files, 0 if not.
  82.  */
  83. int
  84. gnfile(s, n)
  85. char *s;
  86. int n;
  87. {
  88.     if (--nfiles >= 0) {
  89.     strncpy(s, *lp, n);
  90.     lp++;
  91.     return 1;
  92.     } else
  93.     return 0;
  94. }
  95.  
  96. /*
  97.  * Do Kermit receiving.  The file and more arguments in this routine are
  98.  * for Get'ting files when the remote machine is the server.
  99.  */
  100. dokreceive(file,more)
  101. char *file;
  102. int more;
  103. {
  104.     naks = npackets = 0;
  105.     message[0] = '\0';            /* Initialize            */
  106.     if (!server)
  107.     start = 'v';            /* Start state to receive    */
  108.     else {
  109.     cmarg = file;            /* Files to get from remote    */
  110.     start = 'r';            /* Start state to get        */
  111.     }
  112.     proto();
  113.     return TRUE;
  114. }
  115.  
  116. /* kermit_directory()--request a remote directory from a Kermit server.
  117.  */
  118.  
  119. #define tochar(c) ((c) + 32)
  120.  
  121. void
  122. kermit_directory(dir)
  123. char *dir;
  124. {
  125.     char command[80];
  126.  
  127.     strcpy(command, "D");        /* Generic directory command */
  128.     command[1] = tochar(strlen(dir));    /* Length of directory name */
  129.     strcpy(&command[2], dir);        /* The directory itself */
  130.     cmarg = command;
  131.     start = 'g';            /* Generic command start state */
  132.     naks = npackets = 0;
  133.     proto();
  134. }
  135.  
  136. /*
  137.  * saybye()--send a FINISH command to a remote Kermit server.  This is
  138.  * in fact what the original VT100 saybye() does.  A true Kermit BYE
  139.  * command would mean changing the "F" below to "L", and it would actually
  140.  * log out the remote host as well as shut down the Kermit server.
  141.  */
  142. void
  143. saybye()
  144. {
  145.     static char bye_command[] = "F";
  146.  
  147.     cmarg = &bye_command[0];
  148.     start = 'g';            /* Generic command start state    */
  149.     naks = npackets = 0;
  150.     proto();
  151.     return /* TRUE */;
  152. }
  153.  
  154. /*
  155.  * ttinl(dest, max, eol, timelimit)
  156.  *
  157.  * Read up to max characters from serial port into the array pointed
  158.  * to by dest.  Return value is the number of characters received.
  159.  *    If eol is greater than 0, terminate read upon first
  160.  * eol character received.  If timelimit is greater than 0, wait at
  161.  * most timelimit seconds for the characters.  The array is null
  162.  * terminated;  in addition, if we do see an eol, we overwrite it
  163.  * with the NULL and the returned character count does not include it.
  164.  * (This behavior is required by the code in the C Kermit book but is
  165.  * not explicitly stated there.)
  166.  *
  167.  * This version is most unsatisfactory as it does I/O one character
  168.  * at a time, but extensive changes in the rest of VT100 would be
  169.  * needed in order to use a multi-character read.
  170.  */
  171.  
  172. static int pushedser = -1;            /* pushed character    */
  173.  
  174. int ttinl(dest, max, eol, timelimit)
  175. char *dest;
  176. int max, eol, timelimit;
  177. {
  178.     int i;
  179.     void ttflui();
  180.  
  181.     if (timelimit > 0)
  182.     ttime = timelimit;
  183.     else
  184.     ttime = 30;            /* Maximum timeout if not given    */
  185.     for (i = 0; i < max; i++) {
  186.     dest[i] = readchar();
  187.     if (timeout != GOODREAD) {
  188.         if (timeout == USERABORT) {    /* User abort requested        */
  189.         if (cx == 1)
  190.             start = 'a';    /* Second escape--abort mess    */
  191.         else
  192.             cx = cz = 1;    /* Set abort flags        */
  193.         continue;        /* Continue receiving anyway    */
  194.         } else {
  195.         i = -1;            /* Some other error.        */
  196.         break;
  197.         }
  198.     }
  199.     if (eol > 0 && dest[i] == eol)
  200.         break;
  201.     ttime = 2;            /* Intrapacket timeout        */
  202.     }
  203.     if (i >= 0)
  204.     dest[i] = '\0';            /* Null terminate what we got    */
  205.     else
  206.     dest[0] = '\0';
  207.     return i;                /* Return length or failure    */
  208. }
  209.  
  210. /*
  211.  * ttol(out, n)
  212.  *
  213.  * Send n characters pointed to by out through the serial port using
  214.  * current settings of word length, parity, and flow control. Return
  215.  * 
  216.  *
  217.  * Here I bypass sendchar() and go direct to the low level.
  218.  */
  219. int
  220. ttol(out, n)
  221. char *out;
  222. int n;
  223. {
  224.     int retval;
  225.  
  226.     Write_Request->IOSer.io_Data = (APTR) out;
  227.     Write_Request->IOSer.io_Length = n;
  228.     Write_Request->IOSer.io_Command = CMD_WRITE;
  229.     SendIO((struct IORequest *)Write_Request);
  230.     retval = WaitIO((struct IORequest *)Write_Request);
  231.     /*
  232.      * Restore old values.
  233.      */
  234.     Write_Request->IOSer.io_Data = (APTR) rs_out;
  235.     Write_Request->IOSer.io_Length = 1;
  236.     if (retval != 0)
  237.     return -1;
  238.     else
  239.     return ((int)Write_Request->IOSer.io_Actual);
  240. }
  241.  
  242. /*
  243.  * ttflui()
  244.  *
  245.  * Remove any pending characters from the serial port.
  246.  *
  247.  * Even worse than ttinl() and ttol(), this reads characters with a minimal
  248.  * timeout until there aren't any more.  Note that I also changed readchar()
  249.  * in xmodem.c to check if ttime is 0, and if it is, to set its timeout to
  250.  * 100,000 ticks (0.1 seconds).  I also removed the InfoMsg1Line call which
  251.  * warned about timeouts so this would work.  Ideally, ttinl() should do
  252.  * a single CMD_READ in ReadRequest, and ttflui() should AbortIO() it.
  253.  */
  254. void
  255. ttflui()
  256. {
  257.     int c;
  258.  
  259.     ttime = 0;
  260.     do {
  261.     c = readchar();
  262.     } while (timeout == GOODREAD);
  263. }
  264.  
  265. void
  266. sleep(seconds) int seconds;
  267. {
  268.     if (seconds > 0)
  269.     Delay(seconds*TICKS_PER_SECOND);
  270. }
  271.  
  272. /*
  273.  * Now here are tmsg() and tchar() for putting out warnings.  What I've done
  274.  * is to use tchar()'s argument as a flag to put out whatever status we need.
  275.  * tmsg()'s argument is put out as a message line.
  276.  */
  277.  
  278. /*
  279.  * tchar(c)--put the single character c onto the user's screen as part
  280.  * of Kermit's communication to said user.
  281.  */
  282. void
  283. tchar(c)
  284. char c;
  285. {
  286.     char status[80];
  287.     void tmsg();
  288.  
  289.     switch (c) {
  290.     case '.':
  291.         npackets++;
  292.         break;
  293.     case '%':
  294.         naks++;
  295.         break;
  296.     default:
  297.         status[0] = c;
  298.         status[1] = '\0';
  299.         tmsg(status);            /* Output unknown chars */
  300.         return;
  301.     }
  302.     sprintf(status, "Packets: %4d Retries: %4d", npackets, naks);
  303.     InfoMsgNoScroll(status);
  304. }
  305.  
  306. /*
  307.  * tmsg(s) char *s;--Put a message string onto the user's screen as part
  308.  * of the communication from Kermit.
  309.  *
  310.  * I put out a message using InfoMsg.  We store it up until we get a newline,
  311.  * then we scroll and put it out.
  312.  */
  313.  
  314. void
  315. tmsg(more_message)
  316. char *more_message;
  317. {
  318.     /*
  319.      * If new message won't fit, put out message so far and copy it.
  320.      * Otherwise, just catenate new message to old.
  321.      */
  322.     if (strlen(more_message) + strlen(message) < sizeof(message)) {
  323.     strcat(message,more_message);
  324.     } else {
  325.     InfoMsg1Line(message);
  326.     strcpy(message,more_message);
  327.     }
  328. }
  329.  
  330. /*
  331.  * tmsgl(s) char *s;--Put out a newline-terminated message to the user's
  332.  * screen as part of Kermit communication.
  333.  */
  334. void
  335. tmsgl(more_message)
  336. char *more_message;
  337. {
  338.     tmsg(more_message);
  339.     InfoMsg1Line(message);
  340.     message[0] = '\0';
  341. }
  342.  
  343.