home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / sinclairqla.zip / qlkus1.c < prev    next >
C/C++ Source or Header  |  1987-05-08  |  19KB  |  514 lines

  1. /*
  2.     US1_C - QL-Kermit user command routines (Part 1)
  3.  
  4.     Based on ckuus[123].c, (C) Columbia University
  5. */
  6.  
  7.  
  8. /* Include files */
  9.  
  10. #include "flp1_ctype_h"                          /* Character type macros */
  11. #include "flp1_fcntl_h"                          /* File opening modes */
  12.  
  13. #include "ram1_ker_h"                            /* Kermit definitions */
  14. #include "ram1_cmd_h"                            /* Command interpreter definitions */
  15. #include "ram1_usr_h"                            /* User command definitions */
  16.  
  17.  
  18. /* External variables */
  19.  
  20. extern int slen;                                 /* Send packet size */
  21. extern int rlen;                                 /* Initial receive packet size */
  22. extern int rtmo;                                 /* Timeout we use */
  23. extern int stmo;                                 /* Timeout remote uses */
  24. extern int state;                                /* Switcher start state */
  25. extern int ttychid;                              /* QDOS channel ID for serial line */
  26. extern int tlevel;                               /* TAKE file nesting level */
  27. extern int trans;                                /* File name translation */
  28. extern int debug;                                /* Debugging level */
  29. extern int speed;                                /* Line speed (baud rate) */
  30. extern int xfertyp;                              /* File transfer type */
  31. extern int retry;                                /* Retry limit */
  32. extern int delay;                                /* Delay before SEND starts */
  33. extern int serno;                                /* Serial port in use */
  34. extern int parity;                               /* Parity setting */
  35. extern int npad;                                 /* Padding amount remote needs */
  36.  
  37. extern bool timer;                               /* Timer enabled flag */
  38. extern bool echo;                                /* Local echo flag */
  39. extern bool local;                               /* Operating mode */
  40. extern bool keep;                                /* Incomplete file disposition */
  41. extern bool tkecho;                              /* Show TAKE commands flag */
  42. extern bool tkabort;                             /* Error abort flag */
  43.  
  44. extern char ssop;                                /* Packet start remote needs */
  45. extern char rsop;                                /* Packet start I need */
  46. extern char reol;                                /* EOL I need */
  47. extern char seol;                                /* EOL remote needs */
  48. extern char quote;                               /* Control quote prefix */
  49. extern char pebq;                                /* 8-bit quote prefix */
  50. extern char enter[];                             /* What ENTER sends */
  51.  
  52. extern unsigned char padch;                      /* Pad character remote needs */
  53.  
  54. extern char stype;                               /* Server command to be done */
  55.  
  56. extern char ttyname[];                           /* Communication device name */
  57.  
  58. extern char *sourdev;                            /* Default source device */
  59. extern char *destdev;                            /* Default destination device */
  60. extern char *takedev;                            /* Default TAKE file device */
  61. extern char *suffix;                             /* Sending file suffix */
  62.  
  63. extern char *vers;                               /* Program version */
  64.  
  65. extern char *cmarg,*cmarg2;                      /* Switcher parameters */
  66.  
  67. extern FILE *tfile[MAXTAKE];                     /* TAKE file stack */
  68.  
  69.  
  70. /* External functions */
  71.  
  72. extern char *ptype();                            /* Parity type name */
  73. extern bool test();                              /* Bit test */
  74.  
  75.  
  76. /* Local variables */
  77.  
  78. char line[CMDBL+10];                             /* General character buffer */
  79. char *lp;                                        /* General pointer */
  80.  
  81. int n;                                           /* General temporary */
  82.  
  83. bool repars;                                     /* Reparse flag */
  84.  
  85. char cmdbuf[CMDBL+4];                            /* Command string buffer */
  86.  
  87.  
  88. /* Macros */
  89.  
  90. #define CHKLINE    { if (!local) { error("Communication line not set"); return(-2); } }
  91.  
  92.  
  93. /* Keyword tables */
  94.  
  95. struct keytab cmdtab[] =                         /* Top-level commands */
  96. {
  97.     0,        "connect",          XXCON,
  98.     0,        "do",               XXDOC,
  99.     0,        "exit",             XXQUI,
  100.     0,        "finish",           XXFIN,
  101.     0,        "get",              XXGET,
  102.     0,        "help",             XXHELP,
  103.     CM_INV,   "quit",             XXQUI,
  104.     0,        "receive",          XXREC,
  105.     0,        "send",             XXSEN,
  106.     0,        "set",              XXSET,
  107.     0,        "show",             XXSHO,
  108.     0,        "take",             XXTAK
  109. };
  110.  
  111. int ncmd = (sizeof(cmdtab) / sizeof(struct keytab));
  112.  
  113.  
  114. struct keytab prmtab[] =                         /* SET parameters */
  115. {
  116.     0,        "baud",             XYSPEE,
  117.     0,        "control-quote",    XYQCTL,
  118.     0,        "debugging",        XYDEB,
  119.     0,        "delay",            XYDEL,
  120.     0,        "device",           XYDEV,
  121.     0,        "eight-bit-quote",  XYEBQ,
  122.     CM_INV,   "end-of-line",      XYEOL,
  123.     0,        "enter",            XYENT,
  124.     0,        "file",             XYFILE,
  125.     0,        "line",             XYLINE,
  126.     0,        "local-echo",       XYECHO,
  127.     CM_INV,   "marker",           XYMARK,
  128.     CM_INV,   "packet-length",    XYLEN,
  129.     0,        "padding",          XYPAD,
  130.     0,        "parity",           XYPARI,
  131.     0,        "receive",          XYRECV,
  132.     0,        "retries",          XYRETR,
  133.     0,        "send",             XYSEND,
  134.     CM_INV,   "speed",            XYSPEE,
  135.     CM_INV,   "start-of-packet",  XYMARK,
  136.     0,        "take-abort",       XYTKAB,
  137.     0,        "take-echo",        XYTKEC,
  138.     CM_INV,   "timeout",          XYTIMO,
  139.     0,        "timer",            XYTIME
  140. };
  141.  
  142. int nprm = (sizeof(prmtab) / sizeof(struct keytab));
  143.  
  144.  
  145. struct keytab shotab[] =                         /* SHOW parameters */
  146. {
  147.     0,        "all",              SHALL,
  148.     0,        "communication",    SHCOM,
  149.     0,        "devices",          SHDEV,
  150.     0,        "file",             SHFILE,
  151.     0,        "prefix",           SHPRE,
  152.     CM_INV,   "quote",            SHPRE,
  153.     0,        "system",           SHSYS,
  154.     0,        "transfer",         SHXFER,
  155.     0,        "version",          SHVER
  156. };
  157.  
  158. int nshotab = (sizeof(shotab) / sizeof(struct keytab));
  159.  
  160.  
  161. /* CMDINI - Initialize the interactive command parser */
  162.  
  163. cmdini()
  164. {
  165.     cls(fgetchid(stdout));                       /* Clear the screen window */
  166.     printf("\n%s\n\n",vers);                     /* Say who we are */
  167.     cmsetp("QLK> ");                             /* Set up prompt */
  168.     tlevel = -1;                                 /* No TAKE files */
  169.  
  170.     if ((tfile[++tlevel] = fopen(DFTAKE,"r"))==NULL)
  171.     {                                            /* Try startup file */
  172.          if (debon) printf("No startup file found\n");
  173.          tlevel--;
  174.     }
  175. }
  176.  
  177.  
  178. /* PARSER - Top-level interactive command parser */
  179.  
  180. parser(status)
  181. bool status;
  182. {
  183.     int xx,cbn;
  184.     char *cbp;
  185.  
  186. /* Abandon all the TAKE files, if the previous file transfer failed */
  187.  
  188.     if (!status && tkabort && tlevel>-1)
  189.     {
  190.          error("Transfer error, TAKE files abandoned");
  191.          while (tlevel>-1) tclose();
  192.     }
  193.     status = TRUE;
  194.  
  195. /* state becomes nonzero when a command has been parsed that requires some
  196.    action from the protocol module.  Any non-protocol actions, such as local
  197.    directory listing or terminal emulation, are invoked directly from below.
  198. */
  199.  
  200.     state = 0;                                   /* Begin with no start state */
  201.     while (state==0)                             /* Parse cmds until action requested */
  202.     {
  203.          *cmarg = '\0';                          /* Start clean */
  204.          *cmarg2 = '\0';
  205.  
  206.          if (tlevel>-1)                          /* If in TAKE file, */
  207.          {
  208.               cmini();
  209.               cbp = cmdbuf;
  210.               cbn = CMDBL;                       /* try for next command from there */
  211.               if (fgets(line,cbn,tfile[tlevel])==NULL)
  212.               {
  213.                    if (feof(tfile[tlevel])!=0)   /* If end of file, close & pop level */
  214.                         tclose();
  215.                    continue;
  216.               }
  217.               if (tkecho) printf("TAKE-%d> %s",tlevel,line);
  218.  
  219.               lp = line;                         /* Got one, copy it */
  220.               while (*cbp++ = *lp++);
  221.          }
  222.          else                                    /* No TAKE file, get user input */
  223.          {
  224.               prompt();                          /* Issue interactive prompt */
  225.               cmini();
  226.          }
  227.  
  228.          repars = TRUE;
  229.          while (repars)                          /* Repeat until a command done */
  230.          {
  231.               cmres();                           /* Reset buffer pointers */
  232.               switch (xx = docmd(cmkey(cmdtab,ncmd,"","Command")))
  233.               {
  234. case -4:           doexit();                     /* EOF, exit successfully */
  235.  
  236. case -1:           repars = TRUE;                /* Reparse needed */
  237.                    continue;
  238.  
  239. case -2:           if (tkabort && tlevel>-1)     /* Unknown command */
  240.                    {                             /* If in TAKE file, quit */
  241.                         error("Command error, TAKE files abandoned");
  242.                         while (tlevel>-1) tclose();
  243.                    }
  244.                    cmini();                      /* Fall through */
  245.  
  246. case -3:                                         /* Empty command, OK at top level */
  247. default:           repars = FALSE;               /* Anything else, get new command */
  248.                    continue;
  249.               }
  250.          }
  251.     }
  252. }
  253.  
  254.  
  255. /* DOEXIT - Exit from the program */
  256.  
  257. doexit()
  258. {
  259.     cls(fgetchid(stdout));                       /* Clear the screen window */
  260.     exit(0);                                     /* Exit from the program */
  261. }
  262.  
  263.  
  264. /* DOCMD - Do a command
  265.  
  266.     Returns:
  267.        -2: user typed an illegal command
  268.        -1: reparse needed
  269.         0: parse was successful (even though command may have failed)
  270. */
  271.  
  272. int docmd(cx)
  273. int cx;
  274. {
  275.     int x,y;
  276.     char *s,*cp;
  277.  
  278.     switch (cx)
  279.     {
  280.  
  281. case -3: return(0);                              /* Null command */
  282.  
  283. case -4:                                         /* EOF */
  284. case -2:                                         /* Error */
  285. case -1: return(cx);                             /* Reparse needed */
  286.  
  287. case XXCON:                                      /* CONNECT */
  288.          if ((x = cmcfm())<0) return(x);
  289.          CHKLINE;
  290.          doconnect();
  291.          return(0);
  292.  
  293. case XXDOC:                                      /* DO */
  294.          if ((x = cmtxt("",&s,"Remote command"))<0) return(x);
  295.          CHKLINE;
  296.          strcpy(cmarg,s);
  297.          stype = 'C';
  298.          state = S_COMD;                         /* Set start state */
  299.          return(0);
  300.  
  301. case XXFIN:                                      /* FINISH */
  302.          if ((x = cmcfm())<0) return(x);
  303.          CHKLINE;
  304.          strcpy(cmarg,"F");
  305.          stype = 'G';
  306.          state = S_COMD;
  307.          return(0);
  308.  
  309. case XXGET:                                      /* GET remote [local=F] */
  310.          CHKLINE;
  311.          x = cmfld("",&s,"Remote filename");     /* Get remote name */
  312.          if (x==-3)
  313.          {
  314.               error("Remote name not specified");
  315.               x = -2;
  316.          }
  317.          if (x<0) return(x);
  318.  
  319.          strcpy(cmarg,s);                        /* Save remote filename */
  320.  
  321.          if ((y = cmfld("",&s,"Optional local filename"))==-3) s = "";
  322.          else if (y<0) return(y);
  323.          strcpy(cmarg2,s);                       /* Get & save local name */
  324.  
  325.          if ((x = cmcfm())<0) return(x);         /* Confirm end of command */
  326.  
  327.          state = G_INIT;                         /* All OK, set start state */
  328.          return(0);
  329.  
  330. case XXHELP:                                     /* HELP */
  331.          if ((x = cmcfm())<0) return(x);
  332.          printf("\nQL-Kermit control keys:\n");
  333.          printf(" Command mode:\n  F1  Context-sensitive help\n  F3  Delete line\n");
  334.          printf("  F4  Complete/default word\n  F5  Delete character\n");
  335.          printf("  ^R  Replay line\n");
  336.          printf("\n Terminal mode:\n  F2  Return to command mode\n");
  337.          printf("  F3  Send a NULL\n  F4  Send a ^C\n  F5  Send a DEL\n");
  338.          printf("\n Transfer mode:\n  ^X  Interrupt file\n  ^Z  Interrupt batch\n");
  339.          printf("  ^E  Interrupt transaction\n  ^T  Resend packet\n");
  340.          printf("\n");
  341.          return(0);
  342.  
  343. case XXQUI:                                      /* QUIT or EXIT */
  344.          if ((x = cmcfm())>-1) doexit();
  345.          else return(x);
  346.  
  347. case XXREC:                                      /* RECEIVE [local=F] */
  348.          CHKLINE;
  349.          x = cmfld("",&s,"Optional local filename");
  350.          if ((x==-1) || (x==-2)) return(x);      /* Get local name */
  351.          if (x==-3) s = "";                      /* Can be omitted */
  352.          strcpy(cmarg2,s);                       /* Given, save it away */
  353.  
  354.          if ((x = cmcfm())<0) return(x);         /* Confirm end */
  355.  
  356.          printf("Waiting\n");
  357.          state = R_INIT;
  358.          return(0);
  359.  
  360. case XXSEN:                                      /* SEND local [remote=local]*/
  361.          CHKLINE;
  362.          x = cmfld("",&s,"Local filename");      /* Get local name */
  363.          if (x==-3)
  364.          {
  365.               error("Local name not specified");
  366.               x = -2;
  367.          }
  368.          if (x<0) return(x);
  369.  
  370.          strcpy(cmarg,s);                        /* Save local name */
  371.          y = cmfld("",&s,"Optional remote filename");
  372.          if ((y==-1) || (y==-2)) return(y);      /* Get remote name */
  373.          if (y!=-3) strcpy(cmarg2,s);            /* If given, store it away */
  374.          if ((y = cmcfm())<0) return(y);
  375.  
  376.          printf("Pausing\n");
  377.          wait(delay);                            /* Wait for the set time */
  378.          state = S_INIT;                         /* Set start state */
  379.          return(0);
  380.  
  381. case XXSET:                                      /* SET */
  382.          x = cmkey(prmtab,nprm,"","What to set");
  383.          if (x==-3)
  384.          {
  385.               error("SET parameter not specified");
  386.               x = -2;
  387.          }
  388.          if (x<0) return(x);
  389.          else return(doprm(x));
  390.  
  391. case XXSHO:                                      /* SHOW */
  392.          x = cmkey(shotab,nshotab,"all","What to show");
  393.          if (x<0) return(x);                     /* Find out what to show */
  394.          if (y = (cmcfm())<0) return(y);
  395.  
  396.          if (x==SHVER) printf("\nVersion: %s\n\n",vers);
  397.          else shopar(x);
  398.          return(0);
  399.  
  400. case XXTAK:                                      /* TAKE */
  401.          if (tlevel>MAXTAKE-1)                   /* Check not too many */
  402.          {
  403.               error("TAKE files nested too deeply");
  404.               return(-2);
  405.          }
  406.          if ((y = cmfld("",&s,"Command file name"))<0)
  407.          {                                       /* Get file name */
  408.               if (y==-3)
  409.               {
  410.                    error("Command file not specified");
  411.                    return(-2);
  412.               }
  413.               else return(y);
  414.          }
  415.          strcpy(line,s);                         /* Make a safe copy of the name */
  416.          if ((y = cmcfm())<0) return(y);
  417.  
  418.          if ((tfile[++tlevel] = fopen(line,"r"))==NULL)
  419.          {                                       /* Try to open file */
  420.               if (debon) printf("Couldn't open TAKE file %s\n",line);
  421.               strcpy(s,takedev);                 /* Prepend TAKE device */
  422.               cp = line;
  423.               strncat(s,cp,15);
  424.               if ((tfile[tlevel] = fopen(s,"r"))==NULL)
  425.               {                                   /* Try again */
  426.                    qdoserr();
  427.                    error("Cannot open %s or %s",line,s);
  428.                    tlevel--;                     /* Give up if can't */
  429.               }
  430.          }
  431.          return(0);                              /* Whether opened or not */
  432.  
  433. default: error("Invalid command - %s\n",cmdbuf);
  434.          return(-2);
  435.     }
  436. }
  437.  
  438.  
  439. /*  SHOPAR - Show Parameters */
  440.  
  441. shopar(f)
  442. int f;
  443. {
  444.     if (test(f,SHCOM))
  445.     {
  446.          printf("\nCommunications parameters:\n");
  447.          printf(" Line ");
  448.          if (serno<0) printf("not set"); else printf("%s",ttyname);
  449.          printf(", speed ");
  450.          if (speed<0) printf("not set"); else printf("%d",speed);
  451.          printf(", parity %s\n",ptype(parity));
  452.          printf(" Local echo %s\n",(echo ? "on" : "off"));
  453.          printf(" ENTER sends %s",(enter[0]==CR ? "CR" : "LF"));
  454.          if (enter[1]!=0) printf("+%s",(enter[1]==CR ? "CR" : "LF"));
  455.          printf("\n");
  456.     }
  457.  
  458.     if (test(f,SHXFER))
  459.     {
  460.          printf("\nTransfer parameters:    Send   Receive\n");
  461.          printf(" Timeout        %11d%9d\n",stmo,rtmo);
  462.          printf(" Packet start   %11d%9d\n",ssop,rsop);
  463.          printf(" Packet end     %11d%9d\n",seol,reol);
  464.          printf(" Packet length  %11d%9d\n",slen,rlen);
  465.          printf(" Delay          %11d\n",delay);
  466.          printf(" Padding        ");
  467.          if (npad==0) printf("%12s\n","none");
  468.          else printf("%11d\n  of                     0%o ('%c')\n",npad,padch,padch);
  469.     }
  470.  
  471.     if (test(f,SHFILE))
  472.     {
  473.          printf("\nFile parameters:\n");
  474.          printf(" Incomplete files %s\n",keep ? "kept" : "deleted");
  475.          printf(" Transfer mode %s\n",xfertyp==FTASC ? "ASCII" : "binary");
  476.          printf(" Naming %s\n",trans==FNNORM ? "normal" : "untranslated");
  477.          if (strlen(suffix)==0) printf(" No send suffix\n");
  478.          else printf(" Send suffix %s\n",suffix);
  479.     }
  480.  
  481.     if (test(f,SHPRE))
  482.     {
  483.          printf("\nPrefix characters:\n");
  484.          printf(" Control quote     %c\n",quote);
  485.          printf(" Eight-bit quote   %c\n",pebq);
  486.     }
  487.  
  488.     if (test(f,SHSYS))
  489.     {
  490.          printf("\nSystem parameters:\n");
  491.          printf(" Mode %s\n",(local ? "local" : "remote"));
  492.          printf(" Timer %s, retry limit %d\n",timer ? "enabled" : "disabled",retry);
  493.          printf(" Debugging ");
  494.          switch (debug)
  495.          {
  496. case DBOFF:   printf("off"); endcase;
  497. case DBON:    printf("on"); endcase;
  498. case DBFULL:  printf("full"); endcase;
  499.          }
  500.          printf("\n TAKE file echo %s,",tkecho ? "on" : "off");
  501.          printf(" %s on error\n",tkabort ? "abort" : "continue");
  502.     }
  503.  
  504.     if (test(f,SHDEV))
  505.     {
  506.          printf("\nDevices:\n");
  507.          printf(" Transfer source       %s\n",sourdev);
  508.          printf(" Transfer destination  %s\n",destdev);
  509.          printf(" TAKE file source      %s\n",takedev);
  510.     }
  511.  
  512.     printf("\n");
  513. }
  514.