home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / ncr9800 / ckvusr.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  51KB  |  1,502 lines

  1. char     *userv = "User Interface 4E(060), 06 June 90";
  2.  
  3. /*  C K V U S R --  "User Interface" for NCR-VRX Kermit (Part 1)  */
  4.  
  5. /**********************************************************************
  6. *                                                                     *
  7. * IVS / MCS-Kermit REL 2                                              *
  8. * source code                                                         *
  9. *                                                                     *
  10. * Change History:                                                     *
  11. *                                                                     *
  12. *                1. Modify C-Kermit(4E) source code to                *
  13. *                   produce new module for MCS/IVS-Kermit             *
  14. *                   ORIGINAL RELEASE                                  *
  15. *                   June 22, 1990                                     *
  16. *                                                                     *
  17. *                                                                     *
  18. ***********************************************************************/
  19.  
  20.  
  21. /*
  22.  4E, support for Apollo Aegis, Data General added, July 87.
  23. */
  24. /*
  25.  Author: Frank da Cruz (fdc@cunixc.cc.columbia.edu, FDCCU@CUVMA.BITNET),
  26.  Columbia University Center for Computing Activities.
  27.  First released January 1985.
  28.  Copyright (C) 1985, 1989, Trustees of Columbia University in the City of New
  29.  York.  Permission is granted to any individual or institution to use, copy, or
  30.  redistribute this software so long as it is not sold for profit, provided this
  31.  copyright notice is retained.
  32. */
  33.  
  34. /*
  35.  The ckuusr module contains the terminal input and output functions for VRX
  36.  Kermit.  It includes a simple NCR-VRX-style command line parser as well as
  37.  an interactive prompting keyword command parser.  It depends on the existence
  38.  of VRX facilities like fopen, fgets, feof, (f)printf, argv/argc, etc.  Other
  39.  functions that are likely to vary among VRX implementations -- like setting
  40.  terminal modes or interrupts -- are invoked via calls to functions that are
  41.  defined in the system-dependent modules, ck?[ft]io.c.
  42.  
  43.  The command line parser processes any arguments found on the command line,
  44.  as passed to main() via argv/argc.  The interactive parser uses the facilities
  45.  of the cmd package (developed for this program, but usable by any program).
  46.  
  47.  Any command parser may be substituted for this one.  The only requirements
  48.  for the Kermit command parser are these:
  49.  
  50.  1. Set parameters via global variables like duplex, speed, ttname, etc.
  51.     See ckmain.c for the declarations and descriptions of these variables.
  52.  
  53.  2. If a command can be executed without the use of Kermit protocol, then
  54.     execute the command directly and set the variable sstate to 0. Examples
  55.     include 'set' commands, local directory listings, the 'connect' command.
  56.  
  57.  3. If a command requires the Kermit protocol, set the following variables:
  58.  
  59.     sstate                             string data
  60.       'x' (enter server mode)            (none)
  61.       'r' (send a 'get' command)         cmarg, cmarg2
  62.       'v' (enter receive mode)           cmarg2
  63.       'g' (send a generic command)       cmarg
  64.       's' (send files)                   nfils, cmarg & cmarg2 OR cmlist
  65.       'c' (send a remote host command)   cmarg
  66.  
  67.     cmlist is an array of pointers to strings.
  68.     cmarg, cmarg2 are pointers to strings.
  69.     nfils is an integer.
  70.  
  71.     cmarg can be a filename string (possibly wild), or
  72.        a pointer to a prefabricated generic command string, or
  73.        a pointer to a host command string.
  74.     cmarg2 is the name to send a single file under, or
  75.        the name under which to store an incoming file; must not be wild.
  76.     cmlist is a list of nonwild filenames, such as passed via argv.
  77.     nfils is an integer, interpreted as follows:
  78.       -1: argument string is in cmarg, and should be expanded internally.
  79.        0: stdin.
  80.       >0: number of files to send, from cmlist.
  81.  
  82.  The screen() function is used to update the screen during file transfer.
  83.  The tlog() function maintains a transaction log.
  84.  The debug() function maintains a debugging log.
  85.  The intmsg() and chkint() functions provide the user i/o for interrupting
  86.    file transfers.
  87. */
  88.  
  89. /* Includes */
  90.  
  91. #include "ckcdeb.h"
  92. #include <stdio.h>
  93. #include <ctype.h>
  94. #include <signal.h>
  95. #include "ckcker.h"
  96. #include "ckucmd.h"
  97. #include "ckuusr.h"
  98. #include "kermisc.h"
  99.  
  100. #ifdef MCS_FLAG
  101. #include "mcs.h"
  102. #endif
  103.  
  104. /* External Kermit Variables, see ckmain.c for description. */
  105.  
  106. extern int     EXECL();
  107.  
  108. extern void errhdlr();
  109.  
  110. #ifdef MCS_FLAG
  111. extern void \:FINISH();
  112. #endif
  113.  
  114. extern int     size, rpsiz, urpsiz, speed, local,
  115. server, displa, binary, parity, deblog, escape, xargc, flow,
  116. turn, duplex, nfils, ckxech, pktlog, seslog, tralog, stdouf,
  117. turnch, dfloc, keep, maxrps, /*  warn, */ quiet, cnflg, tlevel,
  118. send_id, recv_id, send_num, recv_num, send_renum, recv_renum,
  119. send_addnum, recv_addnum;
  120.  
  121. extern char     *versio, *protv, *ckxv, *ckzv, *fnsv, *connv, *dftty, *cmdv;
  122. extern char     *dialv, *loginv;
  123. extern char     *ckxsys, *ckzsys, *cmarg, *cmarg2, **xargv, **cmlist;
  124. extern char     cmerrp[];
  125. extern CHAR sstate, ttname[];
  126. char     *strcpy(), *GETENV();
  127.  
  128. /* Declarations from cmd package */
  129.  
  130. extern char     cmdbuf[];                   /* Command buffer */
  131. extern int      cmflgs;                     /* Command flags */
  132.  
  133. /* Declarations from ck?fio.c module */
  134.  
  135. extern char     *zhome();           /* Space command, home directory. */
  136. extern int     backgrd;             /* Kermit executing in background */
  137.  
  138. /* The background flag is set by ckutio.c (via conint() ) to note whether */
  139. /* this kermit is executing in background ('&' on shell command line).    */
  140.  
  141.  
  142. /* Variables and symbols local to this module */
  143.  
  144. char     line[CMDBL+10], *lp;               /* Character buffer for anything */
  145. char     debfil[50];                        /* Debugging log file name */
  146. char     pktfil[50];                        /* Packet log file name */
  147. char     sesfil[50];                        /* Session log file name */
  148. char     trafil[50];                        /* Transaction log file name */
  149.  
  150. int     n,                                  /* General purpose int */
  151. cflg,                               /* Command-line connect cmd given */
  152. action,                             /* Action selected on command line*/
  153. repars,                             /* Reparse needed */
  154. cwdf = 0;                           /* CWD has been done */
  155.  
  156. #define MAXTAKE 20                  /* Maximum nesting of TAKE files */
  157. FILE *tfile[MAXTAKE];               /* File pointers for TAKE command */
  158.  
  159. char     *homdir;                   /* Pointer to home directory string */
  160. char     cmdstr[100];               /* Place to build generic command */
  161.  
  162. /*  C M D L I N  --  Get arguments from command line  */
  163. /*
  164.  Simple NCR-VRX-style command line parser, conforming with 'A Proposed Command
  165.  Syntax Standard for NCR-VRX Systems', Hemenway & Armitage, Unix/World, Vol.1,
  166.  No.3, 1984.
  167. */
  168. cmdlin()
  169. {
  170.      char     x;                             /* Local general-purpose int */
  171.      cmarg = "";                         /* Initialize globals */
  172.      cmarg2 = "";
  173.      action = cflg = 0;
  174.  
  175.      while (--xargc > 0) {               /* Go through command line words */
  176.           xargv++;
  177.           if (deblog)
  178.                debug(F111, "xargv", *xargv, xargc);
  179.           if (**xargv == '-') {       /* Got an option (begins with dash) */
  180.                x = *(*xargv + 1);     /* Get the option letter */
  181.                x = doarg(x);          /* Go handle the option */
  182.                if (x < 0)
  183.                     doexit(BAD_EXIT);
  184.           } else {                        /* No dash where expected */
  185.                usage();
  186.                doexit(BAD_EXIT);
  187.           }
  188.      }
  189.      if (deblog)
  190.           debug(F101, "action", "", action);
  191.      if (!local) {
  192.           if ((action == 'g') || (action == 'r') ||  (action ==
  193.               'c') || (cflg != 0))
  194.                fatal("-l and -b required");
  195.      }
  196.      if (*cmarg2 != 0) {
  197.           if ((action != 's') && (action != 'r') &&  (action !=
  198.               'v'))
  199.                fatal("-a without -s, -r, or -g");
  200.      }
  201.      if ((action == 'v') && (stdouf) && (!local)) {
  202.           if (isatty(1))
  203.                fatal("unredirected -k can only be used in local mode");
  204.      }
  205.      if ((action == 's') || (action == 'v') ||  (action == 'r') ||
  206.          (action == 'x')) {
  207.           if (local)
  208.                displa = 1;
  209.           if (stdouf) {
  210.                displa = 0;
  211.                quiet = 1;
  212.           }
  213.      }
  214.  
  215.      if (quiet)
  216.           displa = 0;              /* No display if quiet requested */
  217.  
  218.      if (cflg) {
  219.           conect();                       /* Connect if requested */
  220.           if (action == 0) {
  221.                if (cnflg)
  222.                     conect();        /* And again if requested */
  223.                doexit(GOOD_EXIT);          /* Then exit indicating success */
  224.           }
  225.      }
  226.      if (displa)
  227.           concb(escape);          /* (for console "interrupts") */
  228.      return(action);                     /* Then do any requested protocol */
  229. }
  230.  
  231.  
  232. /*  D O A R G  --  Do a command-line argument.  */
  233.  
  234. doarg(x)
  235. char     x;
  236. {
  237.      int     z;
  238.      char     *xp;
  239.  
  240.      if (deblog) debug(F101,"funct: doarg> x:","",x);
  241.  
  242.      xp = *xargv + 1;                      /* Pointer for bundled args */
  243.      while (x) {
  244.           switch (x) {
  245.  
  246.           case 'x':                               /* server */
  247.                if (action)
  248.                     fatal("conflicting actions");
  249.                action = 'x';
  250.                break;
  251.  
  252.           case 'f':
  253.                if (action)
  254.                     fatal("conflicting actions");
  255.                action = setgen('F', "", "", "");
  256.                break;
  257. /*
  258. *         case 'r':                               * receive *
  259. *              if (action)
  260. *                   fatal("conflicting actions");
  261. *              action = 'v';
  262. *              break;
  263. *
  264. *         case 'k':                               * receive to stdout *
  265. *              if (action)
  266. *                   fatal("conflicting actions");
  267. *              stdouf = 1;
  268. *              action = 'v';
  269. *              break;
  270. *
  271. *         case 's':                                * send *
  272. *              if (action)
  273. *                   fatal("conflicting actions");
  274. *              if (*(xp + 1))
  275. *                   fatal("invalid argument bundling after -s");
  276. *               * Initialize file counter, flag *
  277. *               z = nfils = 0;
  278. *               * Remember this pointer *
  279. *               cmlist = xargv + 1;
  280. *               while (--xargc > 0) {                * Traverse the list *
  281. *                    *xargv++;
  282. *                    if (**xargv == '-') {       * Check for sending stdin *
  283. *                         if (strcmp(*xargv, "-") != 0)
  284. *                              break;
  285. *                         z++;
  286. *                    }
  287. *                    nfils++;                         * Bump file counter *
  288. *               }
  289. *               xargc++, *xargv--;                   * Adjust argv/argc *
  290. *               if (nfils < 1)
  291. *                    fatal("missing filename for -s");
  292. *               if (z > 1)
  293. *                    fatal("-s: too many -'s");
  294. *               if (z == 1) {
  295. *                    if (nfils == 1)
  296. *                         nfils = 0;
  297. *                    else
  298. *                         fatal("invalid mixture of filenames and '-' in -s");
  299. *               }
  300. *               if (nfils == 0) {
  301. *                    if (isatty(0))
  302. *                         fatal("sending from terminal not allowed");
  303. *               }
  304. *               if (deblog)
  305. *                    debug(F101, *xargv, "", nfils);
  306. *               action = 's';
  307. *               break;
  308. *
  309. *          case 'g':                                * get *
  310. *               if (action)
  311. *                    fatal("conflicting actions");
  312. *               if (*(xp + 1))
  313. *                    fatal("invalid argument bundling after -g");
  314. *               *xargv++, xargc--;
  315. *               if ((xargc == 0) || (**xargv == '-'))
  316. *                    fatal("missing filename for -g");
  317. *               cmarg = *xargv;
  318. *               action = 'r';
  319. *               break;
  320. *
  321. *          case 'c':                                * connect before *
  322. *               cflg = 1;
  323. *               break;
  324. *
  325. *          case 'n':                                * connect after *
  326. *               cnflg = 1;
  327. *               break;
  328. */
  329.           case 'h':                               /* help */
  330.                usage();
  331.                return(-1);
  332.  
  333. /*         case 'a':                                * "as" *
  334. *               if (*(xp + 1))
  335. *                    fatal("invalid argument bundling after -a");
  336. *               *xargv++, xargc--;
  337. *               if ((xargc < 1) || (**xargv == '-'))
  338. *                    fatal("missing name in -a");
  339. *               cmarg2 = *xargv;
  340. *               break;
  341. *
  342. *          case 'l':                                * set line *
  343. *               if (*(xp + 1))
  344. *                    fatal("invalid argument bundling after -l");
  345. *               *xargv++, xargc--;
  346. *               if ((xargc < 1) || (**xargv == '-'))
  347. *                    fatal("communication line device name missing");
  348. *               strcpy(ttname, *xargv);
  349. *
  350. *                *  if (strcmp(ttname,dftty) == 0) local = dfloc;
  351. *                   else local = 1;  *
  352. *
  353. *                * (better than old way) *
  354. *               local = (strcmp(ttname, CTTNAM) != 0);
  355. *               if (deblog)
  356. *                    debug(F101, "local", "", local);
  357. *               ttopen(ttname, &local, 0);
  358. *               break;
  359. *
  360. *          case 'b':                                * set baud *
  361. *               if (*(xp + 1))
  362. *                    fatal("invalid argument bundling");
  363. *               *xargv++, xargc--;
  364. *               if ((xargc < 1) || (**xargv == '-'))
  365. *                    fatal("missing baud");
  366. *               z = atoi(*xargv);                    * Convert to number *
  367. *               if (chkspd(z) > -1)
  368. *                    speed = z;       * Check it *
  369. *               else
  370. *                    fatal("unsupported baud rate");
  371. *              break;
  372. */
  373.           case 'e':                               /* Extended packet length */
  374.                if (*(xp + 1))
  375.                     fatal("invalid argument bundling");
  376.                *xargv++, xargc--;
  377.                if ((xargc < 1) || (**xargv == '-'))
  378.                     fatal("missing length");
  379.                z = atoi(*xargv);                   /* Convert to number */
  380.                if (z > 10 && z < maxrps) {
  381.                     rpsiz = urpsiz = z;
  382.                     if (z > 94)
  383.                          rpsiz = 94;      /* Fallback if other Kermit can't */
  384.                } else
  385.                     fatal("Unsupported packet length");
  386.                break;
  387.  
  388.           case 'i':                               /* Treat files as binary */
  389.                binary = 1;
  390.                break;
  391.  
  392.  
  393.        /* case 'w':                                * File warning *
  394.         *      warn = 1;
  395.         *      break;
  396.         */
  397.  
  398.           case 'q':                               /* Quiet */
  399.                quiet = 1;
  400.                break;
  401.  
  402.           case 'd':                               /* debug */
  403.                debopn("debuglog");
  404.                break;
  405.  
  406.           case 'p':                               /* set parity */
  407.                if (*(xp + 1))
  408.                     fatal("invalid argument bundling");
  409.                *xargv++, xargc--;
  410.                if ((xargc < 1) || (**xargv == '-'))
  411.                     fatal("missing parity");
  412.                switch (x = **xargv) {
  413.                case 'e':
  414.                case 'o':
  415.                case 'm':
  416.                case 's':
  417.                     parity = x;
  418.                     break;
  419.                case 'n':
  420.                     parity = 0;
  421.                     break;
  422.                default:
  423.                     fatal("invalid parity");
  424.                }
  425.                break;
  426.  
  427.           case 't':
  428.                turn = 1;            /* Line turnaround handshake */
  429.                turnch = XON;        /* XON is turnaround character */
  430.                duplex = 1;          /* Half duplex */
  431.                flow = 0;            /* No flow control */
  432.                break;
  433.  
  434.           default:
  435.                fatal("invalid argument, type 'kermit -h' for help");
  436.           }
  437.  
  438.           x = *++xp;                          /* See if options are bundled */
  439.      }
  440.      return(0);
  441. }
  442.  
  443.  
  444. fatal(msg)
  445. char     *msg;
  446. {                 /* Fatal error message */
  447.      fprintf(stderr, "\r\nFatal: %s\n", msg);
  448.      tlog(F110, "Fatal:", msg, 0l);
  449.      doexit(BAD_EXIT);                   /* Exit indicating failure */
  450. }
  451.  
  452.  
  453. ermsg(msg)
  454. char     *msg;
  455. {                 /* Print error message */
  456.      if (!quiet)
  457.           fprintf(stderr, "\r\n%s - %s\n", cmerrp, msg);
  458.      tlog(F110, "Error -", msg, 0l);
  459. }
  460.  
  461.  
  462. /* Interactive command parser */
  463.  
  464.  
  465. /* Top-Level Keyword Table */
  466.  
  467. struct keytab cmdtab[] = {
  468.      "!",           XXSHE, CM_INV,
  469.      "%",           XXCOM, CM_INV,
  470.      "bye",         XXBYE, CM_INV,
  471.      "c",           XXCON, CM_INV,
  472.      "cd",          XXCWD, CM_INV,
  473.      "close",       XXCLO, 0,
  474.      "connect",     XXCON, CM_INV,
  475.      "cwd",         XXCWD, CM_INV,
  476.      "dial",        XXDIAL, CM_INV,
  477.      "directory",   XXDIR, CM_INV,
  478.      "echo",        XXECH, 0,
  479.      "exit",        XXEXI, 0,
  480.      "finish",      XXFIN, CM_INV,
  481.      "get",         XXGET, CM_INV,
  482.      "hangup",      XXHAN, CM_INV,
  483.      "help",        XXHLP, 0,
  484.      "log",         XXLOG, 0,
  485.      "quit",        XXQUI, 0,
  486.      "r",           XXREC, CM_INV,
  487.      "receive",     XXREC, CM_INV,
  488.      "remote",      XXREM, CM_INV,
  489.      "s",           XXSEN, CM_INV,
  490.      "script",      XXLOGI, CM_INV,
  491.      "send",        XXSEN, CM_INV,
  492.      "server",      XXSER, 0,
  493.      "set",         XXSET, 0,
  494.      "show",        XXSHO, 0,
  495.      "space",       XXSPA, CM_INV,
  496.      "statistics",  XXSTA, 0,
  497.      "take",        XXTAK, 0
  498. };
  499.  
  500.  
  501. int     ncmd = (sizeof(cmdtab)
  502.  / sizeof(struct keytab )
  503. );
  504.  
  505. /* Parameter keyword table */
  506.  
  507. struct keytab prmtab[] = {
  508.      "baud",             XYSPEE,  CM_INV,
  509.      "add-linenum",      XYADD,   CM_INV,    /* moved to send/receive */
  510.      "block-check",      XYCHKT,  0,
  511.      "delay",            XYDELA,  CM_INV,
  512.      "duplex",           XYDUPL,  0,
  513.      "end-of-packet",    XYEOL,   CM_INV,    /* moved to send/receive */
  514.      "escape-character", XYESC,   CM_INV,
  515.      "file",             XYFILE,  0,
  516.      "flow-control",     XYFLOW,  0,
  517.      "handshake",        XYHAND,  0,
  518.      "id-fields",        XYID,    CM_INV,    /* moved to send/receive */
  519.      "incomplete",       XYIFD,   0,
  520.      "line",             XYLINE,  CM_INV,
  521.      "line-numbers",     XYNUM,   CM_INV,    /* moved to send/receive */
  522.      "modem-dialer",     XYMODM,  CM_INV,
  523.      "packet-length",    XYLEN,   CM_INV,    /* moved to send/receive */
  524.      "pad-character",    XYPADC,  CM_INV,    /* moved to send/receive */
  525.      "padding",          XYNPAD,  CM_INV,    /* moved to send/receive */
  526.      "parity",           XYPARI,  0,
  527.      "prompt",           XYPROM,  0,
  528.      "receive",          XYRECV,  0,
  529.      "retry",            XYRETR,  0,
  530.      "renumber",         XYRNUM,  CM_INV, /* moved to send/receive */
  531.      "send",             XYSEND,  0,
  532.      "speed",            XYSPEE,  CM_INV,
  533.      "start-of-packet",  XYMARK,  CM_INV,    /* moved to send/receive */
  534.      "terminal",         XYTERM,  CM_INV,
  535.      "timeout",          XYTIMO,  CM_INV     /* moved to send/receive */
  536. };
  537.  
  538.  
  539. int     nprm = (sizeof(prmtab)
  540.  / sizeof(struct keytab )
  541. ); /* How many parameters */
  542.  
  543.  
  544. /* Remote Command Table */
  545.  
  546. struct keytab remcmd[] = {
  547.      "cd",        XZCWD, CM_INV,
  548.      "cwd",       XZCWD, 0,
  549.      "delete",    XZDEL, 0,
  550.      "directory", XZDIR, 0,
  551.      "help",      XZHLP, 0,
  552.      "host",      XZHOS, 0,
  553.      "space",     XZSPA, 0,
  554.      "type",      XZTYP, 0,
  555.      "who",       XZWHO, 0
  556. };
  557.  
  558.  
  559. int     nrmt = (sizeof(remcmd)
  560.  / sizeof(struct keytab )
  561. );
  562.  
  563. struct keytab logtab[] = {
  564.      "debugging",    LOGD, 0,
  565.      "packets",      LOGP, 0,
  566.      "session",      LOGS, CM_INV,
  567.      "transactions", LOGT, 0
  568. };
  569.  
  570.  
  571. int     nlog = (sizeof(logtab)
  572.  / sizeof(struct keytab )
  573. );
  574.  
  575. /* Show command arguments */
  576.  
  577. #define SHPAR 0                         /* Parameters */
  578. #define SHVER 1                         /* Versions */
  579.  
  580. struct keytab shotab[] = {
  581.      "parameters", SHPAR, 0,
  582.      "versions",   SHVER, 0
  583. };
  584.  
  585.  
  586. /*  C M D I N I  --  Initialize the interactive command parser  */
  587.  
  588. cmdini()
  589. {
  590.  
  591.      tlevel = -1;                        /* Take file level */
  592. #ifndef MCS_FLAG
  593.      cmsetp("IVS-Kermit>");                /* Set default prompt */
  594. #else
  595.      cmsetp("MCS-Kermit>");                /* Set default prompt */
  596. #endif
  597.  
  598.      /* Look for init file in home or current directory. */
  599.  
  600.      homdir = zhome();         /* home dir not used */
  601.      lp = line;
  602.      lp[0] = '\0';
  603.  
  604. /*
  605.  *   if (homdir) {
  606.  *        strcpy(lp, homdir);
  607.  *         if (lp[0] == '/')
  608.  *             strcat(lp, "/");
  609.  *   }
  610.  *   strcat(lp, KERMRC);
  611.  *   if ((tfile[0] = fopen(line, "r")) != NULL) {
  612.  *        tlevel = 0;
  613.  *        if (deblog)
  614.  *             debug(F110, "init file", line, 0);
  615.  *   }
  616.  *   if (homdir && (tlevel < 0)) {
  617.  *        strcpy(lp, KERMRC);
  618.  *        if ((tfile[0] = fopen(line, "r")) != NULL) {
  619.  *             tlevel = 0;
  620.  *             if (deblog)
  621.  *                  debug(F110, "init file", line, 0);
  622.  *        } else {
  623.  *             if (deblog)
  624.  *                  debug(F100, "no init file", "", 0);
  625.  *        }
  626.  *   }
  627.  */
  628.  
  629.      /* Look for the init file.  In the V environment, the file
  630.         location is controlled by the filelocation parameter.
  631.         If CAT or CAT/NOCAT is specified, we'll look in the
  632.         current subcatalog node.  If NOCAT is specified, we'll
  633.         look on disk.  If there is no volume assigned, then we
  634.         could get a resource not available message.  */
  635.  
  636.      strcpy(lp, KERMRC);
  637.      if ((tfile[0] = fopen(line, "r")) != NULL) {
  638.        tlevel = 0;
  639.        if (deblog) debug(F110, "init file", line, 0);
  640.      } else {
  641.          if (deblog) debug(F100, "no init file", "", 0);
  642.      }
  643.  
  644.      congm();                            /* Get console tty modes */
  645. }
  646.  
  647.  
  648. /* Display version herald and initial prompt */
  649.  
  650. herald()
  651. {
  652.      if (!backgrd)
  653. #ifndef MCS_FLAG
  654.           printf("%s\nType ? for help\n", versio);
  655. #else
  656.           sprintf("%s\nType ? for help\n", versio);
  657.           mcs_printf(print_str);
  658. #endif
  659. }
  660.  
  661.  
  662. /*  T R A P  --  Terminal interrupt handler */
  663.  
  664. trap()
  665. {
  666.      if (deblog)
  667.           debug(F100, "terminal interrupt...", "", 0);
  668.      doexit(GOOD_EXIT);                  /* Exit indicating success */
  669. }
  670.  
  671.  
  672. /*  S T P T R A P -- Handle SIGTSTP signals */
  673.  
  674. stptrap()
  675. {
  676.      conres();                           /* Reset the console */
  677.      doexit(GOOD_EXIT);                  /* Probably won't happen otherwise */
  678.      concb();                            /* Put console back in Kermit mode */
  679. }
  680.  
  681.  
  682. /*  P A R S E R  --  Top-level interactive command parser.  */
  683.  
  684. char     parser()
  685. {
  686.      int     xx, cbn;
  687.      char     *cbp;
  688.  
  689.      concb(escape);              /* Put console in cbreak mode. */
  690.      conint(trap);               /* Turn on console terminal interrupts. */
  691.      /*
  692.  sstate becomes nonzero when a command has been parsed that requires some
  693.  action from the protocol module.  Any non-protocol actions, such as local
  694.  directory listing or terminal emulation, are invoked directly from below.
  695. */
  696.      if (local && !backgrd)
  697. #ifndef MCS_FLAG
  698.           printf("\n"); /*** Temporary kludge ***/
  699. #else
  700.           mcs_printf("\n"); /*** Temporary kludge ***/
  701. #endif
  702.      sstate = 0;                         /* Start with no start state. */
  703.      while (sstate == 0) {   /* Parse cmds until action requested */
  704.           while ((tlevel > -1) && feof(tfile[tlevel])) { /* If end of take */
  705.                fclose(tfile[tlevel--]); /* file, close it. */
  706.                cmini(ckxech);          /* and clear the cmd buffer. */
  707.                if (tlevel < 0) {       /* Just popped out of cmd files? */
  708.                     conint(trap);       /* Check background stuff again. */
  709.                     return(0);          /* End of init file or whatever. */
  710.                }
  711.           }
  712.           if (deblog)
  713.                debug(F101, "tlevel", "", tlevel);
  714.           if (tlevel > -1) {              /* If in take file */
  715.                cbp = cmdbuf;               /* Get the next line. */
  716.                cbn = CMDBL;
  717.  
  718.          /* Loop to get next command line and
  719.             all continuation lines from take file. */
  720.  
  721. again:
  722.                if (fgets(line, cbn, tfile[tlevel]) == NULL)
  723.                     continue;
  724.                lp = line;                  /* Got one, copy it. */
  725.                while (*cbp++ = *lp++)
  726.                     if (--cbn < 1)
  727.                          fatal("Command too long for internal buffer");
  728.                if (*(cbp - 3) == '\\') {   /* Continued on next line? */
  729.                     cbp -= 3;               /* If so, back up pointer, */
  730.                     goto again;             /* go back, get next line. */
  731.                }
  732.                /* Strip any quotes from cmd buffer. */
  733.                stripq(cmdbuf);
  734.  
  735.           } else {                        /* No take file, get typein. */
  736.  
  737.                if (!backgrd)
  738.                     prompt();     /* Issue interactive prompt. */
  739.                cmini(ckxech);
  740.           }
  741.           repars = 1;
  742.           displa = 0;
  743.           while (repars) {
  744.                cmres();                    /* Reset buffer pointers. */
  745.                xx = cmkey(cmdtab, ncmd, "Command", "");
  746.                if (deblog)
  747.                     debug(F101, "top-level cmkey", "", xx);
  748.                switch (docmd(xx)) {
  749.                case -4:                /* EOF */
  750.                     doexit(GOOD_EXIT);  /* ...exit successfully */
  751.                case -1:                /* Reparse needed */
  752.                     repars = 1;
  753.                     continue;
  754.                case -2:                /* Invalid command given */
  755.                     if (backgrd)        /* if in background, terminate */
  756.                          fatal("Kermit command error in background execution");
  757.                     if (tlevel > -1) {  /* If in take file, quit */
  758.                          ermsg("Kermit command error: take file terminated.");
  759.                          fclose(tfile[tlevel]);
  760.                          tlevel--;
  761.                     }
  762.                     cmini(ckxech);     /* fall thru */
  763.                case -3:                /* Empty command OK at top level */
  764.                default:                /* Anything else (fall thru) */
  765.                     repars = 0;        /* No reparse, get new command. */
  766.                     *cmdbuf = NUL;     /* Clear out the command buffer */
  767.                     continue;
  768.                }
  769.           }
  770.      }
  771.      /* Got an action command; disable terminal
  772.         interrupts and return start state */
  773.  
  774.      if (!local)
  775.           connoi();               /* Interrupts off only if remote */
  776.      return(sstate);
  777. }
  778.  
  779.  
  780. /*  D O E X I T  --  Exit from the program.  */
  781.  
  782. doexit(exitstat)
  783. int     exitstat;
  784. {
  785.  
  786.      ttclos();                           /* Close external line, if any */
  787.      if (local) {
  788.           strcpy(ttname, dftty);         /* Restore default tty */
  789.           local = dfloc;                 /* And default remote/local status */
  790.      }
  791.      if (!quiet)
  792.           conres();               /* Restore console terminal. */
  793.      if (!quiet)
  794.           connoi();               /* Turn off console interrupt traps. */
  795.  
  796.      if (deblog) {                       /* Close any open logs. */
  797.           if (deblog)
  798.                debug(F100, "Debug Log Closed", "", 0);
  799.           *debfil = '\0';
  800.           deblog = 0;
  801.           zclose(ZDFILE);
  802.      }
  803.      if (pktlog) {
  804.           *pktfil = '\0';
  805.           pktlog = 0;
  806.           zclose(ZPFILE);
  807.      }
  808. /*   if (seslog) {            packet log disabled from opening
  809.           *sesfil = '\0';
  810.           seslog = 0;
  811.           zclose(ZSFILE);
  812.      }                                                            */
  813.      if (tralog) {
  814.           tlog(F100, "Transaction Log Closed", "", 0l);
  815.           *trafil = '\0';
  816.           tralog = 0;
  817.           zclose(ZTFILE);
  818.      }
  819.      syscleanup();
  820.  
  821. #ifndef MCS_FLAG
  822.     exit(exitstat);                 /* Exit from the program. */
  823. #else
  824.     \:FINISH(exitstat);
  825. #endif
  826. }
  827.  
  828.  
  829. /*  B L D L E N  --  Make length-encoded copy of string  */
  830.  
  831. char     *
  832. bldlen(str, dest)
  833. char     *str, *dest;
  834. {
  835.      int     len;
  836.      len = strlen(str);
  837.      *dest = tochar(len);
  838.      strcpy(dest + 1, str);
  839.      return(dest + len + 1);
  840. }
  841.  
  842.  
  843. /*  S E T G E N  --  Construct a generic command  */
  844.  
  845. setgen(type, arg1, arg2, arg3)
  846. char     type, *arg1, *arg2, *arg3;
  847. {
  848.      char     *upstr, *cp;
  849.  
  850.      cp = cmdstr;
  851.      *cp++ = type;
  852.      *cp = NUL;
  853.      if (*arg1 != NUL) {
  854.           upstr = bldlen(arg1, cp);
  855.           if (*arg2 != NUL) {
  856.                upstr = bldlen(arg2, upstr);
  857.                if (*arg3 != NUL)
  858.                     bldlen(arg3, upstr);
  859.           }
  860.      }
  861.      cmarg = cmdstr;
  862.      if (deblog)
  863.           debug(F110, "setgen", cmarg, 0);
  864.  
  865.      return('g');
  866. }
  867.  
  868.  
  869. /* C M D N O T I -- Command not implemented message */
  870.  
  871. cmdnoti() {
  872.   int  c;
  873.  
  874. #ifndef MCS_FLAG
  875.     printf("\nV-Kermit does not support: %s.\n",cmdbuf);
  876. #else
  877.     sprintf(print_str,"\nV-Kermit does not support: %s.\n",cmdbuf);
  878.     mcs_printf(print_str);
  879. #endif
  880.  
  881.   if (cmflgs != 1) {
  882.     /* The command was not terminated with a carriage return. So there
  883.     must be something following it on the input line.  Since the command
  884.     was not implemented, we'll flush the rest of the input line. */
  885.  
  886.     while ((c = getchar()) != NL && c != CR)  ;
  887.   }
  888.   return(0);
  889. }
  890.  
  891.  
  892. /*  D O C M D  --  Do a command  */
  893.  
  894. /*
  895.  Returns:
  896.    -2: user typed an illegal command
  897.    -1: reparse needed
  898.     0: parse was successful (even tho command may have failed).
  899. */
  900.  
  901. docmd(cx)
  902. int     cx;
  903. {
  904.      int     x, y;
  905.      char     *s;
  906.      char     temp[400];
  907.  
  908.      switch (cx) {
  909.      case -4:                                /* EOF */
  910.           if (!quiet && !backgrd)
  911. #ifndef MCS_FLAG
  912.                printf("\r\n");
  913. #else
  914.                mcs_printf("\r\n");
  915. #endif
  916.           doexit(GOOD_EXIT);
  917.      case -3:                                /* Null command */
  918.           return(0);
  919.      case -2:                                /* Error */
  920.      case -1:                                /* Reparse needed */
  921.           return(cx);
  922.  
  923.      case XXBYE:                             /* bye */
  924.           return(cmdnoti());
  925. /*        if ((x = cmcfm()) < 0)
  926. *              return(x);
  927. *         if (!local) {
  928. *              printf("You have to 'set line' first\n");
  929. *              return(0);
  930. *          }
  931. *         sstate = setgen('L', "", "", "");
  932. *         return(0);
  933. */
  934.      case XXCOM:                             /* comment */
  935.  
  936.           if ((x = cmtxt("Text of comment line", "", &s)) < 0)
  937.                return(x);
  938.           return(0);
  939.  
  940.      case XXCON:                             /* connect */
  941.           return(cmdnoti());    /* command not implemented */
  942. /*
  943.  *        if ((x = cmcfm()) < 0)
  944.  *             return(x);
  945.  *        return(doconect());
  946.  */
  947.      case XXCWD:                            /* change directory */
  948.           return(cmdnoti());    /* command not implemented */
  949. /*
  950.  *        if (cmtxt("Name of local directory, or carriage return",
  951.  *             homdir, &s) < 0)
  952.  *             return(-1);
  953.  *        if (CHDIR(s)) {
  954.  *             sprintf(temp, "docmd: %s", s);
  955.  *             errhdlr(s);
  956.  *        }
  957.  *        cwdf = 1;
  958.  *        return(0);
  959.  */
  960.      case XXCLO:
  961.           x = cmkey(logtab, nlog, "Which log to close", "");
  962.           if (x == -3) {
  963. #ifndef MCS_FLAG
  964.                printf("?You must tell which log\n");
  965. #else
  966.                mcs_printf("?You must tell which log\n");
  967. #endif
  968.                return(-2);
  969.           }
  970.           if (x < 0)
  971.                return(x);
  972.           if ((y = cmcfm()) < 0)
  973.                return(y);
  974.  
  975.           switch (x) {
  976.           case LOGD:
  977.                if (deblog == 0) {
  978. #ifndef MCS_FLAG
  979.                     printf("?Debugging log wasn't open\n");
  980. #else
  981.                     mcs_printf("?Debugging log wasn't open\n");
  982. #endif
  983.                     return(0);
  984.                }
  985.                *debfil = '\0';
  986.                deblog = 0;
  987.                return(zclose(ZDFILE));
  988.  
  989.           case LOGP:
  990.                if (pktlog == 0) {
  991. #ifndef MCS_FLAG
  992.                     printf("?Packet log wasn't open\n");
  993. #else
  994.                     mcs_printf("?Packet log wasn't open\n");
  995. #endif
  996.                     return(0);
  997.                }
  998.                *pktfil = '\0';
  999.                pktlog = 0;
  1000.                return(zclose(ZPFILE));
  1001. /*
  1002.  *        case LOGS:
  1003.  *             if (seslog == 0) {
  1004.  *                  printf("?Session log wasn't open\n");
  1005.  *                  return(0);
  1006.  *             }
  1007.  *             *sesfil = '\0';
  1008.  *             seslog = 0;
  1009.  *             return(zclose(ZSFILE));
  1010.  */
  1011.           case LOGT:
  1012.                if (tralog == 0) {
  1013. #ifndef MCS_FLAG
  1014.                     printf("?Transaction log wasn't open\n");
  1015. #else
  1016.                     mcs_printf("?Transaction log wasn't open\n");
  1017. #endif
  1018.                     return(0);
  1019.                }
  1020.                *trafil = '\0';
  1021.                tralog = 0;
  1022.                return(zclose(ZTFILE));
  1023.  
  1024.           default:
  1025. #ifndef MCS_FLAG
  1026.                printf("\n?Unexpected log designator - %ld\n", x);
  1027. #else
  1028.                sprintf(print_str,"\n?Unexpected log designator - %ld\n", x);
  1029.                mcs_printf(print_str);
  1030. #endif
  1031.                return(0);
  1032.           }
  1033.  
  1034.      case XXDIAL:                            /* dial number */
  1035.           return(cmdnoti());      /* command not implemented */
  1036. /*
  1037.  *        if ((x = cmtxt("Number to be dialed", "", &s)) < 0)
  1038.  *             return(x);
  1039.  *        return(ckdial(s));
  1040.  */
  1041.      case XXDIR:                             /* list directory */
  1042.           return(cmdnoti());      /* command not implemented */
  1043. /*
  1044.  *        if ((x = cmtxt("Directory/file specification", ".",
  1045.  *            &s)) < 0)
  1046.  *             return(x);
  1047.  *        lp = line;
  1048.  *        SYSTEM(line);
  1049.  *        return(0);
  1050.  */
  1051.      case XXECH:                             /* echo */
  1052.           if ((x = cmtxt("Material to be echoed", "", &s)) < 0)
  1053.                return(x);
  1054.           for ( ; *s; s++) {
  1055.                if ((x = *s) == 0134) {         /* Convert octal escapes */
  1056.                     s++;                        /* up to 3 digits */
  1057.                     for (x = y = 0; *s >= '0' && *s <= '7' &&
  1058.                         y < 3; s++, y++) {
  1059.                          x = x * 8 + (int) *s - 48;
  1060.                     }
  1061.                     s--;
  1062.                }
  1063.                putchar(x);
  1064.           }
  1065. #ifndef MCS_FLAG
  1066.           printf("\n");
  1067. #else
  1068.           mcs_printf("\n");
  1069. #endif
  1070.           return(0);
  1071.  
  1072.      case XXQUI:                             /* quit, exit */
  1073.      case XXEXI:
  1074.           if ((x = cmcfm()) > -1)
  1075.                doexit(GOOD_EXIT);
  1076.           else
  1077.                return(x);
  1078.  
  1079.      case XXFIN:                             /* finish */
  1080.           return(cmdnoti());    /* command not implemented */
  1081. /*          if ((x = cmcfm()) < 0)
  1082. *               return(x);
  1083. *          if (!local) {
  1084. *               printf("You have to 'set line' first\n");
  1085. *               return(0);
  1086. *          }
  1087. *          sstate = setgen('F', "", "", "");
  1088. */
  1089.  
  1090.      case XXGET:                             /* get */
  1091.           return(cmdnoti());    /* command not implemented */
  1092. /*        if (!local) {
  1093. *              printf("\nYou have to 'set line' first\n");
  1094. *              return(0);
  1095. *         }
  1096. *         x = cmtxt("Name of remote file(s), or carriage return",
  1097. *              "", &cmarg);
  1098. *         if ((x == -2) || (x == -1))
  1099. *              return(x);
  1100. *
  1101. *          * If foreign file name omitted, get
  1102. *            foreign and local names separately *
  1103. *
  1104. *         x = 0;                               * For some reason cmtxt
  1105. *                                                returns 1 *
  1106. *         if (*cmarg == NUL) {
  1107. *
  1108. *              if (tlevel > -1) {               * Input is from take file *
  1109. *
  1110. *                   if (fgets(line, 100, tfile[tlevel]) ==
  1111. *                       NULL)
  1112. *                        fatal("take file ends prematurely in 'get'");
  1113. *                   if (deblog)
  1114. *                        debug(F110, "take-get 2nd line",
  1115. *                             line, 0);
  1116. *                   stripq(line);
  1117. *                   for (x = strlen(line);  x > 0 && (line[x-1] ==
  1118. *                       '\n' || line[x-1] == '\r');  x--)
  1119. *                        line[x-1] = '\0';
  1120. *                   cmarg = line;
  1121. *                   if (fgets(cmdbuf, CMDBL, tfile[tlevel]) ==
  1122. *                       NULL)
  1123. *                        fatal("take file ends prematurely in 'get'");
  1124. *                   stripq(cmdbuf);
  1125. *                   for (x = strlen(cmdbuf);  x > 0 && (cmdbuf[x-1] ==
  1126. *                       '\n' || cmdbuf[x-1] == '\r');  x--)
  1127. *                        cmdbuf[x-1] = '\0';
  1128. *                   if (*cmdbuf == NUL)
  1129. *                        cmarg2 = line;
  1130. *                   else
  1131. *                        cmarg2 = cmdbuf;
  1132. *                   x = 0;                       * Return code *
  1133. *
  1134. *              } else {                         * Input is from terminal *
  1135. *
  1136. *                   char     psave[40];              * Save old prompt *
  1137. *                   cmsavp(psave, 40);
  1138. *                   cmsetp(" Remote file specification: "); * Make new one *
  1139. *                   cmini(ckxech);
  1140. *                   x = -1;
  1141. *                   if (!backgrd)
  1142. *                        prompt();
  1143. *                   while (x == -1) {       * Prompt till they answer *
  1144. *                        x = cmtxt("Name of remote file(s)",
  1145. *                             "", &cmarg);
  1146. *                        if (deblog)
  1147. *                             debug(F111, " cmtxt",
  1148. *                                  cmarg, x);
  1149. *                   }
  1150. *                   if (x < 0) {
  1151. *                        cmsetp(psave);
  1152. *                        return(x);
  1153. *                   }
  1154. *                   if (*cmarg == NUL) {         * If user types a bare CR, *
  1155. *                        printf("(cancelled)\n");  * Forget about this. *
  1156. *                        cmsetp(psave);           * Restore old prompt, *
  1157. *                        return(0);               * and return. *
  1158. *                   }
  1159. *                   strcpy(line, cmarg);          * Make a safe copy *
  1160. *                   cmarg = line;
  1161. *                    * New prompt *
  1162. *                   cmsetp(" Local name to store it under: ");
  1163. *                   cmini(ckxech);
  1164. *                   x = -1;
  1165. *                   if (!backgrd)  prompt();
  1166. *                   while (x == -1) {       * Again, parse till answered *
  1167. *                        x = cmofi("Local file name", "", &cmarg2);
  1168. *                   }
  1169. *                   if (x == -3) {                   * If bare CR, *
  1170. *                        printf("(cancelled)\n");    * escape from this *
  1171. *                        cmsetp(psave);              * Restore old prompt, *
  1172. *                        return(0);                 * and return. *
  1173. *                   } else if (x < 0)
  1174. *                        return(x);         * Handle parse errors. *
  1175. *
  1176. *                   x = -1;                      * Get confirmation. *
  1177. *                   while (x == -1)
  1178. *                        x = cmcfm();
  1179. *                   cmsetp(psave);              * Restore old prompt. *
  1180. *              }
  1181. *         }
  1182. *         if (x == 0) {                       * Good return from cmtxt or
  1183. *                                                cmcfm,                    *
  1184. *              sstate = 'r';                   * set start state. *
  1185. *              if (local)
  1186. *                   displa = 1;
  1187. *         }
  1188. *         return(x);
  1189. */
  1190.      case XXHLP:                             /* Help */
  1191. #ifndef MCS_FLAG
  1192.           x = cmkey(cmdtab, ncmd, "IVS-Kermit command", "help");
  1193. #else
  1194.           x = cmkey(cmdtab, ncmd, "MCS-Kermit command", "help");
  1195. #endif
  1196.           return(dohlp(x));
  1197.  
  1198.      case XXHAN:                             /* Hangup */
  1199.           return(cmdnoti());       /* command not implemented */
  1200. /*
  1201.  *        if ((x = cmcfm()) > -1)
  1202.  *             return(tthang());
  1203.  */
  1204.      case XXLOG:                             /* Log */
  1205.           x = cmkey(logtab, nlog, "What to log", "");
  1206.           if (x == -3) {
  1207. #ifndef MCS_FLAG
  1208.                printf("?You must specify what is to be logged\n");
  1209. #else
  1210.                mcs_printf("?You must specify what is to be logged\n");
  1211. #endif
  1212.                return(-2);
  1213.           }
  1214.           if (x < 0)
  1215.                return(x);
  1216.           return(dolog(x));
  1217.  
  1218.      case XXLOGI:                            /* Send script remote system */
  1219.           return(cmdnoti());       /* command not implemented */
  1220. /*
  1221.  *        if ((x = cmtxt("Text of login script", "", &s)) < 0)
  1222.  *             return(x);
  1223.  *        return( login(s) );                 * Return 0=completed,
  1224.  *                                               -2=failed *
  1225.  */
  1226.  
  1227.      case XXREC:                             /* Receive */
  1228.           return(cmdnoti());    /* command not implemented */
  1229. /*         cmarg2 = "";
  1230. *          x = cmofi("Name under which to store the file, or CR",
  1231. *               "", &cmarg2);
  1232. *          if ((x == -1) || (x == -2))
  1233. *               return(x);
  1234. *          if (deblog)
  1235. *               debug(F111, "cmofi cmarg2", cmarg2, x);
  1236. *          if ((x = cmcfm()) < 0)
  1237. *               return(x);
  1238. *          sstate = 'v';
  1239. *          if (local)
  1240. *               displa = 1;
  1241. *          return(0);
  1242. */
  1243.      case XXREM:                             /* Remote */
  1244.           return(cmdnoti());      /* command not implemented */
  1245. /*
  1246.  *        if (!local) {
  1247.  *             printf("\nYou have to 'set line' first\n");
  1248.  *             return(-2);
  1249.  *        }
  1250.  *        x = cmkey(remcmd, nrmt, "Remote Kermit server command", "");
  1251.  *        if (x == -3) {
  1252.  *             printf("?You must specify a command for the remote server\n");
  1253.  *             return(-2);
  1254.  *        }
  1255.  *        return(dormt(x));
  1256.  */
  1257.      case XXSEN:                             /* Send */
  1258.           return(cmdnoti());    /* command not implemented */
  1259. /*        cmarg = cmarg2 = "";
  1260. *          if ((x = cmifi("File(s) to send", "", &s, &y)) < 0) {
  1261. *               if (x == -3) {
  1262. *                    printf("?A file specification is required\n");
  1263. *                    return(-2);
  1264. *               }
  1265. *               return(x);
  1266. *          }
  1267. *          nfils = -1;                   * Files come from internal list. *
  1268. *          strcpy(line, s);              * Save copy of string just parsed. *
  1269. *          if (deblog)
  1270. *               debug(F101, "Send: wild", "", y);
  1271. *          *cmarg2 = '\0';                     * Initialize send-as name *
  1272. *          if (y == 0) {
  1273. *               if ((x = cmtxt("Name to send it with", "", &cmarg2)) <
  1274. *                   0)
  1275. *                    return(x);
  1276. *          } else {
  1277. *               if ((x = cmcfm()) < 0)
  1278. *                    return(x);
  1279. *          }
  1280. *          cmarg = line;                       * File to send *
  1281. *          if (deblog)
  1282. *               debug(F110, "Sending:", cmarg, 0);
  1283. *          if (*cmarg2 != '\0' && deblog)
  1284. *               debug(F110, " as:", cmarg2, 0);
  1285. *          sstate = 's';                       * Set start state *
  1286. *          if (local)
  1287. *               displa = 1;
  1288. *          return(0);
  1289. */
  1290.      case XXSER:                             /* Server */
  1291.           if ((x = cmcfm()) < 0)
  1292.                return(x);
  1293.           sstate = 'x';
  1294.           if (local)
  1295.                displa = 1;
  1296.           return(0);
  1297.  
  1298.      case XXSET:                             /* Set */
  1299.           x = cmkey(prmtab, nprm, "Parameter", "");
  1300.           if (x == -3) {
  1301. #ifndef MCS_FLAG
  1302.                printf("?You must specify a parameter to set\n");
  1303. #else
  1304.                mcs_printf("?You must specify a parameter to set\n");
  1305. #endif
  1306.                return(-2);
  1307.           }
  1308.           if (x < 0)
  1309.                return(x);
  1310.           return(doprm(x));
  1311.  
  1312.  /* XXSHE code by H. Fischer; copyright rights assigned to Columbia Univ */
  1313.  /*
  1314.  Adapted to use getpwuid to find login shell because many systems do not
  1315.  have SHELL in environment, and to use direct calling of shell rather
  1316.  than intermediate system() call. -- H. Fischer
  1317.  */
  1318.      case XXSHE:                             /* Local shell command */
  1319.            return(cmdnoti());       /* command not implemented */
  1320. /*
  1321.  *         {
  1322.  *             int     pid;
  1323.  *             if (cmtxt("NCR-VRX shell command to execute",
  1324.  *                  "", &s) < 0)
  1325.  *                  return(-1);
  1326.  *             conres();                           * Make console normal  *
  1327.  *
  1328.  *             SYSTEM("x :cli prefix Kermit_Baby:");
  1329.  *
  1330.  *             if ((pid = FORK()) == 0) {          * Make child *
  1331.  *                  char     *shpath, *shname, *shptr;
  1332.  *                                        * For finding desired shell *
  1333.  *                  struct passwd *p;
  1334.  *                  extern struct passwd *GETPWUID();
  1335.  *                  extern int     GETUID();
  1336.  *                  char     *defShel = "/bin/sh";      * Default *
  1337.  *
  1338.  *                  p = GETPWUID( GETUID() );       * Get login data *
  1339.  *                  if ( p == (struct passwd *) NULL ||
  1340.  *                      !*(p->pw_shell) )
  1341.  *                       shpath = defShel;
  1342.  *                  else
  1343.  *                       shpath = p->pw_shell;
  1344.  *                  shptr = shname = shpath;
  1345.  *                  while (*shptr != '\0')
  1346.  *                       if (*shptr++ == '/')
  1347.  *                            shname = shptr;
  1348.  *
  1349.  *                  * Remove following uid calls if they cause trouble *
  1350.  *
  1351.  *                  if (*s == NUL)          * Interactive shell requested? *
  1352.  *                       EXECL(shpath, shname, "-i",
  1353.  *                           NULL);    * Yes, do that *
  1354.  *                  else * Otherwise, *
  1355.  *                       EXECL(shpath, shname, "-c",
  1356.  *                           s, NULL); * exec the given command *
  1357.  *                  exit(BAD_EXIT);
  1358.  *             }               * Just punt if it didn't work *
  1359.  *                 else {                             * Parent *
  1360.  *
  1361.  *                  int     wstat;          * Kermit must wait for child *
  1362.  *                  SIGTYP (*istat)(), (*qstat)();
  1363.  *
  1364.  *                  istat = SIGNAL(SIGINT, SIG_IGN); * Let the fork handle
  1365.  *                                                      keyboard          *
  1366.  *                  qstat = SIGNAL(SIGQUIT, SIG_IGN); * interrupts itself *
  1367.  *
  1368.  *                  while (((wstat = WAIT((int *)0)) !=
  1369.  *                      pid) && (wstat != -1))
  1370.  *                       ;
  1371.  *                  * Wait for fork *
  1372.  *                  SIGNAL(SIGINT, istat);           * Restore interrupts *
  1373.  *                  SIGNAL(SIGQUIT, qstat);
  1374.  *             }
  1375.  *             concb(escape);                      * Console back in cbreak
  1376.  *                                                    mode                *
  1377.  *             return(0);
  1378.  *        }
  1379.  */
  1380.      case XXSHO:                             /* Show */
  1381.           x = cmkey(shotab, 2, "", "parameters");
  1382.           if (x < 0)
  1383.                return(x);
  1384.           if ((y = cmcfm()) < 0)
  1385.                return(y);
  1386.           switch (x) {
  1387.  
  1388.           case SHPAR:
  1389.                shopar();
  1390.                break;
  1391.  
  1392.           case SHVER:
  1393. #ifndef MCS_FLAG
  1394.                printf("\nVersions:\n %s\n %s\n", versio, protv);
  1395.                printf(" %s\n", fnsv);
  1396.                printf(" %s\n %s\n", cmdv, userv);
  1397.                printf(" %s for%s\n", ckxv, ckxsys);
  1398.                printf(" %s for%s\n", ckzv, ckzsys);
  1399. #else
  1400.                sprintf(print_str,"\nVersions:\n %s\n %s\n", versio, protv);
  1401.                mcs_printf(print_str);
  1402.                sprintf(print_str," %s\n", fnsv);
  1403.                mcs_printf(print_str);
  1404.                sprintf(print_str," %s\n %s\n", cmdv, userv);
  1405.                mcs_printf(print_str);
  1406.                sprintf(print_str," %s for%s\n", ckxv, ckxsys);
  1407.                mcs_printf(print_str);
  1408.                sprintf(print_str," %s for%s\n", ckzv, ckzsys);
  1409.                mcs_printf(print_str);
  1410. #endif
  1411.                break;
  1412.  
  1413.           default:
  1414.                printf("\nNothing to show...\n");
  1415.                break;
  1416.           }
  1417.           return(0);
  1418.  
  1419.      case XXSPA:                             /* space */
  1420.           return(cmdnoti());       /* command not implemented */
  1421. /*
  1422.  *        if ((x = cmcfm()) < 0)
  1423.  *             return(x);
  1424.  *        return(0);
  1425.  */
  1426.      case XXSTA:                             /* statistics */
  1427.           if ((x = cmcfm()) < 0)
  1428.                return(x);
  1429.           return(dostat());
  1430.  
  1431.      case XXTAK:                             /* take */
  1432.           if (tlevel > MAXTAKE - 1) {
  1433. #ifndef MCS_FLAG
  1434.                printf("?Take files nested too deeply\n");
  1435. #else
  1436.                mcs_printf("?Take files nested too deeply\n");
  1437. #endif
  1438.                return(-2);
  1439.           }
  1440. #ifndef MCS_FLAG
  1441.           if ((y = cmifi("IVS-Kermit command file", "", &s, &x)) <
  1442. #else
  1443.           if ((y = cmifi("MCS-Kermit command file", "", &s, &x)) <
  1444. #endif
  1445.               0) {
  1446.                if (y == -3) {
  1447. #ifndef MCS_FLAG
  1448.                     printf("?A file specification is required\n");
  1449. #else
  1450.                     mcs_printf("?A file specification is required\n");
  1451. #endif
  1452.                     return(-2);
  1453.                } else
  1454.                     return(y);
  1455.           }
  1456.           if (x != 0) {
  1457. #ifndef MCS_FLAG
  1458.                printf("?Wildcards not allowed in command file name\n");
  1459. #else
  1460.                mcs_printf("?Wildcards not allowed in command file name\n");
  1461. #endif
  1462.                return(-2);
  1463.           }
  1464.           strcpy(line, s);        /* Make a safe copy of the string */
  1465.           if ((y = cmcfm()) < 0)
  1466.                return(y);
  1467.           if ((tfile[++tlevel] = fopen(line, "r")) == NULL) {
  1468.                sprintf(temp, "docmd: %s", line);
  1469.                errhdlr(temp);
  1470.                if (deblog)
  1471.                     debug(F110, "Failure to open", line, 0);
  1472.                tlevel--;
  1473.           }
  1474.           return(0);
  1475.  
  1476.      default:
  1477. #ifndef MCS_FLAG
  1478.           printf("V-Kermit does not support: %s\n", cmdbuf);
  1479. #else
  1480.           sprintf(print_str,"V-Kermit does not support: %s.\n",cmdbuf);
  1481.           mcs_printf(print_str);
  1482. #endif
  1483.           return(-2);
  1484.      }
  1485. }
  1486.  
  1487.  
  1488. /*  D O C O N E C T  --  Do the connect command  */
  1489.  
  1490. /*  Note, we don't call this directly from dial, because we need to give */
  1491. /*  the user a chance to change parameters (e.g. parity) after the */
  1492. /*  connection is made. */
  1493.  
  1494. doconect()
  1495. {
  1496.      int     x;
  1497.      conres();                           /* Put console back to normal */
  1498.      x = conect();                       /* Connect */
  1499.      concb(escape);                      /* Put console into cbreak mode, */
  1500.      return(x);                          /* for more command parsing. */
  1501. }
  1502.