home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ckc190.zip / ckuus5.c < prev    next >
C/C++ Source or Header  |  1994-11-12  |  128KB  |  4,692 lines

  1. #include "ckcsym.h"
  2.  
  3. #ifndef NOICP
  4.  
  5. /*  C K U U S 5 --  "User Interface" for C-Kermit, part 5  */
  6.  
  7. /*
  8.   Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
  9.   Columbia University Academic Information Systems, New York City.
  10.  
  11.   Copyright (C) 1985, 1994, Trustees of Columbia University in the City of New
  12.   York.  The C-Kermit software may not be, in whole or in part, licensed or
  13.   sold for profit as a software product itself, nor may it be included in or
  14.   distributed with commercial products or otherwise distributed by commercial
  15.   concerns to their clients or customers without written permission of the
  16.   Office of Kermit Development and Distribution, Columbia University.  This
  17.   copyright notice must not be removed, altered, or obscured.
  18. */
  19.  
  20. /* Includes */
  21.  
  22. #include "ckcdeb.h"
  23. #include "ckcasc.h"
  24. #include "ckcker.h"
  25. #include "ckuusr.h"
  26. #include "ckcnet.h"
  27. #ifndef NOCSETS
  28. #include "ckcxla.h"
  29. #endif /* NOCSETS */
  30. #ifdef MAC
  31. #include "ckmasm.h"
  32. #endif /* MAC */
  33.  
  34. /* For formatted screens, "more?" prompting, etc. */
  35.  
  36. #ifdef FT18
  37. #define isxdigit(c) isdigit(c)
  38. #endif /* FT18 */
  39.  
  40. #ifdef STRATUS                /* Stratus Computer, Inc.  VOS */
  41. #ifdef putchar
  42. #undef putchar
  43. #endif /* putchar */
  44. #define putchar(x) conoc(x)
  45. #ifdef getchar
  46. #undef getchar
  47. #endif /* getchar */
  48. #define getchar(x) coninc(0)
  49. #endif /* STRATUS */
  50.  
  51. /* External variables */
  52.  
  53. extern int carrier, cdtimo, local, backgrd, bgset, sosi, suspend,
  54.   displa, binary, deblog, escape, xargs, flow, cmdmsk,
  55.   duplex, ckxech, pktlog, seslog, tralog, what,
  56.   keep, warn, tlevel, cwdf, nfuncs, unkcs, msgflg,
  57.   mdmtyp, zincnt, cmask, rcflag, success, xitsta, pflag, lf_opts, tnlm, tn_nlm,
  58.   xfrcan, xfrchr, xfrnum, xitwarn, debses, pktpaus;
  59.  
  60. #ifndef NOKVERBS
  61. extern struct keytab kverbs[];        /* Table of \Kverbs */
  62. extern int nkverbs;            /* Number of \Kverbs */
  63. #endif /* NOKVERBS */
  64.  
  65. #ifdef CK_RECALL
  66. extern int cm_recall;
  67. #endif /* CK_RECALL */
  68.  
  69. extern char *ccntab[];
  70. #ifdef OS2
  71. extern char *printfile;
  72. _PROTOTYP (int os2getcp, (void) );
  73. _PROTOTYP (int os2getcplist, (int *, int) );
  74. #ifdef OS2MOUSE
  75. extern int tt_mouse ;
  76. #endif /* OS2MOUSE */
  77. #endif /* OS2 */
  78.  
  79. #ifndef NOFRILLS
  80. extern int en_cwd, en_del, en_dir, en_fin, en_bye,
  81.   en_get, en_hos, en_sen, en_set, en_spa, en_typ, en_who;
  82. #endif /* NOFRILLS */
  83. extern long vernum;
  84. extern int srvtim, srvdis, inecho, insilence, nvars, verwho;
  85. extern char *protv, *fnsv, *cmdv, *userv, *ckxv, *ckzv, *ckzsys, *xlav,
  86.  *cknetv, *clcmds;
  87. #ifdef OS2
  88. extern char *ckonetv;
  89. #ifdef CK_NETBIOS
  90. extern char *ckonbiv;
  91. #endif /* CK_NETBIOS */
  92. #ifdef OS2MOUSE
  93. extern char *ckomouv;
  94. #endif /* OS2MOUSE */
  95. #endif /* OS2 */
  96. extern char *connv, *dialv, *loginv, *nvlook();
  97.  
  98. #ifndef NOSCRIPT
  99. extern int secho;
  100. #endif /* NOSCRIPT */
  101.  
  102. #ifndef NODIAL
  103. extern int nmdm;
  104. extern struct keytab mdmtab[];
  105. #endif /* NODIAL */
  106.  
  107. #ifdef NETCONN
  108. extern int network, ttnproto;
  109. #endif /* NETCONN */
  110.  
  111. #ifdef OS2
  112. /* SET TERMINAL items... */
  113. extern int tt_type, tt_arrow, tt_keypad, tt_wrap, tt_answer, tt_scrsize;
  114. extern int tt_bell, tt_roll, tt_ctstmo, tt_cursor, tt_hide, tt_pacing;
  115. extern struct tt_info_rec tt_info[];    /* Indexed by terminal type */
  116. extern int max_tt;
  117. #endif /* OS2 */
  118. _PROTOTYP( int ttgwsiz, (void) );
  119.  
  120. extern int tt_rows, tt_cols;
  121. int cmd_rows = 24, cmd_cols = 80;
  122.  
  123. #ifdef CK_TMPDIR
  124. extern int f_tmpdir;            /* Directory changed temporarily */
  125. extern char savdir[];            /* Temporary directory */
  126. #endif /* CK_TMPDIR */
  127.  
  128. extern int tt_crd;
  129.  
  130. #ifndef NOCSETS
  131. extern int language, nfilc, tcsr, tcsl;
  132. extern struct keytab fcstab[];
  133. extern struct csinfo fcsinfo[];
  134. #ifndef MAC
  135. extern struct keytab ttcstab[];
  136. #endif /* MAC */
  137. #endif /* NOCSETS */
  138.  
  139. extern int atcapr,
  140.   atenci, atenco, atdati, atdato, atleni, atleno, atblki, atblko,
  141.   attypi, attypo, atsidi, atsido, atsysi, atsyso, atdisi, atdiso; 
  142.  
  143. #ifdef STRATUS
  144. extern int atfrmi, atfrmo, atcrei, atcreo, atacti, atacto;
  145. #endif /* STRATUS */
  146.  
  147. extern long speed;
  148.  
  149. extern char *DIRCMD, *PWDCMD, *DELCMD;
  150. #ifndef NOXMIT
  151. extern int xmitf, xmitl, xmitp, xmitx, xmits, xmitw;
  152. extern char xmitbuf[];
  153. #endif /* NOXMIT */
  154.  
  155. extern char **xargv, *versio, *ckxsys, *dftty, *cmarg, *lp;
  156.  
  157. #ifdef DCMDBUF
  158. extern char *cmdbuf, *atmbuf;        /* Command buffers */
  159. #ifndef NOSPL
  160. extern char *savbuf;            /* Command buffers */
  161. #endif /* NOSPL */
  162. #else
  163. extern char cmdbuf[], atmbuf[];        /* Command buffers */
  164. #ifndef NOSPL
  165. extern char savbuf[];            /* Command buffers */
  166. #endif /* NOSPL */
  167. #endif /* DCMDBUF */
  168.  
  169. extern char toktab[], ttname[], psave[];
  170. extern CHAR sstate;
  171. extern int cmflgs, techo, repars, ncmd;
  172. extern struct keytab cmdtab[];
  173.  
  174. #ifndef NOSETKEY
  175. KEY *keymap;
  176. MACRO *macrotab;
  177. #endif /* NOSETKEY */
  178.  
  179. #ifndef NOSPL
  180. extern struct mtab *mactab;
  181. extern struct keytab vartab[], fnctab[];
  182. extern int cmdlvl, maclvl, nmac, mecho;
  183. #endif /* NOSPL */
  184.  
  185. FILE *tfile[MAXTAKE];            /* TAKE file stack */
  186. char *tfnam[MAXTAKE];
  187.  
  188. #ifdef DCMDBUF                /* Initialization filespec */
  189. char *kermrc = NULL;
  190. #else
  191. char kermrcb[KERMRCL];
  192. char *kermrc = kermrcb;
  193. #endif /* DCMDBUF */
  194.  
  195. int noherald = 0;
  196. int cm_retry = 1;            /* Command retry enabled */
  197. xx_strp xxstring = zzstring;
  198.  
  199. #ifndef NOSPL
  200.  
  201. extern int query;            /* QUERY active */
  202.  
  203. /* Local declarations */
  204.  
  205. static int nulcmd = 0;            /* Flag for next cmd to be ignored */
  206.  
  207. /* Definitions for predefined macros */
  208.  
  209. /* First, the single-line macros, installed with addmac()... */
  210.  
  211. /* IBM-LINEMODE macro */
  212. char *m_ibm = "set parity mark, set dupl half, set handsh xon, set flow none";
  213.  
  214. /* FATAL macro */
  215. char *m_fat = "if def \\%1 echo \\%1, if not = \\v(local) 0 hangup, stop 1";
  216.  
  217. /* Now the multiline macros, defined with addmmac()... */
  218.  
  219. /* FOR macro */
  220. char *for_def[] = { "_assign _for\\v(cmdlevel) { _getargs,",
  221. "define \\\\\\%1 \\%2,:top,if \\%5 \\\\\\%1 \\%3 goto bot,",
  222. "\\%6,:inc,incr \\\\\\%1 \\%4,goto top,:bot,_putargs},",
  223. "def break goto bot, def continue goto inc,",
  224. "do _for\\v(cmdlevel) \\%1 \\%2 \\%3 \\%4 { \\%5 },_assign _for\\v(cmdlevel)",
  225. ""};
  226.  
  227. /* WHILE macro */
  228. char *whil_def[] = { "_assign _whi\\v(cmdlevel) {_getargs,",
  229. ":inc,\\%1,\\%2,goto inc,:bot,_putargs},",
  230. "_def break goto bot, _def continue goto inc,",
  231. "do _whi\\v(cmdlevel),_assign _whi\\v(cmdlevel)",
  232. ""};
  233.  
  234. /* XIF macro */
  235. char *xif_def[] = {
  236. "_assign _if\\v(cmdlevel) {_getargs,\\%1,_putargs},",
  237. "do _if\\v(cmdlevel),_assign _if\\v(cmdlevel)",
  238. ""};
  239.  
  240. /*
  241.   Variables declared here for use by other ckuus*.c modules.
  242.   Space is allocated here to save room in ckuusr.c.
  243. */
  244. #ifdef DCMDBUF
  245. struct cmdptr *cmdstk;
  246. int *ifcmd, *count, *iftest, *intime, *inpcas, *takerr, *merror;
  247. #else
  248. struct cmdptr cmdstk[CMDSTKL];
  249. int ifcmd[CMDSTKL], count[CMDSTKL], iftest[CMDSTKL], intime[CMDSTKL],
  250.   inpcas[CMDSTKL], takerr[CMDSTKL], merror[CMDSTKL];
  251. #endif /* DCMDBUF */
  252.  
  253. char *m_arg[MACLEVEL][NARGS];
  254. char *g_var[GVARS], *macp[MACLEVEL], *mrval[MACLEVEL];
  255. int macargc[MACLEVEL];
  256. char *macx[MACLEVEL];
  257. extern char varnam[];
  258.  
  259. char **a_ptr[27];            /* Array pointers, for arrays a-z */
  260. int a_dim[27];                /* Dimensions for each array */
  261.  
  262. char inpbuf[INPBUFSIZ] = { NUL };    /* Buffer for INPUT and REINPUT */
  263. char inpbufa[2] = { NUL, NUL };        /* Null terminators for INPUT buffer */
  264. char inchar[2] = { NUL, NUL };        /* Last character that was INPUT */
  265. int  incount = 0;            /* INPUT character count */
  266. int pacing = 0;                /* OUTPUT pacing */
  267.  
  268. char lblbuf[LBLSIZ];            /* Buffer for labels */
  269. #else
  270. int takerr[MAXTAKE];
  271. #endif /* NOSPL */
  272.  
  273. #ifdef DCMDBUF
  274. char *line;                /* Character buffer for anything */
  275. char *tmpbuf;
  276. #else
  277. char line[LINBUFSIZ];
  278. char tmpbuf[TMPBUFSIZ];            /* Temporary buffer */
  279. #endif /* DCMDBUF */
  280. char *tp;                /* Temporary buffer pointer */
  281.  
  282. #ifdef CK_APC                /* Application Program Command (APC) */
  283. int apcactive = 0;
  284. int apcstatus = APC_OFF;        /* OFF by default everywhere */
  285. #ifdef DCMDBUF
  286. char *apcbuf;
  287. #else
  288. char apcbuf[APCBUFLEN];
  289. #endif /* DCMDBUF */
  290. #endif /* CK_APC */
  291.  
  292. #ifdef CK_CURSES
  293. #ifdef DCMDBUF
  294. char *trmbuf;                /* Character buffer for termcap */
  295. #else
  296. char trmbuf[TRMBUFL];            /* (Defined in ckcdeb.h) */
  297. #endif /* DCMDBUF */
  298. #endif /* CK_CURSES */
  299.  
  300. extern char pktfil[],
  301. #ifdef DEBUG
  302.   debfil[],
  303. #endif /* DEBUG */
  304. #ifdef TLOG
  305.   trafil[],
  306. #endif /* TLOG */
  307.   sesfil[];
  308.  
  309. #ifndef NOFRILLS
  310. extern int rmailf, rprintf;        /* REMOTE MAIL & PRINT items */
  311. extern char optbuf[];
  312. #endif /* NOFRILLS */
  313.  
  314. char *homdir = "";            /* Pointer to home directory string */
  315.  
  316. char numbuf[20];            /* Buffer for numeric strings. */
  317. int noinit = 0;                /* Flag for skipping init file */
  318.  
  319. #ifndef NOSPL
  320. _PROTOTYP( static long expon, (long, long) );
  321. _PROTOTYP( static long gcd, (long, long) );
  322. _PROTOTYP( static long fact, (long) );
  323. int            /* Initialize macro data structures. */
  324. macini() {        /* Allocate mactab and preset the first element. */
  325.     if (!(mactab = (struct mtab *) malloc(sizeof(struct mtab) * MAC_MAX)))
  326.       return(-1);
  327.     mactab[0].kwd = NULL;
  328.     mactab[0].mval = NULL;
  329.     mactab[0].flgs = 0;
  330.     return(0);
  331. }
  332. #endif /* NOSPL */
  333.  
  334. /*  C M D I N I  --  Initialize the interactive command parser  */
  335.  
  336. VOID
  337. cmdini() {
  338.     int i, x, y, z;
  339. #ifndef NOSPL
  340. /*
  341.   On stack to allow recursion!
  342. */
  343.     char vnambuf[VNAML];        /* Buffer for variable names */
  344. #endif /* NOSPL */
  345.  
  346. #ifndef NOSETKEY            /* Allocate & initialize the keymap */
  347.     if (!(keymap = (KEY *) malloc(sizeof(KEY)*KMSIZE)))
  348.       fatal("cmdini: no memory for keymap");
  349.     if (!(macrotab = (MACRO *) malloc(sizeof(MACRO)*KMSIZE)))
  350.       fatal("cmdini: no memory for macrotab");
  351.     for ( i = 0; i < KMSIZE; i++ ) {
  352.     keymap[i] = i;
  353.     macrotab[i] = NULL;
  354.     }
  355. #ifdef OS2
  356.     keymapinit();
  357.     keynaminit();
  358. #endif /* OS2 */
  359. #endif /* NOSETKEY */
  360.  
  361. #ifdef DCMDBUF
  362.     if (cmsetup() < 0) fatal("Can't allocate command buffers!");
  363. #ifndef NOSPL
  364.     if (!(cmdstk = (struct cmdptr *) malloc(sizeof(struct cmdptr)*CMDSTKL)))
  365.       fatal("cmdini: no memory for cmdstk");
  366.     if (!(ifcmd = (int *) malloc(sizeof(int)*CMDSTKL)))
  367.       fatal("cmdini: no memory for ifcmd");
  368.     if (!(count = (int *) malloc(sizeof(int)*CMDSTKL)))
  369.       fatal("cmdini: no memory for count");
  370.     if (!(iftest = (int *) malloc(sizeof(int)*CMDSTKL)))
  371.       fatal("cmdini: no memory for iftest");
  372.     if (!(intime = (int *) malloc(sizeof(int)*CMDSTKL)))
  373.       fatal("cmdini: no memory for intime");
  374.     if (!(inpcas = (int *) malloc(sizeof(int)*CMDSTKL)))
  375.       fatal("cmdini: no memory for inpcas");
  376.     if (!(takerr = (int *) malloc(sizeof(int)*CMDSTKL)))
  377.       fatal("cmdini: no memory for takerr");
  378.     if (!(merror = (int *) malloc(sizeof(int)*CMDSTKL)))
  379.       fatal("cmdini: no memory for merror");
  380.     if (!kermrc)
  381.       if (!(kermrc = (char *) malloc(KERMRCL+1)))
  382.     fatal("cmdini: no memory for kermrc");
  383. #endif /* NOSPL */
  384. #ifdef CK_CURSES
  385. /*
  386.   Termcap buffer for fullscreen display, UNIX only.  VMS and OS/2 do it
  387.   another way.  The fullscreen display is not supported on AOS/VS or OS-9,
  388.   etc, yet, and the Mac has its own built-in fullscreen display.
  389. */
  390. #ifdef UNIX
  391.     if (!(trmbuf = malloc(TRMBUFL+1)))
  392.     fatal("cmdini: no memory for termcap buffer");
  393. #endif /* UNIX */
  394. #endif /* CK_CURSES */
  395.  
  396.     if (!(line = malloc(LINBUFSIZ)))
  397.     fatal("cmdini: no memory for line");
  398.     if (!(tmpbuf = malloc(LINBUFSIZ)))
  399.     fatal("cmdini: no memory for tmpbuf");
  400.  
  401. #ifdef CK_APC
  402.     if (!(apcbuf = malloc(APCBUFLEN)))
  403.     fatal("cmdini: no memory for apcbuf");
  404. #endif /* CK_APC */
  405.  
  406. #endif /* DCMDBUF */
  407.  
  408. #ifdef CK_MINPUT
  409.     {                    /* Initialize MINPUT pointers */
  410.     int i;
  411.     extern char *ms[];
  412.     for (i = 0; i < MINPMAX; i++)
  413.       ms[i] = NULL;
  414.     }
  415. #endif /* CK_MINPUT */
  416.  
  417. #ifndef NOSPL
  418.     if (macini() < 0)
  419.       fatal("Can't allocate macro buffers!");
  420.  
  421.     ifcmd[0] = 0;            /* Command-level related variables. */
  422.     iftest[0] = 0;            /* Initialize variables at top level */
  423.     count[0] = 0;            /* of stack... */
  424.     intime[0] = 0;
  425.     inpcas[0] = 0;
  426.     takerr[0] = 0;
  427.     merror[0] = 0;
  428. #endif /* NOSPL */
  429.  
  430. #ifdef AMIGA
  431.     if (tlevel < 0)    
  432.       concb(escape);
  433. #endif /* AMIGA */
  434.  
  435. #ifndef NOSPL
  436.     cmdlvl = 0;                /* Start at command level 0 */
  437.     cmdstk[cmdlvl].src = CMD_KB;
  438.     cmdstk[cmdlvl].lvl = 0;
  439. #endif /* NOSPL */
  440.  
  441.     tlevel = -1;            /* Take file level = keyboard */
  442.     for (i = 0; i < MAXTAKE; i++)    /* Initialize command file names */
  443.       tfnam[i] = NULL;
  444.  
  445. #ifdef MAC 
  446.     cmsetp("Mac-Kermit>");        /* Set default prompt */
  447. #else
  448.     cmsetp("C-Kermit>");        /* Set default prompt */
  449. #endif /* MAC */
  450.  
  451. #ifndef NOSPL
  452.     initmac();                /* Initialize macro table */
  453. /* Add one-line macros */
  454.     addmac("ibm-linemode",m_ibm);    /* Add built-in macros. */
  455.     addmac("fatal",m_fat);        /* FATAL macro. */
  456. /* Add multiline macros */
  457.     addmmac("_forx",for_def);        /* FOR macro. */
  458.     addmmac("_xif",xif_def);        /* XIF macro. */
  459.     addmmac("_while",whil_def);        /* WHILE macro. */
  460. /* Fill in command line argument vector */
  461.     sprintf(vnambuf,"\\&@[%d]",xargs);     /* Command line argument vector */
  462.     y = arraynam(vnambuf,&x,&z);    /* goes in array \&@[] */
  463.     if (y > -1) {
  464.     dclarray((char)x,z);        /* Declare the array */
  465.     for (i = 0; i < xargs; i++) {    /* Fill it */
  466.         sprintf(vnambuf,"\\&@[%d]",i);
  467.         addmac(vnambuf,xargv[i]);
  468.     }
  469.     }
  470.     *vnambuf = NUL;
  471. #endif /* NOSPL */
  472.  
  473. #ifdef CK_NAWS    
  474.     if (ttgwsiz() > 0) {
  475.     if (tt_rows > 0 && tt_cols > 0) {
  476.         cmd_rows = tt_rows;
  477.         cmd_cols = tt_cols;
  478.     }
  479.     }
  480. #endif /* CK_NAWS */
  481.  
  482. /* Get our home directory now.  This needed in lots of places. */
  483.  
  484.     homdir = zhome();
  485.  
  486. #ifdef MAC
  487.     return;                /* Mac Kermit has no init file */
  488.  
  489. #else /* !MAC */
  490.  
  491. /* If skipping init file ('-Y' on Kermit command line), return now. */
  492.  
  493.     if (noinit) return;
  494.  
  495. #ifdef OS2
  496. /*
  497.   The -y init file must be fully specified or in the current directory.
  498.   KERMRC is looked for via INIT, DPATH and PATH in that order.  Finally, our
  499.   own executable file path is taken and the .EXE suffix is replaced by .INI
  500.   and this is tried as the initialization file.
  501. */
  502.     if (rcflag) {
  503.     strcpy(line, kermrc);
  504.     } else {
  505.     _searchenv(kermrc,"INIT",line);
  506.     if (line[0] == 0)
  507.       _searchenv(kermrc,"DPATH",line);
  508.     if (line[0] == 0)
  509.       _searchenv(kermrc,"PATH",line);
  510.     if (line[0] == 0) {
  511.         char *pgmptr = GetLoadPath();
  512.         if (pgmptr) {
  513.           lp = strrchr(pgmptr, '.');
  514.           strncpy(line, pgmptr, lp - pgmptr);
  515.           strcpy(line + (lp - pgmptr), ".ini");
  516.         }
  517.     }
  518.     }
  519.     if ((tfile[0] = fopen(line,"r")) != NULL) {
  520.         tlevel = 0;
  521.     if (tfnam[tlevel] = malloc(strlen(line)+1))
  522.       strcpy(tfnam[tlevel],line);
  523. #ifndef NOSPL
  524.     cmdlvl++;
  525.     cmdstk[cmdlvl].src = CMD_TF;
  526.     cmdstk[cmdlvl].lvl = tlevel;
  527.     ifcmd[cmdlvl] = 0;
  528.     iftest[cmdlvl] = 0;
  529.     count[cmdlvl] =  count[cmdlvl-1]; /* Inherit from previous level */
  530.     intime[cmdlvl] = intime[cmdlvl-1];
  531.     inpcas[cmdlvl] = inpcas[cmdlvl-1];
  532.     takerr[cmdlvl] = takerr[cmdlvl-1];
  533.     merror[cmdlvl] = merror[cmdlvl-1];
  534. #endif /* NOSPL */
  535.         debug(F110,"init file",line,0);
  536.     } else {
  537.         debug(F100,"no init file","",0);
  538.     }
  539. #else /* not OS2 */
  540.     lp = line;
  541.     lp[0] = '\0';
  542. #ifdef GEMDOS
  543.     zkermini(line, rcflag, kermrc);
  544. #else
  545. #ifdef VMS
  546.     zkermini(line,LINBUFSIZ,kermrc);
  547. #else /* not VMS */
  548.     if (rcflag) {            /* If init file name from cmd line */
  549.     strcpy(lp,kermrc);        /* use it, */
  550.     } else {                /* otherwise... */
  551. #ifdef CK_INI_A                /* If we've a system-wide init file */
  552.     /* And it takes precedence over the user's... */
  553.     strncpy(lp,CK_SYSINI,KERMRCL);    /* Use it */
  554.     if (zchki(lp) < 0) {        /* (it it exists...) */
  555. #endif /* CK_INI_A */
  556.         line[0] = NUL;
  557.         if (homdir) {        /* Home directory for init file. */
  558.         strcpy(lp,homdir);
  559. #ifdef STRATUS
  560.         strcat(lp,">");        /* VOS separates dirs with >'s */
  561. #else
  562.         if (lp[0] == '/') strcat(lp,"/");
  563. #endif /* STRATUS */
  564.         }
  565.         strcat(lp,kermrc);        /* Append the default file name */
  566. #ifdef CK_INI_A
  567.     }
  568. #endif /* CK_INI_A */
  569.     }
  570. #ifdef CK_INI_B                /* System-wide init defined? */
  571.     /* But user's ini file takes precedence */
  572.     if (zchki(lp) < 0)            /* If user doesn't have her own, */
  573.     strncpy(lp,CK_SYSINI,KERMRCL);    /* use system-wide one. */
  574. #endif /* CK_INI_B */
  575.  
  576. #endif /* VMS */
  577. #endif /* GEMDOS */
  578.  
  579. #ifdef AMIGA
  580.     reqoff();                /* Disable requestors */
  581. #endif /* AMIGA */
  582.  
  583.     debug(F110,"ini file is",line,0);
  584.     if ((tfile[0] = fopen(line,"r")) != NULL) {    /* Try to open init file. */
  585.     tlevel = 0;
  586.     if (tfnam[tlevel] = malloc(strlen(line)+1))
  587.       strcpy(tfnam[tlevel],line);
  588. #ifndef NOSPL
  589.     cmdlvl++;
  590.     ifcmd[cmdlvl] = 0;
  591.     iftest[cmdlvl] = 0;
  592.     count[cmdlvl] =  count[cmdlvl-1]; /* Inherit from previous level */
  593.     intime[cmdlvl] = intime[cmdlvl-1];
  594.     inpcas[cmdlvl] = inpcas[cmdlvl-1];
  595.     takerr[cmdlvl] = takerr[cmdlvl-1];
  596.     merror[cmdlvl] = merror[cmdlvl-1];
  597.     debug(F101,"open ok","",cmdlvl);
  598.     cmdstk[cmdlvl].src = CMD_TF;
  599.     cmdstk[cmdlvl].lvl = tlevel;
  600. #endif /* NOSPL */
  601.     debug(F110,"init file",line,0);
  602.     }
  603.  
  604. #ifdef datageneral
  605. /* If CKERMIT.INI not found in home directory, look in searchlist */
  606.     if (homdir && (tlevel < 0)) {
  607.         strcpy(lp,kermrc);
  608.     if ((tfile[0] = fopen(line,"r")) != NULL) {
  609.         tlevel = 0;
  610.     if (tfnam[tlevel] = malloc(strlen(line)+1))
  611.       strcpy(tfnam[tlevel],line);
  612. #ifndef NOSPL
  613.         cmdlvl++;
  614.         cmdstk[cmdlvl].src = CMD_TF;
  615.         cmdstk[cmdlvl].lvl = tlevel;
  616.         ifcmd[cmdlvl] = 0;
  617.         iftest[cmdlvl] = 0;
  618.         count[cmdlvl] =  count[cmdlvl-1]; /* Inherit from previous level */
  619.         intime[cmdlvl] = intime[cmdlvl-1];
  620.         inpcas[cmdlvl] = inpcas[cmdlvl-1];
  621.         takerr[cmdlvl] = takerr[cmdlvl-1];
  622.         merror[cmdlvl] = merror[cmdlvl-1];
  623. #endif /* NOSPL */
  624.     }
  625.     }
  626. #endif /* datageneral */
  627.  
  628. #ifdef AMIGA                /* Amiga... */
  629.     reqpop();                /* Restore requestors */
  630. #endif /* AMIGA */
  631.  
  632. #endif /* OS2 */
  633.  
  634.  
  635. #endif /* MAC */
  636. }
  637.  
  638. #ifndef NOSPL
  639. /*
  640.   G E T N C M
  641.  
  642.   Get next command from current macro definition.
  643.  
  644.   Moved to a separate routine in edit 181 to allow multiline GET
  645.   to work when issued in a macro.
  646.  
  647.   Command is copied into string pointed to by argument s, max length n.
  648.   Returns:
  649.    0 if a string was copied, -1 if there was no string to copy.
  650. */
  651. int
  652. getncm(s,n) char *s; int n; {
  653.     int y,                /* Character counter */
  654. #ifdef COMMENT
  655.       quote = 0,
  656. #endif /* COMMENT */
  657.       kp = 0,                /* Brace up-down counter */
  658.       pp = 0;                /* Parenthesis up-down counter */
  659.     char *s2;                /* Copy of destination pointer */
  660.     
  661.     s2 = s;                /* Initialize string pointers */
  662.     *s = NUL;                /* and destination buffer */
  663.     
  664.     debug(F101,"getncm dest length","",n);
  665.  
  666.     for (y = 0;                /* Loop for n bytes max */
  667.       macp[maclvl] && *macp[maclvl] && y < n;
  668.      y++, s++, macp[maclvl]++) {
  669.     
  670.     *s = *macp[maclvl];        /* Get next char from macro def */
  671.     /* debug(F000,"char","",*s); */
  672. #ifdef COMMENT
  673. /*
  674.   The intention here was to allow quoting of commas, braces, etc,
  675.   in macro definitions, e.g. "define rows mode co80\,\%1".  And it
  676.   works, but it breaks just about everything else.
  677. */
  678.     if (*s == CMDQ && quote == 0) {    /* Allow for quoting of */
  679.         quote = 1;            /* braces, commas, etc. */
  680.         continue;
  681.     }
  682. #endif /* COMMENT */
  683. /*
  684.   Allow braces around macro definition to prevent commas from being turned to
  685.   end-of-lines and also treat any commas within parens as text so that
  686.   multiple-argument functions won't cause the command to break prematurely.
  687. */
  688. #ifdef COMMENT
  689.     if (!quote) {
  690. #endif /* COMMENT */
  691.         if (*s == '{') kp++;    /* Count braces */
  692.         if (*s == '}') kp--;
  693.         if (*s == '(') pp++;    /* Count parentheses. */
  694.         if (*s == ')') pp--;
  695.         if (*s == ',' && pp <= 0 && kp <= 0) {
  696.         macp[maclvl]++;        /* Comma not in {} or () */
  697.         debug(F110,"next cmd",s,0);
  698.         kp = pp = 0;        /* so we have the next command */
  699.         break;
  700.         }
  701. #ifdef COMMENT
  702.     }
  703. #endif /* COMMENT */
  704.     }                    /* Reached end. */
  705.     if (*s2 == NUL) {            /* If nothing was copied, */
  706.     debug(F100,"getncm eom","",0);
  707.     popclvl();            /* pop command level. */
  708.     return(-1);
  709.     } else {                /* otherwise, tack CR onto end */
  710.     *s++ = CR;
  711.     *s = '\0';
  712.     if (mecho && pflag)        /* If MACRO ECHO ON, echo the cmd */
  713.       printf("%s\n",s2);
  714.     debug(F110,"getncm returns ptr to",s2,0);
  715.     }
  716.     return(0);
  717. }
  718.  
  719. /*  D O M A C  --  Define and then execute a macro */
  720.  
  721. int
  722. domac(name, def) char *name, *def; {
  723.     int x, m;
  724.     m = maclvl;                /* Current macro stack level */
  725.     debug(F101,"domac entry maclvl","",maclvl);
  726.     x = addmac(name, def);        /* Define a new macro */
  727.     if (x > -1) {            /* If successful, */
  728.     dodo(x,NULL);            /* start it (increments maclvl). */
  729.     while (maclvl > m) {        /* Keep going till done with it, */
  730.         debug(F101,"domac loop maclvl 1","",maclvl);
  731.         sstate = parser(1);        /* parsing & executing each command, */
  732.         debug(F101,"domac loop maclvl 2","",maclvl);
  733.         if (sstate) proto();    /* including protocol commands. */
  734.     }
  735.     debug(F101,"domac loop exit maclvl","",maclvl);
  736.     }        
  737.     return(success);
  738. }
  739. #endif /* NOSPL */
  740.  
  741. /*
  742.   G E T N C T
  743.  
  744.   Get next command from current TAKE file.
  745.  
  746.   Moved to a separate routine in edit 181 to allow multiline GET
  747.   to work when issued in a macro.
  748.  
  749.   Command is copied into string pointed to by argument s, max length n.
  750.   Returns:
  751.    0 if a string was copied,
  752.   -1 on EOF,
  753.   -2 on malloc failure
  754.   -3 if line not properly terminated
  755. */
  756. int
  757. getnct(s,n) char *s; int n; {
  758.     int i, j;
  759.     char c, *s2, *lp, *lp2;
  760.  
  761.     s2 = s;                /* Remember original pointer */
  762.  
  763.     debug(F101,"getnct","",n);
  764.     if (!(lp2 = (char *) malloc(n+1))) { /* Get a temporary buffer */
  765.     debug(F101,"getnct malloc failure","",0);
  766.     return(-2);
  767.     }
  768.     while (1) {                /* Loop to read lines from file */
  769.     
  770.     if (fgets(lp2,n,tfile[tlevel]) == NULL) { /* EOF */
  771.         free(lp2);            /* Free temporary storage */
  772.         *s = NUL;            /* Make destination be empty */
  773.         return(-1);            /* Return failure code */
  774.     }
  775.     if (techo && pflag)        /* If TAKE ECHO ON, */
  776.       printf("%s",lp2);        /* echo it. */
  777.  
  778.     lp = lp2;            /* Make a working pointer */
  779.  
  780. /* Trim trailing whitespace */
  781.  
  782.     j = strlen(lp2) - 1;        /* Position of line terminator */
  783.     debug(F111,"Line from TAKE file",lp2,j); /* Got a line */
  784.     if (j < 0) j = 0;
  785.     c = lp2[j];            /* Value of line terminator */
  786.     debug(F101,"getnct nl","",c);
  787.     if (c < LF || c > CR) {        /* It's not a terminator */
  788.         debug(F111,"getnct bad line",lp2,c);
  789.         if (feof(tfile[tlevel]) && j > 0 && j < n) {
  790.         printf("Warning: Last line of TAKE file lacks terminator\n");
  791.         c = lp2[++j] = '\n';
  792.         } else { free(lp2); return(-3); }
  793.     }
  794.     for (i = j - 1; i > -1; i--)    /* Back up over spaces and tabs */
  795.       if (lp2[i] != SP && lp2[i] != HT && lp2[i] != NUL)
  796.         break;
  797.     debug(F101,"getnct i","",i);
  798.     lp2[i+1] = c;            /* Move after last nonblank char */
  799.     lp2[i+2] = NUL;            /* Terminate the string */
  800.     debug(F110,"getnct lp2",lp2,0);
  801.     while (*s++ = *lp++) {        /* Copy result to target buffer */
  802.         if (--n < 2) {
  803.         printf("?Command too long, maximum length: %d.\n",CMDBL);
  804.         free(lp2);
  805.         return(dostop());
  806.         }
  807.  
  808. /* Check for trailing comment, " ;" or " #" */
  809.  
  810.         if ((s > s2 + 1) &&
  811.         (*(s-1) == ';' || *(s-1) == '#') &&
  812.         (*(s-2) == SP  || *(s-2) == HT)) {
  813.         debug(F100,"Trailing comment","",0);
  814.         s -= 2;            /* Got one, back up buffer pointer */
  815.         n += 2;            /* and adjust free space count. */
  816.         while ((s >= s2)    /* Trim whitespace again. */
  817.                && (*s == SP || *s == HT))
  818.           s--, n++;
  819.         s++;            /* Point after last character */
  820.         *s++ = c;        /* Put back line terminator */
  821.         *s++ = NUL;        /* and string terminator */
  822.         n -= 3;            /* Adjust free count */
  823.         debug(F110,"Comment trimmed & terminated",s2,0);
  824.         break;
  825.         }
  826.     }
  827.  
  828. /* Check whether this line is continued */
  829.  
  830.     if (s > s2 + 2) {
  831.         debug(F000,"Last char in line","",*(s-3));
  832.         if (*(s - 3) != CMDQ && *(s - 3) != '-') /* Line continued? */
  833.           break;            /* No, done. */
  834.         s -= 3;            /* No, back up pointer */
  835.         debug(F100,"Line is continued","",0); /* and continue */
  836.     } else break;
  837.     }
  838.     untab(s2);                /* Done, convert tabs to spaces */
  839.     free(lp2);                /* Free temporary storage */
  840.     return(0);                /* Return success */
  841. }
  842.  
  843. /*  P A R S E R  --  Top-level interactive command parser.  */
  844.  
  845. /*
  846.   Call with:
  847.     m = 0 for normal behavior: keep parsing and executing commands
  848.           until an action command is parsed, then return with a
  849.           Kermit start-state as the value of this function.
  850.     m = 1 to parse only one command, can also be used to call parser()
  851.           recursively.
  852.     m = 2 to read but do not execute one command.
  853.   In all cases, parser() returns:
  854.     0     if no Kermit protocol action required
  855.     > 0   with a Kermit protocol start-state.
  856.     < 0   upon error.
  857. */
  858. int
  859. parser(m) int m; {
  860.     int tfcode, xx, yy, zz;        /* Workers */
  861.  
  862. #ifndef NOSPL
  863.     int inlevel;            /* Level we were called at */
  864. #endif /* NOSPL */
  865.     char *cbp;                /* Command buffer pointer */
  866. #ifdef MAC
  867.     extern char *lfiles;        /* Fake extern cast */
  868. #endif /* MAC */
  869.  
  870. #ifdef AMIGA
  871.     reqres();            /* restore AmigaDOS requestors */
  872. #endif /* AMIGA */
  873.  
  874.     what = W_COMMAND;        /* Now we're parsing commands. */
  875.     if (            /* If at top (interactive) level ... */
  876. #ifndef NOSPL
  877.     cmdlvl == 0
  878. #else
  879.     tlevel < 0
  880. #endif /* NOSPL */
  881.     )
  882.     concb((char)escape);    /* ... put console in 'cbreak' mode. */
  883.  
  884. #ifdef CK_TMPDIR
  885. /* If we were cd'd temporarily to another device or directory ... */
  886.     if (f_tmpdir) {
  887.     int x;
  888.     x = zchdir((char *) savdir);    /* ... restore previous directory */
  889.     f_tmpdir = 0;            /* and remember we did it. */
  890.     debug(F111,"tmpdir restoring",savdir,x);
  891.     }
  892. #endif /* CK_TMPDIR */
  893.  
  894. #ifndef NOSPL
  895.     inlevel = cmdlvl;        /* Current macro level */
  896.     debug(F101,"&parser entry maclvl","",maclvl);
  897.     debug(F101,"&parser entry inlevel","",inlevel);
  898.     debug(F101,"&parser entry tlevel","",tlevel);
  899.     debug(F101,"&parser entry cmdlvl","",cmdlvl);
  900.     debug(F101,"&parser entry m","",m);
  901. #endif /* NOSPL */
  902.  
  903. /*
  904.   sstate becomes nonzero when a command has been parsed that requires some
  905.   action from the protocol module.  Any non-protocol actions, such as local
  906.   directory listing or terminal emulation, are invoked directly from below.
  907. */
  908.     sstate = 0;                /* Start with no start state. */
  909. #ifndef NOFRILLS
  910.     rmailf = rprintf = 0;        /* MAIL and PRINT modifiers for SEND */
  911.     *optbuf = NUL;            /* MAIL and PRINT options */
  912. #endif /* NOFRILLS */
  913. #ifndef NOSPL
  914.     query = 0;                /* QUERY not active */
  915. #endif /* NOSPL */
  916.  
  917.     while (sstate == 0) {        /* Parse cmds until action requested */
  918. #ifdef DEBUG
  919.     int nnn;
  920.     debug(F100,"top of parse loop","",0);
  921.     nnn = ttchk();
  922.     debug(F101,"APC ttchk p1","",nnn);
  923. #endif /* DEBUG */
  924.  
  925.     /* Take requested action if there was an error in the previous command */
  926.  
  927. #ifndef MAC
  928.     conint(trap,stptrap);        /* In case we were just fg'd */
  929.     bgchk();            /* Check background status */
  930. #endif /* MAC */
  931.  
  932.     debug(F101,"tlevel","",tlevel);
  933.  
  934. #ifndef NOSPL
  935.     if (success == 0) {
  936.         if (cmdstk[cmdlvl].src == CMD_TF && takerr[cmdlvl]) {
  937.         printf("Command file terminated by error.\n");
  938.         popclvl();
  939.         if (cmdlvl == 0) return(0);
  940.         }
  941.         if (cmdstk[cmdlvl].src == CMD_MD && merror[cmdlvl]) {
  942.         printf("Command error: macro terminated.\n");
  943.         popclvl();
  944.         if (m && (cmdlvl < inlevel))
  945.           return((int) sstate);
  946.         }
  947.     }
  948.  
  949.     nulcmd = (m == 2);
  950. #else
  951.     if (success == 0 && tlevel > -1 && takerr[tlevel]) {
  952.         printf("Command file terminated by error.\n");
  953.         popclvl();
  954.         cmini(ckxech);        /* Clear the cmd buffer. */
  955.         if (tlevel < 0)         /* Just popped out of cmd files? */
  956.           return(0);        /* End of init file or whatever. */
  957.     }
  958. #endif /* NOSPL */
  959.  
  960. #ifdef MAC
  961.     /* Check for TAKE initiated by menu. */
  962.     if ((tlevel == -1) && lfiles)
  963.         startlfile();
  964. #endif /* MAC */
  965.  
  966.         /* If in TAKE file, check for EOF */
  967. #ifndef NOSPL
  968. #ifdef MAC
  969.     if
  970. #else
  971.     while
  972. #endif /* MAC */
  973.       ((cmdstk[cmdlvl].src == CMD_TF)  /* If end of take file */
  974.            && (tlevel > -1)
  975.            && feof(tfile[tlevel])) {
  976.         popclvl();            /* pop command level */
  977.         cmini(ckxech);        /* and clear the cmd buffer. */
  978.         if (cmdlvl == 0)        /* Just popped out of all cmd files? */
  979.           return(0);        /* End of init file or whatever. */
  980.      }
  981. #ifdef MAC
  982.     miniparser(1);
  983.     if (sstate == 'a') {        /* if cmd-. cancel */
  984.         debug(F100, "parser: cancel take due to sstate", "", sstate);
  985.         sstate = '\0';
  986.         dostop();
  987.         return(0);            /* End of init file or whatever. */
  988.     }
  989. #endif /*  MAC */
  990.  
  991. #else /* NOSPL */
  992.     if ((tlevel > -1) && feof(tfile[tlevel])) { /* If end of take */
  993.         popclvl();            /* Pop up one level. */
  994.         cmini(ckxech);        /* and clear the cmd buffer. */
  995.         if (tlevel < 0)         /* Just popped out of cmd files? */
  996.           return(0);        /* End of init file or whatever. */
  997.      }
  998. #endif /* NOSPL */
  999.  
  1000. #ifndef NOSPL
  1001.         if (cmdstk[cmdlvl].src == CMD_MD) { /* Executing a macro? */
  1002.         debug(F100,"parser macro","",0);
  1003.         maclvl = cmdstk[cmdlvl].lvl; /* Get current level */
  1004.         debug(F101,"parser maclvl","",maclvl);
  1005.         cbp = cmdbuf;        /* Copy next cmd to command buffer. */
  1006.         *cbp = NUL;
  1007.         if (*savbuf) {        /* In case then-part of 'if' command */
  1008.         strcpy(cbp,savbuf);    /* was saved, restore it. */
  1009.         *savbuf = '\0';
  1010.         } else {            /* Else get next cmd from macro def */
  1011.         if (getncm(cbp,CMDBL) < 0) {
  1012.             if (m && (cmdlvl < inlevel))
  1013.               return((int) sstate);
  1014.             else /* if (!m) */ continue;
  1015.         }
  1016.         }
  1017.         debug(F110,"cmdbuf from macro",cmdbuf,0);
  1018.  
  1019.     } else if (cmdstk[cmdlvl].src == CMD_TF)
  1020. #else
  1021.       if (tlevel > -1)  
  1022. #endif /* NOSPL */
  1023.       {
  1024. #ifndef NOSPL
  1025.         if (*savbuf) {        /* In case THEN-part of IF command */
  1026.         strcpy(cmdbuf,savbuf);    /* was saved, restore it. */
  1027.         *savbuf = '\0';
  1028.         } else
  1029. #endif /* NOSPL */
  1030.  
  1031.           /* Get next line from TAKE file */
  1032.  
  1033.           if ((tfcode = getnct(cmdbuf,CMDBL)) < 0) {
  1034.           if (tfcode < -1) {    /* Error */
  1035.               printf("?Error in TAKE command file: %s\n",
  1036.                  (tfcode == -2) ? "Memory allocation failure" :
  1037.                  "Line too long or contains NUL characters"
  1038.                  );
  1039.               popclvl();
  1040.           }
  1041.           continue;        /* -1 means EOF */
  1042.           }        
  1043.  
  1044.         /* If interactive, get next command from user. */
  1045.  
  1046.     } else {            /* User types it in. */
  1047.         if (pflag) prompt(xxstring);
  1048.         cmini(ckxech);
  1049.         }
  1050.  
  1051.         /* Now know where next command is coming from. Parse and execute it. */
  1052.  
  1053.     repars = 1;            /* 1 = command needs parsing */
  1054.     displa = 0;            /* Assume no file transfer display */
  1055.  
  1056.     while (repars) {        /* Parse this cmd until entered. */
  1057.         debug(F101,"parser top of while loop","",0);
  1058.         cmres();            /* Reset buffer pointers. */
  1059.         xx = cmkey2(cmdtab,ncmd,"Command","",toktab,xxstring);
  1060.         debug(F101,"top-level cmkey2","",xx);
  1061.         if (xx == -5) {
  1062.         yy = chktok(toktab);
  1063.         debug(F101,"top-level cmkey token","",yy);
  1064.         ungword();
  1065.         switch (yy) {
  1066. #ifndef NOPUSH
  1067.           case '!': xx = XXSHE; break; /* Shell escape */
  1068. #endif /* NOPUSH */
  1069.           case '#': xx = XXCOM; break; /* Comment */
  1070.           case ';': xx = XXCOM; break; /* Comment */
  1071. #ifndef NOSPL
  1072.           case ':': xx = XXLBL; break; /* GOTO label */
  1073. #endif /* NOSPL */
  1074. #ifndef NOPUSH
  1075. #ifdef CK_REDIR
  1076.                   case '<': xx = XXFUN; break; /* REDIRECT */
  1077. #endif /* CK_REDIR */
  1078.                   case '@': xx = XXSHE; break; /* Shell (DCL) escape */
  1079. #endif /* NOPUSH */
  1080.           default: 
  1081.             printf("\n?Invalid - %s\n",cmdbuf);
  1082.             xx = -2;
  1083.         }
  1084.         }
  1085.  
  1086. #ifndef NOSPL
  1087.             /* Special handling for IF..ELSE */
  1088.  
  1089.         if (ifcmd[cmdlvl])        /* Count stmts after IF */
  1090.           ifcmd[cmdlvl]++;
  1091.         if (ifcmd[cmdlvl] > 2 && xx != XXELS && xx != XXCOM)
  1092.           ifcmd[cmdlvl] = 0;
  1093.  
  1094.         /* Execute the command and take action based on return code. */
  1095.  
  1096.         if (nulcmd) {        /* Ignoring this command? */
  1097.         xx = XXCOM;        /* Make this command a comment. */
  1098.         }
  1099. #endif /* NOSPL */
  1100.  
  1101.         zz = docmd(xx);    /* Parse rest of command & execute. */
  1102.         debug(F101,"docmd returns","",zz);
  1103.         debug(F110,"cmdbuf",cmdbuf,"");
  1104.         debug(F110,"atmbuf",atmbuf,"");
  1105. #ifdef MAC
  1106.         if (tlevel > -1) {
  1107.         if (sstate == 'a') {    /* if cmd-. cancel */
  1108.             debug(F110, "parser: cancel take, sstate:", "a", 0);
  1109.             sstate = '\0';
  1110.             dostop();
  1111.             return(0);        /* End of init file or whatever. */
  1112.         }
  1113.         }
  1114. #endif /* MAC */
  1115.         switch (zz) {
  1116.         case -4:        /* EOF (e.g. on redirected stdin) */
  1117.             doexit(GOOD_EXIT,xitsta); /* ...exit successfully */
  1118.             case -1:        /* Reparse needed */
  1119.             repars = 1;        /* Just set reparse flag and  */
  1120.             continue;
  1121.         case -6:        /* Invalid command given w/no args */
  1122.             case -2:        /* Invalid command given w/args */
  1123. #ifdef COMMENT
  1124. #ifndef NOSPL
  1125.             /* This is going to be really ugly... */
  1126.             yy = mlook(mactab,atmbuf,nmac); /* Look in macro table */
  1127.             if (yy > -1) {                /* If it's there */
  1128.             if (zz == -2) {                /* insert "do" */
  1129.                 char *mp;
  1130.                 mp = malloc((int)strlen(cmdbuf) + 5);
  1131.                 if (!mp) {
  1132.                 printf("?malloc error 1\n");
  1133.                 return(-2);
  1134.                 }
  1135.                 sprintf(mp,"do %s ",cmdbuf);
  1136.                 strcpy(cmdbuf,mp);
  1137.                 free(mp);
  1138.             } else sprintf(cmdbuf,"do %s %c",atmbuf, CR);
  1139.             if (ifcmd[cmdlvl] == 2)    /* This one doesn't count! */
  1140.               ifcmd[cmdlvl]--;
  1141.             debug(F111,"stuff cmdbuf",cmdbuf,zz);
  1142.             repars = 1;    /* go for reparse */
  1143.             continue;
  1144.             } else {
  1145.             char *p;
  1146.             int n;
  1147.             p = cmdbuf;
  1148.             lp = line;     
  1149.             n = LINBUFSIZ;
  1150.             if (cmflgs == 0) printf("\n");
  1151.             if (zzstring(p,&lp,&n) > -1) 
  1152.               printf("?Invalid: %s\n",line);
  1153.             else
  1154.               printf("?Invalid: %s\n",cmdbuf);
  1155.             } /* (fall thru...) */
  1156. #else
  1157.             printf("?Invalid: %s\n",cmdbuf);
  1158. #endif /* NOSPL */
  1159. #else
  1160.             printf("?Invalid: %s\n",cmdbuf);
  1161. #endif /* COMMENT */
  1162.  
  1163.         case -9:        /* Bad, error message already done */
  1164.             success = 0;
  1165.             debug(F110,"top-level cmkey failed",cmdbuf,0);
  1166.             /* If in background w/ commands coming stdin, terminate */
  1167.             if (pflag == 0 && tlevel < 0)
  1168.               fatal("Kermit command error in background execution");
  1169. /*
  1170.   Command retry feature, edit 190.  If we're at interactive prompting level,
  1171.   reprompt the user with as much of the command as didn't fail.
  1172. */
  1173. #ifdef CM_RETRY
  1174.             if (cm_retry &&    /* If command retry enabled... */
  1175. #ifndef NOSPL
  1176.             (cmdlvl == 0)    /* and at top (interactive) level... */
  1177.             
  1178. #else
  1179.             (tlevel < 0)
  1180. #endif /* NOSPL */
  1181.             ) {
  1182.             int len;
  1183.             char *p, *s;
  1184.             len = strlen(cmdbuf); /* Length of command buffer */
  1185.             p = malloc(len + 1);  /* Allocate space for copy */
  1186.             if (p) {          /* If we got the space */
  1187.                 strcpy(p,cmdbuf); /* copy the command buffer. */
  1188.                 /* Chop off final field, the one that failed. */
  1189.                 s = p + len - 1;          /* Point to end */
  1190.                 while (*s == SP && s > p) /* Trim blanks */
  1191.                   s--;
  1192.                 while (*s != SP && s > p) /* Trim last field */
  1193.                   s--;
  1194.                 if (s > p)        /* Keep the space */
  1195.                   s++;          /* after last good field */
  1196.                 if (s >= p)          /* Cut off remainder */
  1197.                   *s = NUL;
  1198.                 cmini(ckxech);    /* Reinitialize the parser */
  1199.                 strcpy(cmdbuf,p); /* Copy truncated cmd back */
  1200.                 free(p);          /* Free temporary storage */
  1201.                 prompt(xxstring); /* Reprint the prompt */
  1202.                 printf("%s",cmdbuf); /* Reprint partial command */
  1203.                 repars = 1;          /* Force reparse */
  1204.                 continue;
  1205.             }
  1206.             } else
  1207. #endif /* CM_RETRY */
  1208.               cmini(ckxech);    /* (fall thru) */
  1209.  
  1210.              case -3:        /* Empty command OK at top level */
  1211.             repars = 0;        /* Don't need to reparse. */
  1212.             continue;        /* Go back and get another command. */
  1213.  
  1214.         default:        /* Command was successful. */
  1215. #ifndef NOSPL
  1216.             debug(F101,"parser preparing to continue","",maclvl);
  1217. #endif /* NOSPL */
  1218.             repars = 0;        /* Don't need to reparse. */
  1219.             continue;        /* Go back and get another command. */
  1220.         }
  1221.     }
  1222. #ifndef NOSPL
  1223.     debug(F101,"parser breaks out of while loop","",maclvl);
  1224.     if (m && (cmdlvl < inlevel))  return((int) sstate);
  1225. #endif /* NOSPL */
  1226.     }
  1227.  
  1228. /* Got an action command, return start state. */
  1229.  
  1230.     return((int) sstate);
  1231. }
  1232.  
  1233. #ifndef NOSPL
  1234. /*
  1235.   OUTPUT command.
  1236.   Buffering and pacing added by L.I. Kirby, 5A(189), June 1993.
  1237. */
  1238. #define OBSIZE 80            /* Size of local character buffer */
  1239.  
  1240. static int obn;                /* Buffer offset (high water mark) */
  1241. static char obuf[OBSIZE];        /* OUTPUT buffer. */
  1242. static char *obp;            /* Pointer to output buffer. */
  1243. _PROTOTYP( static int oboc, (char) );
  1244. _PROTOTYP( static int xxout, (char *, int) );
  1245.  
  1246. static int
  1247. #ifdef CK_ANSIC
  1248. xxout(char *obuf, int obsize)
  1249. #else
  1250. xxout(obuf, obsize) char *obuf; int obsize; 
  1251. #endif /* CK_ANSIC */
  1252. /* xxout */ {                /* OUTPUT command's output function */
  1253.     int i, rc;
  1254.  
  1255.     debug(F101,"xxout obsize","",obsize);
  1256.     debug(F101,"xxout pacing","",pacing);
  1257.     debug(F111,"xxout string",obuf,strlen(obuf));
  1258.  
  1259.     rc = 0;                /* Initial return code. */
  1260.     if (!obuf || (obsize <= 0))        /* Nothing to output. */
  1261.       goto xxout_x;            /* Return successfully */
  1262.  
  1263.     rc = -1;                  /* Now assume failure */
  1264.     if (pacing == 0) {              /* Is pacing enabled? */
  1265.     if ((local ?               /* No, write entire string at once */
  1266.          ttol((CHAR *)obuf, obsize) : /* to communications device */
  1267.          conxo(obsize, obuf))      /* or to console */
  1268.         != obsize)
  1269.       goto xxout_x;
  1270.     } else {
  1271.     for (i = 0; i < obsize; i++) {    /* Write individual chars */
  1272.         if ((local ? ttoc(obuf[i]) : conoc(obuf[i])) < 0)
  1273.           goto xxout_x;
  1274.         msleep(pacing);
  1275.     }
  1276.     }
  1277.     rc = 0;                /* Success */
  1278.   xxout_x:
  1279.     obn = 0;                /* Reset count */
  1280.     obp = obuf;                /* and pointers */
  1281.     return(rc);                /* return our return code */
  1282. }
  1283.  
  1284. #ifdef COMMENT
  1285. /*
  1286.   Macros for OUTPUT command execution, to make it go faster. 
  1287. */
  1288. #define obfls() ((xxout(obuf,obn)<0)?-1:0)
  1289. #define oboc(c) ((*obp++=(char)(c)),*obp=0,(((++obn)>=OBSIZE)?obfls():0))
  1290.  
  1291. #else /* The macros cause some compilers to generate bad code. */
  1292.  
  1293. static int
  1294. #ifdef CK_ANSIC
  1295. oboc(char c)
  1296. #else
  1297. oboc(c) char c;
  1298. #endif /* CK_ANSIC */
  1299. /* oboc */ {                /* OUTPUT command's output function */
  1300.  
  1301.     *obp++ = c;                /* Deposit character */
  1302.     *obp = NUL;                /* Flush buffer if it's now full */
  1303.  
  1304.     return(((++obn) >= OBSIZE) ? xxout(obuf,obn) : 0);
  1305. }
  1306. #endif /* COMMENT */
  1307.  
  1308. /*  D O O U T P U T  --  Returns 0 on failure, 1 on success */
  1309.  
  1310. int
  1311. dooutput(s) char *s; {
  1312.  
  1313.     int x, xx, y, quote;        /* Workers */
  1314.  
  1315.     debug(F111,"dooutput s",s,(int)strlen(s));
  1316.  
  1317. #ifndef NOLOCAL
  1318.     if (local) {            /* Condition external line */
  1319.     y = ttvt(speed,flow);
  1320.     if (y < 0) return(0);
  1321.     }
  1322. #endif /* NOLOCAL */
  1323.     quote = 0;                /* Initialize backslash (\) quote */
  1324.     obn = 0;                /* Reset count */
  1325.     obp = obuf;                /* and pointers */
  1326.  
  1327.     while (x = *s++) {            /* Loop through the string */
  1328.     y = 0;                /* Error code, 0 = no error. */
  1329.     debug(F000,"dooutput","",x);
  1330.     if (x == CMDQ) {        /* Look for \b or \B in string */
  1331.             quote++;            /* Got \ */
  1332.         continue;            /* Get next character */
  1333.     } else if (quote) {        /* This character is quoted */
  1334.         if (quote == 1 && (x == 'n' || x == 'N')) { /* \n or \N */
  1335.         if (xxout(obuf,obn) < 0) /* Flush buffer */
  1336.           goto outerr;
  1337.         debug(F100,"OUTPUT NUL","",0); /* Send a NUL */
  1338.         ttoc(NUL);
  1339.         quote = 0;
  1340.         continue;
  1341.         } else if (quote == 1 && (x == 'b' || x == 'B')) { /* \b or \B */
  1342.  
  1343.         if (xxout(obuf,obn) < 0) /* Flush buffer first */
  1344.           goto outerr;
  1345.         debug(F100,"OUTPUT BREAK","",0);
  1346. #ifndef NOLOCAL
  1347.         ttsndb();        /* Send BREAK signal */
  1348. #else
  1349.         ttoc(NUL);
  1350. #endif /* NOLOCAL */
  1351.         quote = 0;        /* Turn off quote flag */
  1352.         continue;        /* and not the b or B */
  1353. #ifdef CK_LBRK
  1354.         } else if (quote == 1 && (x == 'l' || x == 'L')) { /* \l or \L */
  1355.         if (xxout(obuf,obn) < 0) /* Flush buffer first */
  1356.           goto outerr;
  1357.         debug(F100,"OUTPUT Long BREAK","",0);
  1358. #ifndef NOLOCAL
  1359.         ttsndlb();        /* Send Long BREAK signal */
  1360. #else
  1361.         ttoc(NUL);
  1362. #endif /* NOLOCAL */
  1363.         quote = 0;        /* Turn off quote flag */
  1364.         continue;        /* and not the l or L */
  1365. #endif /* CK_LBRK */
  1366.         } else {            /* if \ not followed by b or B */
  1367.         /* Note: Atari ST compiler won't allow macro call in "if ()" */
  1368.         xx = oboc(dopar(CMDQ));    /* Output the backslash. */
  1369.         if (xx < 0)
  1370.           goto outerr;
  1371.         quote = 0;        /* Turn off quote flag */
  1372.         }
  1373.     } else                /* No quote */
  1374.       quote = 0;            /* Turn off quote flag */
  1375.  
  1376.     xx = oboc(dopar((char)x));    /* Output this character */
  1377.     debug(F111,"dooutput",obuf,obn);
  1378.     if (xx < 0)
  1379.       goto outerr;
  1380.     if (seslog && duplex)        /* Log the character if log is on */
  1381.       if (zchout(ZSFILE,(char)x) < 0) /* and connection is half duplex */
  1382.         seslog = 0;
  1383.     if (x == '\015') {        /* String contains carriage return */
  1384.         int stuff = -1;
  1385.         if (tnlm) {            /* TERMINAL NEWLINE ON */
  1386.         stuff = LF;        /* Stuff LF */
  1387. #ifdef TNCODE
  1388.         } else if (network &&    /* TELNET NEWLINE ON/OFF/RAW */
  1389.                (ttnproto == NP_TELNET) &&
  1390.                (tn_nlm != TNL_CR)) {
  1391.         stuff = (tn_nlm == TNL_CRLF) ? LF : NUL;
  1392. #endif /* TNCODE */
  1393.         }
  1394.         if (stuff > -1) {        /* Stuffing another character... */
  1395.         xx = oboc(dopar((CHAR)stuff)); 
  1396.         if (xx < 0)
  1397.           goto outerr;
  1398.         if (seslog && duplex)    /* Log stuffed char if appropriate */
  1399.           if (zchout(ZSFILE, (CHAR)stuff) < 0)
  1400.             seslog = 0;
  1401.         }
  1402.         if (xxout(obuf,obn) < 0)    /* Flushing is required here! */
  1403.           goto outerr;
  1404.     }
  1405.     }
  1406.     if (obn > 0)            /* OUTPUT done */
  1407.       if (xxout(obuf,obn) < 0)        /* Flush the buffer if necessary. */
  1408.     goto outerr;
  1409.     return(1);
  1410.  
  1411. outerr:                    /* OUTPUT command error handler */
  1412.     if (msgflg) printf("OUTPUT error\n");
  1413.     return(0);
  1414.  
  1415. /* Remove "local" OUTPUT macro defininitions */
  1416.  
  1417. #ifdef COMMENT
  1418. /* No more macros ... */
  1419. #undef oboc
  1420. #undef obfls
  1421. #endif /* COMMENT */
  1422. }
  1423. #endif /* NOSPL */
  1424.  
  1425. /* Display version herald and initial prompt */
  1426.  
  1427. VOID
  1428. herald() {
  1429.     int x = 0;
  1430.     if (noherald || bgset > 0 || (bgset != 0 && backgrd != 0)) x = 1;
  1431.     debug(F101,"herald","",backgrd);
  1432.     if (x == 0) {
  1433. #ifdef datageneral
  1434.     printf("%s, for%s\n",versio,ckxsys);
  1435. #else
  1436.     printf("%s, for%s\n\r",versio,ckxsys);
  1437. #endif /* datageneral */
  1438.     printf(" Copyright (C) 1985, 1994,\n");
  1439.     printf("  Trustees of Columbia University in the City of New York.\n");
  1440.     printf("Type ? or HELP for help.\n");
  1441.     }
  1442. }
  1443.  
  1444. #ifndef NOSPL
  1445. /*  M L O O K  --  Lookup the macro name in the macro table  */
  1446.  
  1447. /*
  1448.  Call this way:  v = mlook(table,word,n);
  1449.  
  1450.    table - a 'struct mtab' table.
  1451.    word  - the target string to look up in the table.
  1452.    n     - the number of elements in the table.
  1453.  
  1454.  The keyword table must be arranged in ascending alphabetical order, and
  1455.  all letters must be lowercase.
  1456.  
  1457.  Returns the table index, 0 or greater, if the name was found, or:
  1458.  
  1459.   -3 if nothing to look up (target was null),
  1460.   -2 if ambiguous,
  1461.   -1 if not found.
  1462.  
  1463.  A match is successful if the target matches a keyword exactly, or if
  1464.  the target is a prefix of exactly one keyword.  It is ambiguous if the
  1465.  target matches two or more keywords from the table.
  1466. */
  1467. int
  1468. mlook(table,cmd,n) struct mtab table[]; char *cmd; int n; {
  1469.  
  1470.     int i, v, cmdlen;
  1471.  
  1472. /* Lowercase & get length of target, if it's null return code -3. */
  1473.  
  1474.     if ((((cmdlen = lower(cmd))) == 0) || (n < 1)) return(-3);
  1475.  
  1476. /* Not null, look it up */
  1477.  
  1478.     for (i = 0; i < n-1; i++) {
  1479.         if (!strcmp(table[i].kwd,cmd) ||
  1480.            ((v = !strncmp(table[i].kwd,cmd,cmdlen)) &&
  1481.              strncmp(table[i+1].kwd,cmd,cmdlen))) {
  1482.                 return(i);
  1483.              }
  1484.         if (v) return(-2);
  1485.     }   
  1486.  
  1487. /* Last (or only) element */
  1488.  
  1489.     if (!strncmp(table[n-1].kwd,cmd,cmdlen)) {
  1490.         return(n-1);
  1491.     } else return(-1);
  1492. }
  1493.  
  1494. /* mxlook is like mlook, but an exact full-length match is required */
  1495.  
  1496. int
  1497. mxlook(table,cmd,n) char *cmd; struct mtab table[]; int n; {
  1498.     int i, cmdlen;
  1499.     if ((((cmdlen = lower(cmd))) == 0) || (n < 1)) return(-3);
  1500.     for (i = 0; i < n; i++)
  1501.       if (((int)strlen(table[i].kwd) == cmdlen) &&
  1502.       (!strncmp(table[i].kwd,cmd,cmdlen))) return(i);
  1503.     return(-1);
  1504. }
  1505.  
  1506. /*
  1507.   This routine is for the benefit of those compilers that can't handle
  1508.   long string constants or continued lines within them.  Long predefined
  1509.   macros like FOR, WHILE, and XIF have their contents broken up into
  1510.   arrays of string pointers.  This routine concatenates them back into a
  1511.   single string again, and then calls the real addmac() routine to enter
  1512.   the definition into the macro table.
  1513. */
  1514. int
  1515. addmmac(nam,s) char *nam, *s[]; {    /* Add a multiline macro definition */
  1516.     int i, x, y; char *p;
  1517.     x = 0;                /* Length counter */
  1518.     for (i = 0; (y = (int)strlen(s[i])) > 0; i++) { /* Add up total length */
  1519.         debug(F111,"addmmac line",s[i],y);    
  1520.     x += y;
  1521.     }
  1522.     debug(F101,"addmmac lines","",i);
  1523.     debug(F101,"addmmac loop exit","",y);
  1524.     debug(F111,"addmmac length",nam,x);
  1525.     if (x < 0) return(-1);
  1526.  
  1527.     p = malloc(x+1);            /* Allocate space for all of it. */
  1528.     if (!p) {
  1529.     printf("?addmmac malloc error: %s\n",nam);
  1530.     debug(F110,"addmmac malloc error",nam,0);
  1531.     return(-1);
  1532.     }
  1533.     *p = '\0';                /* Start off with null string. */
  1534.     for (i = 0; *s[i]; i++)        /* Concatenate them all together. */
  1535.       strcat(p,s[i]);
  1536.     y = (int)strlen(p);            /* Final precaution. */
  1537.     debug(F111,"addmmac constructed string",p,y);
  1538.     if (y == x) {
  1539.     y = addmac(nam,p);        /* Add result to the macro table. */
  1540.     } else {
  1541.     debug(F100,"addmmac length mismatch","",0);
  1542.     printf("\n!addmmac internal error!\n");
  1543.     y = -1;
  1544.     }
  1545.     free(p);                /* Free the temporary copy. */
  1546.     return(y);    
  1547. }
  1548.  
  1549. /* Here is the real addmac routine. */
  1550.  
  1551. int
  1552. addmac(nam,def) char *nam, *def; {    /* Add a macro to the macro table */
  1553.     int i, x, y, z, namlen, deflen;
  1554.     char *p, c;
  1555.  
  1556.     if (!nam) return(-1);
  1557.     namlen = (int)strlen(nam);        /* Get argument lengths */
  1558.     debug(F111,"addmac nam",nam,namlen);
  1559.     if (!def) {                /* Watch out for null pointer */
  1560.     deflen = 0;
  1561.     debug(F111,"addmac def","(null pointer)",deflen);
  1562.     } else {
  1563.     deflen = (int)strlen(def);
  1564.     debug(F111,"addmac def",def,deflen);
  1565.     }
  1566.     if (deflen < 0) return(-1);        /* strlen() failure, fail. */
  1567.     if (namlen < 1) return(-1);        /* No name given, fail. */
  1568.  
  1569.     if (*nam == CMDQ) nam++;        /* Backslash quote? */
  1570.     if (*nam == '%') {            /* Yes, if it's a variable name, */
  1571.     delmac(nam);            /* Delete any old value. */
  1572.     if (!(c = *(nam + 1))) return(-1); /* Variable name letter or digit */
  1573.     if (deflen < 1) {        /* Null definition */
  1574.         p = NULL;            /* Better not malloc or strcpy! */
  1575.     } else {            /* A substantial definition */
  1576.         p = malloc(deflen + 1);    /* Allocate space for it */
  1577.         if (!p) {
  1578.         printf("?addmac malloc error 2\n");
  1579.         return(-1);
  1580.         } else strcpy(p,def);    /* Copy definition into new space */
  1581.     }
  1582.  
  1583.     /* Now p points to the definition, or is a null pointer */
  1584.  
  1585.     if (p)
  1586.       debug(F110,"addmac p",p,0);
  1587.     else
  1588.       debug(F110,"addmac p","(null pointer)",0);
  1589.  
  1590.     if (c >= '0' && c <= '9') {    /* Digit variable */
  1591.         if (maclvl < 0) {        /* Are we calling or in a macro? */
  1592.         g_var[c] = p;        /* No, it's a global "top level" one */
  1593.         debug(F101,"addmac numeric global maclvl","",maclvl);
  1594.         } else {            /* Yes, it's a macro argument */
  1595.         m_arg[maclvl][c - '0'] = p;
  1596.         debug(F101,"addmac macro arg maclvl","",maclvl);
  1597.         }
  1598.     } else {            /* It's a global variable */
  1599.         if (c < 33 || c > GVARS) return(-1);
  1600.         if (isupper(c)) c = tolower(c);
  1601.         g_var[c] = p;        /* Put pointer in global-var table */
  1602.         debug(F100,"addmac global","",0);
  1603.     }
  1604.     return(0);
  1605.     } else if (*nam == '&') {        /* An array reference? */
  1606.     char **q;
  1607.     if ((y = arraynam(nam,&x,&z)) < 0) /* If syntax is bad */
  1608.       return(-1);            /* return -1. */
  1609.     if (chkarray(x,z) < 0)        /* If array not declared or */
  1610.       return(-2);            /* subscript out of range, ret -2 */
  1611.     delmac(nam);            /* Delete any current definition. */
  1612.     x -= 96;            /* Convert name letter to index. */
  1613.     if ((q = a_ptr[x]) == NULL)    /* If array not declared, */
  1614.       return(-3);            /* return -3. */
  1615.     if (deflen > 0) {
  1616.         if ((p = malloc(deflen+1)) == NULL) { /* Allocate space */
  1617.         printf("addmac macro error 7: %s\n",nam);
  1618.         return(-4);        /* for new def, return -4 on fail. */
  1619.         }
  1620.         strcpy(p,def);        /* Copy definition into new space. */
  1621.     } else p = NULL;
  1622.     q[z] = p;            /* Store pointer to it. */
  1623.     return(0);            /* Done. */
  1624.     } else debug(F110,"addmac macro def",nam,0);
  1625.  
  1626. /* Not a macro argument or a variable, so it's a macro definition */
  1627.  
  1628.     lower(nam);                /* Lowercase the name */
  1629.     if (mxlook(mactab,nam,nmac) > -1)    /* Look up, requiring exact match */
  1630.       delmac(nam);            /* if it's there, delete it. */
  1631.     debug(F111,"addmac table size",nam,nmac);
  1632.     for (y = 0;                /* Find the alphabetical slot */
  1633.      y < MAC_MAX && mactab[y].kwd != NULL && strcmp(nam,mactab[y].kwd) > 0;
  1634.      y++) ;
  1635.     if (y == MAC_MAX) {            /* No more room. */
  1636.     debug(F101,"addmac table overflow","",y);
  1637.     return(-1);
  1638.     } else debug(F111,"addmac position",nam,y);
  1639.     if (mactab[y].kwd != NULL) {    /* Must insert */
  1640.     for (i = nmac; i > y; i--) {    /* Move the rest down one slot */
  1641.         mactab[i].kwd = mactab[i-1].kwd;
  1642.         mactab[i].mval = mactab[i-1].mval;
  1643.         mactab[i].flgs = mactab[i-1].flgs;
  1644.     }
  1645.     }
  1646.     p = malloc(namlen + 1);        /* Allocate space for name */
  1647.     if (!p) {
  1648.     printf("?addmac malloc error 3: %s\n",nam);
  1649.     return(-1);
  1650.     }
  1651.     strcpy(p,nam);            /* Copy name into new space */
  1652.     mactab[y].kwd = p;            /* Add pointer to table */
  1653.  
  1654.     if (deflen > 0) {            /* Same deal for definition */
  1655.     p = malloc(deflen + 1);        /* but watch out for null pointer */
  1656.     if (p == NULL) {
  1657.         printf("?addmac malloc error 5: %s\n", nam);
  1658.         free(mactab[y].kwd);
  1659.         mactab[y].kwd = NULL;
  1660.         return(-1);
  1661.     } else strcpy(p,def);        /* Copy the definition */
  1662.     } else p = NULL;
  1663.     mactab[y].mval = p;
  1664.     mactab[y].flgs = 0;
  1665.     nmac++;                /* Count this macro */
  1666.     return(y);
  1667. }
  1668.  
  1669. int
  1670. delmac(nam) char *nam; {        /* Delete the named macro */
  1671.     int i, x, z;
  1672.     char *p, c;
  1673.  
  1674.     if (!nam) return(0);        /* Watch out for null pointer */
  1675.     debug(F110,"delmac nam",nam,0);
  1676.     if (*nam == CMDQ) nam++;
  1677.     if (*nam == '%') {            /* If it's a variable name */
  1678.     if (!(c = *(nam+1))) return(0);    /* Get variable name letter or digit */
  1679.     p = (char *)0;            /* Initialize value pointer */
  1680.     if (maclvl > -1 && c >= '0' && c <= '9') { /* Digit? */
  1681.         p = m_arg[maclvl][c - '0'];    /* Get pointer from macro-arg table */
  1682.         m_arg[maclvl][c - '0'] = NULL; /* Zero the table pointer */
  1683.     } else {            /* It's a global variable */
  1684.         if (c < 33 || c > GVARS) return(0);
  1685.         p = g_var[c];        /* Get pointer from global-var table */
  1686.         g_var[c] = NULL;        /* Zero the table entry */
  1687.     }
  1688.     if (p) {
  1689.         debug(F110,"delmac def",p,0);
  1690.         free(p);            /* Free the storage */
  1691.     } else debug(F110,"delmac def","(null pointer)",0);
  1692.     return(0);
  1693.     }
  1694.         
  1695.     if (*nam == '&') {            /* An array reference? */
  1696.     char **q;
  1697.     if (arraynam(nam,&x,&z) < 0)    /* If syntax is bad */
  1698.       return(-1);            /* return -1. */
  1699.     x -= 96;            /* Convert name to number. */
  1700.     if ((q = a_ptr[x]) == NULL)    /* If array not declared, */
  1701.       return(-2);            /* return -2. */
  1702.     if (z > a_dim[x])        /* If subscript out of range, */
  1703.       return(-3);            /* return -3. */
  1704.     if (q[z]) {            /* If there is an old value, */
  1705.         debug(F110,"delman def",q[z],0);
  1706.         free(q[z]);            /* delete it. */
  1707.         q[z] = NULL;
  1708.     } else debug(F110,"delmac def","(null pointer)",0);
  1709.     }
  1710.  
  1711.    /* Not a variable or an array, so it must be a macro. */
  1712.  
  1713.     if ((x = mlook(mactab,nam,nmac)) < 0) { /* Look it up */
  1714.     debug(F111,"delmac mlook",nam,x);
  1715.     return(x);
  1716.     }
  1717.     if (mactab[x].kwd)            /* Free the storage for the name */
  1718.       free(mactab[x].kwd);
  1719.     if (mactab[x].mval)            /* and for the definition */
  1720.       free(mactab[x].mval);
  1721.  
  1722.     for (i = x; i < nmac; i++) {    /* Now move up the others. */
  1723.     mactab[i].kwd = mactab[i+1].kwd;
  1724.     mactab[i].mval = mactab[i+1].mval;
  1725.     mactab[i].flgs = mactab[i+1].flgs;
  1726.     }
  1727.     nmac--;                /* One less macro */
  1728.     mactab[nmac].kwd = NULL;        /* Delete last item from table */
  1729.     mactab[nmac].mval = NULL;
  1730.     mactab[nmac].flgs = 0;
  1731.     return(0);
  1732. }
  1733.  
  1734. VOID
  1735. initmac() {                /* Init macro & variable tables */
  1736.     int i, j;
  1737.  
  1738.     nmac = 0;                /* No macros */
  1739.     for (i = 0; i < MAC_MAX; i++) {    /* Initialize the macro table */
  1740.     mactab[i].kwd = NULL;
  1741.     mactab[i].mval = NULL;
  1742.     mactab[i].flgs = 0;
  1743.     }
  1744.     for (i = 0; i < MACLEVEL; i++) {    /* Init the macro argument tables */
  1745.     mrval[i] = NULL;
  1746.     for (j = 0; j < 10; j++) {
  1747.         m_arg[i][j] = NULL;
  1748.     }
  1749.     }
  1750.     for (i = 0; i < GVARS; i++) {    /* And the global variables table */
  1751.     g_var[i] = NULL;
  1752.     }
  1753.     for (i = 0; i < 26; i++) {        /* And the table of arrays */
  1754.     a_ptr[i] = (char **) NULL;    /* Null pointer for each */
  1755.     a_dim[i] = 0;            /* and a dimension of zero */
  1756.     }
  1757. }
  1758.  
  1759. int
  1760. popclvl() {                /* Pop command level, return cmdlvl */
  1761.     if (cmdlvl < 1) {            /* If we're already at top level */
  1762.     cmdlvl = 0;            /* just make sure all the */
  1763.     tlevel = -1;            /* stack pointers are set right */
  1764.     maclvl = -1;            /* and return */
  1765.     } else if (cmdstk[cmdlvl].src == CMD_TF) { /* Reading from TAKE file? */
  1766.     if (tlevel > -1) {        /* Yes, */
  1767.         if (tfnam[tlevel]) {
  1768.         free(tfnam[tlevel]);
  1769.         tfnam[tlevel] = NULL;
  1770.         }
  1771.         fclose(tfile[tlevel--]);    /* close it and pop take level */
  1772.         cmdlvl--;            /* pop command level */
  1773.     } else tlevel = -1;
  1774.     } else if (cmdstk[cmdlvl].src == CMD_MD) { /* In a macro? */
  1775.     if (maclvl > -1) {        /* Yes, */
  1776.         debug(F111,"popclvl before",macx[maclvl],maclvl);
  1777.         macp[maclvl] = "";        /* set macro pointer to null string */
  1778.         *cmdbuf = '\0';        /* clear the command buffer */
  1779.         if (mrval[maclvl+1]) {    /* Free any deeper return values. */
  1780.         free(mrval[maclvl+1]);
  1781.         mrval[maclvl+1] = NULL;
  1782.         }
  1783.         maclvl--;            /* pop macro level */
  1784.         cmdlvl--;            /* and command level */
  1785.         debug(F111,"popclvl after ",
  1786.           macx[maclvl] ? macx[maclvl] : "",maclvl);
  1787.     } else maclvl = -1;
  1788.     }
  1789. #ifndef MAC
  1790.     if (cmdlvl < 1) {            /* If back at top level */
  1791.     conint(trap,stptrap);        /* Fix interrupts */
  1792.     bgchk();            /* Check background status */
  1793.     concb((char)escape);        /* Go into cbreak mode */
  1794.     }
  1795. #endif /* MAC */
  1796.     return(cmdlvl < 1 ? 0 : cmdlvl);    /* Return command level */
  1797. }
  1798. #else /* No script programming language */
  1799. int popclvl() {                /* Just close current take file. */
  1800.     if (tlevel > -1) {            /* if any... */
  1801.     if (tfnam[tlevel]) {
  1802.         free(tfnam[tlevel]);
  1803.         tfnam[tlevel] = NULL;
  1804.     }
  1805.     fclose(tfile[tlevel--]);
  1806.     }
  1807.     if (tlevel == -1) {            /* And if back at top level */
  1808.     conint(trap,stptrap);        /* check and set interrupts */
  1809.         bgchk();            /* and background status */
  1810.         concb((char)escape);        /* and go back into cbreak mode. */
  1811.     }
  1812.     return(tlevel + 1);
  1813. }
  1814. #endif /* NOSPL */
  1815.  
  1816. /* STOP - get back to C-Kermit prompt, no matter where from. */
  1817.  
  1818. int
  1819. dostop() {
  1820.     while ( popclvl() )  ;    /* Pop all macros & take files */
  1821. #ifndef NOSPL
  1822.     while (cmpop() > -1) ;    /* And all recursive cmd pkg invocations */
  1823. #endif /* NOSPL */
  1824.     cmini(ckxech);        /* Clear the command buffer. */
  1825.     return(0);
  1826. }
  1827.  
  1828.  
  1829. /* Close the given log */
  1830.  
  1831. int
  1832. doclslog(x) int x; {
  1833.     int y;
  1834.     switch (x) {
  1835. #ifdef DEBUG
  1836.     case LOGD:
  1837.         if (deblog == 0) {
  1838.         printf("?Debugging log wasn't open\n");
  1839.         return(0);
  1840.         }
  1841.         *debfil = '\0';
  1842.         deblog = 0;
  1843.         return(zclose(ZDFILE));
  1844. #endif /* DEBUG */
  1845.  
  1846.     case LOGP:
  1847.         if (pktlog == 0) {
  1848.         printf("?Packet log wasn't open\n");
  1849.         return(0);
  1850.         }
  1851.         *pktfil = '\0';
  1852.         pktlog = 0;
  1853.         return(zclose(ZPFILE));
  1854.  
  1855. #ifndef NOLOCAL
  1856.     case LOGS:
  1857.         if (seslog == 0) {
  1858.         printf("?Session log wasn't open\n");
  1859.         return(0);
  1860.         }
  1861.         *sesfil = '\0';
  1862.         seslog = 0;
  1863.         return(zclose(ZSFILE));
  1864. #endif /* NOLOCAL */
  1865.  
  1866. #ifdef TLOG
  1867.         case LOGT:
  1868.         if (tralog == 0) {
  1869.         printf("?Transaction log wasn't open\n");
  1870.         return(0);
  1871.         }
  1872.         *trafil = '\0';
  1873.         tralog = 0;
  1874.         return(zclose(ZTFILE));
  1875. #endif /* TLOG */
  1876.  
  1877. #ifndef NOSPL
  1878.           case LOGW:            /* WRITE file */
  1879.       case LOGR:            /* READ file */
  1880.         y = (x == LOGR) ? ZRFILE : ZWFILE;
  1881.         if (chkfn(y) < 1)        /* If no file to close */
  1882.           return(1);        /* succeed silently. */
  1883.         return(zclose(y));        /* Otherwise, close the file. */
  1884. #endif /* NOSPL */
  1885.  
  1886.     default:
  1887.         printf("\n?Unexpected log designator - %d\n", x);
  1888.         return(0);
  1889.     }
  1890. }
  1891.  
  1892. #ifndef NOSERVER
  1893. #ifndef NOFRILLS
  1894. static char *nm[] = { "disabled", "enabled" };
  1895. #endif /* NOFRILLS */
  1896. #endif /* NOSERVER */
  1897.  
  1898. static int slc = 0;            /* Screen line count */
  1899.  
  1900. #ifndef NOSHOW
  1901. char *
  1902. showoff(x) int x; {
  1903.     return( x ? "on" : "off");
  1904. }
  1905.  
  1906. #ifndef NOFRILLS
  1907. #define xxdiff(v,sys) strncmp(v,sys,strlen(sys))
  1908. VOID
  1909. shover() {
  1910.     printf("\nVersions:\n %s\n Numeric: %ld",versio,vernum);
  1911.     if (verwho) printf("-%d",verwho);
  1912.     printf(xxdiff(ckxv,ckxsys) ? "\n %s for%s\n" : "\n %s\n",ckxv,ckxsys);
  1913.     printf(xxdiff(ckzv,ckzsys) ? " %s for%s\n" : " %s\n",ckzv,ckzsys);
  1914.     printf(" %s\n",protv);
  1915.     printf(" %s\n",fnsv);
  1916.     printf(" %s\n %s\n",cmdv,userv);
  1917. #ifndef NOCSETS
  1918.     printf(" %s\n",xlav);
  1919. #endif /* NOCSETS */
  1920. #ifndef MAC
  1921.     printf(" %s\n",connv);
  1922. #endif /* MAC */
  1923. #ifndef NODIAL
  1924.     printf(" %s\n",dialv);
  1925. #endif /* NODIAL */
  1926. #ifndef NOSCRIPT
  1927.     printf(" %s\n",loginv);
  1928. #endif /* NOSCRIPT */
  1929. #ifdef NETCONN
  1930.     printf(" %s\n",cknetv);
  1931. #ifdef OS2
  1932.     printf(" %s\n",ckonetv);
  1933. #ifdef CK_NETBIOS
  1934.     printf(" %s\n",ckonbiv);
  1935. #endif /* CK_NETBIOS */
  1936. #ifdef OS2MOUSE
  1937.    printf(" %s\n",ckomouv);
  1938. #endif /* OS2MOUSE */
  1939. #endif /* OS2 */
  1940. #endif /* NETCONN */
  1941.     printf("\n");
  1942. }
  1943.  
  1944. VOID
  1945. shofea() {
  1946.     int flag = 0;
  1947. #ifdef OS2
  1948. #ifdef M_I286
  1949.     printf("\nOS/2 16-bit.\n");
  1950. #else
  1951.     printf("\nOS/2 32-bit.\n");
  1952. #endif /* M_I286 */
  1953. #endif /* OS2 */
  1954.     printf("\nSpecial features:\n");
  1955. #ifdef NETCONN
  1956.     printf(" Network support (type SHOW NET for further info)\n");
  1957. #endif /* NETCONN */
  1958. #ifdef CK_RTSCTS
  1959.     printf(" Hardware flow control\n");
  1960. #endif /* CK_RTSCTS */
  1961.  
  1962. #ifndef NOCSETS
  1963.     printf(" Latin-1 (West European) character-set translation\n");
  1964. #ifdef LATIN2
  1965.     printf(" Latin-2 (East European) character-set translation\n");
  1966. #endif /* LATIN2 */
  1967. #ifdef CYRILLIC
  1968.     printf(" Cyrillic (Russian, Ukrainian, etc) character-set translation\n");
  1969. #endif /* CYRILLIC */
  1970. #ifdef HEBREW
  1971.     printf(" Hebrew character-set translation\n");
  1972. #endif /* HEBREW */
  1973. #ifdef KANJI
  1974.     printf(" Kanji (Japanese) character-set translation\n");
  1975. #endif /* KANJI */
  1976. #endif /* NOCSETS */
  1977.  
  1978. #ifdef CK_REDIR
  1979.     printf(" REDIRECT command\n");
  1980. #endif /* CK_REDIR */
  1981. #ifdef CK_RESEND
  1982.     printf(" RESEND command\n");
  1983. #endif /* CK_RESEND */
  1984.  
  1985. #ifdef CK_CURSES
  1986.     printf(" Fullscreen file transfer display\n");
  1987. #endif /* CK_CURSES */
  1988.  
  1989. #ifdef CK_SPEED
  1990.     printf(" Control-character unprefixing\n");
  1991. #endif /* CK_SPEED */
  1992.  
  1993. #ifdef OS2MOUSE
  1994.    printf(" OS/2 Mouse support\n") ;
  1995. #endif /* OS2MOUSE */
  1996.  
  1997. #ifdef CK_REXX
  1998.    printf(" REXX script language interface\n");
  1999. #endif /* CK_REXX */
  2000.  
  2001.     printf("\nFeatures not included:\n");
  2002. #ifndef CK_CURSES
  2003. #ifndef MAC
  2004.     printf(" No fullscreen file transfer display\n");
  2005.     flag = 1;
  2006. #endif /* MAC */
  2007. #endif /* CK_CURSES */
  2008. #ifdef NOSERVER
  2009.     printf(" No server mode\n");
  2010.     flag = 1;
  2011. #endif /* NOSERVER */
  2012. #ifdef NODEBUG
  2013.     printf(" No debugging\n");
  2014.     flag = 1;
  2015. #endif /* NODEBUG */
  2016. #ifdef NOTLOG
  2017.     printf(" No transaction log\n");
  2018.     flag = 1;
  2019. #endif /* NOTLOG */
  2020. #ifdef NOHELP
  2021.     printf(" No built-in help\n");
  2022.     flag = 1;
  2023. #endif /* NOHELP */
  2024. #ifndef NETCONN
  2025.     printf(" No network support\n");
  2026.     flag = 1;
  2027. #endif /* NETCONN */
  2028. #ifdef NOMSEND
  2029.     printf(" No MSEND command\n");
  2030.     flag = 1;
  2031. #endif /* NOMSEND */
  2032. #ifdef NODIAL
  2033.     printf(" No DIAL command\n");
  2034.     flag = 1;
  2035. #else
  2036. #ifdef MINIDIAL
  2037.     printf(
  2038.      " No DIAL command for modems other than Hayes, CCITT, and Unknown\n");
  2039.     flag = 1;
  2040. #endif /* MINIDIAL */
  2041. #ifndef CK_RTSCTS
  2042. #ifndef MAC
  2043.     printf(" No hardware flow control\n");
  2044.     flag = 1;
  2045. #endif /* MAC */
  2046. #endif /* CK_RTSCTS */
  2047. #endif /* NODIAL */
  2048. #ifdef NOXMIT
  2049.     printf(" No TRANSMIT command\n");
  2050.     flag = 1;
  2051. #endif /* NOXMIT */
  2052. #ifdef NOSCRIPT
  2053.     printf(" No SCRIPT command\n");
  2054.     flag = 1;
  2055. #endif /* NOSCRIPT */
  2056. #ifdef NOSPL
  2057.     printf(" No script programming features\n");
  2058.     flag = 1;
  2059. #endif /* NOSPL */
  2060. #ifdef NOCSETS
  2061.     printf(" No character-set translation\n");
  2062.     flag = 1;
  2063. #else
  2064. #ifndef LATIN2
  2065.     printf(" No Latin-2 character-set translation\n");
  2066.     flag = 1;
  2067. #endif /* LATIN2 */
  2068. #ifdef NOHEBREW
  2069.     printf(" No Hebrew character-set translation\n");
  2070.     flag = 1;
  2071. #endif /* NOHEBREW */
  2072. #ifdef NOCYRIL
  2073.     printf(" No Cyrillic character-set translation\n");
  2074.     flag = 1;
  2075. #endif /* NOCYRIL */
  2076. #ifndef KANJI
  2077.     printf(" No Kanji character-set translation\n");
  2078.     flag = 1;
  2079. #endif /* KANJI */
  2080. #endif /* NOCSETS */
  2081. #ifdef NOCMDL
  2082.     printf(" No command-line arguments\n");
  2083.     flag = 1;
  2084. #endif /* NOCMDL */
  2085. #ifdef NOFRILLS
  2086.     printf(" No frills\n");
  2087.     flag = 1;
  2088. #endif /* NOFRILLS */
  2089. #ifdef NOPUSH
  2090.     printf(" No escape to system\n");
  2091.     flag = 1;
  2092. #endif /* NOPUSH */
  2093. #ifdef NOJC
  2094. #ifdef UNIX
  2095.     printf(" No UNIX job control\n");
  2096.     flag = 1;
  2097. #endif /* UNIX */
  2098. #endif /* NOJC */
  2099. #ifdef NOSETKEY
  2100.     printf(" No SET KEY command\n");
  2101.     flag = 1;
  2102. #endif /* NOSETKEY */
  2103. #ifndef PARSENSE
  2104.     printf(" No automatic parity detection\n");
  2105.     flag = 1;
  2106. #endif /* PARSENSE */
  2107. #ifndef CK_SPEED
  2108.     printf(" No control-character unprefixing\n");
  2109.     flag = 1;
  2110. #endif /* CK_SPEED */
  2111. #ifndef CK_REDIR
  2112.     printf(" No REDIRECT command\n");
  2113.     flag = 1;
  2114. #endif /* CK_REDIR */
  2115. #ifndef CK_RESEND
  2116.     printf(" No RESEND command\n");
  2117.     flag = 1;
  2118. #endif /* CK_RESEND */
  2119. #ifdef OS2
  2120. #ifdef __32BIT__
  2121. #ifndef OS2MOUSE
  2122.     printf(" No OS/2 Mouse support\n") ;
  2123.     flag = 1;
  2124. #endif /* __32BIT__ */
  2125. #endif /* OS2 */
  2126. #endif /* OS2MOUSE */
  2127. #ifdef OS2
  2128. #ifndef CK_REXX
  2129.     printf(" No REXX script language interface\n");
  2130.     flag = 1;
  2131. #endif /* CK_REXX */
  2132. #endif /* OS2 */
  2133.  
  2134.     if (flag == 0) printf(" None\n");
  2135. /*
  2136.   Print compile-time (-D) options, as well as C preprocessor
  2137.   predefined symbols that might affect us...
  2138. */
  2139. #ifdef __DATE__                /* GNU and other ANSI */
  2140. #ifdef __TIME__
  2141.     printf("\nCompiled %s %s, options:\n", __DATE__, __TIME__);
  2142. #else
  2143.     printf("\nCompiled %s, options:\n", __DATE__);
  2144. #endif /* __TIME__ */
  2145. #else /* !__DATE__ */
  2146.     printf("\nCompiler options:\n");
  2147. #endif /* __DATE__ */
  2148.  
  2149. #ifdef MAC
  2150. #ifdef MPW
  2151.     prtopt("MPW");
  2152. #else
  2153. #ifdef THINK_C
  2154.     prtopt("THINK_C");
  2155. #endif /* THINK_C */
  2156. #endif /* MPW */
  2157. #endif /* MAC */
  2158.  
  2159. #ifdef __386__
  2160.     prtopt("__386__");
  2161. #endif
  2162.  
  2163. #ifdef DEBUG
  2164. #ifdef IFDEBUG
  2165.     prtopt("IFDEBUG");
  2166. #else
  2167.     prtopt("DEBUG");
  2168. #endif /* IFDEBUG */
  2169. #endif /* DEBUG */
  2170. #ifdef TLOG
  2171.     prtopt("TLOG");
  2172. #endif /* TLOG */
  2173. #ifdef XFRCAN
  2174.     prtopt("XFRCAN");
  2175. #endif /* XFRCAN */
  2176. #ifdef CK_SPEED
  2177.     prtopt("CK_SPEED");
  2178. #endif /* CK_SPEED */
  2179. #ifdef CK_APC
  2180.     prtopt("CK_APC");
  2181. #endif /* CK_APC */
  2182. #ifdef CK_MKDIR
  2183.     prtopt("CK_MKDIR");
  2184. #endif /* CK_MKDIR */
  2185. #ifdef NOMKDIR
  2186.     prtopt("NOMKDIR");
  2187. #endif /* NOMKDIR */
  2188. #ifdef CK_LABELED
  2189.     prtopt("CK_LABELED");
  2190. #endif /* CK_LABELED */
  2191. #ifdef NODIAL
  2192.     prtopt("NODIAL");
  2193. #endif /* NODIAL */
  2194. #ifdef MINIDIAL
  2195.     prtopt("MINIDIAL");
  2196. #endif /* MINIDIAL */
  2197. #ifdef DYNAMIC
  2198.     prtopt("DYNAMIC");
  2199. #endif /* IFDEBUG */
  2200. #ifndef NOSPL
  2201.     sprintf(line,"CMDDEP=%d",CMDDEP);
  2202.     prtopt(line);
  2203. #endif /* NOSPL */
  2204. #ifdef UNIX
  2205.     prtopt("UNIX");
  2206. #endif /* UNIX */
  2207. #ifdef VMS
  2208.     prtopt("VMS");
  2209. #endif /* VMS */
  2210. #ifdef OLD_VMS
  2211.     prtopt("OLD_VMS");
  2212. #endif /* OLD_VMS */
  2213. #ifdef vms
  2214.     prtopt("vms");
  2215. #endif /* vms */
  2216. #ifdef VMSSHARE
  2217.     prtopt("VMSSHARE");
  2218. #endif /* VMSSHARE */
  2219. #ifdef datageneral
  2220.     prtopt("datageneral");
  2221. #endif /* datageneral */
  2222. #ifdef apollo
  2223.     prtopt("apollo");
  2224. #endif /* apollo */
  2225. #ifdef aegis
  2226.     prtopt("aegis");
  2227. #endif /* aegis */
  2228. #ifdef A986
  2229.     prtopt("A986");
  2230. #endif /* A986 */
  2231. #ifdef AMIGA
  2232.     prtopt("AMIGA");
  2233. #endif /* AMIGA */
  2234. #ifdef CONVEX9
  2235.     prtopt("CONVEX9");
  2236. #endif /* CONVEX9 */
  2237. #ifdef CONVEX10
  2238.     prtopt("CONVEX10");
  2239. #endif /* CONVEX9 */
  2240. #ifdef MAC
  2241.     prtopt("MAC");
  2242. #endif /* MAC */
  2243. #ifdef AUX
  2244.     prtopt("AUX");
  2245. #endif /* AUX */
  2246. #ifdef OS2
  2247.     prtopt("OS2");
  2248. #endif /* OS2 */
  2249. #ifdef OS9
  2250.     prtopt("OS9");
  2251. #endif /* OS9 */
  2252. #ifdef MSDOS
  2253.     prtopt("MSDOS");
  2254. #endif /* MSDOS */
  2255. #ifdef DIRENT
  2256.     prtopt("DIRENT");
  2257. #endif /* DIRENT */
  2258. #ifdef SDIRENT
  2259.     prtopt("SDIRENT");
  2260. #endif /* SDIRENT */
  2261. #ifdef NDIR
  2262.     prtopt("NDIR");
  2263. #endif /* NDIR */
  2264. #ifdef XNDIR
  2265.     prtopt("XNDIR");
  2266. #endif /* XNDIR */
  2267. #ifdef MATCHDOT
  2268.     prtopt("MATCHDOT");
  2269. #endif /* MATCHDOT */
  2270. #ifdef SAVEDUID
  2271.     prtopt("SAVEDUID");
  2272. #endif /* SAVEDUID */
  2273. #ifdef RENAME
  2274.     prtopt("RENAME");
  2275. #endif /* RENAME */
  2276. #ifdef CK_TMPDIR
  2277.     prtopt("CK_TMPDIR");
  2278. #endif /* CK_TMPDIR */
  2279. #ifdef NOCCTRAP
  2280.     prtopt("NOCCTRAP");
  2281. #endif /* NOCCTRAP */
  2282. #ifdef CK_NEED_SIG
  2283.     prtopt("CK_NEED_SIG");
  2284. #endif /* CK_NEED_SIG */
  2285. #ifdef CK_TTYFD
  2286.     prtopt("CK_TTYFD");
  2287. #endif /* CK_TTYFD */
  2288. #ifdef NETCONN
  2289.     prtopt("NETCONN");
  2290. #endif /* NETCONN */
  2291. #ifdef TCPSOCKET
  2292.     prtopt("TCPSOCKET");
  2293. #ifdef CK_LINGER
  2294.     prtopt("CK_LINGER");
  2295. #endif /* CK_LINGER */
  2296. #ifdef CK_SOCKBUF
  2297.     prtopt("CK_SOCKBUF");
  2298. #endif /* CK_SOCKBUF */
  2299. #endif /* TCPSOCKET */
  2300. #ifdef SUNX25
  2301.     prtopt("SUNX25");
  2302. #endif /* SUNX25 */
  2303. #ifdef DECNET
  2304.     prtopt("DECNET");
  2305. #endif /* DECNET */
  2306. #ifdef NPIPE
  2307.     prtopt("NPIPE");
  2308. #endif /* NPIPE */
  2309. #ifdef CK_NETBIOS
  2310.     prtopt("CK_NETBIOS");
  2311. #endif /* CK_NETBIOS */
  2312. #ifdef ATT7300
  2313.     prtopt("ATT7300");
  2314. #endif /* ATT7300 */
  2315. #ifdef ATT6300
  2316.     prtopt("ATT6300");
  2317. #endif /* ATT6300 */
  2318. #ifdef HDBUUCP
  2319.     prtopt("HDBUUCP");
  2320. #endif /* HDBUUCP */
  2321. #ifdef NOUUCP
  2322.     prtopt("NOUUCP");
  2323. #endif /* NOUUCP */
  2324. #ifdef LONGFN
  2325.     prtopt("LONGFN");
  2326. #endif /* LONGFN */
  2327. #ifdef RDCHK
  2328.     prtopt("RDCHK");
  2329. #endif /* RDCHK */
  2330. #ifdef SELECT
  2331.     prtopt("SELECT");
  2332. #endif /* SELECT */
  2333. #ifdef USLEEP
  2334.     prtopt("USLEEP");
  2335. #endif /* USLEEP */
  2336. #ifdef NAP
  2337.     prtopt("NAP");
  2338. #endif /* NAP */
  2339. #ifdef NAPHACK
  2340.     prtopt("NAPHACK");
  2341. #endif /* NAPHACK */
  2342. #ifdef CK_POLL
  2343.     prtopt("CK_POLL");
  2344. #endif /* CK_POLL */
  2345. #ifdef NOIEXTEN
  2346.     prtopt("NOIEXTEN");
  2347. #endif /* NOIEXTEN */
  2348. #ifdef EXCELAN
  2349.     prtopt("EXCELAN");
  2350. #endif /* EXCELAN */
  2351. #ifdef INTERLAN
  2352.     prtopt("INTERLAN");
  2353. #endif /* INTERLAN */
  2354. #ifdef NOFILEH
  2355.     prtopt("NOFILEH");
  2356. #endif /* NOFILEH */
  2357. #ifdef NOSYSIOCTLH
  2358.     prtopt("NOSYSIOCTLH");
  2359. #endif /* NOSYSIOCTLH */
  2360. #ifdef DCLPOPEN
  2361.     prtopt("DCLPOPEN");
  2362. #endif /* DCLPOPEN */
  2363. #ifdef NOSETBUF
  2364.     prtopt("NOSETBUF");
  2365. #endif /* NOSETBUF */
  2366. #ifdef NOFDZERO
  2367.     prtopt("NOFDZERO");
  2368. #endif /* NOFDZERO */
  2369. #ifdef NOPOPEN
  2370.     prtopt("NOPOPEN");
  2371. #endif /* NOPOPEN */
  2372. #ifdef NOPARTIAL
  2373.     prtopt("NOPARTIAL");
  2374. #endif /* NOPARTIAL */
  2375. #ifdef NOKVERBS
  2376.     prtopt("NOKVERBS");
  2377. #endif /* NOKVERBS */
  2378. #ifdef NOSETREU
  2379.     prtopt("NOSETREU");
  2380. #endif /* NOSETREU */
  2381. #ifdef _POSIX_SOURCE
  2382.     prtopt("_POSIX_SOURCE");
  2383. #endif /* _POSIX_SOURCE */
  2384. #ifdef LCKDIR
  2385.     prtopt("LCKDIR");
  2386. #endif /* LCKDIR */
  2387. #ifdef ACUCNTRL
  2388.     prtopt("ACUCNTRL");
  2389. #endif /* ACUCNTRL */
  2390. #ifdef BSD4
  2391.     prtopt("BSD4");
  2392. #endif /* BSD4 */
  2393. #ifdef BSD44
  2394.     prtopt("BSD44");
  2395. #endif /* BSD44 */
  2396. #ifdef BSD41
  2397.     prtopt("BSD41");
  2398. #endif /* BSD41 */
  2399. #ifdef BSD43
  2400.     prtopt("BSD43");
  2401. #endif /* BSD43 */
  2402. #ifdef BSD29
  2403.     prtopt("BSD29");
  2404. #endif /* BSD29 */
  2405. #ifdef BSDI
  2406.     prtopt("BSDI");
  2407. #endif /* BSDI */
  2408. #ifdef __bsdi__
  2409.     prtopt("__bsdi__");
  2410. #endif /* __bsdi__ */
  2411. #ifdef __NetBSD__
  2412.     prtopt("__NetBSD__");
  2413. #endif /* __NetBSD__ */
  2414. #ifdef __FreeBSD__
  2415.     prtopt("__FreeBSD__");
  2416. #endif /* __FreeBSD__ */
  2417. #ifdef __linux__
  2418.     prtopt("__linux__");
  2419. #endif /* __linux__ */
  2420. #ifdef LINUX_HI_SPD
  2421.     prtopt("LINUX_HI_SPD");
  2422. #endif /* LINUX_HI_SPD */
  2423. #ifdef LYNXOS
  2424.     prtopt("LYNXOS");
  2425. #endif /* LYNXOS */
  2426. #ifdef V7
  2427.     prtopt("V7");
  2428. #endif /* V7 */
  2429. #ifdef AIX370
  2430.     prtopt("AIX370");
  2431. #endif /* AIX370 */
  2432. #ifdef RTAIX
  2433.     prtopt("RTAIX");
  2434. #endif /* RTAIX */
  2435. #ifdef HPUX
  2436.     prtopt("HPUX");
  2437. #endif /* HPUX */
  2438. #ifdef HPUXPRE65
  2439.     prtopt("HPUXPRE65");
  2440. #endif /* HPUXPRE65 */
  2441. #ifdef DGUX
  2442.     prtopt("DGUX");
  2443. #endif /* DGUX */
  2444. #ifdef DGUX430
  2445.     prtopt("DGUX430");
  2446. #endif /* DGUX430 */
  2447. #ifdef DGUX540
  2448.     prtopt("DGUX540");
  2449. #endif /* DGUX540 */
  2450. #ifdef sony_news
  2451.     prtopt("sony_news");
  2452. #endif /* sony_news */
  2453. #ifdef CIE
  2454.     prtopt("CIE");
  2455. #endif /* CIE */
  2456. #ifdef XENIX
  2457.     prtopt("XENIX");
  2458. #endif /* XENIX */
  2459. #ifdef SCO_XENIX
  2460.     prtopt("SCO_XENIX");
  2461. #endif /* SCO_XENIX */
  2462. #ifdef ISIII
  2463.     prtopt("ISIII");
  2464. #endif /* ISIII */
  2465. #ifdef I386IX
  2466.     prtopt("I386IX");
  2467. #endif /* I386IX */
  2468. #ifdef RTU
  2469.     prtopt("RTU");
  2470. #endif /* RTU */
  2471. #ifdef PROVX1
  2472.     prtopt("PROVX1");
  2473. #endif /* PROVX1 */
  2474. #ifdef PYRAMID
  2475.     prtopt("PYRAMID");
  2476. #endif /* PYRAMID */
  2477. #ifdef TOWER1
  2478.     prtopt("TOWER1");
  2479. #endif /* TOWER1 */
  2480. #ifdef UTEK
  2481.     prtopt("UTEK");
  2482. #endif /* UTEK */
  2483. #ifdef ZILOG
  2484.     prtopt("ZILOG");
  2485. #endif /* ZILOG */
  2486. #ifdef TRS16
  2487.     prtopt("TRS16");
  2488. #endif /* TRS16 */
  2489. #ifdef MINIX
  2490.     prtopt("MINIX");
  2491. #endif /* MINIX */
  2492. #ifdef C70
  2493.     prtopt("C70");
  2494. #endif /* C70 */
  2495. #ifdef AIXPS2
  2496.     prtopt("AIXPS2");
  2497. #endif /* AIXPS2 */
  2498. #ifdef AIXRS
  2499.     prtopt("AIXRS");
  2500. #endif /* AIXRS */
  2501. #ifdef UTSV
  2502.     prtopt("UTSV");
  2503. #endif /* UTSV */
  2504. #ifdef ATTSV
  2505.     prtopt("ATTSV");
  2506. #endif /* ATTSV */
  2507. #ifdef SVR3
  2508.     prtopt("SVR3");
  2509. #endif /* SVR3 */
  2510. #ifdef SVR4
  2511.     prtopt("SVR4");
  2512. #endif /* SVR4 */
  2513. #ifdef DELL_SVR4
  2514.     prtopt("DELL_SVR4");
  2515. #endif /* DELL_SVR4 */
  2516. #ifdef ICL_SVR4
  2517.     prtopt("ICL_SVR4");
  2518. #endif /* ICL_SVR4 */
  2519. #ifdef OSF
  2520.     prtopt("OSF");
  2521. #endif /* OSF */
  2522. #ifdef OSF1
  2523.     prtopt("OSF1");
  2524. #endif /* OSF1 */
  2525. #ifdef __OSF
  2526.     prtopt("__OSF");
  2527. #endif /* __OSF */
  2528. #ifdef __OSF__
  2529.     prtopt("__OSF__");
  2530. #endif /* __OSF__ */
  2531. #ifdef __osf__
  2532.     prtopt("__osf__");
  2533. #endif /* __osf__ */
  2534. #ifdef __OSF1
  2535.     prtopt("__OSF1");
  2536. #endif /* __OSF1 */
  2537. #ifdef __OSF1__
  2538.     prtopt("__OSF1__");
  2539. #endif /* __OSF1__ */
  2540. #ifdef PTX
  2541.     prtopt("PTX");
  2542. #endif /* PTX */
  2543. #ifdef POSIX
  2544.     prtopt("POSIX");
  2545. #endif /* POSIX */
  2546. #ifdef SOLARIS
  2547.     prtopt("SOLARIS");
  2548. #endif /* SOLARIS */
  2549. #ifdef SUNOS4
  2550.     prtopt("SUNOS4");
  2551. #endif /* SUNOS4 */
  2552. #ifdef SUN4S5
  2553.     prtopt("SUN4S5");
  2554. #endif /* SUN4S5 */
  2555. #ifdef ENCORE
  2556.     prtopt("ENCORE");
  2557. #endif /* ENCORE */
  2558. #ifdef ultrix
  2559.     prtopt("ultrix");
  2560. #endif
  2561. #ifdef sxaE50
  2562.     prtopt("sxaE50");
  2563. #endif
  2564. #ifdef mips
  2565.     prtopt("mips");
  2566. #endif
  2567. #ifdef MIPS
  2568.     prtopt("MIPS");
  2569. #endif
  2570. #ifdef vax
  2571.     prtopt("vax");
  2572. #endif
  2573. #ifdef VAX
  2574.     prtopt("VAX");
  2575. #endif
  2576. #ifdef alpha
  2577.     prtopt("alpha");
  2578. #endif
  2579. #ifdef ALPHA
  2580.     prtopt("ALPHA");
  2581. #endif
  2582. #ifdef __ALPHA
  2583.     prtopt("__ALPHA");
  2584. #endif
  2585. #ifdef __alpha
  2586.     prtopt("__alpha");
  2587. #endif
  2588. #ifdef __AXP
  2589.     prtopt("__AXP");
  2590. #endif
  2591. #ifdef AXP
  2592.     prtopt("AXP");
  2593. #endif
  2594. #ifdef axp
  2595.     prtopt("axp");
  2596. #endif
  2597. #ifdef __ALPHA__
  2598.     prtopt("__ALPHA__");
  2599. #endif
  2600. #ifdef __alpha__
  2601.     prtopt("__alpha__");
  2602. #endif
  2603. #ifdef sun
  2604.     prtopt("sun");
  2605. #endif
  2606. #ifdef sun3
  2607.     prtopt("sun3");
  2608. #endif
  2609. #ifdef sun386
  2610.     prtopt("sun386");
  2611. #endif
  2612. #ifdef _SUN
  2613.     prtopt("_SUN");
  2614. #endif
  2615. #ifdef sun4
  2616.     prtopt("sun4");
  2617. #endif
  2618. #ifdef sparc
  2619.     prtopt("sparc");
  2620. #endif
  2621. #ifdef _CRAY
  2622.     prtopt("_CRAY");
  2623. #endif /* _CRAY */
  2624. #ifdef NEXT
  2625.     prtopt("NEXT");
  2626. #endif
  2627. #ifdef NeXT
  2628.     prtopt("NeXT");
  2629. #endif
  2630. #ifdef MACH
  2631.     prtopt("MACH");
  2632. #endif
  2633. #ifdef sgi
  2634.     prtopt("sgi");
  2635. #endif
  2636. #ifdef M_SYS5
  2637.     prtopt("M_SYS5");
  2638. #endif
  2639. #ifdef __SYSTEM_FIVE
  2640.     prtopt("__SYSTEM_FIVE");
  2641. #endif
  2642. #ifdef sysV
  2643.     prtopt("sysV");
  2644. #endif
  2645. #ifdef M_XENIX                /* SCO Xenix V and UNIX/386 */
  2646.     prtopt("M_XENIX");
  2647. #endif 
  2648. #ifdef M_UNIX                /* SCO UNIX */
  2649.     prtopt("M_UNIX");
  2650. #endif
  2651. #ifdef _M_UNIX                /* SCO UNIX 3.2v4 = ODT 2.0 */
  2652.     prtopt("_M_UNIX");
  2653. #endif
  2654. #ifdef M_I586
  2655.     prtopt("M_I586");
  2656. #endif
  2657. #ifdef _M_I586
  2658.     prtopt("_M_I586");
  2659. #endif
  2660. #ifdef i586
  2661.     prtopt("i586");
  2662. #endif
  2663. #ifdef M_I486
  2664.     prtopt("M_I486");
  2665. #endif
  2666. #ifdef _M_I486
  2667.     prtopt("_M_I486");
  2668. #endif
  2669. #ifdef i486
  2670.     prtopt("i486");
  2671. #endif
  2672. #ifdef M_I386
  2673.     prtopt("M_I386");
  2674. #endif
  2675. #ifdef _M_I386
  2676.     prtopt("_M_I386");
  2677. #endif
  2678. #ifdef i386
  2679.     prtopt("i386");
  2680. #endif
  2681. #ifdef i286
  2682.     prtopt("i286");
  2683. #endif
  2684. #ifdef M_I286
  2685.     prtopt("M_I286");
  2686. #endif
  2687. #ifdef mc68000
  2688.     prtopt("mc68000");
  2689. #endif
  2690. #ifdef mc68010
  2691.     prtopt("mc68010");
  2692. #endif
  2693. #ifdef mc68020
  2694.     prtopt("mc68020");
  2695. #endif
  2696. #ifdef mc68030
  2697.     prtopt("mc68030");
  2698. #endif
  2699. #ifdef mc68040
  2700.     prtopt("mc68040");
  2701. #endif
  2702. #ifdef M_68000
  2703.     prtopt("M_68000");
  2704. #endif
  2705. #ifdef M_68010
  2706.     prtopt("M_68010");
  2707. #endif
  2708. #ifdef M_68020
  2709.     prtopt("M_68020");
  2710. #endif
  2711. #ifdef M_68030
  2712.     prtopt("M_68030");
  2713. #endif
  2714. #ifdef M_68040
  2715.     prtopt("M_68040");
  2716. #endif
  2717. #ifdef m68k
  2718.     prtopt("m68k");
  2719. #endif
  2720. #ifdef m88k
  2721.     prtopt("m88k");
  2722. #endif
  2723. #ifdef pdp11
  2724.     prtopt("pdp11");
  2725. #endif
  2726. #ifdef iAPX
  2727.     prtopt("iAPX");
  2728. #endif
  2729. #ifdef __hp9000s800
  2730.     prtopt("__hp9000s800");
  2731. #endif
  2732. #ifdef __hp9000s700
  2733.     prtopt("__hp9000s700");
  2734. #endif
  2735. #ifdef __hp9000s500
  2736.     prtopt("__hp9000s500");
  2737. #endif
  2738. #ifdef __hp9000s300
  2739.     prtopt("__hp9000s300");
  2740. #endif
  2741. #ifdef __hp9000s200
  2742.     prtopt("__hp9000s200");
  2743. #endif
  2744. #ifdef AIX
  2745.     prtopt("AIX");
  2746. #endif
  2747. #ifdef _AIXFS
  2748.     prtopt("_AIXFS");
  2749. #endif
  2750. #ifdef u370
  2751.     prtopt("u370");
  2752. #endif
  2753. #ifdef u3b
  2754.     prtopt("u3b");
  2755. #endif
  2756. #ifdef u3b2
  2757.     prtopt("u3b2");
  2758. #endif
  2759. #ifdef multimax
  2760.     prtopt("multimax");
  2761. #endif
  2762. #ifdef balance
  2763.     prtopt("balance");
  2764. #endif
  2765. #ifdef ibmrt
  2766.     prtopt("ibmrt");
  2767. #endif
  2768. #ifdef _IBMRT
  2769.     prtopt("_IBMRT");
  2770. #endif
  2771. #ifdef ibmrs6000
  2772.     prtopt("ibmrs6000");
  2773. #endif
  2774. #ifdef _AIX
  2775.     prtopt("_AIX");
  2776. #endif /* _AIX */
  2777. #ifdef _IBMR2
  2778.     prtopt("_IBMR2");
  2779. #endif
  2780. #ifdef UNIXWARE
  2781.     prtopt("UNIXWARE");
  2782. #endif
  2783. #ifdef QNX
  2784.     prtopt("QNX");
  2785. #ifdef __QNX__
  2786.     prtopt("__QNX__");
  2787. #ifdef __16BIT__
  2788.     prtopt("__16BIT__");
  2789. #endif
  2790. #ifdef CK_QNX16
  2791.     prtopt("CK_QNX16");
  2792. #endif
  2793. #ifdef __32BIT__
  2794.     prtopt("__32BIT__");
  2795. #endif
  2796. #ifdef CK_QNX32
  2797.     prtopt("CK_QNX32");
  2798. #endif
  2799. #endif /* __QNX__ */
  2800. #endif /* QNX */
  2801.  
  2802. #ifdef __STRICT_BSD__
  2803.     prtopt("__STRICT_BSD__");
  2804. #endif
  2805. #ifdef __STRICT_ANSI__
  2806.     prtopt("__STRICT_ANSI__");
  2807. #endif
  2808. #ifdef _ANSI_C_SOURCE
  2809.     prtopt("_ANSI_C_SOURCE");
  2810. #endif
  2811. #ifdef __STDC__
  2812.     prtopt("__STDC__");
  2813. #endif
  2814. #ifdef __DECC
  2815.     prtopt("__DECC");
  2816. #endif
  2817. #ifdef __GNUC__                /* gcc in ansi mode */
  2818.     prtopt("__GNUC__");
  2819. #endif
  2820. #ifdef GNUC                /* gcc in traditional mode */
  2821.     prtopt("GNUC");
  2822. #endif
  2823. #ifdef __WATCOMC__
  2824.     prtopt("__WATCOMC__");
  2825. #endif
  2826. #ifdef CK_ANSIC
  2827.     prtopt("CK_ANSIC");
  2828. #endif
  2829. #ifdef CK_ANSILIBS
  2830.     prtopt("CK_ANSILIBS");
  2831. #endif
  2832. #ifdef _XOPEN_SOURCE
  2833.     prtopt("_XOPEN_SOURCE");
  2834. #endif
  2835. #ifdef _ALL_SOURCE
  2836.     prtopt("_ALL_SOURCE");
  2837. #endif
  2838. #ifdef _SC_JOB_CONTROL
  2839.     prtopt("_SC_JOB_CONTROL");
  2840. #endif
  2841. #ifdef _POSIX_JOB_CONTROL
  2842.     prtopt("_POSIX_JOB_CONTROL");
  2843. #endif
  2844. #ifdef CK_POSIX_SIG
  2845.     prtopt("CK_POSIX_SIG");
  2846. #endif
  2847. #ifdef SVR3JC
  2848.     prtopt("SVR3JC");
  2849. #endif
  2850. #ifdef _386BSD
  2851.     prtopt("_386BSD");
  2852. #endif
  2853. #ifdef _BSD
  2854.     prtopt("_BSD");
  2855. #endif
  2856. #ifdef TERMIOX
  2857.     prtopt("TERMIOX");
  2858. #endif /* TERMIOX */
  2859. #ifdef STERMIOX
  2860.     prtopt("STERMIOX");
  2861. #endif /* STERMIOX */
  2862. #ifdef CK_CURSES
  2863.     prtopt("CK_CURSES");
  2864. #endif /* CK_CURSES */
  2865. #ifdef CK_WREFRESH
  2866.     prtopt("CK_WREFRESH");
  2867. #endif /* CK_WREFRESH */
  2868. #ifdef CK_PCT_BAR
  2869.     prtopt("CK_PCT_BAR");
  2870. #endif /* CK_PCT_BAR */
  2871. #ifdef CK_DTRCD
  2872.     prtopt("CK_DTRCD");
  2873. #endif /* CK_DTRCD */
  2874. #ifdef CK_DTRCTS
  2875.     prtopt("CK_DTRCTS");
  2876. #endif /* CK_DTRCTS */
  2877. #ifdef CK_RTSCTS
  2878.     prtopt("CK_RTSCTS");
  2879. #endif /* CK_RTSCTS */
  2880. #ifdef POSIX_CRTSCTS
  2881.     prtopt("POSIX_CRTSCTS");
  2882. #endif /* POSIX_CRTSCTS */
  2883. #ifdef CK_DSYSINI
  2884.     prtopt("CK_DSYSINI");
  2885. #endif /* CK_DSYSINI */
  2886. #ifdef CK_SYSINI
  2887.     prtopt("CK_SYSINI");
  2888. #endif /* CK_SYSINI */
  2889. #ifdef CK_INI_A
  2890.     prtopt("CK_INI_A");
  2891. #endif /* CK_INI_A */
  2892. #ifdef CK_INI_B
  2893.     prtopt("CK_INI_B");
  2894. #endif /* CK_INI_B */
  2895. #ifdef CK_NAWS
  2896.     prtopt("CK_NAWS");
  2897. #endif /* CK_NAWS */
  2898. #ifdef DCMDBUF
  2899.     prtopt("DCMDBUF");
  2900. #endif /* DCMDBUF */
  2901. #ifdef CK_RECALL
  2902.     prtopt("CK_RECALL");
  2903. #endif /* CK_RECALL */
  2904. #ifdef CLSOPN
  2905.     prtopt("CLSOPN");
  2906. #endif /* CLSOPN */
  2907. #ifdef STRATUS
  2908.     prtopt("STRATUS");
  2909. #endif /* STRATUS */
  2910. #ifdef __VOS__
  2911.     prtopt("__VOS__");
  2912. #endif /* __VOS__ */
  2913. #ifdef STRATUSX25
  2914.     prtopt("STRATUSX25");
  2915. #endif /* STRATUSX25 */
  2916. #ifdef OS2MOUSE 
  2917.    prtopt("OS2MOUSE") ;
  2918. #endif /* OS2MOUSE */
  2919. #ifdef CK_REXX
  2920.    prtopt("CK_REXX") ;
  2921. #endif /* CK_REXX */
  2922.     prtopt((char *)0);
  2923.     printf("\n\n");
  2924. }
  2925. #endif /* NOFRILLS */
  2926.  
  2927. #ifdef CK_LABELED
  2928. VOID
  2929. sholbl() {
  2930. #ifdef VMS
  2931.     printf("VMS Labeled File Features:\n");
  2932.     printf(" acl %s (ACL info %s)\n",
  2933.        showoff(lf_opts & LBL_ACL),
  2934.        lf_opts & LBL_ACL ? "preserved" : "discarded");
  2935.     printf(" backup-date %s (backup date/time %s)\n",
  2936.        showoff(lf_opts & LBL_BCK),
  2937.        lf_opts & LBL_BCK ? "preserved" : "discarded");
  2938.     printf(" name %s (original filename %s)\n",
  2939.        showoff(lf_opts & LBL_NAM),
  2940.        lf_opts & LBL_NAM ? "preserved" : "discarded");
  2941.     printf(" owner %s (original file owner id %s)\n",
  2942.        showoff(lf_opts & LBL_OWN),
  2943.        lf_opts & LBL_OWN ? "preserved" : "discarded");
  2944.     printf(" path %s (original file's disk:[directory] %s)\n",
  2945.        showoff(lf_opts & LBL_PTH),
  2946.        lf_opts & LBL_PTH ? "preserved" : "discarded");
  2947. #else
  2948. #ifdef OS2
  2949.     printf("OS/2 Labeled File features (attributes):\n");
  2950.     printf(" archive:   %s\n", showoff(lf_opts & LBL_ARC));
  2951.     printf(" extended:  %s\n", showoff(lf_opts & LBL_EXT));
  2952.     printf(" hidden:    %s\n", showoff(lf_opts & LBL_HID));
  2953.     printf(" read-only: %s\n", showoff(lf_opts & LBL_RO ));
  2954.     printf(" system:    %s\n", showoff(lf_opts & LBL_SYS));
  2955. #endif /* OS2 */
  2956. #endif /* VMS */
  2957. }
  2958. #endif /* CK_LABELED */
  2959.  
  2960. VOID
  2961. shotcs(cs1,cs2) int cs1, cs2; {        /* Show terminal character set */
  2962. #ifndef NOCSETS
  2963. #ifndef MAC
  2964.     char *s;
  2965. #ifdef CK_ANSIC
  2966.     int gettcs(int, int);
  2967. #else
  2968.     int gettcs();
  2969. #endif /* CK_ANSIC */
  2970.  
  2971.     printf(" Terminal character-set: ");
  2972.     if (cs1 == cs2) {            /* No translation */
  2973.     printf("transparent\n");
  2974.     } else {                /* Translation */
  2975.     printf("%s (remote) %s (local)\n",
  2976.            fcsinfo[cs2].keyword,fcsinfo[cs1].keyword);
  2977.     if (cs2 != cs1) {
  2978.         switch(gettcs(cs2,cs1)) {
  2979.           case TC_USASCII:  s = "ascii";        break;
  2980.           case TC_1LATIN:   s = "latin1-iso";   break;
  2981.           case TC_2LATIN:   s = "latin2-iso";   break;
  2982.           case TC_CYRILL:   s = "cyrillic-iso"; break;
  2983.           case TC_JEUC:     s = "japanese-euc"; break;
  2984.           case TC_HEBREW:   s = "hebrew-iso";   break;
  2985.           default:          s = "transparent";  break;
  2986.         }
  2987.         if (strcmp(s,fcsinfo[cs1].keyword) &&
  2988.         strcmp(s,fcsinfo[cs2].keyword))
  2989.           printf("                         (via %s)\n",s);
  2990.     }
  2991.     }
  2992. #endif /* MAC */
  2993. #endif /* NOCSETS */
  2994. }
  2995. #endif /* NOSHOW */
  2996.  
  2997. #ifndef NOSETKEY
  2998. VOID
  2999. shokeycode(c) int c; {
  3000.     KEY ch;
  3001.     CHAR *s;
  3002.  
  3003.     printf("\n Key code \\%d => ",c);
  3004. #ifndef NOKVERBS
  3005.     if (IS_KVERB(keymap[c])) {    /* \Kverb? */
  3006.     int i, kv;
  3007.     kv = keymap[c] & ~(F_KVERB);
  3008.     printf("Verb: ");
  3009.     for (i = 0; i < nkverbs; i++)
  3010.       if (kverbs[i].kwval == kv) {
  3011.           printf("\\K%s",kverbs[i].kwd);
  3012.           break;
  3013.       }
  3014.     printf("\n");
  3015.     } else
  3016. #endif /* NOKVERBS */
  3017.     if (macrotab[c]) {            /* See if there's a macro */
  3018.     printf("String: ");        /* If so, display its definition */
  3019.     s = macrotab[c];
  3020.     while (ch = *s++)
  3021.       if (ch < 32 || ch == 127
  3022. /*
  3023.   Systems whose native character sets have graphic characters in C1...
  3024. */
  3025. #ifndef NEXT                /* NeXT */
  3026. #ifndef AUX                /* Macintosh */
  3027. #ifndef XENIX                /* IBM PC */
  3028. #ifndef OS2                /* IBM PC */
  3029.           || (ch > 127 && ch < 160)
  3030. #endif /* OS2 */
  3031. #endif /* XENIX */
  3032. #endif /* AUX */
  3033. #endif /* NEXT */
  3034.           )
  3035.         printf("\\{%d}",ch);    /* Display control characters */
  3036.       else putchar((char) ch);    /* in backslash notation */
  3037.     printf("\n");
  3038. #ifndef NOKVERBS
  3039.     } else if (keymap[c] > 0x100) {    /* This means "undefined" */
  3040.     printf("Undefined\n");
  3041. #endif /* NOKVERBS */
  3042.     } else {            /* No macro, show single character */
  3043.     printf("Character: ");
  3044.     ch = keymap[c];
  3045.     if (ch < 32 || ch == 127 || ch > 255
  3046. #ifndef NEXT
  3047. #ifndef AUX
  3048. #ifndef XENIX
  3049. #ifndef OS2
  3050.         || (ch > 127 && ch < 160)
  3051. #endif /* OS2 */
  3052. #endif /* XENIX */
  3053. #endif /* AUX */
  3054. #endif /* NEXT */
  3055.         )
  3056. /*
  3057.   These used to be %d, but gcc 1.93 & later complain about type mismatches.
  3058.   %u is supposed to be totally portable.
  3059. */
  3060.       printf("\\%u",(unsigned int) ch);
  3061.     else printf("%c \\%u",(CHAR) (ch & 0xff),(unsigned int) ch);
  3062.     if (ch == (KEY) c)
  3063.       printf(" (self, no translation)\n");
  3064.     else
  3065.       printf("\n");
  3066.     }
  3067. }
  3068. #endif /* NOSETKEY */
  3069.  
  3070. #ifndef NOSHOW
  3071. int
  3072. doshow(x) int x; {
  3073.     int y, i; long zz;
  3074.     char *s;
  3075.  
  3076. #ifndef NOSETKEY
  3077.     if (x == SHKEY) {            /* SHOW KEY */
  3078.     int c;
  3079.     if ((y = cmcfm()) < 0) return(y);        
  3080. #ifdef MAC
  3081.     printf("Not implemented\n");
  3082.     return(0);
  3083. #else /* Not MAC */
  3084.     printf(" Press key: ");
  3085. #ifdef UNIX
  3086. #ifdef NOSETBUF
  3087.     fflush(stdout);
  3088. #endif /* NOSETBUF */
  3089. #endif /* UNIX */
  3090.     conbin((char)escape);        /* Put terminal in binary mode */
  3091.     c = congks(0);            /* Get character or scan code */
  3092.     concb((char)escape);        /* Restore terminal to cbreak mode */
  3093.     if (c < 0) {            /* Check for error */
  3094.         printf("?Error reading key\n");
  3095.         return(0);
  3096.     }
  3097. #ifndef OS2
  3098. /*
  3099.   Do NOT mask when it can be a raw scan code, perhaps > 255
  3100. */
  3101.     c &= cmdmsk;            /* Apply command mask */
  3102. #endif /* OS2 */
  3103.     shokeycode(c);
  3104.     return(1);
  3105. #endif /* MAC */
  3106.     }
  3107. #ifndef NOKVERBS
  3108.     if (x == SHKVB) {            /* SHOW KVERBS */
  3109.     if ((y = cmcfm()) < 0) return(y);        
  3110.     printf("\nThe following %d keyboard verbs are available:\n\n",nkverbs);
  3111.     kwdhelp(kverbs,nkverbs,"\\K","",3);
  3112.     return(1);
  3113.     }
  3114. #endif /* NOKVERBS */
  3115. #endif /* NOSETKEY */
  3116.  
  3117. #ifndef NOSPL
  3118.     if (x == SHMAC) {            /* SHOW MACRO */
  3119.     x = cmfld("Macro name, or carriage return to see them all","",&s,
  3120.           NULL);
  3121.     if (x == -3)            /* This means they want see all */
  3122.       *line = '\0';
  3123.     else if (x < 0)            /* Otherwise negative = parse error */
  3124.       return(x);
  3125.     else                /* 0 or greater */
  3126.       strcpy(line,s);        /* means they typed something */
  3127.     if ((y = cmcfm()) < 0) return(y); /* Get confirmation */
  3128.     if (*line) {
  3129.         slc = 0;            /* Initial SHO MAC line number */
  3130.         x = mlook(mactab,s,nmac);    /* Look up what they typed */
  3131.         switch (x) {
  3132.           case -3:            /* Nothing to look up */
  3133.         return(0);
  3134.           case -1:            /* Not found */
  3135.         printf("%s - not found\n",s);
  3136.         return(0);
  3137.           case -2:            /* Ambiguous, matches more than one */
  3138.         y = (int)strlen(line);
  3139.         slc = 1;
  3140.         for (x = 0; x < nmac; x++)
  3141.           if (!strncmp(mactab[x].kwd,line,y))
  3142.             if (shomac(mactab[x].kwd,mactab[x].mval) < 0) break;
  3143.         return(1);
  3144.           default:            /* Matches one exactly */
  3145.         shomac(mactab[x].kwd,mactab[x].mval);
  3146.         return(1);
  3147.         }
  3148.     } else {            /* They want to see them all */
  3149.         printf("Macros:\n");
  3150.         slc = 1;
  3151.         for (y = 0; y < nmac; y++)
  3152.           if (shomac(mactab[y].kwd,mactab[y].mval) < 0) break;
  3153.         return(1);
  3154.     }
  3155.     }
  3156. #endif /* NOSPL */
  3157.  
  3158. /*
  3159.   Other SHOW commands only have two fields.  Get command confirmation here,
  3160.   then handle with big switch() statement.
  3161. */
  3162.     if ((y = cmcfm()) < 0) return(y);
  3163.     switch (x) {
  3164.  
  3165. #ifdef ANYX25
  3166.         case SHPAD:
  3167.             shopad();
  3168.             break;
  3169. #endif /* ANYX25 */
  3170.  
  3171. #ifdef NETCONN
  3172.     case SHNET:
  3173.         shonet();
  3174.         break;
  3175. #endif /* NETCONN */
  3176.  
  3177.     case SHPAR:
  3178.         shopar();
  3179.         break;
  3180.  
  3181.         case SHATT:
  3182.         shoatt();
  3183.         break;
  3184.  
  3185. #ifndef NOSPL
  3186.     case SHCOU:
  3187.         printf(" %d\n",count[cmdlvl]);
  3188.         break;
  3189. #endif /* NOSPL */
  3190.  
  3191. #ifndef NOSERVER
  3192.         case SHSER:            /* Show Server */
  3193. #ifndef NOFRILLS
  3194.         printf("Function           Status:\n");
  3195.         printf(" GET                %s\n",nm[en_get]);
  3196.         printf(" SEND               %s\n",nm[en_sen]);        
  3197.         printf(" REMOTE CD/CWD      %s\n",nm[en_cwd]);
  3198.         printf(" REMOTE DELETE      %s\n",nm[en_del]);
  3199.         printf(" REMOTE DIRECTORY   %s\n",nm[en_dir]);
  3200.         printf(" REMOTE HOST        %s\n",nm[en_hos]);        
  3201.         printf(" REMOTE SET         %s\n",nm[en_set]);        
  3202.         printf(" REMOTE SPACE       %s\n",nm[en_spa]);        
  3203.         printf(" REMOTE TYPE        %s\n",nm[en_typ]);        
  3204.         printf(" REMOTE WHO         %s\n",nm[en_who]);
  3205.         printf(" BYE                %s\n",nm[en_bye]);
  3206.             printf(" FINISH             %s\n",nm[en_fin]);
  3207. #endif /* NOFRILLS */
  3208.         printf("Server timeout: %d\n",srvtim);
  3209.         printf("Server display: %s\n\n", showoff(srvdis));
  3210.         break;
  3211. #endif /* NOSERVER */
  3212.  
  3213.         case SHSTA:            /* Status of last command */
  3214.         printf( " %s\n", success ? "SUCCESS" : "FAILURE" );
  3215.         return(0);            /* Don't change it */
  3216.  
  3217. #ifdef MAC
  3218.     case SHSTK: {            /* Stack for MAC debugging */
  3219.         long sp;
  3220.  
  3221.         sp = -1;
  3222.         loadA0 ((char *)&sp);    /* set destination address */
  3223.         SPtoaA0();            /* move SP to destination */
  3224.         printf("Stack at 0x%x\n", sp);
  3225.         show_queue();        /* more debugging */
  3226.         break; 
  3227.     }
  3228. #endif /* MAC */
  3229.  
  3230. #ifndef NOLOCAL
  3231.     case SHTER:            /* SHOW TERMINAL */
  3232.         printf(" Command  bytesize:      %d bits\n",
  3233.            (cmdmsk == 0377) ? 8 : 7);
  3234.         printf(" Terminal bytesize:      %d bits\n",
  3235.            (cmask == 0377) ? 8 : 7);
  3236. #ifdef OS2
  3237.         printf(" Terminal type:          %s",
  3238.            (tt_type >= 0 && tt_type <= max_tt) ?
  3239.            tt_info[tt_type].x_name :
  3240.            "unknown"
  3241.            );
  3242.         if (tt_type >= 0 && tt_type <= max_tt)
  3243.           if (strlen(tt_info[tt_type].x_id))
  3244.         printf(", ID = <ESC>%s",tt_info[tt_type].x_id);
  3245.         printf("\n");
  3246. #else
  3247.         s = getenv("TERM");
  3248.         printf(" Terminal type:          %s\n", s ? s : "(unknown)");
  3249. #endif /* OS2 */
  3250.         printf(" Terminal echo:          %s\n",
  3251.            duplex ? "local" : "remote");
  3252.         printf(" Terminal locking-shift: %s\n", showoff(sosi));
  3253.         printf(" Terminal newline-mode:  %s\n", showoff(tnlm));
  3254.         printf(" Terminal cr-display:    %s\n",
  3255.            tt_crd ? "crlf" : "normal");
  3256. #ifdef OS2
  3257.         printf(" Terminal cursor:        %s",
  3258.            (tt_cursor == 2) ? "full" :
  3259.            (tt_cursor == 1) ? "half" : "underline");
  3260.         printf(", hide-cursor: %s\n", showoff(tt_hide));
  3261. #endif /* OS2 */
  3262.         printf(" Terminal debug:         %s\n",showoff(debses));
  3263. #ifdef OS2
  3264. /* Should show colors here too. */
  3265. /* But colors are hard, because we don't really know what they are without */
  3266. /* also knowing the state of the emulator. */
  3267.         printf(" Terminal arrow-keys:    %s\n",
  3268.            tt_arrow ? "application" : "cursor");
  3269.         printf(" Terminal keypad-mode:   %s\n",
  3270.            tt_keypad ? "application" : "numeric");
  3271.         printf(" Terminal answerback:    %s\n",showoff(tt_answer));
  3272.         printf(" Terminal wrap:          %s\n",showoff(tt_wrap));
  3273.         printf(" Terminal bell:          %s\n",
  3274.           tt_bell ? ((tt_bell == 1) ? "audible" : "visible") : "none");
  3275.         printf(" Terminal transmit-timeout: %d",tt_ctstmo);
  3276.         printf(", output-pacing: %d\n",tt_pacing);
  3277.         printf(" Terminal roll:          %s\n",showoff(tt_roll));
  3278.         printf(" Terminal scrollback:    %d\n", tt_scrsize);
  3279. #endif /* OS2 */
  3280. #ifdef CK_APC
  3281.         if (apcstatus == APC_ON) s = "on";
  3282.         else if (apcstatus == APC_OFF) s = "off";
  3283.         else if (apcstatus == APC_UNCH) s = "unchecked";
  3284.         printf(" Terminal APC:           %s\n", s);
  3285. #endif /* CK_APC */
  3286. #ifndef NOCSETS
  3287.         shotcs(tcsl,tcsr);        /* Show terminal character sets */
  3288. #endif /* NOCSETS */
  3289. #ifdef OS2
  3290.         printf(" Terminal code-page:     %d\n", os2getcp());
  3291.         printf(" Available code pages:   ");
  3292.         {
  3293.         int cplist[8], cps;
  3294.         cps = os2getcplist(cplist, sizeof(cplist));
  3295.         for (i = 1; i < cps; i++)
  3296.           printf("%s%d", i == 1 ? "" : ", ", cplist[i]);
  3297.         printf("\n");
  3298.       }
  3299. #endif /* OS2 */
  3300.         if (seslog)
  3301.           printf(" SESSION LOG ACTIVE:     %s\n",sesfil);
  3302. #ifdef CK_NAWS                /* Console terminal screen size */
  3303.         ttgwsiz();            /* Try to get latest size */
  3304.         printf(" Rows = %d, Columns = %d", tt_rows, tt_cols);
  3305. #ifdef OS2MOUSE
  3306.         printf(", Mouse: %s\n",showoff(tt_mouse));
  3307. #else
  3308.         printf("\n");
  3309. #endif /* OS2MOUSE */
  3310. #else
  3311. #ifdef OS2MOUSE
  3312.         printf(" Terminal mouse:         %s\n",showoff(tt_mouse));
  3313. #endif /* OS2MOUSE */
  3314. #endif /* CK_NAWS */
  3315.  
  3316. #ifdef COMMENT
  3317. /* No more Alt-x */
  3318. #ifdef OS2
  3319.         printf(
  3320. " To return to the C-Kermit> prompt from CONNECT mode, use Alt-x, or:\n"
  3321.            );
  3322. #endif /* OS2 */
  3323. #endif /* COMMENT */
  3324.         printf(" CONNECT-mode escape character: %d (Ctrl-%c, %s)\n",
  3325.          escape,ctl(escape),(escape == 127 ? "DEL" : ccntab[escape]));
  3326. #ifdef UNIX
  3327. #ifndef NOJC
  3328.         printf(" Suspend: %s\n", showoff(suspend));
  3329. #endif /* NOJC */
  3330. #endif /* UNIX */
  3331.         break;
  3332. #endif /* NOLOCAL */
  3333.  
  3334. #ifndef NOFRILLS
  3335.     case SHVER:
  3336.         shover();
  3337.         break;
  3338. #endif /* NOFRILLS */
  3339.  
  3340. #ifndef NOSPL
  3341.     case SHBUI:            /* Built-in variables */
  3342.     case SHFUN:            /* or built-in functions */
  3343. #ifdef CK_NAWS    
  3344.         if (ttgwsiz() > 0) {    /* Get current screen size */
  3345.         if (tt_rows > 0 && tt_cols > 0) {
  3346.             cmd_rows = tt_rows;
  3347.             cmd_cols = tt_cols;
  3348.         }
  3349.         }
  3350. #endif /* CK_NAWS */
  3351.         if (x == SHFUN) {        /* Functions */
  3352.         printf("\nThe following functions are available:\n\n");
  3353.         kwdhelp(fnctab,nfuncs,"\\F","()",3);
  3354.         break;
  3355.         } else {            /* Variables */
  3356.         i = 0;
  3357.         for (y = 0; y < nvars; y++) {
  3358.             char *s;
  3359.             if ((vartab[y].flgs & CM_INV))
  3360.               continue;
  3361.             s = nvlook(vartab[y].kwd);
  3362.             printf(" \\v(%s) = ",vartab[y].kwd);
  3363.             if (vartab[y].kwval == VN_NEWL) { /* \v(newline) */
  3364.             while (*s)    /* Show control chars symbolically */
  3365.               printf("\\{%d}",*s++);
  3366.             printf("\n");
  3367.             } else if (vartab[y].kwval == VN_IBUF || /* \v(input) */
  3368.                    vartab[y].kwval == VN_QUE) {  /* \v(query) */
  3369.             int r = 12;    /* This one can wrap around */
  3370.             char buf[10];
  3371.             while (*s) {
  3372.                 if (isprint(*s)) {
  3373.                 buf[0] = *s;
  3374.                 buf[1] = NUL;
  3375.                 r++;
  3376.                 } else {
  3377.                 sprintf(buf,"\\{%d}",*s);
  3378.                 r += (int) strlen(buf);
  3379.                 }
  3380.                 if (r >= cmd_cols - 1) {
  3381.                 printf("\n");
  3382.                 r = 0;
  3383.                 i++;
  3384.                 }
  3385.                 printf("%s",buf);
  3386.                 s++;
  3387.             }
  3388.             printf("\n");
  3389.             } else
  3390.               printf("%s\n",s);
  3391.             if (++i > (cmd_rows - 3)) {    /* More than a screenful... */
  3392.             if ((y >= nvars - 1) || !askmore())
  3393.               break;
  3394.             else
  3395.               i = 0;
  3396.             }
  3397.         }
  3398.         }
  3399.             break;
  3400.  
  3401.         case SHVAR:            /* Global variables */
  3402.         x = 0;            /* Variable count */
  3403.         slc = 1;            /* Screen line count for "more?" */
  3404.         for (y = 33; y < GVARS; y++)
  3405.           if (g_var[y]) {
  3406.           if (x++ == 0) printf("Global variables:\n");
  3407.           sprintf(line," \\%%%c",y);
  3408.           if (shomac(line,g_var[y]) < 0) break;
  3409.           }
  3410.         if (!x) printf(" No variables defined\n");
  3411.         break;
  3412.  
  3413.         case SHARG:            /* Args */
  3414.         if (maclvl > -1) {
  3415.         printf("Macro arguments at level %d\n",maclvl);
  3416.         for (y = 0; y < 10; y++)
  3417.           if (m_arg[maclvl][y])
  3418.             printf(" \\%%%d = %s\n",y,m_arg[maclvl][y]);
  3419.         } else {
  3420.         printf(" No macro arguments at top level\n");
  3421.         }
  3422.         break;
  3423.  
  3424.         case SHARR:            /* Arrays */
  3425.         x = 0;
  3426.         for (y = 0; y < 27; y++)
  3427.           if (a_ptr[y]) {
  3428.           if (x == 0) printf("Declared arrays:\n");
  3429.           x = 1;
  3430.           printf(" \\&%c[%d]\n",(y == 0) ? 64 : y + 96, a_dim[y]);
  3431.           }
  3432.         if (!x) printf(" No arrays declared\n");
  3433.         break;
  3434. #endif /* NOSPL */
  3435.  
  3436.     case SHPRO:            /* Protocol parameters */
  3437.         shoparp();
  3438. #ifdef XFRCAN
  3439.         printf("\n Cancellation: %s",showoff(xfrcan));
  3440.         if (xfrcan) printf(" %d %d\n", xfrchr, xfrnum);
  3441.         else printf("\n");
  3442. #endif /* XFRCAN */
  3443.         printf(" Send / Receive Pause:   %d (msec)\n\n",pktpaus);
  3444.         break;
  3445.  
  3446.     case SHCOM:            /* Communication parameters */
  3447.         printf("\n");
  3448.         shoparc();
  3449. #ifndef NODIAL
  3450.         printf("\n");
  3451. #ifdef NETCONN
  3452.         if (!network)
  3453. #endif /* NETCONN */
  3454.           shodial();
  3455. #endif /* NODIAL */
  3456.         printf("\n");
  3457. #ifdef NETCONN
  3458.         if (!network) {
  3459. #endif /* NETCONN */
  3460.         shomdm();
  3461.         printf("\n");
  3462. #ifdef NETCONN
  3463.         }
  3464. #endif /* NETCONN */
  3465.         break;
  3466.  
  3467.     case SHFIL:            /* File parameters */
  3468.         shoparf();
  3469.         printf("\n");
  3470.         break;
  3471.  
  3472. #ifndef NOCSETS
  3473.     case SHLNG:            /* Languages */
  3474.         shoparl();
  3475.         break;
  3476. #endif /* NOCSETS */
  3477.  
  3478. #ifndef NOSPL
  3479.     case SHSCR:            /* Scripts */
  3480.         printf(" Command Quoting: %s\n", showoff(cmdgquo()));
  3481.         printf(" Take  Echo:      %s\n", showoff(techo));
  3482.         printf(" Take  Error:     %s\n", showoff(takerr[cmdlvl]));
  3483.         printf(" Macro Echo:      %s\n", showoff(mecho));
  3484.         printf(" Macro Error:     %s\n", showoff(merror[cmdlvl]));
  3485.         printf(" Input Case:      %s\n", inpcas[cmdlvl] ?
  3486.            "Observe" : "Ignore");
  3487.         printf(" Input Echo:      %s\n", showoff(inecho));
  3488.             printf(" Input Silence:   %d (seconds)\n", insilence);
  3489.         printf(" Input Timeout:   %s\n", intime[cmdlvl] ?
  3490.            "quit" : "proceed");
  3491.         printf(" Output Pacing:   %d (milliseconds)\n",pacing);
  3492. #ifndef NOSCRIPT
  3493.         printf(" Script Echo:     %s\n", showoff(secho));
  3494. #endif /* NOSCRIPT */
  3495.         break;
  3496. #endif /* NOSPL */
  3497.  
  3498. #ifndef NOXMIT
  3499.       case SHXMI:
  3500.         printf(" File type: %s\n", binary ? "binary" : "text");
  3501. #ifndef NOCSETS
  3502.         shotcs(tcsl,tcsr);
  3503. #endif /* NOCSETS */
  3504.         printf(" Terminal echo: %s\n", duplex ? "local" : "remote");
  3505.             printf(" Transmit EOF: ");
  3506.         if (*xmitbuf == NUL) {
  3507.         printf("none\n");
  3508.         } else {
  3509.         char *p;
  3510.         p = xmitbuf;
  3511.         while (*p) {
  3512.             if (*p < SP)
  3513.               printf("^%c",ctl(*p));
  3514.             else
  3515.               printf("%c",*p);
  3516.             p++;
  3517.         }
  3518.         printf("\n");
  3519.         }
  3520.         if (xmitf)
  3521.           printf(" Transmit Fill: %d (fill character for blank lines)\n",
  3522.            xmitf);
  3523.         else printf(" Transmit Fill: none\n");
  3524.         printf(" Transmit Linefeed: %s\n",
  3525.            xmitl ? "on (send linefeeds too)" : "off");
  3526.         if (xmitp) 
  3527.           printf(" Transmit Prompt: %d (host line end character)\n",xmitp);
  3528.         else printf(" Transmit Prompt: none\n");
  3529.         printf(" Transmit Echo: %s\n", showoff(xmitx));
  3530.         printf(" Transmit Locking-Shift: %s\n", showoff(xmits));
  3531.         printf(" Transmit Pause: %d milliseconds\n", xmitw);
  3532.         break;
  3533. #endif /* NOXMIT */
  3534.  
  3535.       case SHMOD:            /* SHOW MODEM */
  3536.         shmdmlin();
  3537.         printf("\n");
  3538. #ifdef NETCONN
  3539.         if (!network)
  3540. #endif /* NETCONN */
  3541.           shomdm();
  3542.         break;
  3543.  
  3544. #ifndef MAC
  3545.           case SHDFLT:
  3546.         zsyscmd(PWDCMD);
  3547.             break;
  3548. #endif /* MAC */
  3549.  
  3550. #ifndef NOLOCAL
  3551.           case SHESC:
  3552.         printf(" Escape character: Ctrl-%c (ASCII %d, %s)\r\n",
  3553.            ctl(escape), escape, (escape == 127 ? "DEL" : ccntab[escape]));
  3554.         break;
  3555. #endif /* NOLOCAL */
  3556.  
  3557. #ifndef NODIAL
  3558.       case SHDIA:
  3559.         shmdmlin();
  3560.         printf(", speed: ");
  3561.         if ((zz = ttgspd()) < 0) {
  3562.         printf("unknown\n");
  3563.         } else {
  3564.         if (zz == 8880) printf("75/1200\n"); else printf("%ld\n",zz);
  3565.         }
  3566.         doshodial();
  3567.         if (carrier == CAR_OFF) s = "off";
  3568.         else if (carrier == CAR_ON) s = "on";
  3569.         else if (carrier == CAR_AUT) s = "auto";
  3570.         else s = "unknown";
  3571.         printf(" Carrier: %s", s);
  3572.         if (carrier == CAR_ON) {
  3573.         if (cdtimo) printf(", timeout: %d sec", cdtimo);
  3574.         else printf(", timeout: none");
  3575.         }
  3576.         if (local
  3577. #ifdef NETCONN
  3578.         && !network
  3579. #endif /* NETCONN */
  3580.         ) {
  3581.         printf("\n%s modem signals:\n",ttname);
  3582.         shomdm();
  3583.         } else printf("\n");
  3584.         break;
  3585. #endif /* NODIAL */
  3586.  
  3587. #ifdef CK_LABELED
  3588.     case SHLBL:            /* Labeled file info */
  3589.         sholbl();
  3590.         break;
  3591. #endif /* CK_LABELED */
  3592.  
  3593.     case SHCSE:            /* Character sets */
  3594. #ifdef NOCSETS
  3595.         printf(
  3596. " Character set translation is not supported in this version of C-Kermit\n");
  3597. #else
  3598.         shocharset();
  3599.             printf("\n Unknown-Char-Set: %s\n",
  3600.            unkcs ? "Keep" : "Discard");
  3601.         shotcs(tcsl,tcsr);
  3602.         printf("\n");
  3603. #endif /* NOCSETS */
  3604.         break;
  3605.  
  3606. #ifndef NOFRILLS
  3607.       case SHFEA:            /* Features */
  3608.         shofea();
  3609.         break;
  3610. #endif /* NOFRILLS */
  3611.  
  3612. #ifdef CK_SPEED
  3613.       case SHCTL:            /* Control-Prefix table */
  3614.         shoctl();
  3615.         break;
  3616. #endif /* CK_SPEED */
  3617.  
  3618.       case SHEXI:
  3619.         printf("\n EXIT WARNING %s\n", xitwarn ? "ON" : "OFF");
  3620.         printf(" Current EXIT status: %d\n\n", xitsta);
  3621.         break;
  3622.  
  3623. #ifdef OS2
  3624.       case SHPRT:
  3625.         printf("Printer: %s\n", printfile ? printfile : "PRN");
  3626.         break;
  3627. #endif /* OS2 */
  3628.  
  3629.       case SHCMD:
  3630.         printf(" Command bytesize: %d bits\n",
  3631.            (cmdmsk == 0377) ? 8 : 7);
  3632. #ifdef CK_RECALL
  3633.         printf(" Command recall-buffer-size: %d\n",cm_recall);
  3634. #else
  3635.         printf(" Command recall-buffer not available in this version\n");
  3636. #endif /* CK_RECALL */
  3637. #ifdef CM_RETRY
  3638.         printf(" Command retry: %s\n",cm_retry ? "on" : "off");
  3639. #else
  3640.         printf(" Command retry not available in this version\n");
  3641. #endif /* CM_RETRY */
  3642.         printf(" Command quoting: %s\n", showoff(cmdgquo()));
  3643. #ifdef UNIX
  3644. #ifndef NOJC
  3645.         printf(" Suspend: %s\n", showoff(suspend));
  3646. #endif /* NOJC */
  3647. #endif /* UNIX */
  3648.         break;
  3649.  
  3650.     default:
  3651.         printf("\nNothing to show...\n");
  3652.         return(-2);
  3653.     }
  3654.     return(success = 1);
  3655. }
  3656.  
  3657. VOID
  3658. shmdmlin() {                /* Briefly show modem & line */
  3659. #ifndef NODIAL
  3660.     int i;
  3661. #ifndef MINIDIAL
  3662.     extern int tbmodel;
  3663.     _PROTOTYP( char * gtbmodel, (void) );
  3664. #endif /* MINIDIAL */
  3665. #endif /* NODIAL */
  3666.     if (local)
  3667.       printf(" Line: %s, Modem: ",ttname);
  3668.     else
  3669.       printf(" Communication device not yet selected with SET LINE\n Modem: ");
  3670. #ifndef NODIAL
  3671.     for (i = 0; i < nmdm; i++) {
  3672.     if (mdmtab[i].kwval == mdmtyp) {
  3673.         if (!strcmp(mdmtab[i].kwd,"courier"))
  3674.           printf("courier or sportster");
  3675.         else
  3676.           printf("%s",mdmtab[i].kwd);
  3677.         break;
  3678.     }
  3679.     }
  3680. #ifndef MINIDIAL
  3681.     if (tbmodel) printf(" (%s)",gtbmodel()); /* Telebit model info */
  3682. #endif /* MINIDIAL */
  3683. #else
  3684.     printf("(disabled)");
  3685. #endif /* NODIAL */
  3686. }
  3687. #endif /* NOSHOW */
  3688.  
  3689. #ifdef GEMDOS
  3690. isxdigit(c) int c; {
  3691.     return(isdigit(c) ||
  3692.        (c >= 'a' && c <= 'f') ||
  3693.        (c >= 'A' && c <= 'F'));
  3694. }
  3695. #endif /* GEMDOS */
  3696.  
  3697. #ifndef NOSHOW
  3698. #ifndef NOSPL
  3699. int                    /* SHO MACROS */
  3700. shomac(s1, s2) char *s1, *s2; {
  3701.     int x, n, pp;
  3702.     pp = 0;                /* Parenthesis counter */
  3703.  
  3704.     if (!s1)
  3705.       return(0);
  3706.     else
  3707.       printf("\n%s = ",s1);        /* Print blank line and macro name */
  3708.     slc++;                /* Count the line */
  3709.     n = (int)strlen(s1) + 4;        /* Width of current line */
  3710.     if (!s2) s2 = "(null definition)";
  3711.  
  3712.     while (x = *s2++) {            /* Loop thru definition */
  3713.     if (x == '(') pp++;        /* Treat commas within parens */
  3714.     if (x == ')') pp--;        /* as ordinary text */
  3715.     if (pp < 0) pp = 0;        /* Outside parens, */
  3716.     if (x == ',' && pp == 0) {    /* comma becomes comma-dash-NL. */
  3717.         putchar(',');
  3718.         putchar('-');
  3719.         x = '\n';
  3720.     }
  3721.     putchar(x);            /* Output the character */
  3722.     if (x == '\n') {        /* If it was a newline */
  3723. #ifdef UNIX
  3724. #ifdef NOSETBUF
  3725.         fflush(stdout);
  3726. #endif /* NOSETBUF */
  3727. #endif /* UNIX */
  3728.         putchar(' ');        /* Indent the next line 1 space */
  3729.         while(*s2 == ' ') s2++;    /* skip past leading blanks */
  3730.         n = 2;            /* restart the character counter */
  3731.         slc++;            /* and increment the line counter. */
  3732.     } else if (++n > (cmd_cols - 1)) { /* If line is too wide */
  3733.         putchar('-');        /* output a dash */
  3734.         putchar(NL);        /* and a newline */
  3735. #ifdef UNIX
  3736. #ifdef NOSETBUF
  3737.         fflush(stdout);
  3738. #endif /* NOSETBUF */
  3739. #endif /* UNIX */
  3740.         n = 1;            /* and restart the char counter */
  3741.         slc++;            /* and increment the line counter */
  3742.     }
  3743.     if (n < 3 && slc > (cmd_rows - 3)) { /* If new line and screen full */
  3744.         if (!askmore()) return(-1);    /* ask if they want more. */
  3745.         n = 1;            /* They do, start a new line */
  3746.         slc = 0;            /* and restart line counter */
  3747.     }
  3748.     }
  3749.     putchar(NL);            /* End of definition */
  3750.     if (++slc > (cmd_rows - 3)) {
  3751.     if (!askmore()) return(-1);
  3752.     slc = 0;
  3753.     }
  3754.     return(0);
  3755. }
  3756. #endif /* NOSPL */
  3757. #endif /* NOSHOW */
  3758.  
  3759. #ifndef NOSHOW
  3760. int
  3761. shoatt() {
  3762.     printf("Attributes: %s\n", showoff(atcapr));
  3763.     if (!atcapr) return(0);
  3764.     printf(" Blocksize: %s\n", showoff(atblki));
  3765.     printf(" Date: %s\n", showoff(atdati));
  3766.     printf(" Disposition: %s\n", showoff(atdisi));
  3767.     printf(" Encoding (Character Set): %s\n", showoff(atenci));
  3768.     printf(" Length: %s\n", showoff(atleni));
  3769.     printf(" Type (text/binary): %s\n", showoff(attypi));
  3770.     printf(" System ID: %s\n", showoff(atsidi));
  3771.     printf(" System Info: %s\n", showoff(atsysi));
  3772. #ifdef STRATUS
  3773.     printf(" Format: %s\n", showoff(atfrmi));
  3774.     printf(" Creator: %s\n", showoff(atcrei));
  3775.     printf(" Account: %s\n", showoff(atacti));
  3776. #endif /* STRATUS */
  3777.     return(0);
  3778. }
  3779. #endif /* NOSHOW */
  3780.  
  3781. #ifndef NOSPL
  3782. /* Evaluate an arithmetic expression. */
  3783. /* Code adapted from ev, by Howie Kaye of Columbia U & others. */
  3784.  
  3785. static int xerror;
  3786. static char *cp;
  3787. static long tokval;
  3788. static char curtok;
  3789. static long expval;
  3790.  
  3791. #define LONGBITS (8*sizeof (long))
  3792. #define NUMBER 'N'
  3793. #define EOT 'E'
  3794.  
  3795. /*
  3796.  Replacement for strchr() and index(), neither of which seem to be universal.
  3797. */
  3798.  
  3799. static char *
  3800. #ifdef CK_ANSIC
  3801. windex(char * s, char c)
  3802. #else
  3803. windex(s,c) char *s, c;
  3804. #endif /* CK_ANSIC */
  3805. /* windex */ {
  3806.     while (*s != NUL && *s != c) s++;
  3807.     if (*s == c) return(s); else return(NULL);
  3808. }
  3809.  
  3810. /*
  3811.  g e t t o k
  3812.  
  3813.  Returns the next token.  If token is a NUMBER, sets tokval appropriately.
  3814. */
  3815. static char
  3816. gettok() {
  3817.     while (isspace(*cp)) cp++ ;
  3818.     switch(*cp) {
  3819.       case '$':                /* ??? */
  3820.       case '+':                /* Add */
  3821.       case '-':                /* Subtract or Negate */
  3822.       case '@':                /* Greatest Common Divisor */
  3823.       case '*':                /* Multiply */
  3824.       case '/':                /* Divide */
  3825.       case '%':                /* Modulus */
  3826.       case '<':                /* Left shift */
  3827.       case '>':                /* Right shift */
  3828.       case '&':                /* And */
  3829.       case '|':                /* Or */
  3830.       case '#':                /* Exclusive Or */
  3831.       case '~':                /* Not */
  3832.       case '^':                /* Exponent */
  3833.       case '!':                /* Factorial */
  3834.       case '(':                /* Parens for grouping */
  3835.       case ')': return(*cp++);        /* operator, just return it */
  3836.       case '\n':
  3837.       case '\0': return(EOT);        /* end of line, return that */
  3838.     }
  3839.     if (isxdigit(*cp)) {        /* digit, must be a number */
  3840.     char tbuf[80],*tp;        /* buffer to accumulate number */
  3841.     int radix = 10;            /* default radix */
  3842.     for (tp=tbuf; isxdigit(*cp); cp++)
  3843.       *tp++ = isupper(*cp) ? tolower(*cp) : *cp;
  3844.     *tp = '\0';            /* end number */
  3845.     switch(isupper(*cp) ? tolower(*cp) : *cp) { /* examine break char */
  3846.       case 'h':
  3847.       case 'x': radix = 16; cp++; break; /* if radix signifier... */
  3848.       case 'o':
  3849.       case 'q': radix = 8; cp++; break;
  3850.       case 't': radix = 2; cp++; break;
  3851.     }
  3852.     for (tp=tbuf,tokval=0; *tp != '\0'; tp++)  {
  3853.         int dig;
  3854.         dig = *tp - '0';        /* convert number */
  3855.         if (dig > 10) dig -= 'a'-'0'-10;
  3856.         if (dig >= radix) {
  3857.         xerror = 1;
  3858.         if (cmdlvl == 0)
  3859.           printf("invalid digit '%c' in number\n",*tp);
  3860.         return(NUMBER);
  3861.         }
  3862.         tokval = radix*tokval + dig;
  3863.     }
  3864.     return(NUMBER);
  3865.     }
  3866.     if (cmdlvl == 0)
  3867.       printf("Invalid character '%c' in input\n",*cp);
  3868.     xerror = 1;
  3869.     cp++;
  3870.     return(gettok());
  3871. }
  3872.  
  3873. static long
  3874. #ifdef CK_ANSIC
  3875. expon(long x, long y)
  3876. #else
  3877. expon(x,y) long x,y;
  3878. #endif /* CK_ANSIC */
  3879. /* expon */ {
  3880.     long result = 1;
  3881.     int sign = 1;
  3882.     if (y < 0) return(0);
  3883.     if (x < 0) {
  3884.     x = -x;
  3885.     if (y & 1) sign = -1;
  3886.     }
  3887.     while (y != 0) {
  3888.     if (y & 1) result *= x;
  3889.     y >>= 1;
  3890.     if (y != 0) x *= x;
  3891.   }
  3892.   return(result * sign);
  3893. }
  3894.  
  3895. /*
  3896.  * factor ::= simple | simple ^ factor
  3897.  *
  3898.  */
  3899. _PROTOTYP( static VOID simple, (void) );
  3900.  
  3901. static VOID
  3902. factor() {
  3903.     long oldval;
  3904.     simple();
  3905.     if (curtok == '^') {
  3906.     oldval = expval;
  3907.     curtok = gettok();
  3908.     factor();
  3909.     expval = expon(oldval,expval);
  3910.     }
  3911. }
  3912.  
  3913. /*
  3914.  * termp ::= NULL | {*,/,%,&} factor termp
  3915.  *
  3916.  */
  3917. static VOID
  3918. termp() {
  3919.     while (curtok == '*' || curtok == '/' || curtok == '%' || curtok == '&') {
  3920.     long oldval;
  3921.     char op;
  3922.     op = curtok;
  3923.     curtok = gettok();        /* skip past operator */
  3924.     oldval = expval;
  3925.     factor();
  3926.     switch(op) {
  3927.       case '*': expval = oldval * expval; break;
  3928.       case '/':
  3929.         if (expval == 0) expval = -1; /* don't divide by 0 */
  3930.         else expval = oldval / expval; break;
  3931.       case '%': expval = oldval % expval; break;
  3932.       case '&': expval = oldval & expval; break;
  3933.     }
  3934.     }
  3935. }
  3936.  
  3937. static long
  3938. #ifdef CK_ANSIC
  3939. fact(long x)
  3940. #else
  3941. fact(x) long x;
  3942. #endif /* CK_ANSIC */
  3943. /* fact */ {                /* factorial */
  3944.     long result = 1;
  3945.     while (x > 1)
  3946.       result *= x--;
  3947.     return(result);
  3948. }
  3949.  
  3950. /*
  3951.  * term ::= factor termp
  3952.  *
  3953.  */
  3954. static VOID
  3955. term() {
  3956.     factor();
  3957.     termp();
  3958. }
  3959.  
  3960. static long
  3961. #ifdef CK_ANSIC
  3962. gcd(long x, long y)
  3963. #else
  3964. gcd(x,y) long x,y;
  3965. #endif /* CK_ANSIC */
  3966. /* gcd */ {                /* Greatest Common Divisor */
  3967.     int nshift = 0;
  3968.     if (x < 0) x = -x;
  3969.     if (y < 0) y = -y;            /* validate arguments */
  3970.     if (x == 0 || y == 0) return(x + y);    /* this is bogus */
  3971.     
  3972.     while (!((x & 1) | (y & 1))) {    /* get rid of powers of 2 */
  3973.     nshift++;
  3974.     x >>= 1;
  3975.     y >>= 1;
  3976.     }
  3977.     while (x != 1 && y != 1 && x != 0 && y != 0) {
  3978.     while (!(x & 1)) x >>= 1;    /* eliminate unnecessary */
  3979.     while (!(y & 1)) y >>= 1;    /* powers of 2 */
  3980.     if (x < y) {            /* force x to be larger */
  3981.         long t;
  3982.         t = x;
  3983.         x = y;
  3984.         y = t;
  3985.     }
  3986.     x -= y;
  3987.     }
  3988.     if (x == 0 || y == 0) return((x + y) << nshift); /* gcd is non-zero one */
  3989.     else return((long) 1 << nshift);    /* else gcd is 1 */
  3990. }
  3991.  
  3992. /*
  3993.  * exprp ::= NULL | {+,-,|,...} term exprp
  3994.  *
  3995.  */
  3996. static VOID
  3997. exprp() {
  3998.     while (windex("+-|<>#@",curtok) != NULL) {
  3999.     long oldval;
  4000.     char op;
  4001.     op = curtok;
  4002.     curtok = gettok();        /* skip past operator */
  4003.     oldval = expval;
  4004.     term();
  4005.     switch(op) {
  4006.       case '+' : expval = oldval + expval; break;
  4007.       case '-' : expval = oldval - expval; break;
  4008.       case '|' : expval = oldval | expval; break;
  4009.       case '#' : expval = oldval ^ expval; break;
  4010.       case '@' : expval = gcd(oldval,expval); break;
  4011.       case '<' : expval = oldval << expval; break;
  4012.       case '>' : expval = oldval >> expval; break;
  4013.     }
  4014.     }
  4015. }
  4016.  
  4017. /*
  4018.  * expr ::= term exprp
  4019.  *
  4020.  */
  4021. static VOID
  4022. expr() {
  4023.     term();
  4024.     exprp();
  4025. }
  4026.  
  4027. static long
  4028. xparse() {
  4029.     curtok = gettok();
  4030.     expr();
  4031. #ifdef COMMENT
  4032.     if (curtok == '$') {
  4033.     curtok = gettok();
  4034.     if (curtok != NUMBER) {
  4035.         if (cmdlvl == 0) printf("illegal radix\n");
  4036.         return(0);
  4037.     }
  4038.     curtok = gettok();
  4039.     }
  4040. #endif /* COMMENT */
  4041.     if (curtok != EOT) {
  4042.     if (cmdlvl == 0)
  4043.       printf("extra characters after expression\n");
  4044.     xerror = 1;
  4045.     }
  4046.     return(expval);
  4047. }
  4048.  
  4049. char *
  4050. evala(s) char *s; {
  4051.     char *p;                /* Return pointer */
  4052.     long v;                /* Numeric value */
  4053.  
  4054.     xerror = 0;                /* Start out with no error */
  4055.     cp = s;                /* Make the argument global */
  4056.     v = xparse();            /* Parse the string */
  4057.     p = numbuf;                /* Convert long number to string */
  4058.     sprintf(p,"%ld",v);
  4059.     return(xerror ? "" : p);        /* Return empty string on error */
  4060. }
  4061.  
  4062. /*
  4063.  * simplest ::= NUMBER | ( expr )
  4064.  *
  4065.  */
  4066. static VOID
  4067. simplest() {
  4068.     if (curtok == NUMBER) expval = tokval;
  4069.     else if (curtok == '(') {
  4070.     curtok = gettok();        /* skip over paren */
  4071.     expr();
  4072.     if (curtok != ')') {
  4073.         if (cmdlvl == 0) printf("missing right parenthesis\n");
  4074.         xerror = 1;
  4075.     }
  4076.     }
  4077.     else {
  4078.     if (cmdlvl == 0) printf("operator unexpected\n");
  4079.     xerror = 1;
  4080.     }
  4081.     curtok = gettok();
  4082. }
  4083.  
  4084. /*
  4085.  * simpler ::= simplest | simplest !
  4086.  *
  4087.  */
  4088. static VOID
  4089. simpler() {
  4090.     simplest();
  4091.     if (curtok == '!') {
  4092.     curtok = gettok();
  4093.     expval = fact(expval);
  4094.     }
  4095. }
  4096.  
  4097. /*
  4098.  * simple ::= {-,~} simpler | simpler
  4099.  *
  4100.  */
  4101.  
  4102. static VOID
  4103. simple() {
  4104.     if (curtok == '-' || curtok == '~') {
  4105.     int op = curtok;
  4106.     curtok = gettok();        /* skip over - sign */
  4107.     simpler();            /* parse the factor again */
  4108.     expval = op == '-' ? -expval : ~expval;
  4109.     } else simpler();
  4110. }
  4111. #endif /* NOSPL */
  4112.  
  4113. #ifndef NOSPL
  4114. /*  D C L A R R A Y  --  Declare an array  */
  4115.  
  4116. int                    /* Declare an array of size n */
  4117. #ifdef CK_ANSIC
  4118. dclarray(char a, int n)
  4119. #else
  4120. dclarray(a,n) char a; int n;
  4121. #endif /* CK_ANSIC */
  4122. /* dclarray */ {
  4123.     char **p; int i, n2;
  4124.  
  4125.     if (a > 63 && a < 96) a += 32;    /* Convert to lowercase */
  4126.     if (a < 96 || a > 122) return(-1);    /* Verify name */
  4127.     a -= 96;                /* Convert name to number */
  4128.     if ((p = a_ptr[a]) != NULL) {    /* Delete old array of same name */
  4129.     n2 = a_dim[a];
  4130.     for (i = 0; i <= n2; i++)    /* First delete its elements */
  4131.       if (p[i]) free(p[i]);
  4132.     free(a_ptr[a]);            /* Then the element list */
  4133.     a_ptr[a] = (char **) NULL;    /* Remove pointer to element list */
  4134.     a_dim[a] = 0;            /* Set dimension at zero. */
  4135.     }
  4136.     if (n == 0) return(0);        /* If dimension 0, just deallocate. */
  4137.  
  4138.     p = (char **) malloc((n+1) * sizeof(char **)); /* Allocate for new array */
  4139.     if (p == NULL) return(-1);        /* Check */
  4140.     a_ptr[a] = p;            /* Save pointer to member list */
  4141.     a_dim[a] = n;            /* Save dimension */
  4142.     for (i = 0; i <= n; i++)        /* Initialize members to null */
  4143.       p[i] = NULL;
  4144.     return(0);
  4145. }
  4146.  
  4147. /*  A R R A Y N A M  --  Parse an array name  */
  4148.  
  4149. /*
  4150.   Call with pointer to string that starts with the array reference.
  4151.   String may begin with either \& or just &.
  4152.   On success,
  4153.     Returns letter ID (always lowercase) in argument c,
  4154.       which can also be accent grave (` = 96; '@' is converted to grave);
  4155.     Dimension or subscript in argument n;
  4156.     IMPORTANT: These arguments must be provided by the caller as addresses
  4157.     of ints (not chars), for example:
  4158.       char *s; int x, y;
  4159.       arraynam(s,&x,&y);
  4160.   On failure, returns a negative number, with args n and c set to zero.
  4161. */
  4162. int
  4163. arraynam(ss,c,n) char *ss; int *c; int *n; {
  4164.     int i, y, pp;
  4165.     char x;
  4166.     char *s, *p, *sx, *vnp;
  4167.     char vnbuf[VNAML+1];        /* On stack to allow for */
  4168.     char ssbuf[VNAML+1];        /* recursive calls... */
  4169.     char sxbuf[VNAML+1];
  4170.  
  4171.     *c = *n = 0;            /* Initialize return values */
  4172.     for (i = 0; i < (int)strlen(ss); i++) /* Check length */
  4173.       if (ss[i] == ']')
  4174.     break;
  4175.     if (i > VNAML) {
  4176.     printf("?Array reference too long - %s\n",ss);
  4177.     return(-9);
  4178.     }
  4179.     strncpy(vnbuf,ss,VNAML);
  4180.     vnp = vnbuf;
  4181.     if (vnbuf[0] == CMDQ && vnbuf[1] == '&') vnp++;
  4182.     if (*vnp != '&') {
  4183.     printf("?Not an array - %s\n",vnbuf);
  4184.     return(-9);
  4185.     }
  4186.     x = *(vnp + 1);            /* Fold case of array name */
  4187.     /* We don't use isupper & tolower here on purpose because these */
  4188.     /* would produce undesired effects with accented letters. */
  4189.     if (x > 63 && x < 91) x  = *(vnp +1) = x + 32;
  4190.     if ((x < 96) || (x > 122) || (*(vnp+2) != '[')) {
  4191.     printf("?Invalid format for array name - %s\n",vnbuf);
  4192.     return(-9);
  4193.     }
  4194.     *c = x;                /* Return the array name */
  4195.     s = vnp+3;                /* Get dimension */
  4196.     p = ssbuf;    
  4197.     pp = 1;                /* Bracket counter */
  4198.     for (i = 0; i < VNAML && *s != NUL; i++) { /* Copy up to ] */
  4199.     if (*s == '[') pp++;
  4200.     if (*s == ']' && --pp == 0) break;
  4201.     *p++ = *s++;
  4202.     }
  4203.     if (*s != ']') {
  4204.     printf("?No closing bracket on array dimension - %s\n",vnbuf);
  4205.     return(-9);
  4206.     }
  4207.     *p = NUL;                /* Terminate subscript with null */
  4208.     p = ssbuf;                /* Point to beginning of subscript */
  4209.     sx = sxbuf;                /* Where to put expanded subscript */
  4210.     y = VNAML-1;
  4211.     zzstring(p,&sx,&y);            /* Convert variables, etc. */
  4212.     if (!chknum(sxbuf)) {        /* Make sure it's all digits */
  4213.     printf("?Array dimension or subscript must be numeric - %s\n",sxbuf);
  4214.     return(-9);
  4215.     }
  4216.     if ((y = atoi(sxbuf)) < 0) {
  4217.         if (cmflgs == 0) printf("\n");
  4218.         printf("?Array dimension or subscript must be positive or zero - %s\n",
  4219.            sxbuf);
  4220.     return(-9);
  4221.     }
  4222.     *n = y;                /* Return the subscript or dimension */
  4223.     return(0);
  4224. }
  4225.  
  4226. int
  4227. chkarray(a,i) int a, i; {        /* Check if array is declared */
  4228.     int x;                /* and if subscript is in range */
  4229.     if (a == 64) a = 96;        /* Convert atsign to grave accent */
  4230.     x = a - 96;                /* Values must be in range 96-122 */
  4231.     if (x < 0 || x > 26) return(-2);    /* Not in range */
  4232.     if (a_ptr[x] == NULL) return(-1);    /* Not declared */
  4233.     if (i > a_dim[x]) return(-2);    /* Declared but out of range. */
  4234.     return(a_dim[x]);            /* All ok, return dimension */
  4235. }
  4236.  
  4237. char *
  4238. arrayval(a,i) int a, i; {        /* Return value of \&a[i] */
  4239.     int x; char **p;            /* (possibly NULL) */
  4240.  
  4241.     if (a == 64) a = 96;        /* Convert atsign to grave accent */
  4242.     x = a - 96;                /* Values must be in range 96-122 */
  4243.     if (x < 0 || x > 26) return(NULL);    /* Not in range */
  4244.     if ((p = a_ptr[x]) == NULL)        /* Array not declared */
  4245.       return(NULL);
  4246.     if (i > a_dim[x])            /* Subscript out of range. */
  4247.       return(NULL);
  4248.     return(p[i]);            /* All ok, return pointer to value. */
  4249. }
  4250. #endif /* NOSPL */
  4251.  
  4252. #ifndef NOSPL
  4253. /*  P A R S E V A R  --  Parse a variable name or array reference.  */
  4254. /*
  4255.  Call with:
  4256.    s  = pointer to candidate variable name or array reference.
  4257.    *c = address of integer in which to return variable ID.
  4258.    *i = address of integer in which to return array subscript.
  4259.  Returns:
  4260.    -2:  syntax error in variable name or array reference.
  4261.     1:  successful parse of a simple variable, with ID in c.
  4262.     2:  successful parse of an array reference, w/ID in c and subscript in i.
  4263. */
  4264. int
  4265. parsevar(s,c,i) char *s; int *c, *i; {
  4266.     char *p;
  4267.     int x,y,z;
  4268.  
  4269.     p = s;
  4270.     if (*s == CMDQ) s++;        /* Point after backslash */
  4271.  
  4272.     if (*s != '%' && *s != '&') {    /* Make sure it's % or & */
  4273.     printf("?Not a variable name - %s\n",p);
  4274.     return(-9);
  4275.     }
  4276.     if ((int)strlen(s) < 2) {
  4277.     printf("?Incomplete variable name - %s\n",p);
  4278.     return(-9);
  4279.     }
  4280.     if (*s == '%' && *(s+2) != '\0') {
  4281.     printf("?Only one character after '%%' in variable name, please\n");
  4282.     return(-9);
  4283.     }
  4284.     if (*s == '&' && *(s+2) != '[') {
  4285.     printf("?Array subscript expected - %s\n",p);
  4286.     return(-9);
  4287.     }
  4288.     if (*s == '%') {            /* Simple variable. */
  4289.     y = *(s+1);            /* Get variable ID letter/char */
  4290.     if (isupper(y)) y -= ('a'-'A');    /* Convert upper to lower case */
  4291.     *c = y;                /* Set the return values. */
  4292.     *i = -1;            /* No array subscript. */
  4293.     return(1);            /* Return 1 = simple variable */
  4294.     }
  4295.     if (*s == '&') {            /* Array reference. */
  4296.     if (arraynam(s,&x,&z) < 0) { /* Go parse it. */
  4297.         printf("?Invalid array reference - %s\n",p);
  4298.         return(-9);
  4299.     }
  4300.     if (chkarray(x,z) < 0) {    /* Check if declared, etc. */
  4301.         printf("?Array not declared or subscript out of range\n");
  4302.         return(-9);
  4303.     }
  4304.     *c = x;                /* Return array letter */
  4305.     *i = z;                /* and subscript. */
  4306.     return(2);
  4307.     }    
  4308.     return(-2);                /* None of the above. */
  4309. }
  4310.  
  4311. #define VALN 20
  4312.  
  4313. /* Get the numeric value of a variable */
  4314. /*
  4315.   Call with pointer to variable name, pointer to int for return value.
  4316.   Returns:
  4317.     0 on success with second arg containing the value.
  4318.    -1 on failure (bad variable syntax, variable not defined or not numeric).
  4319. */
  4320. int
  4321. varval(s,v) char *s; int *v; {
  4322.     char valbuf[VALN+1];        /* s is pointer to variable name */
  4323.     char *p;
  4324.     int y;
  4325.  
  4326.     p = valbuf;                /* Expand variable into valbuf. */
  4327.     y = VALN;
  4328.     if (zzstring(s,&p,&y) < 0) return(-1);
  4329.     p = valbuf;                /* Make sure value is numeric */
  4330.     if (!chknum(p)) return(-1);
  4331.     *v = atoi(p);            /* Convert numeric string to int */
  4332.     return(0);    
  4333. }
  4334.  
  4335. /* Increment or decrement a variable */
  4336. /* Returns -1 on failure, 0 on success, with 4th argument set to result */
  4337.  
  4338. int
  4339. incvar(s,x,z,r) char *s; int x, z, *r; { /* Increment a numeric variable */
  4340.     char valbuf[VALN+1];        /* s is pointer to variable name */
  4341.                     /* x is amount to increment by */
  4342.     int n;                /* z != 0 means add */
  4343.                     /* z = 0 means subtract */
  4344.  
  4345.     if (varval(s,&n) < 0)        /* Convert numeric string to int */
  4346.       return(-1);
  4347.     if (z)                /* Increment it by the given amount */
  4348.       n += x;
  4349.     else                /* or decrement as requested. */
  4350.       n -= x;
  4351.     sprintf(valbuf,"%d",n);        /* Convert back to numeric string */
  4352.     addmac(s,valbuf);            /* Replace old variable */
  4353.     *r = n;                /* Return the integer value */
  4354.     return(0);
  4355. }
  4356. #endif /* NOSPL */
  4357.  
  4358. /* Functions moved here from ckuusr.c to even out the module sizes... */
  4359.  
  4360. #ifndef NOSPL                /* Need xwords() function to break */
  4361. #define XWORDS                /* string up into words. */
  4362. #endif /* NOSPL */
  4363. #ifndef NODIAL
  4364. #ifndef XWORDS
  4365. #define XWORDS
  4366. #endif /* XWORDS */
  4367. #endif /* NODIAL */
  4368.  
  4369. #ifdef XWORDS
  4370. /*
  4371.   Breaks string s up into a list of up to max words.
  4372.   Pointers to each word go into the array list[].
  4373.   If list is NULL, then they are added to the macro table.
  4374. */
  4375.  
  4376. VOID
  4377. xwords(s,max,list) char *s; int max; char *list[]; {
  4378.     char *p;
  4379.     int b, k, y, z;
  4380. #ifndef NOSPL
  4381.     int macro;
  4382.     macro = (list == NULL);
  4383.     debug(F101,"xwords macro","",macro);
  4384. #endif /* NOSPL */
  4385.  
  4386.     p = s;                /* Pointer to beginning of string */
  4387.     b = 0;                /* Flag for outer brace removal */
  4388.     k = 0;                /* Flag for in-word */
  4389.     y = 0;                /* Brace nesting level */
  4390.     z = 0;                /* Argument counter, 0 thru max */
  4391.  
  4392.     while (1) {                /* Go thru argument list */
  4393.     if (!s || (*s == '\0')) {    /* No more characters? */
  4394.         if (k != 0) {
  4395.         if (z == max) break;    /* Only go up to max. */
  4396.         z++;            /* Count it. */
  4397. #ifndef NOSPL
  4398.         if (macro) {
  4399.             varnam[1] = z + '0'; /* Assign last argument */
  4400.             addmac(varnam,p);
  4401.         } else
  4402. #endif /* NOSPL */
  4403.           list[z] = p;
  4404.         break;            /* And get out. */
  4405.         } else break;
  4406.     } 
  4407.     if (k == 0 && (*s == SP || *s == HT)) { /* Eat leading blanks */
  4408.         s++;
  4409.         continue;
  4410.     } else if (*s == '{') {        /* An opening brace */
  4411.         if (k == 0 && y == 0) {    /* If leading brace */
  4412.         p = s+1;        /* point past it */
  4413.         b = 1;            /* and flag that we did this */
  4414.         }
  4415.         k = 1;            /* Flag that we're in a word */
  4416.         y++;            /* Count the brace. */
  4417.     } else if (*s == '}') {        /* A closing brace. */
  4418.         y--;            /* Count it. */
  4419.         if (y == 0 && b != 0) {    /* If it matches the leading brace */
  4420.         *s = SP;        /* change it to a space */
  4421.         b = 0;            /* and we're not in braces any more */
  4422.         } else if (y < 0) k = 1;    /* otherwise just start a new word. */
  4423.     } else if (*s != SP && *s != HT) { /* Nonspace means we're in a word */
  4424.         if (k == 0) p = s;        /* Mark the beginning */
  4425.         k = 1;            /* Set in-word flag */
  4426.     }
  4427.     /* If we're not inside a braced quantity, and we are in a word, and */
  4428.     /* we have hit whitespace, then we have an argument to assign. */
  4429.     if ((y < 1) && (k != 0) && (*s == SP || *s == HT)) { 
  4430.         *s = '\0';            /* terminate the arg with null */
  4431.         k = 0;            /* say we're not in a word any more */
  4432.         y = 0;            /* start braces off clean again */
  4433.         if (z == max) break;    /* Only go up to max. */
  4434.         z++;            /* count this arg */
  4435. #ifndef NOSPL
  4436.         if (macro) {
  4437.         varnam[1] = z + '0';    /* compute its name */
  4438.         addmac(varnam,p);    /* add it to the macro table */
  4439.         } else
  4440. #endif /* NOSPL */
  4441.           list[z] = p;
  4442.         p = s+1;
  4443.     }
  4444.     s++;                /* Point past this character */
  4445.     }
  4446.     if ((z == 0) && (y > 1)) {        /* Extra closing brace(s) at end */
  4447.     z++;
  4448. #ifndef NOSPL
  4449.     if (macro) {
  4450.         varnam[1] = z + '0';    /* compute its name */
  4451.         addmac(varnam,p);        /* Add rest of line to last arg */
  4452.     } else
  4453. #endif /* NOSPL */
  4454.       list[z] = p;
  4455.     }
  4456. #ifndef NOSPL
  4457.     if (macro) macargc[maclvl] = z + 1;    /* Set \v(argc) variable */
  4458. #endif /* NOSPL */
  4459.     return;
  4460. }
  4461. #endif /* XWORDS */
  4462.  
  4463. #ifndef NOSPL
  4464. /* D O D O  --  Do a macro */
  4465.  
  4466. /*
  4467.   Call with x = macro table index, s = pointer to arguments.
  4468.   Returns 0 on failure, 1 on success.
  4469. */
  4470.  
  4471. int
  4472. dodo(x,s) int x; char *s; {
  4473.     int y;
  4474.  
  4475.     debug(F101,"dodo maclvl","",maclvl);
  4476.     if (++maclvl > MACLEVEL) {        /* Make sure we have storage */
  4477.         debug(F101,"dodo maclvl too deep","",maclvl);
  4478.     --maclvl;
  4479.     printf("Macros nested too deeply\n");
  4480.     return(0);
  4481.     }
  4482.     macp[maclvl] = mactab[x].mval;    /* Point to the macro body */ 
  4483.     macx[maclvl] = mactab[x].mval;    /* Remember where the beginning is */
  4484.     debug(F111,"do macro",macp[maclvl],maclvl);
  4485.  
  4486.     cmdlvl++;                /* Entering a new command level */
  4487.     if (cmdlvl > CMDSTKL) {        /* Too many macros + TAKE files? */
  4488.         debug(F101,"dodo cmdlvl too deep","",cmdlvl);
  4489.     cmdlvl--;
  4490.     printf("?TAKE files and DO commands nested too deeply\n");
  4491.     return(0);
  4492.     }
  4493. #ifdef VMS
  4494.     conres();                /* So Ctrl-C, etc, will work. */
  4495. #endif /* VMS */
  4496.     ifcmd[cmdlvl] = 0;
  4497.     iftest[cmdlvl] = 0;
  4498.     count[cmdlvl] = count[cmdlvl-1]; /* Inherit COUNT from previous level */
  4499.     intime[cmdlvl] = intime[cmdlvl-1];    /* Inherit previous INPUT TIMEOUT */
  4500.     inpcas[cmdlvl] = inpcas[cmdlvl-1];    /*   and INPUT CASE */
  4501.     takerr[cmdlvl] = takerr[cmdlvl-1];    /*   and TAKE ERROR */
  4502.     merror[cmdlvl] = merror[cmdlvl-1];    /*   and MACRO ERROR */
  4503.     cmdstk[cmdlvl].src = CMD_MD;    /* Say we're in a macro */
  4504.     cmdstk[cmdlvl].lvl = maclvl;    /* and remember the macro level */
  4505.     mrval[maclvl] = NULL;        /* Initialize return value */
  4506.  
  4507.     debug(F110,"do macro",mactab[x].kwd,0);
  4508.  
  4509. /* Clear old %0..%9 arguments */
  4510.  
  4511.     addmac("%0",mactab[x].kwd);        /* Define %0 = name of macro */
  4512.     varnam[0] = '%';
  4513.     varnam[2] = '\0';
  4514.     for (y = 1; y < 10; y++) {        /* Clear args %1..%9 */
  4515.     varnam[1] = y + '0';
  4516.     delmac(varnam);
  4517.     }    
  4518.  
  4519. /* Assign the new args one word per arg, allowing braces to group words */
  4520.  
  4521.     xwords(s,9,NULL);
  4522.     return(1);
  4523. }
  4524.  
  4525. /* Insert "literal" quote around each comma-separated command to prevent */
  4526. /* its premature expansion.  Only do this if object command is surrounded */
  4527. /* by braces. */
  4528.  
  4529. static char* flit = "\\flit(";
  4530.  
  4531. int
  4532. litcmd(src,dest) char **src, **dest; {
  4533.     int bc = 0, pp = 0;
  4534.     char *s, *lp, *ss;
  4535.  
  4536.     s = *src;
  4537.     lp = *dest;
  4538.  
  4539.     while (*s == SP) s++;        /* strip extra leading spaces */
  4540.     if (*s == '{') {
  4541.  
  4542.         pp = 0;                /* paren counter */
  4543.     bc = 1;                /* count leading brace */
  4544.     *lp++ = *s++;            /* copy it */
  4545.     while (*s == SP) s++;        /* strip interior leading spaces */
  4546.     ss = flit;            /* point to "\flit(" */
  4547.     while (*lp++ = *ss++) ;        /* copy it */
  4548.     lp--;                /* back up over null */
  4549.     while (*s) {            /* go thru rest of text */
  4550.         ss = flit;            /* point back to start of "\flit(" */
  4551.         if (*s == '{') bc++;    /* count brackets */
  4552.         if (*s == '(') pp++;    /* and parens */
  4553.         if (*s == ')') pp--;
  4554.         if (*s == '}') {        /* Closing brace. */
  4555.         if (--bc == 0) {    /* Final one? */
  4556.             *lp++ = ')';    /* Add closing paren for "\flit()" */
  4557.             *lp++ = *s++;
  4558.             break;
  4559.         }
  4560.         }
  4561.         if (*s == ',' && pp == 0) {    /* comma not inside of parens */
  4562.         *lp++ = ')';        /* closing ) of \flit( */
  4563.         *lp++ = ',';        /* insert the comma */
  4564.         while (*lp++ = *ss++) ;    /* start new "\flit(" */
  4565.         lp--;            /* back up over null */
  4566.         s++;            /* skip over comma in source string */
  4567.         while (*s++ == SP);    /* eat leading spaces again. */
  4568.         s--;            /* back up over nonspace */
  4569.         continue;
  4570.         }
  4571.             *lp++ = *s++;        /* Copy anything but comma here. */
  4572.         }
  4573.     *lp = NUL;
  4574.     } else {                /* No brackets around, */
  4575.     while (*lp++ = *s++) ;        /* just copy. */
  4576.     lp--;
  4577.     }
  4578.     *src = s;
  4579.     *dest = lp;
  4580.     if (bc) return(-1);
  4581.     else return(0);
  4582. }
  4583. #endif /* NOSPL */
  4584.  
  4585. int
  4586. docd() {                /* Do the CD command */
  4587.     int x;
  4588.     extern int quiet;
  4589.     char *s;
  4590. #ifdef MAC
  4591.     char temp[34];
  4592. #endif /* MAC */
  4593.  
  4594. #ifdef GEMDOS
  4595.     if ((x = cmdir("Name of local directory, or carriage return",homdir,&s,
  4596.            NULL)) < 0 )
  4597.       return(x);
  4598. #else
  4599. #ifdef OS2
  4600.     if ((x = cmdir("Name of PC disk and/or directory,\n\
  4601.        or press the Enter key for the default",homdir,&s,
  4602.            xxstring)) < 0 )
  4603.       return(x);
  4604. #else
  4605. #ifdef MAC
  4606.     strncpy(temp,homdir,32);
  4607.     x = strlen(temp);
  4608.     if (x > 0) if (temp[x-1] != ':') { temp[x] = ':'; temp[x+1] = NUL; }
  4609.     if ((x = cmtxt("Name of Macintosh volume and/or folder,\n\
  4610.  or press the Return key for the desktop on the boot disk",
  4611.            temp,&s, xxstring)) < 0 )
  4612.       return(x);
  4613. #else
  4614.     if ((x = cmdir("Name of local directory, or carriage return",homdir,&s,
  4615.            xxstring)) < 0 )
  4616.       return(x);
  4617. #endif /* MAC */
  4618. #endif /* OS2 */
  4619. #endif /* GEMDOS */
  4620. #ifndef MAC
  4621.     if (x == 2) {
  4622.     printf("?Wildcards not allowed in directory name\n");
  4623.     return(-9);
  4624.     }
  4625. #endif /* MAC */
  4626.     strcpy(line,s);            /* Make a safe copy */
  4627.     s = line;
  4628. #ifndef MAC
  4629.     if ((x = cmcfm()) < 0)        /* Get confirmation */
  4630.       return(x);
  4631. #endif /* MAC */
  4632. #ifdef datageneral
  4633.     x = strlen(line);            /* homdir ends in colon, */
  4634.     if (line[x-1] == ':')        /* and "dir" doesn't like that... */
  4635.       line[x-1] = NUL;
  4636. #endif /* datageneral */
  4637.  
  4638. #ifdef MAC
  4639.     cwdf = 1;
  4640.     if (! zchdir(s)) {
  4641.     cwdf = 0;
  4642.     if (*s != ':') {        /* If it failed, */
  4643.         char *p;            /* supply leading colon */
  4644.         p = malloc((int)strlen(s) + 2); /* and try again... */
  4645.         if (p) {
  4646.         strcpy(p,":");
  4647.         strcat(p,s);
  4648.         if (zchdir(p))
  4649.           cwdf = 1;
  4650.         free(p);
  4651.         }
  4652.     }
  4653.     }
  4654.     if (!cwdf)
  4655.       perror(s);
  4656. #else
  4657.     if (! zchdir(s)) {
  4658.     cwdf = 0;
  4659.     perror(s);
  4660.     } else cwdf = 1;
  4661. #endif /* MAC */
  4662.     if (!quiet)
  4663.       printf("%s\n", zgtdir());
  4664.     return(cwdf);
  4665. }
  4666.  
  4667. VOID
  4668. fixcmd() {            /* Fix command parser after interruption */
  4669.     dostop();            /* Back to top level (also calls conint()). */
  4670.     bgchk();            /* Check background status */
  4671.     if (*psave) {        /* If old prompt saved, */
  4672.     cmsetp(psave);        /* restore it. */
  4673.     *psave = NUL;
  4674.     }
  4675.     success = 0;        /* Tell parser last command failed */
  4676. }
  4677.  
  4678. VOID
  4679. prtopt(s) char *s; {            /* Print an option */
  4680.     static int x = 0;            /* (used by SHOW VER) */
  4681.     int y;                /* Does word wrap. */
  4682.     if (!s) { x = 0; return; }        /* Call with null pointer to */
  4683.     y = (int)strlen(s) + 1;        /* reset horizontal position. */
  4684.     x += y;
  4685.     if (x > ((tt_cols > 40) ? (tt_cols - 1) : 79)) {
  4686.     printf("\n %s",s);
  4687.     x = y;
  4688.     } else printf(" %s",s);
  4689. }
  4690.  
  4691. #endif /* NOICP */
  4692.