home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / old / ckermit5a188 / ckuusr.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  56KB  |  2,033 lines

  1. char *userv = "User Interface 5A(095), 19 Jan 93";
  2.  
  3. /*  C K U U S R --  "User Interface" for Unix Kermit (Part 1)  */
  4.  
  5. /*
  6.   Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
  7.   Columbia University Center for Computing Activities.
  8.   First released January 1985.
  9.   Copyright (C) 1985, 1993, Trustees of Columbia University in the City of New
  10.   York.  Permission is granted to any individual or institution to use this
  11.   software as long as it is not sold for profit.  This copyright notice must be
  12.   retained.  This software may not be included in commercial products without
  13.   written permission of Columbia University.
  14. */
  15.  
  16. /*
  17.   NOTE: Because of the massive additions in functionality, and therefore
  18.   the increase in the number of commands, much code was moved from here to
  19.   the two new modules, ckuus4.c and ckuus5.c.  This module now contains only
  20.   the top-level command keyword table, the SET command keyword table, and
  21.   the top-level interactive command parser/dispatcher.  ckuus3.c contains the
  22.   rest of the SET and REMOTE command parsers; ckuus2.c contains the help
  23.   command parser and help text strings, and ckuus4.c and ckuus5.c contain
  24.   miscellaneous pieces that logically belong in the ckuusr.c file but had to
  25.   be moved because of size problems with some C compilers / linkers.
  26.   Later...  as the other modules became too large, a ckuus6.c was created.
  27.   Still later...  ckuus7.c.
  28.   Also: ckuusy.c contains the UNIX-style command-line interface;
  29.   ckuusx.c contains routines needed by both the command-line interface and
  30.   the interactive command parser.
  31. */
  32.  
  33. /*
  34.  The ckuus*.c modules depend on the existence of C library features like fopen,
  35.  fgets, feof, (f)printf, argv/argc, etc.  Other functions that are likely to
  36.  vary among Unix implementations -- like setting terminal modes or interrupts
  37.  -- are invoked via calls to functions that are defined in the system-
  38.  dependent modules, ck?[ft]io.c.  The command line parser processes any
  39.  arguments found on the command line, as passed to main() via argv/argc.  The
  40.  interactive parser uses the facilities of the cmd package (developed for this
  41.  program, but usable by any program).  Any command parser may be substituted
  42.  for this one.  The only requirements for the Kermit command parser are these:
  43.  
  44. 1. Set parameters via global variables like duplex, speed, ttname, etc.  See
  45.    ckmain.c for the declarations and descriptions of these variables.
  46.  
  47. 2. If a command can be executed without the use of Kermit protocol, then
  48.    execute the command directly and set the variable sstate to 0. Examples
  49.    include 'set' commands, local directory listings, the 'connect' command.
  50.  
  51. 3. If a command requires the Kermit protocol, set the following variables:
  52.  
  53.     sstate                             string data
  54.       'x' (enter server mode)            (none)
  55.       'r' (send a 'get' command)         cmarg, cmarg2
  56.       'v' (enter receive mode)           cmarg2
  57.       'g' (send a generic command)       cmarg
  58.       's' (send files)                   nfils, cmarg & cmarg2 OR cmlist
  59.       'c' (send a remote host command)   cmarg
  60.  
  61.     cmlist is an array of pointers to strings.
  62.     cmarg, cmarg2 are pointers to strings.
  63.     nfils is an integer.
  64.  
  65.     cmarg can be a filename string (possibly wild), or
  66.        a pointer to a prefabricated generic command string, or
  67.        a pointer to a host command string.
  68.     cmarg2 is the name to send a single file under, or
  69.        the name under which to store an incoming file; must not be wild.
  70.        If it's the name for receiving, a null value means to store the
  71.        file under the name it arrives with.
  72.     cmlist is a list of nonwild filenames, such as passed via argv.
  73.     nfils is an integer, interpreted as follows:
  74.       -1: filespec (possibly wild) in cmarg, must be expanded internally.
  75.        0: send from stdin (standard input).
  76.       >0: number of files to send, from cmlist.
  77.  
  78.  The screen() function is used to update the screen during file transfer.
  79.  The tlog() function writes to a transaction log.
  80.  The debug() function writes to a debugging log.
  81.  The intmsg() and chkint() functions provide the user i/o for interrupting
  82.    file transfers.
  83. */
  84.  
  85. #ifndef NOICP
  86. /* Includes */
  87.  
  88. #include "ckcdeb.h"
  89. #include "ckcasc.h"
  90. #include "ckcker.h"
  91. #include "ckuusr.h"
  92. #include "ckcxla.h"
  93. #include "ckcnet.h"            /* Network symbols */
  94.  
  95. #ifdef datageneral
  96. #include <packets:common.h>
  97. #define fgets(stringbuf,max,fd) dg_fgets(stringbuf,max,fd)
  98. #endif /* datageneral */
  99.  
  100. /* External Kermit Variables, see ckmain.c for description. */
  101.  
  102. extern int size, local, sndsrc, xitsta, server, displa, binary, msgflg, 
  103.   escape, duplex, nfils, quiet, tlevel, pflag, zincnt, atcapr, atdiso, verwho;
  104.  
  105. extern long vernum;
  106. extern char *versio;
  107. extern char *ckxsys, *cmarg, *cmarg2, **cmlist;
  108. #ifndef NOHELP
  109. extern char *introtxt[];
  110. #endif /* NOHELP */
  111. extern char *PWDCMD, *WHOCMD, *TYPCMD;
  112. extern char ttname[];
  113. #ifndef NOFRILLS
  114. extern int rmailf;            /* MAIL command items */
  115. extern char optbuf[];
  116. #endif /* NOFRILLS */
  117. extern CHAR sstate;
  118.  
  119. #ifdef NETCONN
  120. extern int network;            /* Have active network connection */
  121. #endif /* NETCONN */
  122.  
  123. #ifndef NOMSEND                /* Multiple SEND */
  124. extern char *msfiles[];
  125. #endif /* NOMSEND */
  126. extern char fspec[];            /* Most recent filespec */
  127.  
  128. #ifndef NOCSETS
  129. extern int nfilc;
  130. extern struct keytab fcstab[];
  131. #endif /* NOCSETS */
  132.  
  133. int rcflag = 0;                /* Pointer to home directory string */
  134. int repars,                /* Reparse needed */
  135.     techo = 0;                /* Take echo */
  136. #ifndef NOSCRIPT
  137. int secho = 1;
  138. #endif /* NOSCRIPT */
  139.  
  140. #ifndef NOXMIT
  141. /* Variables for TRANSMIT command */
  142.  
  143. int xmitx = 1;            /* Whether to echo during TRANSMIT */
  144. int xmitf = 0;            /* Character to fill empty lines */
  145. int xmitl = 0;            /* 0 = Don't send linefeed too */
  146. int xmitp = LF;            /* Host line prompt */
  147. int xmits = 0;            /* Use shift-in/shift-out, 0 = no */
  148. int xmitw = 0;            /* Milliseconds to pause during TRANSMIT */
  149. #endif /* NOXMIT */
  150.  
  151. /* Declarations from ck?fio.c module */
  152.  
  153. extern char *SPACMD, *SPACM2;        /* SPACE commands */
  154.  
  155. /* Command-oriented items */
  156.  
  157. #ifdef DCMDBUF
  158. extern char *cmdbuf;            /* Command buffers */
  159. extern char *atmbuf;
  160. extern char *line;            /* Character buffer for anything */
  161. extern int *ifcmd;
  162. extern int *intime, *terror, *merror;
  163. #else
  164. extern char cmdbuf[];            /* Command buffers */
  165. extern char atmbuf[];
  166. extern char line[];            /* Character buffer for anything */
  167. extern int ifcmd[];
  168. extern int intime[], terror[], merror[];
  169. #endif /* DCMDBUF */
  170.  
  171. char *lp;                /* Pointer to line buffer */
  172.  
  173. #ifndef NOSPL
  174. extern char inpbuf[];            /* Buffer for INPUT and REINPUT */
  175. char *inpbp = inpbuf;            /* And pointer to same */
  176. extern char lblbuf[];            /* Buffer for labels */
  177. #endif /* NOSPL */
  178.  
  179. char psave[80] = { NUL };        /* For saving & restoring prompt */
  180.  
  181. extern char tmpbuf[];            /* Temporary buffer */
  182.  
  183. extern int success;            /* Command success/failure flag */
  184.  
  185. #ifndef NOSPL
  186. int                    /* SET INPUT parameters. */
  187. /* Note, INPUT TIMEOUT, intime[], is on the command-level stack. */
  188.   indef = 1,                /* default timeout, seconds */
  189.   inecho = 1,                /* 1 = echo on */
  190.   insilence = 0;            /* 0 = no silence constraint */
  191.  
  192. int maclvl = -1;            /* Macro nesting level */
  193. int mecho = 0;                /* Macro echo, 0 = don't */
  194. char varnam[6];                /* For variable names */
  195. extern int macargc[];            /* ARGC from macro invocation */
  196.  
  197. extern char *m_arg[MACLEVEL][NARGS];    /* Stack of macro arguments */
  198.  
  199. extern char **a_ptr[];            /* Array pointers */
  200. extern int a_dim[];            /* Array dimensions */
  201.  
  202. #ifdef DCMDBUF
  203. extern struct cmdptr *cmdstk;        /* The command stack itself */
  204. #else
  205. extern struct cmdptr cmdstk[];        /* The command stack itself */
  206. #endif /* DCMDBUF */
  207. extern int cmdlvl;            /* Current position in command stack */
  208. #endif /* NOSPL */
  209.  
  210. static int x, y, z = 0;            /* Local workers */
  211. static char *s;
  212.  
  213. #define xsystem(s) zsyscmd(s)
  214.  
  215. /* Top-Level Interactive Command Keyword Table */
  216.  
  217. struct keytab cmdtab[] = {
  218. #ifndef NOPUSH
  219.     "!",       XXSHE, CM_INV,    /* shell escape */
  220. #endif /* NOPUSH */
  221.     "#",           XXCOM, CM_INV,    /* comment */
  222. #ifndef NOSPL
  223.     ":",           XXLBL, CM_INV,    /* label */
  224. #endif /* NOSPL */
  225. #ifndef NOPUSH
  226.     "@",           XXSHE, CM_INV,    /* DCL escape */
  227. #endif /* NOPUSH */
  228. #ifndef NOSPL
  229.     "asg",         XXASS, CM_INV,       /* invisible synonym for assign */
  230.     "ask",         XXASK, 0,        /* ask */
  231.     "askq",        XXASKQ,0,            /* ask quietly */
  232.     "assign",      XXASS, 0,            /* assign */
  233. #endif /* NOSPL */
  234. #ifndef NOFRILLS
  235.     "bug",         XXBUG, 0,        /* bug report instructions */
  236. #endif /* NOFRILLS */
  237.     "bye",         XXBYE, 0,        /* bye to remote server */
  238.     "c",           XXCON, CM_INV|CM_ABR, /* invisible synonym for connect */
  239. #ifndef NOFRILLS
  240.     "cat",         XXTYP, CM_INV,    /* display a local file */
  241. #endif /* NOFRILLS */
  242.     "cd",          XXCWD, 0,        /* change directory */
  243.     "check",       XXCHK, 0,        /* check for a feature */
  244. #ifndef NOFRILLS
  245.     "clear",       XXCLE, 0,        /* clear input buffer */
  246. #endif /* NOFRILLS */
  247.     "close",       XXCLO, 0,        /* close a log file */
  248. #ifdef NOFRILLS
  249.     "comment",     XXCOM, CM_INV,    /* comment */
  250. #else
  251.     "comment",     XXCOM, 0,        /* comment */
  252. #endif /* NOFRILLS */
  253.     "connect",     XXCON, 0,        /* connect to remote system */
  254.     "cwd",       XXCWD, CM_INV,    /* invisisble synonym for cd */
  255. #ifndef NOSPL
  256.     "dcl",         XXDCL, CM_INV,    /* declare an array */
  257.     "declare",     XXDCL, 0,        /* declare an array */
  258.     "decrement",   XXDEC, 0,        /* decrement a numeric variable */
  259.     "define",      XXDEF, 0,        /* define a macro */
  260. #endif /* NOSPL */
  261. #ifndef NOFRILLS
  262.     "delete",      XXDEL, 0,        /* delete a file */
  263. #endif /* NOFRILLS */
  264. #ifndef NODIAL
  265.     "dial",       XXDIAL,0,        /* dial a phone number */
  266. #endif /* NODIAL */
  267. #ifndef MAC
  268.     "directory",   XXDIR, 0,        /* directory of files */
  269. #endif /* MAC */
  270. #ifndef NOFRILLS
  271.     "disable",     XXDIS, 0,        /* disable server function */
  272. #endif /* NOFRILLS */
  273. #ifndef NOSPL
  274.     "do",          XXDO,  0,        /* execute a macro */
  275. #endif /* NOSPL */
  276. #ifndef NOFRILLS
  277.     "e-packet",    XXERR, CM_INV,    /* Send an Error packet */
  278. #endif /* NOFRILLS */
  279.     "echo",        XXECH, 0,        /* echo argument */
  280. #ifndef NOSPL
  281.     "else",        XXELS, CM_INV,    /* ELSE part of IF statement */
  282. #endif /* NOSPL */
  283. #ifndef NOFRILLS
  284.     "enable",      XXENA, 0,        /* ENABLE a server function */
  285. #endif /* NOFRILLS */
  286. #ifndef NOSPL
  287.     "end",         XXEND, 0,        /* END command file or macro */
  288. #endif /* NOSPL */
  289.     "ex",          XXEXI, CM_INV|CM_ABR, /* Let "ex" still be EXIT */
  290.     "exit",       XXEXI, 0,        /* exit the program */
  291.     "extproc",     XXCOM, CM_INV,       /* dummy command */
  292.     "finish",      XXFIN, 0,        /* FINISH */
  293. #ifndef NOSPL
  294.     "for",         XXFOR, 0,        /* FOR loop */
  295. #endif /* NOSPL */
  296. #ifndef NOFRILLS
  297. #ifndef MAC
  298.     "fot",       XXDIR, CM_INV,    /* "fot" = "dir" (for Chris) */
  299. #endif /* MAC */
  300. #endif /* NOFRILLS */
  301.     "g",           XXGET, CM_INV|CM_ABR, /* Invisible abbreviation for GET */
  302. #ifndef NOSPL
  303.     "ge",          XXGET, CM_INV|CM_ABR, /* Ditto */
  304. #endif /* NOSPL */
  305.     "get",         XXGET, 0,        /* GET */
  306. #ifndef NOSPL
  307. #ifndef NOFRILLS
  308.     "getok",       XXGOK, 0,        /* GETOK (ask for Yes/No) */
  309. #endif /* NOFRILLS */
  310. #endif /* NOSPL */
  311. #ifndef NOSPL
  312.     "goto",        XXGOTO,0,        /* goto label in take file or macro */
  313. #endif /* NOSPL */
  314.     "hangup",      XXHAN, 0,        /* hangup dialed phone connection */
  315.     "help",       XXHLP, 0,        /* display help text */
  316. #ifndef NOSPL
  317.     "i",           XXINP, CM_INV|CM_ABR, /* invisible synonym for INPUT */
  318.     "if",          XXIF,  0,        /* if (condition) command */
  319.     "in",          XXINP, CM_INV|CM_ABR, /* invisible synonym for INPUT */
  320.     "increment",   XXINC, 0,        /* increment a numeric variable */
  321.     "input",       XXINP, 0,        /* input string from comm line */
  322. #endif /* NOSPL */
  323. #ifndef NOHELP
  324.      "introduction", XXINT, 0,        /* Print introductory text */
  325. #endif /* NOHELP */
  326. #ifndef NOFRILLS
  327.     "l",           XXLOG, CM_INV|CM_ABR,/* invisible synonym for log */
  328. #endif /* NOFRILLS */
  329.     "log",         XXLOG, 0,        /* open a log file */
  330. #ifndef NOFRILLS
  331. #ifndef MAC
  332.     "ls",          XXDIR, CM_INV,    /* invisible synonym for directory */
  333. #endif /* MAC */
  334.     "mail",        XXMAI, 0,        /* mail file to user */
  335.     "man",         XXHLP, CM_INV,       /* Synonym for help */
  336. #endif /* NOFRILLS */
  337. #ifndef NOMSEND
  338.     "mget",        XXGET, CM_INV,    /* MGET = GET */
  339. #endif /* NOMSEND */
  340. #ifndef NOSPL
  341.     "mpause",      XXMSL, CM_INV,    /* Millisecond sleep */
  342. #endif /* NOSPL */
  343. #ifndef NOMSEND
  344.     "ms",          XXMSE, CM_INV|CM_ABR,
  345.     "msend",       XXMSE, 0,        /* Multiple SEND */
  346. #endif /* NOMSEND */
  347. #ifndef NOSPL
  348.     "msleep",      XXMSL, 0,        /* Millisecond sleep */
  349. #endif /* NOSPL */
  350. #ifndef NOMSEND
  351.     "mput",        XXMSE, CM_INV,    /* MPUT = MSEND */
  352. #endif /* NOMSEND */
  353. #ifndef NOFRILLS
  354.     "mv",          XXREN, CM_INV,    /* rename a local file */
  355. #endif /* NOFRILLS */
  356. #ifndef NOSPL
  357.     "o",           XXOUT, CM_INV|CM_ABR,/* invisible synonym for OUTPUT */
  358.     "open",        XXOPE, 0,        /* open file for reading or writing */
  359.     "output",      XXOUT, 0,        /* output string to comm line */
  360. #endif /* NOSPL */
  361. #ifdef SUNX25
  362.     "pad",         XXPAD, 0,            /* PAD commands */
  363. #endif /* SUNX25 */
  364. #ifndef NOSPL
  365.     "pause",       XXPAU, 0,        /* sleep for specified interval */
  366. #ifdef TCPSOCKET
  367.     "ping",        XXPNG, 0,        /* PING (for TCP/IP) */
  368. #endif /* TCPSOCKET */
  369.     "pop",         XXEND, CM_INV,    /* allow POP as synonym for END */
  370. #endif /* NOSPL */
  371. #ifndef NOFRILLS
  372.     "print",       XXPRI, 0,        /* PRINT */
  373. #ifndef NOPUSH
  374.     "pu",          XXSHE, CM_INV,    /* PU = PUSH */
  375.     "push",        XXSHE, 0,        /* PUSH command (like RUN, !) */
  376. #endif /* NOPUSH */
  377.     "put",       XXSEN, CM_INV,    /* PUT = SEND */
  378. #ifndef MAC
  379.     "pwd",         XXPWD, 0,            /* print working directory */
  380. #endif /* MAC */
  381. #endif /* NOFRILLS */
  382.     "quit",       XXQUI, 0,        /* quit from program = exit */
  383.     "r",           XXREC, CM_INV,    /* invisible synonym for receive */
  384. #ifndef NOSPL
  385.     "read",        XXREA, 0,            /* read */
  386. #endif /* NOSPL */
  387.     "receive",       XXREC, 0,        /* receive files */
  388. #ifndef NODIAL
  389.     "redial",      XXRED, 0,        /* redial */
  390. #endif /* NODIAL */
  391. #ifndef NOSPL
  392.     "reinput",     XXREI, 0,            /* reinput */
  393. #endif /* NOSPL */
  394.     "remote",       XXREM, 0,        /* send generic command to server */
  395. #ifndef NOFRILLS
  396.     "rename",      XXREN, 0,        /* rename a local file */
  397.     "replay",      XXTYP, CM_INV,    /* replay (for now, just type) */
  398. #endif /* NOFRILLS */
  399. #ifndef NOSPL
  400.     "return",      XXRET, 0,        /* return from function */
  401. #endif /* NOSPL */
  402. #ifndef NOFRILLS
  403.     "rm",          XXDEL, CM_INV,    /* invisible synonym for delete */
  404. #endif /* NOFRILLS */
  405. #ifndef NOPUSH
  406.     "run",         XXSHE, 0,        /* run a program or command */
  407. #endif /* NOPUSH */
  408.     "s",           XXSEN, CM_INV|CM_ABR, /* invisible synonym for send */
  409. #ifndef NOSCRIPT
  410.     "script",       XXLOGI,0,        /* execute a uucp-style script */
  411. #endif /* NOSCRIPT */
  412.     "send",       XXSEN, 0,        /* send files */
  413. #ifndef NOSERVER
  414.     "server",       XXSER, 0,        /* be a server */
  415. #endif /* NOSERVER */
  416.     "set",       XXSET, 0,        /* set parameters */
  417. #ifndef NOSHOW
  418.     "show",        XXSHO, 0,        /* show parameters */
  419. #endif /* NOSHOW */
  420. #ifndef NOSPL
  421. #ifndef NOFRILLS
  422.     "sleep",       XXPAU, CM_INV,    /* sleep for specified interval */
  423. #endif /* NOFRILLS */
  424. #endif /* NOSPL */
  425. #ifndef MAC
  426. #ifndef NOFRILLS
  427.     "sp",          XXSPA, CM_INV|CM_ABR,
  428.     "spa",         XXSPA, CM_INV|CM_ABR,
  429. #endif /* NOFRILLS */
  430.     "space",       XXSPA, 0,        /* show available disk space */
  431. #endif /* MAC */
  432. #ifndef NOFRILLS
  433. #ifndef NOPUSH
  434.     "spawn",       XXSHE, CM_INV,    /* synonym for PUSH, RUN */
  435. #endif /* NOPUSH */
  436. #endif /* NOFRILLS */
  437.     "statistics",  XXSTA, 0,        /* display file transfer stats */
  438. #ifndef NOSPL
  439.     "stop",        XXSTO, 0,        /* stop all take files */
  440. #endif /* NOSPL */
  441. #ifndef NOJC
  442.     "suspend",     XXSUS, 0,        /* Suspend */
  443. #endif /* NOJC */
  444.     "take",       XXTAK, 0,        /* take commands from file */
  445. #ifndef NOFRILLS
  446. #ifdef NETCONN
  447.     "telnet",      XXTEL, 0,        /* telnet */
  448. #endif /* NETCONN */
  449.     "test",        XXTES, CM_INV,    /* (for testing) */
  450. #endif /* NOFRILLS */
  451. #ifndef NOCSETS
  452.     "translate",   XXXLA, 0,        /* translate local file char sets */
  453. #endif
  454. #ifndef NOXMIT
  455.     "transmit",    XXTRA, 0,        /* raw upload file */
  456. #endif /* NOXMIT */
  457. #ifndef NOFRILLS
  458.     "type",        XXTYP, 0,        /* display a local file */
  459. #endif /* NOFRILLS */
  460.     "version",     XXVER, 0        /* version number display */
  461. #ifndef NOSPL
  462. ,   "wait",        XXWAI, 0        /* wait (like pause) */
  463. ,   "while",       XXWHI, 0        /* while */
  464. #endif /* NOSPL */
  465. #ifndef MAC
  466. #ifndef NOFRILLS
  467. ,   "who",         XXWHO, 0        /* who */
  468. #endif /* NOFRILLS */
  469. #endif /* MAC */
  470. #ifndef NOSPL
  471. ,   "write",       XXWRI, 0        /* write */
  472. ,   "xif",         XXIFX, 0        /* Extended IF */
  473. #endif /* NOSPL */
  474. #ifndef NOCSETS
  475. ,   "xlate",       XXXLA, CM_INV    /* translate local file char sets */
  476. #endif
  477. #ifndef NOXMIT
  478. ,   "xmit",        XXTRA, CM_INV    /* raw upload file */
  479. #endif /* NOXMIT */
  480. ,   "z",           XXSUS, CM_INV    /* Suspend */
  481. #ifndef NOSPL
  482. ,   "_assign",     XXASX, CM_INV    /* used internally by FOR, etc */
  483. ,   "_define",     XXDFX, CM_INV    /* used internally by FOR, etc */
  484. ,   "_getargs",    XXGTA, CM_INV        /* used internally by FOR, etc */
  485. ,   "_putargs",    XXPTA, CM_INV        /* used internally by FOR, etc */
  486. #endif /* NOSPL */
  487. };
  488. int ncmd = (sizeof(cmdtab) / sizeof(struct keytab));
  489.  
  490. char toktab[] = {
  491. #ifndef NOPUSH
  492.     '!',                /* Shell escape */
  493. #endif /* NOPUSH */
  494.     '#',                /* Comment */
  495.     ';',                /* Comment */
  496. #ifndef NOSPL
  497.     ':',                /* Label */
  498. #endif /* NOSPL */
  499. #ifndef NOPUSH
  500.     '@',                /* DCL escape */
  501. #endif /* NOPUSH */
  502.     '\0'                /* End of this string */
  503. };
  504.  
  505. #ifndef NOSPL
  506. #ifndef NOFRILLS
  507. struct keytab yesno[] = {
  508.     "no",    0, 0,
  509.     "ok",    1, 0,
  510.     "yes",   1, 0
  511. };
  512. int nyesno = (sizeof(yesno) / sizeof(struct keytab));
  513. #endif /* NOFRILLS */
  514. #endif /* NOSPL */
  515.  
  516. /* Parameter keyword table */
  517.  
  518. struct keytab prmtab[] = {
  519.     "attributes",       XYATTR,  0,
  520.     "b",        XYBACK,  CM_INV|CM_ABR,
  521.     "ba",        XYBACK,  CM_INV|CM_ABR,
  522.     "background",       XYBACK,  0,
  523.     "baud",            XYSPEE,  CM_INV,
  524.     "block-check",      XYCHKT,  0,
  525. #ifdef DYNAMIC
  526.     "buffers",          XYBUF,   0,
  527. #endif /* DYNAMIC */
  528. #ifndef MAC
  529.     "carrier",          XYCARR,  0,
  530. #endif /* MAC */
  531. #ifndef NOSPL
  532.     "case",             XYCASE,  0,
  533. #endif /* NOSPL */
  534.     "command",          XYCMD,   0,
  535. #ifndef NOSPL
  536.     "count",            XYCOUN,  0,
  537. #endif /* NOSPL */
  538.     "d",        XYDELA,  CM_INV|CM_ABR,
  539.     "de",        XYDELA,  CM_INV|CM_ABR,
  540.     "debug",            XYDEBU,  CM_INV,
  541. #ifdef VMS
  542.     "default",          XYDFLT,  0,
  543. #else
  544. #ifndef MAC
  545.     "default",          XYDFLT,  CM_INV,
  546. #endif /* MAC */
  547. #endif /* VMS */
  548.     "delay",            XYDELA,  0,
  549. #ifndef NODIAL
  550.     "dial",             XYDIAL,  0,
  551. #endif /* NODIAL */
  552.     "duplex",            XYDUPL,  0,
  553.     "escape-character", XYESC,   0,
  554.     "file",           XYFILE,  0,
  555.     "flow-control",     XYFLOW,  0,
  556.     "handshake",        XYHAND,  0,
  557. #ifdef NETCONN
  558.     "host",             XYHOST,  0,
  559. #endif /* NETCONN */
  560.     "incomplete",       XYIFD,   CM_INV,
  561. #ifndef NOSPL
  562.     "i",        XYINPU,  CM_INV|CM_ABR,
  563.     "in",        XYINPU,  CM_INV|CM_ABR,
  564.     "input",            XYINPU,  0,
  565. #ifndef MAC
  566. #ifndef NOSETKEY
  567.     "key",        XYKEY,   0,
  568. #endif /* NOSETKEY */
  569. #endif /* MAC */
  570. #endif /* NOSPL */
  571.     "l",                XYLINE,  CM_INV|CM_ABR,
  572. #ifndef NOCSETS
  573.     "language",         XYLANG,  0,
  574. #endif /* NOCSETS */
  575.     "line",             XYLINE,  0,
  576.     "local-echo",    XYLCLE,  CM_INV,
  577. #ifndef NOSPL
  578.     "macro",            XYMACR,  0,
  579. #endif /* NOSPL */
  580. #ifdef COMMENT
  581. #ifdef VMS
  582.     "messages",         XYMSGS,  0,
  583. #endif /* VMS */
  584. #endif /* COMMENT */
  585. #ifndef NODIAL
  586.     "modem-dialer",    XYMODM,     0,
  587. #endif
  588. #ifdef NETCONN
  589.     "network",          XYNET,   0,
  590. #endif /* NETCONN */
  591. #ifdef SUNX25
  592.     "pad",              XYPAD,   0,
  593. #endif /* SUNX25 */
  594.     "parity",            XYPARI,  0,
  595.     "port",             XYLINE,  CM_INV,
  596. #ifndef NOFRILLS
  597.     "prompt",            XYPROM,  0,
  598. #endif /* NOFRILLS */
  599.     "quiet",        XYQUIE,  0,
  600.     "receive",          XYRECV,  0,
  601.     "retry-limit",      XYRETR,  0,
  602. #ifndef NOSCRIPT
  603.     "script",        XYSCRI,  0,
  604. #endif /* NOSCRIPT */
  605.     "send",             XYSEND,  0,
  606. #ifndef NOSERVER
  607.     "server",           XYSERV,  0,
  608. #endif /* NOSERVER */
  609. #ifdef UNIX
  610.     "session-log",      XYSESS,  0,
  611. #endif /* UNIX */
  612.     "speed",            XYSPEE,  0,
  613. #ifndef NOJC
  614.     "suspend",          XYSUSP,  0,
  615. #endif /* NOJC */
  616.     "take",             XYTAKE,  0,
  617. #ifdef TNCODE
  618.     "telnet",           XYTEL,   0,
  619. #endif /* TNCODE */
  620.     "terminal",         XYTERM,  0,
  621.     "transfer",         XYXFER,  0,
  622. #ifndef NOXMIT
  623.     "transmit",         XYXMIT,  0,
  624. #endif /* NOXMIT */
  625. #ifndef NOCSETS
  626.     "unknown-char-set", XYUNCS,  0,
  627. #endif /* NOCSETS */
  628.     "window-size",      XYWIND,  0
  629. #ifdef UNIX
  630. ,   "wildcard-expansion", XYWILD, 0
  631. #endif /* UNIX */
  632. #ifdef SUNX25
  633. ,   "x.25",             XYX25,   0,
  634.     "x25",              XYX25,   CM_INV
  635. #endif /* SUNX25 */
  636. #ifndef NOCSETS
  637. ,   "xfer",             XYXFER,  CM_INV
  638. #endif /* NOCSETS */
  639. #ifndef NOXMIT
  640. ,   "xmit",             XYXMIT,  CM_INV
  641. #endif /* NOXMIT */
  642. };
  643. int nprm = (sizeof(prmtab) / sizeof(struct keytab)); /* How many parameters */
  644.  
  645. /* Table of networks */
  646. #ifdef NETCONN
  647. struct keytab netcmd[] = {
  648. #ifdef DECNET
  649.     "decnet",        NET_DEC,  0,
  650. #endif /* DECNET */
  651. #ifdef NPIPE
  652.     "named-pipe",    NET_PIPE, 0,
  653. #endif /* NPIPE */
  654. #ifdef TCPSOCKET
  655.     "tcp/ip",        NET_TCPB, 0
  656. #endif /* TCPSOCKET */
  657. #ifdef SUNX25
  658. ,   "x",            NET_SX25, CM_INV|CM_ABR,
  659.     "x.25",         NET_SX25, 0,
  660.     "x25",          NET_SX25, CM_INV
  661. #endif /* SUNX25 */
  662. };
  663. int nnets = (sizeof(netcmd) / sizeof(struct keytab)); /* How many networks */
  664. #endif /* NETCONN */
  665.  
  666. /* Remote Command Table */
  667.  
  668. struct keytab remcmd[] = {
  669.     "cd",        XZCWD, 0,
  670.     "cwd",       XZCWD, CM_INV,
  671.     "delete",    XZDEL, 0,
  672.     "directory", XZDIR, 0,
  673.     "help",      XZHLP, 0,
  674. #ifndef NOPUSH
  675.     "host",      XZHOS, 0,
  676. #endif /* NOPUSH */
  677. #ifndef NOFRILLS
  678.     "kermit",    XZKER, 0,
  679.     "login",     XZLGI, 0,
  680.     "logout",    XZLGO, 0,
  681.     "print",     XZPRI, 0,
  682. #endif /* NOFRILLS */
  683.     "set",       XZSET, 0,
  684.     "space",     XZSPA, 0
  685. #ifndef NOFRILLS
  686. ,   "type",      XZTYP, 0,
  687.     "who",       XZWHO, 0
  688. #endif /* NOFRILLS */
  689. };
  690. int nrmt = (sizeof(remcmd) / sizeof(struct keytab));
  691.  
  692. struct keytab logtab[] = {
  693. #ifdef DEBUG
  694.     "debugging",    LOGD, 0,
  695. #endif /* DEBUG */
  696.     "packets",        LOGP, 0,
  697.     "session",      LOGS, 0
  698. #ifdef TLOG
  699. ,   "transactions", LOGT, 0
  700. #endif /* TLOG */
  701. };
  702. int nlog = (sizeof(logtab) / sizeof(struct keytab));
  703.  
  704. struct keytab writab[] = {
  705. #ifndef NOSPL
  706.     "append-file",     LOGW, CM_INV,
  707. #endif /* NOSPL */
  708.     "debug-log",       LOGD, 0,
  709.     "error",           LOGE, 0,
  710. #ifndef NOSPL
  711.     "file",            LOGW, 0,
  712. #endif /* NOSPL */
  713.     "packet-log",      LOGP, 0,
  714.     "screen",          LOGX, 0,
  715.     "session-log",     LOGS, 0,
  716.     "sys$output",      LOGX, CM_INV,
  717.     "transaction-log", LOGT, 0
  718. };
  719. int nwri = (sizeof(writab) / sizeof(struct keytab));
  720.  
  721. #define CLR_DEV  1
  722. #define CLR_INP  2
  723.  
  724. static struct keytab clrtab[] = {    /* Keywords for CLEAR command */
  725. #ifndef NOSPL
  726.     "both",          CLR_DEV|CLR_INP, 0,
  727. #endif /* NOSPL */
  728.     "device-buffer", CLR_DEV,         0,
  729. #ifndef NOSPL
  730.     "input-buffer",  CLR_INP,         0
  731. #endif /* NOSPL */
  732. };
  733. int nclear = (sizeof(clrtab) / sizeof(struct keytab));
  734.  
  735. struct keytab clstab[] = {        /* Keywords for CLOSE command */
  736. #ifndef NOSPL
  737.     "append-file",     LOGW, CM_INV,
  738. #endif /* NOSPL */
  739. #ifdef DEBUG
  740.     "debug-log",       LOGD, 0,
  741. #endif /* DEBUG */
  742.     "packet-log",      LOGP, 0,
  743. #ifndef NOSPL
  744.     "read-file",       LOGR, 0,
  745. #endif /* NOSPL */
  746.     "session-log",     LOGS, 0
  747. #ifdef TLOG
  748. ,   "transaction-log", LOGT, 0
  749. #endif /* TLOG */
  750. #ifndef NOSPL
  751. ,   "write-file",      LOGW, 0
  752. #endif /* NOSPL */
  753. };
  754. int ncls = (sizeof(clstab) / sizeof(struct keytab));
  755.  
  756. /* SHOW command arguments */
  757.  
  758. struct keytab shotab[] = {
  759. #ifndef NOSPL
  760.     "arguments", SHARG, 0,
  761.     "arrays", SHARR, 0,
  762. #endif /* NOSPL */
  763.     "attributes", SHATT, 0,
  764.     "character-sets", SHCSE, 0,
  765.     "communications", SHCOM, 0,
  766. #ifndef NOSPL
  767.     "count", SHCOU, 0,
  768. #endif /* NOSPL */
  769. #ifdef VMS
  770.     "default", SHDFLT, 0,
  771. #else
  772.     "default", SHDFLT, CM_INV,
  773. #endif /* VMS */
  774. #ifndef NODIAL
  775.     "dial", SHDIA, 0,
  776. #endif /* NODIAL */
  777.     "escape", SHESC, 0,
  778.     "features", SHFEA, 0,
  779.     "file", SHFIL, 0,
  780. #ifndef NOSPL
  781.     "functions", SHFUN, 0,
  782.     "globals", SHVAR, 0,
  783. #endif /* NOSPL */
  784. #ifndef NOSETKEY
  785.     "key", SHKEY, 0,
  786. #endif /* NOSETKEY */
  787. #ifdef VMS
  788.     "labeled-file-info", SHLBL, 0,
  789. #endif /* VMS */
  790. #ifndef NOCSETS
  791.     "languages", SHLNG, 0,
  792. #endif /* NOCSETS */
  793. #ifndef NOSPL
  794.     "macros", SHMAC, 0,
  795. #endif /* NOSPL */
  796.     "modem-signals", SHMOD, 0,
  797.     "network", SHNET, 0,
  798. #ifdef SUNX25
  799.     "pad", SHPAD, 0,
  800. #endif /* SUNX25 */
  801.     "parameters", SHPAR, CM_INV,
  802.     "protocol", SHPRO, 0,
  803. #ifndef NOSPL
  804.     "scripts", SHSCR, 0,
  805. #endif /* NOSPL */
  806. #ifndef NOSERVER
  807.     "server", SHSER, 0,
  808. #endif /* NOSERVER */
  809.     "status", SHSTA, 0,
  810. #ifdef MAC
  811.     "stack", SHSTK, 0,            /* debugging */
  812. #endif /* MAC */
  813.     "terminal", SHTER, 0
  814. #ifndef NOXMIT
  815. ,   "transmit", SHXMI, 0
  816. #endif /* NOXMIT */
  817. #ifndef NOSPL
  818. ,   "variables", SHBUI, 0
  819. #endif /* NOSPL */
  820. #ifndef NOFRILLS
  821. ,   "versions", SHVER, 0
  822. #endif /* NOFRILLS */
  823. #ifndef NOXMIT
  824. ,   "xmit", SHXMI, CM_INV
  825. #endif /* NOXMIT */
  826. };
  827. int nsho = (sizeof(shotab) / sizeof(struct keytab));
  828.  
  829. #ifdef SUNX25
  830. struct keytab padtab[] = {              /* PAD commands */
  831.     "clear",      XYPADL, 0,
  832.     "interrupt",  XYPADI, 0,
  833.     "reset",      XYPADR, 0,
  834.     "status",     XYPADS, 0
  835. };
  836. int npadc = (sizeof(padtab) / sizeof(struct keytab));
  837. #endif /* SUNX25 */
  838.  
  839. struct keytab enatab[] = {        /* ENABLE commands */
  840.     "all",        EN_ALL,  0,
  841. #ifndef datageneral
  842.     "bye",        EN_BYE,  0,
  843. #endif /* datageneral */
  844.     "cd",         EN_CWD,  0,
  845.     "cwd",        EN_CWD,  CM_INV,
  846.     "delete",     EN_DEL,  0,
  847.     "directory",  EN_DIR,  0,
  848.     "finish",     EN_FIN,  0,
  849.     "get",        EN_GET,  0,
  850.     "host",       EN_HOS,  0,
  851.     "send",       EN_SEN,  0,
  852.     "set",        EN_SET,  0,
  853.     "space",      EN_SPA,  0,
  854.     "type",       EN_TYP,  0,
  855.     "who",        EN_WHO,  0
  856. };
  857. int nena = (sizeof(enatab) / sizeof(struct keytab));
  858.  
  859. #ifndef NOSPL
  860. #ifdef COMMENT
  861. struct mtab mactab[MAC_MAX] = {        /* Preinitialized macro table */
  862.     NULL, NULL, 0
  863. };
  864. #else
  865. struct mtab *mactab;            /* Dynamically allocated macro table */
  866. #endif /* COMMENT */
  867. int nmac = 0;
  868.  
  869. struct keytab mackey[MAC_MAX];        /* Macro names as command keywords */
  870. #endif /* NOSPL */
  871.  
  872. /* Forward declarations of functions */
  873.  
  874. _PROTOTYP (int doask,   ( int  ) );
  875. _PROTOTYP (int dodef,   ( int  ) );
  876. _PROTOTYP (int dodel,   ( void ) );
  877. _PROTOTYP (int dodial,  ( int  ) );
  878. _PROTOTYP (int dodir,   ( void ) );
  879. _PROTOTYP (int doelse,  ( void ) );
  880. _PROTOTYP (int dofor,   ( void ) );
  881. _PROTOTYP (int dogta,   ( int  ) );
  882. _PROTOTYP (int doincr,  ( int  ) );
  883. _PROTOTYP (int dopaus,  ( int  ) );
  884. _PROTOTYP (int doping,  ( void ) );
  885. _PROTOTYP (int dorenam, ( void ) );
  886.  
  887. #ifdef TCPSOCKET
  888. int
  889. doping() {
  890.     char *p;
  891.     int x;
  892.  
  893.     if (network)            /* If we have a current connection */
  894.       strcpy(line,ttname);        /* get the host name */
  895.     else *line = '\0';            /* as default host to be pinged. */
  896.     for (p = line; *p; p++)        /* Remove ":service" from end. */
  897.       if (*p == ':') { *p = '\0'; break; }
  898.     if ((x = cmtxt("IP host name or number", line, &s, xxstring)) < 0)
  899.       return(x);
  900. /* Construct PING command */
  901. #ifdef VMS
  902. #ifdef MULTINET                /* TGV MultiNet */
  903.     sprintf(line,"multinet ping %s /num=1",s);
  904. #else
  905.     sprintf(line,"ping %s 56 1",s);    /* Other VMS TCP/IP's */
  906. #endif /* MULTINET */
  907. #else                    /* Not VMS */
  908.     sprintf(line,"ping %s",s);
  909. #endif /* VMS */
  910.     conres();                /* Make console normal  */
  911. #ifdef DEC_TCPIP
  912.     printf("\n");            /* Prevent prompt-stomping */
  913. #endif /* DEC_TCPIP */
  914.     x = zshcmd(line);
  915.     concb((char)escape);
  916.     return(success = 1);        /* We don't know the status */
  917. }
  918. #endif /* TCPSOCKET */
  919.  
  920. /*  D O C M D  --  Do a command  */
  921.  
  922. /*
  923.  Returns:
  924.    -2: user typed an illegal command
  925.    -1: reparse needed
  926.     0: parse was successful (even tho command may have failed).
  927. */ 
  928. int
  929. docmd(cx) int cx; {
  930.  
  931.     debug(F101,"docmd entry, cx","",cx);
  932.  
  933. /*
  934.   Massive switch() broken up into many smaller ones, for the benefit of
  935.   compilers that run out of space when trying to handle large switch
  936.   statements.
  937. */
  938.     switch (cx) {
  939.       case -4:            /* EOF */
  940. #ifdef OSK
  941.     if (msgflg)  printf("\n");
  942. #else
  943.     if (msgflg)  printf("\r\n");
  944. #endif /* OSK */
  945.       doexit(GOOD_EXIT,xitsta);
  946.       case -3:                /* Null command */
  947.     return(0);
  948.       case -9:                /* Like -2, but errmsg already done */
  949.       case -1:                /* Reparse needed */
  950.     return(cx);
  951.       case -6:                /* Special */
  952.       case -2:                /* Error, maybe */
  953. #ifndef NOSPL
  954. /*
  955.   Maybe they typed a macro name.  Let's look it up and see.
  956. */
  957.     if (cx == -6)            /* If they typed CR */
  958.       strcat(cmdbuf,"\015");    /*  add it back to command buffer. */
  959.     if (ifcmd[cmdlvl] == 2)        /* Watch out for IF commands. */
  960.       ifcmd[cmdlvl]--;
  961.     repars = 1;            /* Force reparse */
  962.     cmres();
  963.     cx = XXDO;            /* Try DO command */
  964. #else
  965.     return(cx);
  966. #endif /* NOSPL */
  967.       default:
  968.     break;
  969.     }
  970.  
  971. #ifndef NOSPL
  972. /* Copy macro args from/to two levels up, used internally by _floop et al. */
  973.     if (cx == XXGTA || cx == XXPTA) {    /* _GETARGS, _PUTARGS */
  974.     int x;
  975.     debug(F101,"docmd XXGTA","",XXGTA);
  976.     debug(F101,"docmd cx","",cx);
  977.     debug(F101,"docmd XXGTA maclvl","",maclvl);
  978.     x = dogta(cx);
  979.     debug(F101,"docmd dogta returns","",x);
  980.     debug(F101,"docmd dogta maclvl","",maclvl);
  981.     return(x);
  982.     }
  983. #endif /* NOSPL */
  984.  
  985. #ifndef NOSPL
  986. /* ASK, ASKQ, READ */
  987.     if (cx == XXASK || cx == XXASKQ || cx == XXREA) {
  988.     return(doask(cx));
  989.     }
  990. #endif /* NOSPL */
  991.  
  992. #ifndef NOFRILLS
  993.     if (cx == XXBUG) {            /* BUG */
  994.     if ((x = cmcfm()) < 0) return(x);
  995.     return(dobug());
  996.     }
  997. #endif /* NOFRILLS */
  998.  
  999.     if (cx == XXBYE) {            /* BYE */
  1000.     if ((x = cmcfm()) < 0) return(x);
  1001.     sstate = setgen('L',"","","");
  1002.     if (local) ttflui();        /* If local, flush tty input buffer */
  1003.     return(0);
  1004.     } 
  1005.  
  1006. #ifndef NOFRILLS
  1007.     if (cx == XXCLE) {            /* CLEAR */
  1008.     if ((x = cmkey(clrtab,nclear,"buffer(s) to clear",
  1009. #ifdef NOSPL
  1010.           "device-buffer"
  1011. #else
  1012.           "both"
  1013. #endif /* NOSPL */
  1014.           ,xxstring)) < 0) return(x);
  1015.     if ((y = cmcfm()) < 0) return(y);
  1016.  
  1017.     /* Clear device input buffer if requested */
  1018.     y = (x & CLR_DEV) ? ttflui() : 0;
  1019. #ifndef NOSPL
  1020.     /* Clear INPUT command buffer if requested */
  1021.     if (x & CLR_INP) {
  1022.         for (x = 0; x < INPBUFSIZ; x++)
  1023.           inpbuf[x] = 0;
  1024.         inpbp = inpbuf;
  1025.     }
  1026. #endif /* NOSPL */
  1027.     return(success = (y == 0));
  1028.     }
  1029. #endif /* NOFRILLS */
  1030.  
  1031.     if (cx == XXCOM) {            /* COMMENT */
  1032.     if ((x = cmtxt("Text of comment line","",&s,NULL)) < 0)
  1033.       return(x);
  1034.     /* Don't change SUCCESS flag for this one */
  1035.     return(0);
  1036.     } 
  1037.  
  1038.     if (cx == XXCON) {            /* CONNECT */
  1039.     if ((x = cmcfm()) < 0)
  1040.       return(x);
  1041.     return(success = doconect());
  1042.     }
  1043.  
  1044.     if (cx == XXCWD)            /* CWD */
  1045.       return(success = docd());
  1046.  
  1047.     if (cx == XXCHK)            /* CHECK */
  1048.       return(success = dochk());
  1049.  
  1050.     if (cx == XXCLO) {            /* CLOSE */
  1051.     x = cmkey(clstab,ncls,"Which log or file to close","",xxstring);
  1052.     if (x == -3) {
  1053.         printf("?You must say which file or log\n");
  1054.         return(-9);
  1055.     }
  1056.     if (x < 0) return(x);
  1057.     if ((y = cmcfm()) < 0) return(y);
  1058.     y = doclslog(x);
  1059.     success = (y == 1);
  1060.     return(success);
  1061.     }
  1062.  
  1063. #ifndef NOSPL
  1064.     if (cx == XXDEC || cx == XXINC)    /* DECREMENT, INCREMENT */
  1065.       return(doincr(cx));
  1066. #endif /* NOSPL */
  1067.  
  1068. #ifndef NOSPL
  1069.     if (cx == XXDEF || cx == XXASS || cx == XXASX || cx == XXDFX)
  1070.       return(dodef(cx));        /* DEFINE, ASSIGN */
  1071. #endif /* NOSPL */
  1072.  
  1073. #ifndef NOSPL    
  1074.     if (cx == XXDCL) {            /* DECLARE an array */
  1075.     if ((y = cmfld("Array name","",&s,NULL)) < 0) {
  1076.         if (y == -3) {
  1077.         printf("?Array name required\n");
  1078.         return(-9);
  1079.         } else return(y);
  1080.     }
  1081.     if ((y = arraynam(s,&x,&z)) < 0) return(y);
  1082.     if ((y = cmcfm()) < 0) return(y);
  1083.     if (dclarray((char)x,z) < 0) {
  1084.         printf("?Declare failed\n");
  1085.         return(success = 0);
  1086.     }
  1087.     return(success = 1);
  1088.     }
  1089. #endif /* NOSPL */
  1090.  
  1091.  
  1092. #ifndef NODIAL
  1093.     if (cx == XXRED || cx == XXDIAL)    /* DIAL or REDIAL */
  1094.       return(dodial(cx));
  1095. #endif /* NODIAL */
  1096.  
  1097. #ifndef NOFRILLS
  1098.     if (cx == XXDEL)            /* DELETE */
  1099.       return(dodel());
  1100. #endif /* NOFRILLS */
  1101.  
  1102. #ifndef MAC
  1103.     if (cx == XXDIR)            /* DIRECTORY */
  1104.       return(dodir());
  1105. #endif /* MAC */
  1106.  
  1107. #ifndef NOSPL
  1108.     if (cx == XXELS)            /* ELSE */
  1109.       return(doelse());
  1110. #endif /* NOSPL */
  1111.  
  1112. #ifndef NOFRILLS
  1113.     if (cx == XXENA || cx == XXDIS) {    /* ENABLE, DISABLE */
  1114.     s = (cx == XXENA) ?
  1115.       "Server function to enable" :
  1116.         "Server function to disable";
  1117.  
  1118.     if ((x = cmkey(enatab,nena,s,"",xxstring)) < 0) {
  1119.         if (x == -3) {
  1120.         printf("?Name of server function required\n");
  1121.         return(-9);
  1122.         } else return(x);
  1123.     }
  1124.     if ((y = cmcfm()) < 0) return(y);
  1125.     return(doenable(cx,x));
  1126.     }
  1127. #endif /* NOFRILLS */
  1128.  
  1129. #ifndef NOSPL
  1130.     if (cx == XXRET) {            /* RETURN */
  1131.     if (cmdlvl == 0) {        /* At top level, nothing happens... */
  1132.         if ((x = cmcfm()) < 0)
  1133.           return(x);
  1134.         return(success = 1);
  1135.     } else if (cmdstk[cmdlvl].src == CMD_TF) { /* In TAKE file, like POP */
  1136.         if ((x = cmtxt("optional return value","",&s,NULL)) < 0)
  1137.           return(x);        /* Allow trailing text, but ignore. */
  1138.         if ((x = cmcfm()) < 0)
  1139.           return(x);
  1140.         popclvl();            /* pop command level */
  1141.         return(success = 1);    /* always succeeds */
  1142.     } else if (cmdstk[cmdlvl].src == CMD_MD) { /* Within macro */  
  1143.         if ((x = cmtxt("optional return value","",&s,NULL)) < 0)
  1144.           return(x);
  1145.         return(doreturn(s));    /* Trailing text is return value. */
  1146.     } else return(-2);
  1147.     }
  1148. #endif /* NOSPL */
  1149.  
  1150. #ifndef NOSPL
  1151.     if (cx == XXDO) {            /* DO (a macro) */
  1152.     if (nmac == 0) {
  1153.         printf("\n?No macros defined\n");
  1154.         return(-2);
  1155.     }
  1156.     for (y = 0; y < nmac; y++) {    /* copy the macro table */
  1157.         mackey[y].kwd = mactab[y].kwd; /* into a regular keyword table */
  1158.         mackey[y].kwval = y;    /* with value = pointer to macro tbl */
  1159.         mackey[y].flgs = mactab[y].flgs;
  1160.     }
  1161.     /* parse name as keyword */
  1162.     if ((x = cmkey(mackey,nmac,"macro","",xxstring)) < 0) {
  1163.         if (x == -3) {
  1164.         printf("?Macro name required\n");
  1165.         return(-9);
  1166.         } else return(x);
  1167.     }
  1168.     if ((y = cmtxt("optional arguments","",&s,xxstring)) < 0)
  1169.       return(y);            /* get args */
  1170.     return(dodo(x,s) < 1 ? (success = 0) : 1);
  1171.     }
  1172. #endif /* NOSPL */
  1173.  
  1174.     if (cx == XXECH) {            /* ECHO */
  1175.     if ((x = cmtxt("Material to be echoed","",&s,xxstring)) < 0)
  1176.       return(x);
  1177.     if (*s == '{') {        /* Strip enclosing braces */
  1178.         x = (int)strlen(s);
  1179.         if (s[x-1] == '}') {
  1180.         s[x-1] = NUL;
  1181.         s++;
  1182.         }
  1183.     }
  1184.     printf("%s\n",s);
  1185.     return(1);            /* Always succeeds */
  1186.     }
  1187.  
  1188. #ifndef NOSPL
  1189.     if (cx == XXOPE)            /* OPEN */
  1190.       return(doopen());
  1191. #endif /* NOSPL */
  1192.  
  1193. #ifndef NOSPL
  1194.     if (cx == XXOUT) {            /* OUTPUT */
  1195.     if ((x = cmtxt("Text to be output","",&s,NULL)) < 0)
  1196.       return(x);
  1197.     debug(F110,"OUTPUT 1",s,0);
  1198.     if (*s == '{') {        /* Strip enclosing braces, */
  1199.         x = (int)strlen(s);        /* if any. */
  1200.         if (s[x-1] == '}') {
  1201.         s[x-1] = NUL;
  1202.         s++;
  1203.         }
  1204.     }
  1205.     debug(F110,"OUTPUT 2",s,0);
  1206.     for (x = 0, y = 0; s[x]; x++, y++) { /* Convert \B, \L to \\B, \\L */
  1207.         if (x > 0 &&
  1208.         (s[x] == 'B' || s[x] == 'b' || s[x] == 'L' || s[x] == 'l'))
  1209.           if ((x == 1 && s[x-1] == CMDQ) ||
  1210.           (x > 1 && s[x-1] == CMDQ && s[x-2] != CMDQ))
  1211.         line[y++] = CMDQ;
  1212.         line[y] = s[x];
  1213.     }
  1214.     line[y++] = '\0';        /* Now expand variables, etc. */
  1215.     debug(F110,"OUTPUT 3",line,0);
  1216.     s = line+y+1;
  1217.     x = LINBUFSIZ - strlen(line) - 1;
  1218.     debug(F101,"OUTPUT size","",x);
  1219.     if (xxstring(line,&s,&x) < 0)
  1220.       return(success = 0);
  1221.     s = line+y+1;
  1222.     debug(F110,"OUTPUT 4",s,0);
  1223.     return(success = dooutput(s));
  1224.     }
  1225. #endif /* NOSPL */
  1226.  
  1227. #ifdef SUNX25
  1228.     if (cx == XXPAD) {            /* PAD commands */
  1229.     x = cmkey(padtab,npadc,"PAD command","",xxstring);
  1230.     if (x == -3) {
  1231.         printf("?You must specify a PAD command to execute\n");
  1232.         return(-2);
  1233.     }
  1234.     if (x < 0) return(x);
  1235.     
  1236.     switch (x) {
  1237.       case XYPADL: 
  1238.         if (x25stat() < 0)
  1239.           printf("Sorry, you must 'set network' & 'set host' first\r\n");
  1240.         else {
  1241.         x25clear();
  1242.         initpad();
  1243.         }
  1244.         break;
  1245.       case XYPADS:
  1246.         if (x25stat() < 0)
  1247.           printf("Not connected\r\n");
  1248.         else {
  1249.         extern int linkid, lcn;
  1250.         conol("Connected thru ");
  1251.         conol(ttname);
  1252.         printf(", Link id %d, Logical channel number %d\r\n",
  1253.                linkid,lcn);
  1254.         }
  1255.         break;
  1256.       case XYPADR:
  1257.         if (x25stat() < 0)
  1258.           printf("Sorry, you must 'set network' & 'set host' first\r\n");
  1259.         else
  1260.           x25reset(0,0);
  1261.         break;
  1262.       case XYPADI:
  1263.         if (x25stat() < 0)
  1264.           printf("Sorry, you must 'set network' & 'set host' first\r\n");
  1265.         else 
  1266.           x25intr(0);
  1267.     }
  1268.     return(0);
  1269. }
  1270. #endif /* SUNX25 */
  1271.  
  1272. #ifndef NOSPL
  1273.     if (cx == XXPAU || cx == XXWAI || cx == XXMSL) /* PAUSE, WAIT, etc */
  1274.       return(dopaus(cx));
  1275. #endif /* NOSPL */
  1276.  
  1277. #ifndef NOFRILLS
  1278.     if (cx == XXPRI) {
  1279.     if ((x = cmifi("File to print","",&s,&y,xxstring)) < 0) {
  1280.         if (x == -3) {
  1281.         printf("?A file specification is required\n");
  1282.         return(-9);
  1283.         } else return(x);
  1284.     }
  1285.     if (y != 0) {
  1286.         printf("?Wildcards not allowed\n");
  1287.         return(-9);
  1288.     }
  1289.     strcpy(line,s);
  1290.     if ((x = cmtxt("Local print command options, or carriage return","",&s,
  1291.                xxstring)) < 0) return(x);
  1292.     return(success = (zprint(s,line) == 0) ? 1 : 0);
  1293.     }
  1294.  
  1295. #ifdef TCPSOCKET
  1296.     if (cx == XXPNG)             /* PING an IP host */
  1297.       return(doping());
  1298. #endif /* TCPSOCKET */
  1299.  
  1300. #ifndef MAC
  1301.     if (cx == XXPWD) {            /* PWD */
  1302.     if ((x = cmcfm()) < 0) return(x);
  1303.     xsystem(PWDCMD);
  1304.     return(success = 1);        /* blind faith */
  1305.     }
  1306. #endif /* MAC */
  1307. #endif /* NOFRILLS */
  1308.  
  1309.     if (cx == XXQUI || cx == XXEXI) {    /* EXIT, QUIT */
  1310.     if ((y = cmnum("exit status code","",10,&x,xxstring)) < 0) {
  1311.         if (y == -3)
  1312.           x = xitsta;
  1313.         else return(y);
  1314.     }
  1315.     if ((y = cmcfm()) < 0) return(y);
  1316. #ifdef VMS
  1317.     doexit(GOOD_EXIT,x);
  1318. #else
  1319. #ifdef OSK
  1320. /* Returning any codes here makes the OS-9 shell print an error message. */
  1321.     doexit(GOOD_EXIT,-1);
  1322. #else
  1323. #ifdef datageneral
  1324.         doexit(GOOD_EXIT,x);
  1325. #else
  1326.     doexit(x,-1);
  1327. #endif /* datageneral */
  1328. #endif /* OSK */
  1329. #endif /* VMS */
  1330.     }
  1331.  
  1332. #ifndef NOFRILLS
  1333.     if (cx == XXERR) {            /* ERROR */
  1334.     if ((x = cmcfm()) < 0) return(x);
  1335.     ttflui();
  1336.     sstate = 'a';
  1337.     return(0);
  1338.     }
  1339. #endif /* NOFRILLS */
  1340.  
  1341.     if (cx == XXFIN) {            /* FINISH */
  1342.     if ((x = cmcfm()) < 0) return(x);
  1343.     sstate = setgen('F',"","","");
  1344.     if (local) ttflui();        /* If local, flush tty input buffer */
  1345.     return(0);
  1346.     }
  1347.  
  1348. #ifndef NOSPL
  1349.     if (cx == XXFOR)            /* FOR loop */
  1350.       return(dofor());
  1351. #endif /* NOSPL */
  1352.  
  1353.     if (cx == XXGET) {            /* GET */
  1354.     x = cmtxt("Name of remote file(s), or carriage return","",&cmarg,
  1355.           xxstring);
  1356. #ifndef NOFRILLS
  1357.     if ((x == -2) || (x == -1)) return(x);
  1358. #else
  1359.     if (x < 0) return(x);
  1360. #endif /* NOFRILLS */
  1361.     if (*cmarg == '{') {        /* Strip any enclosing braces */
  1362.         x = (int)strlen(cmarg);    /* This allows preservation of */
  1363.         if (cmarg[x-1] == '}') {    /* leading and/or trailing */
  1364.         cmarg[x-1] = NUL;    /* spaces. */
  1365.         cmarg++;
  1366.         }
  1367.     }
  1368.     x = doget();
  1369. #ifdef MAC
  1370.     if (sstate == 'r')
  1371.         scrcreate();
  1372. #endif /* MAC */
  1373.     return(x);
  1374.     }
  1375.  
  1376. #ifndef NOSPL
  1377. #ifndef NOFRILLS
  1378.     if (cx == XXGOK) {            /* GETOK */
  1379.     return(success = doask(cx));
  1380.     }
  1381. #endif /* NOFRILLS */
  1382. #endif /* NOSPL */
  1383.  
  1384.     if (cx == XXHLP) {            /* HELP */
  1385. #ifdef NOHELP
  1386.     return(dohlp(XXHLP));        
  1387. #else
  1388.     x = cmkey2(cmdtab,ncmd,"C-Kermit command","help",toktab,xxstring);
  1389.     debug(F101,"HELP command x","",x);
  1390.     if (x == -5) {
  1391.         y = chktok(toktab);
  1392.         debug(F101,"top-level cmkey token","",y);
  1393.         ungword();
  1394.         switch (y) {
  1395. #ifndef NOPUSH
  1396.           case '!': x = XXSHE; break;
  1397. #endif /* NOPUSH */
  1398.           case '#': x = XXCOM; break;
  1399.           case ';': x = XXCOM; break;
  1400. #ifndef NOSPL
  1401.           case ':': x = XXLBL; break;
  1402. #endif /* NOSPL */
  1403.           case '&': x = XXECH; break;
  1404.           default:
  1405.         printf("\n?Invalid - %s\n",cmdbuf);
  1406.         x = -2;
  1407.         }
  1408.     }
  1409.     return(dohlp(x));
  1410. #endif /* NOHELP */
  1411.     }
  1412.  
  1413. #ifndef NOHELP
  1414.     if (cx == XXINT)            /* INTRO */
  1415.       return(hmsga(introtxt));
  1416. #endif /* NOHELP */
  1417.  
  1418.     if (cx == XXHAN) {            /* HANGUP */
  1419.     if ((x = cmcfm()) < 0) return(x);
  1420. #ifndef NODIAL
  1421.     if ((x = mdmhup()) < 1)
  1422. #endif /* NODIAL */
  1423.       x = (tthang() > -1);
  1424.     return(success = x);
  1425.     }
  1426.  
  1427. #ifndef NOSPL
  1428.     if (cx == XXGOTO) {            /* GOTO */
  1429. /* Note, here we don't set SUCCESS/FAILURE flag */
  1430.     if ((y = cmfld("label","",&s,xxstring)) < 0) {
  1431.         if (y == -3) {
  1432.         printf("?Label name required\n");
  1433.         return(-9);
  1434.         } else return(y);
  1435.     }
  1436.     strcpy(lblbuf,s);
  1437.     if ((x = cmcfm()) < 0) return(x);
  1438.     s = lblbuf;
  1439.     return(dogoto(s));
  1440.     }
  1441. #endif /* NOSPL */
  1442.  
  1443. #ifndef NOSPL
  1444. /* IF, Extended IF, WHILE */
  1445.     if (cx == XXIF || cx == XXIFX || cx == XXWHI) {
  1446.     return(doif(cx));
  1447.     }
  1448. #endif /* NOSPL */
  1449.  
  1450. #ifndef NOSPL
  1451.     if (cx == XXINP || cx == XXREI) {    /* INPUT and REINPUT */
  1452.     sprintf(tmpbuf,"%d",indef);
  1453.     y = cmnum("seconds to wait for input",(char *)tmpbuf,10,&x,xxstring);
  1454.     if (y < 0) {
  1455.         return(y);
  1456.     }
  1457.     if (x <= 0) x = 1;
  1458.     if ((y = cmtxt("Material to be input","",&s,xxstring)) < 0)
  1459.       return(y);
  1460. #ifdef COMMENT
  1461. /*
  1462.   Now it's ok -- null argument means wait for any character.
  1463. */
  1464.     if (*s == '\0') {
  1465.         printf("?Text required\n");
  1466.         return(-9);
  1467.     }
  1468. #endif /* COMMENT */
  1469.     if (*s == '{') {
  1470.         y = (int)strlen(s);
  1471.         if (s[y-1] == '}') {
  1472.         s[y-1] = NUL;
  1473.         s++;
  1474.         }
  1475.     }
  1476.     if (cx == XXINP) {        /* INPUT */
  1477.         debug(F110,"calling doinput",s,0);
  1478.         success = doinput(x,s);    /* Go try to input the search string */
  1479.     } else {            /* REINPUT */
  1480.         debug(F110,"xxrei line",s,0);
  1481.         success = doreinp(x,s);
  1482.     }
  1483.     if (intime[cmdlvl] && !success) { /* TIMEOUT-ACTION = QUIT? */
  1484.         popclvl();            /* If so, pop command level. */
  1485.         if (pflag && cmdlvl == 0) {
  1486.         if (cx == XXINP) printf("?Input timed out\n");
  1487.         if (cx == XXREI) printf("?Reinput failed\n");
  1488.         }
  1489.     }
  1490.     return(success);        /* Return do(re)input's return code */
  1491.     }
  1492. #endif /* NOSPL */
  1493.  
  1494. #ifndef NOSPL
  1495.     if (cx == XXLBL) {            /* LABEL */
  1496.     if ((x = cmfld("label","",&s,xxstring)) < 0) {
  1497.         if (x == -3) {
  1498.         printf("?Label name required\n");
  1499.         return(-9);
  1500.         } else return(x);
  1501.     }
  1502.     if ((x = cmcfm()) < 0) return(x);
  1503.     return(0);
  1504.     }
  1505. #endif /* NOSPL */
  1506.  
  1507.     if (cx == XXLOG) {            /* LOG */
  1508.     x = cmkey(logtab,nlog,"What to log","",xxstring);
  1509.     if (x == -3) {
  1510.         printf("?Type of log required\n");
  1511.         return(-9);
  1512.     }
  1513.     if (x < 0) return(x);
  1514.     x = dolog(x);
  1515.     if (x < 0)
  1516.       return(x);
  1517.     else
  1518.       return(success = x);
  1519.     }
  1520.  
  1521. #ifndef NOSCRIPT
  1522.     if (cx == XXLOGI) {            /* UUCP-style script */
  1523.     if ((x = cmtxt("expect-send expect-send ...","",&s,xxstring)) < 0)
  1524.       return(x);
  1525. #ifdef VMS
  1526.     conres();            /* For Ctrl-C to work... */
  1527. #endif /* VMS */
  1528.     return(success = dologin(s));    /* Return 1=completed, 0=failed */
  1529.     }
  1530. #endif /* NOSCRIPT */
  1531.  
  1532.     if (cx == XXREC) {            /* RECEIVE */
  1533.     cmarg2 = "";
  1534.     x = cmofi("Name under which to store the file, or CR","",&s,
  1535.           xxstring);
  1536.     if ((x == -1) || (x == -2)) return(x);
  1537.     if ((x = cmcfm()) < 0) return(x);
  1538.     strcpy(line,s);
  1539.     cmarg2 = line;
  1540.     debug(F111,"cmofi cmarg2",cmarg2,x);
  1541.     sstate = 'v';
  1542. #ifdef MAC
  1543.     scrcreate();
  1544. #endif /* MAC */
  1545.     if (local) displa = 1;
  1546.     return(0);
  1547.     }
  1548.  
  1549.     if (cx == XXREM) {            /* REMOTE */
  1550.     x = cmkey(remcmd,nrmt,"Remote Kermit server command","",xxstring);
  1551.     if (x == -3) {
  1552.         printf("?You must specify a command for the remote server\n");
  1553.         return(-9);
  1554.     }
  1555.     return(dormt(x));
  1556.     }
  1557.  
  1558. #ifndef NOFRILLS
  1559.     if (cx == XXREN)            /* RENAME */
  1560.       return(dorenam());
  1561. #endif /* NOFRILLS */
  1562.  
  1563.     if (cx == XXSEN || cx == XXMAI) {    /* SEND, MAIL */
  1564.     cmarg = cmarg2 = "";
  1565.     if ((x = cmifi("File(s) to send","",&s,&y,xxstring)) < 0) {
  1566.         if (x == -3) {
  1567.         printf("?A file specification is required\n");
  1568.         return(-9);
  1569.         } else return(x);
  1570.     }
  1571.     nfils = -1;            /* Files come from internal list. */
  1572.     strcpy(line,s);            /* Save copy of string just parsed. */
  1573.     strncpy(fspec,s,FSPECL);    /* and here for \v(filespec) */
  1574.     if (cx == XXSEN) {        /* SEND command */
  1575.         debug(F101,"Send: wild","",y);
  1576.         if (y == 0) {
  1577.         if ((x = cmtxt("Name to send it with","",&cmarg2,
  1578.                    xxstring)) < 0)
  1579.           return(x);
  1580.         } else {
  1581.         if ((x = cmcfm()) < 0) return(x);
  1582.         }
  1583.         cmarg = line;        /* File to send */
  1584.         debug(F110,"Sending:",cmarg,0);
  1585.         if (*cmarg2 != '\0') debug(F110," as:",cmarg2,0);
  1586.     } else {            /* MAIL */
  1587. #ifndef NOFRILLS
  1588.         if (!atdiso || !atcapr) {    /* Disposition attribute off? */
  1589.         printf("?Disposition Attribute is Off\n");
  1590.         return(-2);
  1591.         }
  1592.         debug(F101,"Mail: wild","",y);
  1593.         *optbuf = NUL;        /* Wipe out any old options */
  1594.         if ((x = cmtxt("Address to mail to","",&s,xxstring)) < 0)
  1595.           return(x);
  1596.         if ((int)strlen(s) == 0) {
  1597.         printf("?Address required\n");
  1598.         return(-9);
  1599.         }
  1600.         strcpy(optbuf,s);
  1601.         if ((int)strlen(optbuf) > 94) { /* Ensure legal size */
  1602.         printf("?Option string too long\n");
  1603.         return(-2);
  1604.         }
  1605.         cmarg = line;        /* File to send */
  1606.         debug(F110,"Mailing:",cmarg,0);
  1607.         debug(F110,"To:",optbuf,0);
  1608.         rmailf = 1;            /* MAIL modifier flag for SEND */
  1609. #else
  1610.         printf("?Sorry, MAIL feature not configured.\n");
  1611.         return(-2);
  1612. #endif /* NOFRILLS */
  1613.     }
  1614.     sstate = 's';            /* Set start state to SEND */
  1615. #ifdef MAC
  1616.     scrcreate();
  1617. #endif /* MAC */
  1618.     if (local) {            /* If in local mode, */
  1619.         displa = 1;            /* turn on file transfer display */
  1620. #ifdef COMMENT
  1621. /* Redundant -- this is done later in sipkt() */
  1622.         ttflui();            /* and flush tty input buffer. */
  1623. #endif /* COMMENT */
  1624.     }
  1625.     return(0);
  1626.     }
  1627.  
  1628. #ifndef NOMSEND
  1629.     if (cx == XXMSE) {            /* MSEND command */
  1630.     nfils = 0;            /* Like getting a list of */
  1631.     lp = line;            /* files on the command line */
  1632.     while (1) {
  1633.         char *p;
  1634.         if ((x = cmifi("Names of files to send, separated by spaces","",
  1635.                &s,&y,xxstring)) < 0) {
  1636.         if (x == -3) {
  1637.             if (nfils <= 0) {
  1638.             printf("?A file specification is required\n");
  1639.             return(-9);
  1640.             } else break;
  1641.         }
  1642.         return(x);
  1643.         }
  1644.         msfiles[nfils++] = lp;    /* Got one, count it, point to it, */
  1645.         p = lp;            /* remember pointer, */
  1646.         while (*lp++ = *s++) ;    /* and copy it into buffer */
  1647.         debug(F111,"msfiles",msfiles[nfils-1],nfils-1);
  1648.         if (nfils == 1) *fspec = NUL; /* Take care of \v(filespec) */
  1649.         if (((int)strlen(fspec) + (int)strlen(p) + 1) < FSPECL) {
  1650.         strcat(fspec,p);
  1651.         strcat(fspec," ");
  1652.         }
  1653.     }
  1654.     cmlist = msfiles;        /* Point cmlist to pointer array */
  1655.     cmarg2 = "";            /* No internal expansion list (yet) */
  1656.     sndsrc = nfils;            /* Filenames come from cmlist */
  1657.     sstate = 's';            /* Set start state to SEND */
  1658. #ifdef MAC
  1659.     scrcreate();
  1660. #endif /* MAC */
  1661.     if (local) {            /* If in local mode, */
  1662.         displa = 1;            /* turn on file transfer display */
  1663.         ttflui();            /* and flush tty input buffer. */
  1664.     }
  1665.     return(0);
  1666.     }
  1667. #endif /* NOMSEND */
  1668.  
  1669. #ifndef NOSERVER
  1670.     if (cx == XXSER) {            /* SERVER */
  1671.     if ((x = cmcfm()) < 0) return(x);
  1672.     sstate = 'x';
  1673. #ifdef MAC
  1674.     scrcreate();
  1675. #endif /* MAC */
  1676.     if (local) displa = 1;
  1677. #ifdef AMIGA
  1678.     reqoff();            /* No DOS requestors while server */
  1679. #endif /* AMIGA */
  1680.     return(0);
  1681.     }
  1682. #endif /* NOSERVER */
  1683.  
  1684.     if (cx == XXSET) {            /* SET command */
  1685.     x = cmkey(prmtab,nprm,"Parameter","",xxstring);
  1686.     if (x == -3) {
  1687.         printf("?You must specify a parameter to set\n");
  1688.         return(-9);
  1689.     }
  1690.     if (x < 0) return(x);
  1691.     /* have to set success separately for each item in doprm()... */
  1692.     /* actually not really, could have just had doprm return 0 or 1 */
  1693.     /* and set success here... */
  1694.     y = doprm(x,0);
  1695.     if (y == -3) {
  1696.         printf("?More fields required\n");
  1697.         return(-9);
  1698.     } else return(y);
  1699.     }
  1700.  
  1701. #ifndef NOPUSH
  1702.     if (cx == XXSHE) {            /* SHELL (system) command */
  1703.     if (cmtxt("System command to execute","",&s,xxstring) < 0)
  1704.       return(-1);
  1705.     conres();            /* Make console normal  */
  1706.     x = zshcmd(s);
  1707.     concb((char)escape);
  1708.     return(success = x);
  1709.     }
  1710. #endif /* NOPUSH */
  1711.  
  1712. #ifndef NOSHOW
  1713.     if (cx == XXSHO) {            /* SHOW */
  1714.     x = cmkey(shotab,nsho,"","parameters",xxstring);
  1715.     if (x < 0) return(x);
  1716.     return(doshow(x));
  1717.     }
  1718. #endif /* NOSHOW */
  1719.  
  1720. #ifndef MAC
  1721.     if (cx == XXSPA) {            /* SPACE */
  1722. #ifdef datageneral
  1723.     /* AOS/VS can take an argument after its "space" command. */
  1724.     if ((x = cmtxt("Confirm, or local directory name","",&s,xxstring)) < 0)
  1725.       return(x);
  1726.     if (*s == NUL) xsystem(SPACMD);
  1727.     else {
  1728.         sprintf(line,"space %s",s);
  1729.         xsystem(line);
  1730.     }
  1731. #else
  1732. #ifdef OS2
  1733.     if ((x = cmtxt("Press Enter for current disk,\n\
  1734.  or specify a disk letter like A:","",&s,xxstring)) < 0)
  1735.       return(x);
  1736.     if (*s == NUL) {        /* Current disk */
  1737.         printf(" Free space: %ldK\n", zdskspace(0)/1024L);
  1738.     } else {
  1739.         int drive = toupper(*s);
  1740.         printf(" Drive %c: %ldK free\n", drive, 
  1741.            zdskspace(drive - 'A' + 1) / 1024L);
  1742.     }
  1743. #else
  1744. #ifdef UNIX
  1745. #ifdef COMMENT
  1746.     if ((x = cmtxt("Confirm for current disk,\n\
  1747.  or specify a disk device or directory","",&s,xxstring)) < 0)
  1748.       return(x);
  1749. #else
  1750.     x = cmdir("Confirm for current disk,\n\
  1751.  or specify a disk device or directory","",&s,xxstring);
  1752.     if (x == -3)
  1753.       s = "";
  1754.     else if (x < 0)
  1755.       return(x);
  1756.     if ((x = cmcfm()) < 0) return(x);
  1757. #endif /* COMMENT */
  1758.     if (*s == NUL) {        /* Current disk */
  1759.         xsystem(SPACMD);
  1760.     } else {            /* Specified disk */
  1761.         sprintf(line,"%s %s",SPACM2,s);
  1762.         xsystem(line);
  1763.     }
  1764. #else
  1765.     if ((x = cmcfm()) < 0) return(x);
  1766.     xsystem(SPACMD);
  1767. #endif /* UNIX */
  1768. #endif /* OS2 */
  1769. #endif /* datageneral */
  1770.     return(success = 1);        /* Pretend it worked */
  1771.     }
  1772. #endif /* MAC */
  1773.  
  1774.     if (cx == XXSTA) {            /* STATISTICS */
  1775.     if ((x = cmcfm()) < 0) return(x);
  1776.     return(success = dostat());
  1777.     }
  1778.  
  1779.     if (cx == XXSTO || cx == XXEND) {    /* STOP, END, or POP */
  1780.     if ((y = cmnum("exit status code","0",10,&x,xxstring)) < 0)
  1781.       return(y);
  1782.     if ((y = cmtxt("Message to print","",&s,xxstring)) < 0)
  1783.       return(y);
  1784.     if (*s == '{') {        /* Strip any enclosing braces */
  1785.         x = (int)strlen(s);
  1786.         if (s[x-1] == '}') {
  1787.         s[x-1] = NUL;
  1788.         s++;
  1789.         }
  1790.     }
  1791.     if (*s) printf("%s\n",s);
  1792.     if (cx == XXSTO) dostop(); else popclvl(); 
  1793.     return(success = (x == 0));
  1794.     }
  1795.  
  1796.     if (cx == XXSUS) {            /* SUSPEND */
  1797.     if ((y = cmcfm()) < 0) return(y);
  1798. #ifdef NOJC
  1799.     printf("Sorry, this version of Kermit cannot be suspended\n");
  1800. #else
  1801.     stptrap(0);
  1802. #endif /* NOJC */
  1803.     return(0);
  1804.     }
  1805.  
  1806.     if (cx == XXTAK) {            /* TAKE */
  1807.     if (tlevel > MAXTAKE-1) {
  1808.         printf("?Take files nested too deeply\n");
  1809.         return(-2);
  1810.     }
  1811.     if ((y = cmifi("C-Kermit command file","",&s,&x,xxstring)) < 0) { 
  1812.         if (y == -3) {
  1813.         printf("?A file name is required\n");
  1814.         return(-9);
  1815.         } else return(y);
  1816.     }
  1817.     if (x != 0) {
  1818.         printf("?Wildcards not allowed in command file name\n");
  1819.         return(-9);
  1820.     }
  1821.     strcpy(line,s);
  1822.     if ((y = cmcfm()) < 0) return(y);
  1823.     return(success = dotake(line));
  1824.     }
  1825.  
  1826. #ifdef NETCONN
  1827.     if (cx == XXTEL) {            /* TELNET */
  1828.     if ((y = setlin(XYHOST,0)) < 0) return(y);
  1829.     return (success = (y == 0) ? 0 : doconect());
  1830.     }
  1831. #endif /* NETCONN */
  1832.  
  1833. #ifndef NOXMIT
  1834.     if (cx == XXTRA) {            /* TRANSMIT */
  1835.     if ((x = cmifi("File to transmit","",&s,&y,xxstring)) < 0) {
  1836.         if (x == -3) {
  1837.         printf("?Name of an existing file\n");
  1838.         return(-9);
  1839.         } else return(x);
  1840.     }
  1841.     if (y != 0) {
  1842.         printf("?Only a single file may be transmitted\n");
  1843.         return(-2);
  1844.     }
  1845.     strcpy(line,s);            /* Save copy of string just parsed. */
  1846.     if ((y = cmcfm()) < 0) return(y); /* Confirm the command */
  1847.     debug(F111,"calling transmit",line,xmitp);
  1848.     return(success = transmit(line,(char)xmitp)); /* Do the command */
  1849.     }
  1850. #endif /* NOXMIT */
  1851.  
  1852. #ifndef NOFRILLS
  1853.     if (cx == XXTYP) {            /* TYPE */
  1854. #ifndef MAC
  1855.     char *tc;
  1856. #endif /* MAC */
  1857.     if ((x = cmifi("File to type","",&s,&y,xxstring)) < 0) {
  1858.         if (x == -3) {
  1859.         printf("?Name of an existing file\n");
  1860.         return(-9);
  1861.         } else return(x);
  1862.     }
  1863.     if (y != 0) {
  1864.         printf("?A single file please\n");
  1865.         return(-2);
  1866.     }
  1867. #ifndef MAC
  1868.     if (!(tc = getenv("CK_TYPE"))) tc = TYPCMD;
  1869.     sprintf(line,"%s %s",tc,s);
  1870.     if ((y = cmcfm()) < 0) return(y); /* Confirm the command */
  1871.     xsystem(line);
  1872.     return(success = 1);
  1873. #else
  1874.     strcpy(line,s);
  1875.     if ((y = cmcfm()) < 0) return(y); /* Confirm the command */
  1876.     return(success = dotype(line));
  1877. #endif /* MAC */
  1878.     }
  1879. #endif /* NOFRILLS */
  1880.  
  1881. #ifndef NOFRILLS
  1882.     if (cx == XXTES) {            /* TEST */
  1883.     /* Fill this in with whatever is being tested... */
  1884.     if ((y = cmcfm()) < 0) return(y); /* Confirm the command */
  1885.  
  1886. #ifndef NOSPL
  1887. #ifdef COMMENT
  1888.     { int d, i, j;            /* Dump all arrays */
  1889.       char c, **p;
  1890.       for (i = 0; i < 27; i++) {
  1891.           p = a_ptr[i];
  1892.           d = a_dim[i];
  1893.           c = (i == 0) ? 64 : i + 96;
  1894.           if (d && p) {
  1895.           fprintf(stderr,"&%c[%d]\n",c,d);
  1896.           for (j = 0; j <= d; j++) {
  1897.               if (p[j]) {
  1898.               fprintf(stderr,"  &%c[%2d] = [%s]\n",c,j,p[j]);
  1899.               }
  1900.           }      
  1901.           }
  1902.       }
  1903.       }
  1904. #else /* Not COMMENT */
  1905.     printf("cmdlvl = %d, tlevel = %d, maclvl = %d\n",cmdlvl,tlevel,maclvl);
  1906.     if (maclvl < 0) {
  1907.         printf("%s\n",
  1908.          "Call me from inside a macro and I'll dump the argument stack");
  1909.         return(0);
  1910.     }
  1911.     printf("Macro level: %d, ARGC = %d\n     ",maclvl,macargc[maclvl]);
  1912.     for (y = 0; y < 10; y++) printf("%7d",y);
  1913.     for (x = 0; x <= maclvl; x++) {
  1914.         printf("\n%2d:  ",x);
  1915.         for (y = 0; y < 10; y++) {
  1916.         s = m_arg[x][y];
  1917.         printf("%7s",s ? s : "(none)");
  1918.         }
  1919.     }
  1920.     printf("\n");
  1921. #endif /* COMMENT */
  1922. #endif /* NOSPL */
  1923.     return(0);
  1924.     }
  1925. #endif /* NOFRILLS */
  1926.  
  1927. #ifndef NOCSETS
  1928.     if (cx == XXXLA) {       /* TRANSLATE <ifn> from-cs to-cs <ofn> */
  1929.     int incs, outcs;
  1930.     if ((x = cmifi("File to translate","",&s,&y,xxstring)) < 0) {
  1931.         if (x == -3) {
  1932.         printf("?Name of an existing file\n");
  1933.         return(-9);
  1934.         } else return(x);
  1935.     }
  1936.     if (y != 0) {
  1937.         printf("?A single file please\n");
  1938.         return(-2);
  1939.     }
  1940.     strcpy(line,s);            /* Save copy of string just parsed. */
  1941.  
  1942.     if ((incs = cmkey(fcstab,nfilc,"from character-set","",xxstring)) < 0)
  1943.       return(incs);
  1944.     if ((outcs = cmkey(fcstab,nfilc,"to character-set","",xxstring)) < 0)
  1945.       return(outcs);
  1946.     if ((x = cmofi("output file",CTTNAM,&s,xxstring)) < 0) return(x);
  1947.     strncpy(tmpbuf,s,50);
  1948.     if ((y = cmcfm()) < 0) return(y); /* Confirm the command */
  1949.     return(success = xlate(line,tmpbuf,incs,outcs)); /* Execute it */
  1950.     }
  1951. #endif /* NOCSETS */
  1952.  
  1953.     if (cx == XXVER) {            /* VERSION */
  1954.     if ((y = cmcfm()) < 0) return(y);
  1955.     printf("%s,%s\n Numeric: %ld",versio,ckxsys,vernum);
  1956.     if (verwho) printf("-%d\n",verwho); else printf("\n");
  1957.     return(success = 1);
  1958.     }
  1959.  
  1960. #ifndef MAC
  1961. #ifndef NOFRILLS
  1962.     if (cx == XXWHO) {            /* WHO */
  1963.     char *wc;
  1964. #ifdef datageneral
  1965.         xsystem(WHOCMD);
  1966. #else
  1967.     if ((y = cmtxt("user name","",&s,xxstring)) < 0) return(y);
  1968.     if (!(wc = getenv("CK_WHO"))) wc = WHOCMD;
  1969.     sprintf(line,"%s %s",wc,s);
  1970.     xsystem(line);
  1971. #endif /* datageneral */
  1972.     return(success = 1);
  1973.     }
  1974. #endif /* NOFRILLS */
  1975. #endif /* MAC */
  1976.  
  1977. #ifndef NOFRILLS
  1978.     if (cx == XXWRI) {            /* WRITE */
  1979.     if ((x = cmkey(writab,nwri,"to file or log","",xxstring)) < 0) {
  1980.         if (x == -3) printf("?Write to what?\n");
  1981.         return(x);
  1982.     }
  1983.     if ((y = cmtxt("text","",&s,xxstring)) < 0) return(y);
  1984.     if (*s == '{') {        /* Strip enclosing braces */
  1985.         y = (int)strlen(s);
  1986.         if (s[y-1] == '}') {
  1987.         s[y-1] = NUL;
  1988.         s++;
  1989.         }
  1990.     }
  1991.     switch (x) {
  1992.       case LOGD: y = ZDFILE; break;
  1993.       case LOGP: y = ZPFILE; break;
  1994.       case LOGS: y = ZSFILE; break;
  1995.       case LOGT: y = ZTFILE; break;
  1996. #ifndef NOSPL
  1997.       case LOGW: y = ZWFILE; break;
  1998. #endif /* NOSPL */
  1999.       case LOGX:
  2000.       case LOGE:
  2001.  
  2002. #ifndef MAC
  2003.         if (x == LOGE) fprintf(stderr,"%s",s);
  2004.         else
  2005. #endif /* MAC */
  2006.           printf("%s",s);
  2007.         if (
  2008. #ifndef NOSPL
  2009.         cmdlvl == 0
  2010. #else
  2011.         tlevel == -1
  2012. #endif /* NOSPL */
  2013.         )
  2014. #ifndef MAC
  2015.           if (x == LOGE) fprintf(stderr,"\n");
  2016.           else
  2017. #endif /* MAC */
  2018.         printf("\n");
  2019.         return(success = 1);
  2020.       default: return(-2);
  2021.     }
  2022.     if ((x = zsout(y,s)) < 0)
  2023.       printf("?File or log not open\n");
  2024.     return(success = (x == 0) ? 1 : 0);
  2025.     }
  2026. #endif /* NOFRILLS */
  2027.  
  2028.     debug(F101,"docmd unk arg","",cx);
  2029.     return(-2);                /* None of the above. */
  2030. } /* end of docmnd() */
  2031.  
  2032. #endif /* NOICP */
  2033.