source: trunk/third/kermit/ckuus5.c @ 10780

Revision 10780, 169.0 KB checked in by brlewis, 27 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r10779, which included commits to RCS files with non-trunk default branches.
Line 
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>,
9  Columbia University Academic Information Systems, New York City.
10
11  Copyright (C) 1985, 1996, 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#ifdef OS2
35#include "ckoetc.h"
36#ifndef NT
37#define INCL_NOPM
38#define INCL_VIO /* Needed for ckocon.h */
39#include <os2.h>
40#else /* NT */
41#define APIRET ULONG
42extern int DialerHandle;
43extern int StartedFromDialer;
44#endif /* NT */
45#include "ckouni.h"
46#include "ckocon.h"
47#include "ckokey.h"
48#ifdef putchar
49#undef putchar
50#endif /* putchar */
51#define putchar(x) conoc(x)
52extern int cursor_save ;
53extern bool cursorena[] ;
54#endif /* OS2 */
55
56/* For formatted screens, "more?" prompting, etc. */
57
58#ifdef FT18
59#define isxdigit(c) isdigit(c)
60#endif /* FT18 */
61
62#ifdef STRATUS                          /* Stratus Computer, Inc.  VOS */
63#ifdef putchar
64#undef putchar
65#endif /* putchar */
66#define putchar(x) conoc(x)
67#ifdef getchar
68#undef getchar
69#endif /* getchar */
70#define getchar(x) coninc(0)
71#endif /* STRATUS */
72
73/* External variables */
74
75extern int carrier, cdtimo, local, quiet, backgrd, bgset, sosi, suspend,
76  displa, binary, deblog, escape, xargs, flow, cmdmsk, bye_active,
77  duplex, ckxech, pktlog, seslog, tralog, what, protocol,
78  keep, warn, tlevel, cwdf, nfuncs, unkcs, msgflg, remfile, rempipe, remappd,
79  mdmtyp, zincnt, cmask, rcflag, success, xitsta, pflag, lf_opts, tnlm, tn_nlm,
80  xfrcan, xfrchr, xfrnum, xitwarn, debses, pktpaus, moving, autodl, xaskmore;
81
82extern int ngetpath, exitonclose;
83extern char * getpath[];
84
85#ifndef NOSERVER
86  extern char * x_user, * x_passwd, * x_acct;
87#endif /* NOSERVER */
88
89#ifndef NOSPL
90extern int cfilef, DeleteStartupFile;
91extern char cmdfil[];
92
93struct localvar * localhead[MACLEVEL];
94struct localvar * localtail = NULL;
95struct localvar * localnext = NULL;
96
97_PROTOTYP( static char gettok,   (void) );
98_PROTOTYP( static VOID factor,   (void) );
99_PROTOTYP( static VOID term,     (void) );
100_PROTOTYP( static VOID termp,    (void) );
101_PROTOTYP( static VOID exprp,    (void) );
102_PROTOTYP( static VOID expr,     (void) );
103_PROTOTYP( static VOID simple,   (void) );
104_PROTOTYP( static VOID simpler,  (void) );
105_PROTOTYP( static VOID simplest, (void) );
106_PROTOTYP( static long xparse,   (void) );
107#endif /* NOSPL */
108
109#ifdef MAC
110char * ckprompt = "Mac-Kermit>";        /* Default prompt for Macintosh */
111#else  /* Not MAC */
112#ifdef NOSPL
113#ifdef NT
114char * ckprompt = "K-95> ";             /* Default prompt for Win32 */
115#else
116char * ckprompt = "C-Kermit>";
117#endif /* NT */
118#else  /* NOSPL */
119#ifdef NT
120char * ckprompt = "[\\v(dir)] K-95> ";  /* Default prompt for Windows NT */
121#else
122#ifdef VMS
123char * ckprompt = "\\v(dir) C-Kermit>"; /* Default prompt VMS */
124#else
125char * ckprompt = "[\\v(dir)] C-Kermit>";       /* Default prompt for others */
126#endif /* VMS */
127#endif /* NT */
128#endif /* NOSPL */
129#endif /* MAC */
130
131#ifndef CCHMAXPATH
132#define CCHMAXPATH 257
133#endif /* CCHMAXPATH */
134char inidir[CCHMAXPATH] = { NUL, NUL }; /* Directory INI file executed from */
135
136#ifdef TCPSOCKET
137extern int tn_b_nlm;                    /* TELNET BINARY newline mode */
138extern int me_binary, u_binary;
139#endif /* TCPSOCKET */
140
141#ifndef NOKVERBS
142extern struct keytab kverbs[];          /* Table of \Kverbs */
143extern int nkverbs;                     /* Number of \Kverbs */
144#endif /* NOKVERBS */
145
146#ifndef NOPUSH
147extern int nopush;
148#endif /* NOPUSH */
149
150#ifdef CK_RECALL
151extern int cm_recall;
152#endif /* CK_RECALL */
153
154extern char *ccntab[];
155extern char *printfile;
156extern int printpipe;
157
158#ifdef OS2
159_PROTOTYP (int os2getcp, (void) );
160_PROTOTYP (int os2getcplist, (int *, int) );
161#ifdef OS2MOUSE
162extern int tt_mouse;
163#endif /* OS2MOUSE */
164extern int tt_update, tt_updmode, tt_font, updmode;
165extern struct keytab termfont[];
166extern int ntermfont;
167extern unsigned char colornormal, colorunderline, colorstatus,
168    colorhelp, colorselect, colorborder, colorgraphic, colordebug,
169    colorreverse;
170extern int priority;
171extern struct keytab prtytab[];
172extern int nprty;
173char * cmdmac = NULL;
174#endif /* OS2 */
175
176#ifdef VMS
177_PROTOTYP (int zkermini, (char *, int, char *) );
178#endif /* VMS */
179
180#ifndef NOFRILLS
181extern int en_asg, en_cwd, en_cpy, en_del, en_dir, en_fin, en_bye, en_ret,
182  en_get, en_hos, en_que, en_ren, en_sen, en_set, en_spa, en_typ, en_who,
183  en_mai, en_pri;
184#endif /* NOFRILLS */
185extern long vernum;
186extern int srvtim, srvdis, inecho, insilence, inbufsize, nvars, verwho;
187extern char *protv, *fnsv, *cmdv, *userv, *ckxv, *ckzv, *ckzsys, *xlav,
188 *cknetv, *clcmds;
189#ifdef OS2
190extern char *ckonetv;
191#ifdef CK_NETBIOS
192extern char *ckonbiv;
193#endif /* CK_NETBIOS */
194#ifdef OS2MOUSE
195extern char *ckomouv;
196#endif /* OS2MOUSE */
197#endif /* OS2 */
198extern char *connv, *dialv, *loginv, *nvlook();
199
200#ifndef NOSCRIPT
201extern int secho;
202#endif /* NOSCRIPT */
203
204#ifndef NODIAL
205extern int nmdm, dirline;
206extern struct keytab mdmtab[];
207#endif /* NODIAL */
208
209#ifdef NETCONN
210extern int network, ttnproto;
211#endif /* NETCONN */
212
213#ifdef OS2
214/* SET TERMINAL items... */
215extern int tt_type, tt_arrow, tt_keypad, tt_wrap, tt_answer, tt_scrsize[];
216extern int tt_bell, tt_roll[], tt_ctstmo, tt_cursor, tt_pacing;
217extern char answerback[]; 
218#ifdef COMMENT
219extern int tt_hide;
220#endif /* COMMENT */
221extern struct tt_info_rec tt_info[];    /* Indexed by terminal type */
222extern int max_tt;
223#endif /* OS2 */
224
225#ifdef CK_TTGWSIZ
226_PROTOTYP( int ttgwsiz, (void) );
227#endif /* CK_TTGWSIZ */
228_PROTOTYP( VOID shotrm, (void) );
229_PROTOTYP( VOID shofea, (void) );
230
231#ifdef OS2
232extern int tt_rows[], tt_cols[];
233#else /* OS2 */
234extern int tt_rows, tt_cols;
235#endif /* OS2 */
236int cmd_rows = 24, cmd_cols = 80;
237
238#ifdef CK_TMPDIR
239extern int f_tmpdir;                    /* Directory changed temporarily */
240extern char savdir[];                   /* Temporary directory */
241#endif /* CK_TMPDIR */
242
243#ifndef NOLOCAL
244extern int tt_crd, tt_escape;
245#endif /* NOLOCAL */
246
247#ifndef NOCSETS
248extern int language, nfilc, tcsr, tcsl;
249extern struct keytab fcstab[];
250extern struct csinfo fcsinfo[];
251#ifndef MAC
252extern struct keytab ttcstab[];
253#endif /* MAC */
254#endif /* NOCSETS */
255
256extern int atcapr,
257  atenci, atenco, atdati, atdato, atleni, atleno, atblki, atblko,
258  attypi, attypo, atsidi, atsido, atsysi, atsyso, atdisi, atdiso;
259
260#ifdef STRATUS
261extern int atfrmi, atfrmo, atcrei, atcreo, atacti, atacto;
262#endif /* STRATUS */
263
264extern long speed;
265
266extern char *DIRCMD, *PWDCMD, *DELCMD;
267#ifndef NOXMIT
268extern int xmitf, xmitl, xmitp, xmitx, xmits, xmitw;
269extern char xmitbuf[];
270#endif /* NOXMIT */
271
272extern char **xargv, *versio, *ckxsys, *dftty, *cmarg, *lp;
273
274#ifdef DCMDBUF
275extern char *cmdbuf, *atmbuf;           /* Command buffers */
276#ifndef NOSPL
277extern char *savbuf;                    /* Command buffers */
278#endif /* NOSPL */
279#else
280extern char cmdbuf[], atmbuf[];         /* Command buffers */
281#ifndef NOSPL
282extern char savbuf[];                   /* Command buffers */
283#endif /* NOSPL */
284#endif /* DCMDBUF */
285
286extern char toktab[], ttname[], psave[];
287extern CHAR sstate, feol;
288extern int cmflgs, techo, repars, ncmd;
289extern struct keytab cmdtab[];
290
291#ifndef NOSETKEY
292KEY *keymap;
293#ifndef OS2
294#define mapkey(x) keymap[x]
295#endif /* OS2 */
296MACRO *macrotab;
297_PROTOTYP( VOID shostrdef, (CHAR *) );
298#endif /* NOSETKEY */
299
300#ifndef NOSPL
301extern struct mtab *mactab;
302extern struct keytab vartab[], fnctab[];
303extern int cmdlvl, maclvl, nmac, mecho;
304#endif /* NOSPL */
305
306FILE *tfile[MAXTAKE];                   /* TAKE file stack */
307char *tfnam[MAXTAKE];
308int tfline[MAXTAKE];
309
310#ifdef DCMDBUF                          /* Initialization filespec */
311char *kermrc = NULL;
312#else
313char kermrcb[KERMRCL];
314char *kermrc = kermrcb;
315#endif /* DCMDBUF */
316
317int noherald = 0;
318int cm_retry = 1;                       /* Command retry enabled */
319xx_strp xxstring = zzstring;
320
321#ifndef NOSPL
322
323extern long ck_alarm;
324extern char alrm_date[], alrm_time[];
325
326extern int query;                       /* QUERY active */
327
328/* Local declarations */
329
330static int nulcmd = 0;                  /* Flag for next cmd to be ignored */
331
332/* Definitions for predefined macros */
333
334/* First, the single-line macros, installed with addmac()... */
335
336/* IBM-LINEMODE macro */
337char *m_ibm = "set parity mark, set dupl half, set handsh xon, set flow none";
338
339/* FATAL macro */
340char *m_fat = "if def \\%1 echo \\%1, if not = \\v(local) 0 hangup, stop 1";
341
342#ifdef CK_SPEED
343#ifdef pdp11
344char *m_fast = "set win 3, set rec pack 1024, set prefix minimal";
345#else
346#ifdef BIGBUFOK
347char *m_fast = "set win 20, set rec pack 4096, set prefix minimal";
348#else
349char *m_fast = "set win 4, set rec pack 2200, set prefix minimal";
350#endif /* BIGBUFOK */
351#endif /* pdp11 */
352#ifdef pdp11
353char *m_cautious = "set win 2, set rec pack 512, set prefixing cautious";
354#else
355char *m_cautious = "set win 4, set rec pack 1000, set prefixing cautious";
356#endif /* pdp11 */
357char *m_robust = "set win 1, set rec pack 90, set prefixing all";
358#else
359#ifdef BIGBUFOK
360char *m_fast = "set win 20, set rec pack 4096";
361#else
362char *m_fast = "set win 4, set rec pack 2200";
363#endif /* BIGBUFOK */
364char *m_cautious = "set win 4, set rec pack 1000";
365char *m_robust = "set win 1, set rec pack 90";
366#endif /* CK_SPEED */
367
368/* Now the multiline macros, defined with addmmac()... */
369
370/* FOR macro */
371char *for_def[] = { "_assign _for\\v(cmdlevel) { _getargs,",
372"define \\\\\\%1 \\feval(\\%2),:_..top,if \\%5 \\\\\\%1 \\%3 goto _..bot,",
373"\\%6,:_..inc,incr \\\\\\%1 \\%4,goto _..top,:_..bot,_putargs},",
374"def break goto _..bot, def continue goto _..inc,",
375"do _for\\v(cmdlevel) \\%1 \\%2 \\%3 \\%4 { \\%5 },_assign _for\\v(cmdlevel)",
376""};
377
378/* WHILE macro */
379char *whil_def[] = { "_assign _whi\\v(cmdlevel) {_getargs,",
380":_..inc,\\%1,\\%2,goto _..inc,:_..bot,_putargs},",
381"_def break goto _..bot, _def continue goto _..inc,",
382"do _whi\\v(cmdlevel),_assign _whi\\v(cmdlevel)",
383""};
384
385/* SWITCH macro */
386char *sw_def[] = { "_assign _sw_\\v(cmdlevel) {_getargs,",
387"_forward \\%1,\\%2,:_..bot,_putargs},_def break goto _..bot,",
388"do _sw_\\v(cmdlevel),_assign _sw_\\v(cmdlevel)",
389""};
390
391/* XIF macro */
392char *xif_def[] = {
393"_assign _if\\v(cmdlevel) {_getargs,\\%1,_putargs},",
394"do _if\\v(cmdlevel),_assign _if\\v(cmdlevel)",
395""};
396
397/*
398  Variables declared here for use by other ckuus*.c modules.
399  Space is allocated here to save room in ckuusr.c.
400*/
401#ifdef DCMDBUF
402struct cmdptr *cmdstk;
403int *ifcmd, *count, *iftest, *intime, *inpcas, *takerr, *merror;
404#else
405struct cmdptr cmdstk[CMDSTKL];
406int ifcmd[CMDSTKL], count[CMDSTKL], iftest[CMDSTKL], intime[CMDSTKL],
407  inpcas[CMDSTKL], takerr[CMDSTKL], merror[CMDSTKL];
408#endif /* DCMDBUF */
409
410char *m_arg[MACLEVEL][NARGS];
411char *g_var[GVARS], *macp[MACLEVEL], *mrval[MACLEVEL];
412int macargc[MACLEVEL];
413char *macx[MACLEVEL];
414extern char varnam[];
415
416/* Dimension must be 'z' - ARRAYBASE + 1 */
417
418char **a_ptr[28];                       /* Array pointers, for arrays a-z */
419int a_dim[28];                          /* Dimensions for each array */
420
421char * inpbuf = NULL;                   /* Buffer for INPUT and REINPUT */
422extern char * inpbp;                    /* Global/static pointer to it  */
423char inchar[2] = { NUL, NUL };          /* Last character that was INPUT */
424int  incount = 0;                       /* INPUT character count */
425extern int instatus;                    /* INPUT status */
426static char * i_text[] = {              /* INPUT status text */
427    "success", "timeout", "interrupted", "internal error", "i/o error"
428};
429
430char lblbuf[LBLSIZ];                    /* Buffer for labels */
431#else
432int takerr[MAXTAKE];
433#endif /* NOSPL */
434
435int pacing = 0;                         /* OUTPUT pacing */
436
437#ifdef DCMDBUF
438char *line;                             /* Character buffer for anything */
439char *tmpbuf;
440#else
441char line[LINBUFSIZ];
442char tmpbuf[TMPBUFSIZ];                 /* Temporary buffer */
443#endif /* DCMDBUF */
444char *tp;                               /* Temporary buffer pointer */
445
446#ifdef CK_APC                           /* Application Program Command (APC) */
447int apcactive = APC_INACTIVE;
448int apcstatus = APC_OFF;                /* OFF by default everywhere */
449#ifdef DCMDBUF
450char *apcbuf;
451#else
452char apcbuf[APCBUFLEN];
453#endif /* DCMDBUF */
454#endif /* CK_APC */
455
456extern char pktfil[],
457#ifdef DEBUG
458  debfil[],
459#endif /* DEBUG */
460#ifdef TLOG
461  trafil[],
462#endif /* TLOG */
463  sesfil[];
464
465#ifndef NOFRILLS
466extern int rmailf, rprintf;             /* REMOTE MAIL & PRINT items */
467extern char optbuf[];
468#endif /* NOFRILLS */
469
470char *homdir = "";                      /* Pointer to home directory string */
471
472char numbuf[20];                        /* Buffer for numeric strings. */
473int noinit = 0;                         /* Flag for skipping init file */
474
475#ifndef NOSPL
476_PROTOTYP( VOID freelocal, (int) );
477_PROTOTYP( static long expon, (long, long) );
478_PROTOTYP( static long gcd, (long, long) );
479_PROTOTYP( static long fact, (long) );
480
481int                     /* Initialize macro data structures. */
482macini() {              /* Allocate mactab and preset the first element. */
483    int i;
484    if (!(mactab = (struct mtab *) malloc(sizeof(struct mtab) * MAC_MAX)))
485      return(-1);
486    mactab[0].kwd = NULL;
487    mactab[0].mval = NULL;
488    mactab[0].flgs = 0;
489    for (i = 0; i < MACLEVEL; i++)
490      localhead[i] = NULL;
491    return(0);
492}
493#endif /* NOSPL */
494
495/*  C M D I N I  --  Initialize the interactive command parser  */
496 
497static int cmdinited = 0;
498
499VOID
500cmdini() {
501    int i, x, y, z, n;
502#ifndef NOSPL
503/*
504  On stack to allow recursion!
505*/
506    char vnambuf[VNAML];                /* Buffer for variable names */
507#endif /* NOSPL */
508
509    if (cmdinited)
510      return;
511
512#ifndef NOSETKEY                        /* Allocate & initialize the keymap */
513    if (!(keymap = (KEY *) malloc(sizeof(KEY)*KMSIZE)))
514      fatal("cmdini: no memory for keymap");
515    if (!(macrotab = (MACRO *) malloc(sizeof(MACRO)*KMSIZE)))
516      fatal("cmdini: no memory for macrotab");
517    for (i = 0; i < KMSIZE; i++) {
518       keymap[i] = (KEY) i;
519       macrotab[i] = NULL;
520    }
521#endif /* NOSETKEY */
522
523#ifndef NOSPL
524    if (!inpbuf) {
525        if (!(inpbuf = (char *) malloc(INPBUFSIZ+1)))
526          fatal("cmdini: no memory for INPUT buffer");
527    }
528    for (x = 0; x < INPBUFSIZ; x++)
529      inpbuf[x] = NUL;
530    inpbp = inpbuf;
531    inbufsize = INPBUFSIZ;
532#endif /* NOSPL */
533
534#ifdef DCMDBUF
535    if (cmsetup() < 0) fatal("Can't allocate command buffers!");
536#ifndef NOSPL
537    if (!(cmdstk = (struct cmdptr *) malloc(sizeof(struct cmdptr)*CMDSTKL)))
538      fatal("cmdini: no memory for cmdstk");
539    if (!(ifcmd = (int *) malloc(sizeof(int)*CMDSTKL)))
540      fatal("cmdini: no memory for ifcmd");
541    if (!(count = (int *) malloc(sizeof(int)*CMDSTKL)))
542      fatal("cmdini: no memory for count");
543    if (!(iftest = (int *) malloc(sizeof(int)*CMDSTKL)))
544      fatal("cmdini: no memory for iftest");
545    if (!(intime = (int *) malloc(sizeof(int)*CMDSTKL)))
546      fatal("cmdini: no memory for intime");
547    if (!(inpcas = (int *) malloc(sizeof(int)*CMDSTKL)))
548      fatal("cmdini: no memory for inpcas");
549    if (!(takerr = (int *) malloc(sizeof(int)*CMDSTKL)))
550      fatal("cmdini: no memory for takerr");
551    if (!(merror = (int *) malloc(sizeof(int)*CMDSTKL)))
552      fatal("cmdini: no memory for merror");
553    if (!kermrc)
554      if (!(kermrc = (char *) malloc(KERMRCL+1)))
555        fatal("cmdini: no memory for kermrc");
556#endif /* NOSPL */
557
558    if (!(line = malloc(LINBUFSIZ)))
559        fatal("cmdini: no memory for line");
560    if (!(tmpbuf = malloc(LINBUFSIZ)))
561        fatal("cmdini: no memory for tmpbuf");
562
563#ifdef CK_APC
564    if (!(apcbuf = malloc(APCBUFLEN)))
565        fatal("cmdini: no memory for apcbuf");
566#endif /* CK_APC */
567
568#endif /* DCMDBUF */
569
570#ifdef CK_MINPUT
571    {                                   /* Initialize MINPUT pointers */
572        int i;
573        extern char *ms[];
574        for (i = 0; i < MINPMAX; i++)
575          ms[i] = NULL;
576    }
577#endif /* CK_MINPUT */
578
579#ifndef NOSPL
580    if (macini() < 0)
581      fatal("Can't allocate macro buffers!");
582
583    ifcmd[0] = 0;                       /* Command-level related variables. */
584    iftest[0] = 0;                      /* Initialize variables at top level */
585    count[0] = 0;                       /* of stack... */
586    intime[0] = 0;
587    inpcas[0] = 0;
588    takerr[0] = 0;
589    merror[0] = 0;
590#endif /* NOSPL */
591
592#ifdef AMIGA
593    if (tlevel < 0)   
594      concb(escape);
595#endif /* AMIGA */
596
597#ifndef NOSPL
598    cmdlvl = 0;                         /* Initialize the command stack */
599    cmdstk[cmdlvl].src = CMD_KB;        /* Source is console */
600    cmdstk[cmdlvl].lvl = 0;             /* Level is 0 */
601    cmdstk[cmdlvl].ccflgs = 0;          /* No flags */
602#endif /* NOSPL */
603
604    tlevel = -1;                        /* Take file level = keyboard */
605    for (i = 0; i < MAXTAKE; i++)       /* Initialize command file names */
606      tfnam[i] = NULL;
607
608#ifdef NT
609/*  We tell the difference between Windows NT and 95 at runtime. */
610    if (isWin95())
611#ifdef NOSPL
612      ckprompt = "K-95> ";              /* Default prompt for Windows 95 */
613#else
614      ckprompt = "[\\v(dir)] K-95> ";
615#endif /* NOSPL */
616#endif /* NT */
617    cmsetp(ckprompt);
618
619#ifndef NOSPL
620    initmac();                          /* Initialize macro table */
621/* Add one-line macros */
622    addmac("ibm-linemode",m_ibm);       /* Add built-in macros. */
623    addmac("fatal",m_fat);              /* FATAL macro  */
624    y = addmac("fast",m_fast);          /* FAST macro   */
625    addmac("cautious",m_cautious);      /* CAUTIOUS macro   */
626    addmac("robust",m_robust);          /* ROBUST macro */
627
628/* Add multiline macros */
629    addmmac("_forx",for_def);           /* FOR macro. */
630    addmmac("_xif",xif_def);            /* XIF macro. */
631    addmmac("_while",whil_def);         /* WHILE macro. */
632    addmmac("_switx",sw_def);           /* SWITCH macro. */
633/* Predefine the macro argument vector */
634    strcpy(vnambuf,"\\&_[10]");         /* Macro argument vector */
635    y = arraynam(vnambuf,&x,&z);        /* goes in array \&_[] */
636    if (y > -1) {
637        dclarray((char)x,z);            /* Declare the array */
638        for (i = 0; i < 10; i++) {      /* Fill it */
639            sprintf(vnambuf,"\\&_[%d]",i); /* with NULL pointers */
640            addmac(vnambuf,NULL);
641        }
642    }
643    *vnambuf = NUL;
644/* Fill in command line argument vector */
645    sprintf(vnambuf,"\\&@[%d]",xargs);  /* Command line argument vector */
646    y = arraynam(vnambuf,&x,&z);        /* goes in array \&@[] */
647    if (y > -1) {
648        dclarray((char)x,z);            /* Declare the array */
649        for (i = 0; i < xargs; i++) {   /* Fill it */
650            sprintf(vnambuf,"\\&@[%d]",i);
651            addmac(vnambuf,xargv[i]);
652        }
653    }
654    *vnambuf = NUL;
655#endif /* NOSPL */
656
657#ifdef CK_TTGWSIZ
658#ifdef OS2
659    ttgcwsz();
660#else /* OS2 */
661    if (ttgwsiz() > 0) {
662        if (tt_rows > 0 && tt_cols > 0) {
663            cmd_rows = tt_rows;
664            cmd_cols = tt_cols;
665        }
666    }
667#endif /* OS2 */
668#endif /* CK_TTGWSIZ */
669
670/* Get our home directory now.  This needed in lots of places. */
671
672    homdir = zhome();
673    cmdinited = 1;
674}
675
676VOID
677doinit() {
678#ifdef OS2
679    char * ptr = 0;
680    extern int initvik;
681#endif /* OS2 */
682
683    if (!cmdinited)
684      cmdini();
685
686#ifdef MAC
687    return;                             /* Mac Kermit has no init file */
688
689#else /* !MAC */
690
691#ifdef OS2
692    keymapinit();
693    keynaminit();
694#ifdef OS2MOUSE
695    mousemapinit(-1,-1);
696#endif /* OS2MOUSE */
697    initvik = 1;
698#endif /* OS2 */
699
700/* If skipping init file ('-Y' on Kermit command line), return now. */
701
702    if (noinit) {
703        kermrc[0] = '\0';
704        inidir[0] = '\0';
705/*
706  But returning from here results in inidir[] never being set to anything.
707  Instead it should be set to wherever the init file *would* have been
708  executed from.  So this bit of code should be removed, and then we should
709  sprinkle "if (noinit)" tests throughout the following code until we have
710  set inidir[], and then return without actually taking the init file.
711*/
712        return;
713    }
714
715#ifdef OS2
716/*
717  The -y init file must be fully specified or in the current directory.
718  KERMRC is looked for via INIT, DPATH and PATH in that order.  Finally, our
719  own executable file path is taken and the .EXE suffix is replaced by .INI
720  and this is tried as the initialization file.
721*/
722    if (rcflag) {
723        strcpy(line, kermrc);
724    } else {
725        char * env = 0;
726#ifdef NT
727        env = getenv("K95.INI");
728#else
729        env = getenv("K2.INI");
730#endif /* NT */
731        if (!env)
732          env = getenv("CKERMIT.INI");
733        if (!env)
734          env = getenv("CKERMIT_INI");
735        line[0] = '\0';
736
737        if (env)
738          strcpy(line,env);
739        if (line[0] == 0)
740          _searchenv(kermrc,"INIT",line);
741        if (line[0] == 0)
742          _searchenv(kermrc,"DPATH",line);
743        if (line[0] == 0)
744          _searchenv(kermrc,"PATH",line);
745        if (line[0] == 0) {
746            char *pgmptr = GetLoadPath();
747            if (pgmptr) {
748                lp = strrchr(pgmptr, '.');
749                strncpy(line, pgmptr, lp - pgmptr);
750                strcpy(line + (lp - pgmptr), ".ini");
751            }
752        }
753    }
754    if ((tfile[0] = fopen(line,"r")) != NULL) {
755        tlevel = 0;
756        tfline[tlevel] = 0;
757        if (tfnam[tlevel] = malloc(strlen(line)+1))
758          strcpy(tfnam[tlevel],line);
759#ifndef NOSPL
760        cmdlvl++;
761        cmdstk[cmdlvl].src = CMD_TF;
762        cmdstk[cmdlvl].lvl = tlevel;
763        cmdstk[cmdlvl].ccflgs = 0;
764        ifcmd[cmdlvl] = 0;
765        iftest[cmdlvl] = 0;
766        count[cmdlvl] =  count[cmdlvl-1]; /* Inherit from previous level */
767        intime[cmdlvl] = intime[cmdlvl-1];
768        inpcas[cmdlvl] = inpcas[cmdlvl-1];
769        takerr[cmdlvl] = takerr[cmdlvl-1];
770        merror[cmdlvl] = merror[cmdlvl-1];
771#endif /* NOSPL */
772        debug(F110,"doinit init file",line,0);
773    } else {
774        debug(F100,"doinit no init file","",0);
775    }
776    strncpy(kermrc,line,KERMRCL);       /* XXXX */
777    for (ptr = kermrc; *ptr; ptr++)     /* Convert backslashes to slashes */
778       if (*ptr == '\\')
779         *ptr = '/';
780#else /* not OS2 */
781    lp = line;
782    lp[0] = '\0';
783#ifdef GEMDOS
784    zkermini(line, rcflag, kermrc);
785#else
786#ifdef VMS
787    zkermini(line,LINBUFSIZ,kermrc);
788#else /* not VMS */
789    if (rcflag) {                       /* If init file name from cmd line */
790        strcpy(lp,kermrc);              /* use it, */
791    } else {                            /* otherwise... */
792#ifdef CK_INI_A                         /* If we've a system-wide init file */
793        /* And it takes precedence over the user's... */
794        strncpy(lp,CK_SYSINI,KERMRCL);  /* Use it */
795        if (zchki(lp) < 0) {            /* (if it exists...) */
796#endif /* CK_INI_A */
797            line[0] = NUL;
798            if (homdir) {               /* Home directory for init file. */
799                strcpy(lp,homdir);
800#ifdef STRATUS
801                strcat(lp,">");         /* VOS separates dirs with >'s */
802#else
803                if (lp[0] == '/') strcat(lp,"/");
804#endif /* STRATUS */
805            }
806            strcat(lp,kermrc);          /* Append the default file name */
807#ifdef CK_INI_A
808        }
809#endif /* CK_INI_A */
810    }
811#ifdef CK_INI_B                         /* System-wide init defined? */
812    /* But user's ini file takes precedence */
813    if (zchki(lp) < 0)                  /* If user doesn't have her own, */
814        strncpy(lp,CK_SYSINI,KERMRCL);  /* use system-wide one. */
815#endif /* CK_INI_B */
816
817#endif /* VMS */
818#endif /* GEMDOS */
819
820#ifdef AMIGA
821    reqoff();                           /* Disable requestors */
822#endif /* AMIGA */
823
824    debug(F110,"ini file is",line,0);
825    if ((tfile[0] = fopen(line,"r")) != NULL) { /* Try to open init file. */
826        tlevel = 0;
827        tfline[tlevel] = 0;
828        if (tfnam[tlevel] = malloc(strlen(line)+1))
829          strcpy(tfnam[tlevel],line);
830
831        strncpy(kermrc,line,KERMRCL);   /* XXXX */
832
833#ifndef NOSPL
834        cmdlvl++;
835        ifcmd[cmdlvl] = 0;
836        iftest[cmdlvl] = 0;
837        count[cmdlvl] =  count[cmdlvl-1]; /* Inherit from previous level */
838        intime[cmdlvl] = intime[cmdlvl-1];
839        inpcas[cmdlvl] = inpcas[cmdlvl-1];
840        takerr[cmdlvl] = takerr[cmdlvl-1];
841        merror[cmdlvl] = merror[cmdlvl-1];
842        debug(F101,"open ok","",cmdlvl);
843        cmdstk[cmdlvl].src = CMD_TF;
844        cmdstk[cmdlvl].lvl = tlevel;
845        cmdstk[cmdlvl].ccflgs = 0;
846#endif /* NOSPL */
847        debug(F110,"init file",line,0);
848    }
849
850#ifdef datageneral
851/* If CKERMIT.INI not found in home directory, look in searchlist */
852    if (homdir && (tlevel < 0)) {
853        strcpy(lp,kermrc);
854        if ((tfile[0] = fopen(line,"r")) != NULL) {
855            tlevel = 0;
856            tfline[tlevel] = 0;
857            if (tfnam[tlevel] = malloc(strlen(line)+1))
858              strcpy(tfnam[tlevel],line);
859#ifndef NOSPL
860            cmdlvl++;
861            cmdstk[cmdlvl].src = CMD_TF;
862            cmdstk[cmdlvl].lvl = tlevel;
863            cmdstk[cmdlvl].ccflgs = 0;
864            ifcmd[cmdlvl] = 0;
865            iftest[cmdlvl] = 0;
866            count[cmdlvl] =  count[cmdlvl-1]; /* Inherit from previous level */
867            intime[cmdlvl] = intime[cmdlvl-1];
868            inpcas[cmdlvl] = inpcas[cmdlvl-1];
869            takerr[cmdlvl] = takerr[cmdlvl-1];
870            merror[cmdlvl] = merror[cmdlvl-1];
871#endif /* NOSPL */
872        }
873    }
874#endif /* datageneral */
875
876#ifdef AMIGA                            /* Amiga... */
877    reqpop();                           /* Restore requestors */
878#endif /* AMIGA */
879#endif /* OS2 */
880#endif /* MAC */
881
882    /* Assign value to inidir */
883
884    strcpy(inidir, kermrc);
885    {
886        int x;
887        x = strlen(inidir);
888        if (x > 0) {
889            int i;
890            for (i = x - 1; i > 0; i-- ) {
891                if (inidir[i] ==
892#ifdef MAC
893                    '/'
894#else
895#ifdef UNIX
896                    '/'
897#else
898#ifdef OSK
899                    '/'
900#else
901#ifdef STRATUS
902                    '>'
903#else
904#ifdef VMS
905                    ']' || inidir[i] == ':'
906#else
907#ifdef datageneral
908                    ':'
909#else
910#ifdef OS2
911                    '/' || inidir[i+1] == '\\'
912#else
913#ifdef AMIGA
914                    '/' || inidir[i+1] == ':'
915
916#endif /* AMIGA */
917#endif /* OS2 */
918#endif /* datageneral */
919#endif /* VMS */
920#endif /* STRATUS */
921#endif /* OSK */
922#endif /* UNIX */
923#endif /* MAC */
924                    ) {
925                    inidir[i+1] = NUL;
926                    break;
927                }
928            }
929        }
930    }
931}
932
933#ifndef NOSPL
934/*
935  G E T N C M
936
937  Get next command from current macro definition.
938
939  Moved to a separate routine in edit 181 to allow multiline GET
940  to work when issued in a macro.
941
942  Command is copied into string pointed to by argument s, max length n.
943  Returns:
944   0 if a string was copied, -1 if there was no string to copy.
945*/
946int
947getncm(s,n) char *s; int n; {
948    int y,                              /* Character counter */
949#ifdef COMMENT
950    quote = 0,
951#endif /* COMMENT */
952    kp = 0,                             /* Brace up-down counter */
953    pp = 0;                             /* Parenthesis up-down counter */
954    char *s2;                           /* Copy of destination pointer */
955   
956    s2 = s;                             /* Initialize string pointers */
957    *s = NUL;                           /* and destination buffer */
958   
959    debug(F101,"getncm dest length","",n);
960
961    for (y = 0;                         /* Loop for n bytes max */
962         macp[maclvl] && *macp[maclvl] && y < n;
963         y++, s++, macp[maclvl]++) {
964       
965        *s = *macp[maclvl];             /* Get next char from macro def */
966        /* debug(F000,"char","",*s); */
967#ifdef COMMENT
968/*
969  The intention here was to allow quoting of commas, braces, etc,
970  in macro definitions, e.g. "define rows mode co80\,\%1".  And it
971  works, but it breaks just about everything else.
972*/
973        if (*s == CMDQ && quote == 0) { /* Allow for quoting of */
974            quote = 1;                  /* braces, commas, etc. */
975            continue;
976        }
977#endif /* COMMENT */
978/*
979  Allow braces around macro definition to prevent commas from being turned to
980  end-of-lines and also treat any commas within parens as text so that
981  multiple-argument functions won't cause the command to break prematurely.
982*/
983#ifdef COMMENT
984        if (!quote) {
985#endif /* COMMENT */
986            if (*s == '{') kp++;        /* Count braces */
987            if (*s == '}') kp--;
988            if (*s == '(') pp++;        /* Count parentheses. */
989            if (*s == ')') pp--;
990            if (*s == ',' && pp <= 0 && kp <= 0) {
991                macp[maclvl]++;         /* Comma not in {} or () */
992                debug(F110,"next cmd",s,0);
993                kp = pp = 0;            /* so we have the next command */
994                break;
995            }
996#ifdef COMMENT
997        }
998#endif /* COMMENT */
999    }                                   /* Reached end. */
1000    if (*s2 == NUL) {                   /* If nothing was copied, */
1001        debug(F100,"getncm eom","",0);
1002        popclvl();                      /* pop command level. */
1003        return(-1);
1004    } else {                            /* otherwise, tack CR onto end */
1005        *s++ = CR;
1006        *s = '\0';
1007        if (mecho && pflag)             /* If MACRO ECHO ON, echo the cmd */
1008          printf("%s\n",s2);
1009        debug(F110,"getncm returns ptr to",s2,0);
1010    }
1011    return(0);
1012}
1013
1014/*  D O M A C  --  Define and then execute a macro */
1015
1016int
1017domac(name, def, flags) char *name, *def; int flags; {
1018    int x, m;
1019    m = maclvl;                         /* Current macro stack level */
1020    debug(F101,"domac entry maclvl","",maclvl);
1021    x = addmac(name, def);              /* Define a new macro */
1022    if (x > -1) {                       /* If successful, */
1023        dodo(x,NULL, flags);            /* start it (increments maclvl). */
1024        while (maclvl > m) {            /* Keep going till done with it, */
1025            debug(F101,"domac loop maclvl 1","",maclvl);
1026            sstate = (CHAR) parser(1);  /* parsing & executing each command, */
1027            debug(F101,"domac loop maclvl 2","",maclvl);
1028            if (sstate) proto();        /* including protocol commands. */
1029        }
1030        debug(F101,"domac loop exit maclvl","",maclvl);
1031    }       
1032    return(success);
1033}
1034#endif /* NOSPL */
1035
1036/*
1037  G E T N C T
1038
1039  Get next command from TAKE (command) file.
1040
1041  Call with:
1042   s     Pointer to buffer to read into
1043   n     Length of buffer
1044   f     File descriptor of file to read from
1045   flag  0 == keep line terminator on and allow continuation
1046         1 == discard line terminator and don't allow continuation
1047
1048  Call with flag == 0 to read a command from a TAKE file;
1049  Call with flag != 0 to read a line from a dialing or network directory.
1050
1051  In both cases, trailing comments and/or trailing whitespace is stripped.
1052  If flag == 0, continued lines are combined into one line.  A continued line
1053  is one that ends in hypen or backslash, or any line in a "block", which
1054  starts with "{" at the end of a line and ends with "}" at the beginning of
1055  a line; blocks may be nested.
1056
1057  Returns:
1058   0 if a string was copied,
1059  -1 on EOF,
1060  -2 on malloc failure
1061  -3 if line is not properly terminated
1062  -4 if (possibly continued) line is too long. */
1063int
1064getnct(s,n,f,flag) char *s; int n; FILE *f; int flag; {
1065    int i, len, buflen;
1066    char c, cc, ccl, *s2, *lp, *lp2, *lp3, *lastcomma = NULL;
1067    int bc = 0;                         /* Block counter */
1068
1069    s2 = s;                             /* Remember original pointer */
1070    buflen = n;                         /* Remember original buffer length */
1071
1072    debug(F101,"getnct","",n);
1073    if (!(lp2 = (char *) malloc(n+n+1))) { /* Get a temporary buffer */
1074        debug(F101,"getnct malloc failure","",0);
1075        return(-2);
1076    }
1077    while (1) {                         /* Loop to read lines from file */
1078        if (fgets(lp2,n,f) == NULL) {   /* Read a line into lp2 */
1079            debug(F100,"getnct fgets EOF","",0); /* EOF */
1080            free(lp2);                  /* Free temporary storage */
1081            lp2 = NULL;
1082            *s = NUL;                   /* Make destination be empty */
1083            return(-1);                 /* Return failure code */
1084        }
1085#ifndef NODIAL
1086        if (flag)                       /* Count this line */
1087          dirline++;
1088        else
1089#endif /* NODIAL */
1090          tfline[tlevel]++;
1091        len = strlen(lp2) - 1;          /* Position of line terminator */
1092        debug(F111,"getnct fgets ok",lp2,len);
1093        if (len < 0)
1094          len = 0;
1095        if (techo && pflag)             /* If TAKE ECHO ON, */
1096          printf("%3d. %s",             /* echo it this line. */
1097#ifndef NODIAL
1098                 flag ? dirline :
1099#endif /* NODIAL */
1100                 tfline[tlevel],
1101                 lp2
1102                 );
1103        lp3 = lp2;                      /* Working pointer */
1104        i = len;
1105        while (*lp3 == SP || *lp3 == HT) { /* First nonwhitespace character */
1106            i--;
1107            lp3++;
1108        }
1109        if (i == 0 && bc > 0)           /* Blank line in {...} block */
1110          continue;
1111
1112        /* Isolate, remove, and check terminator */
1113
1114        c = lp2[len];                   /* Value of line terminator */
1115        debug(F101,"getnct terminator","",c);
1116        if (c < LF || c > CR) {         /* It's not a terminator */
1117            debug(F111,"getnct bad line",lp2,c);
1118            if (feof(f) && len > 0 && len < n) {
1119                /* Kludge Alert... */
1120                printf("Warning: Last line of %s lacks terminator\n",
1121                       s2 == cmdbuf ? "command file" : "directory file");
1122                c = lp2[++len] = '\n';  /* No big deal - supply one. */
1123            } else {                    /* Something's wrong, fail. */
1124                free(lp2);
1125                lp2 = NULL;
1126                return(-3);
1127            }
1128        }
1129
1130        /* Trim trailing whitespace */
1131
1132        for (i = len - 1; i > -1; i--)  /* Back up over spaces and tabs */
1133          if (lp2[i] != SP && lp2[i] != HT && lp2[i] != NUL)
1134            break;
1135        debug(F101,"getnct i","",i);
1136        lp2[i+1] = NUL;                 /* Terminate the string */
1137        debug(F110,"getnct lp2",lp2,0);
1138        lp = lp2;                       /* Make a working pointer */
1139
1140        /* Remove trailing or full-line comment */
1141
1142        while (cc = *lp) {
1143            if (cc == ';' || cc == '#') { /* Comment introducer? */
1144                if (lp == lp2) {        /* First char on line */
1145                    *lp = NUL;
1146                    break;
1147                } else if (*(lp - 1) == SP || *(lp - 1) == HT) {
1148                    lp--;
1149                    *lp = NUL;  /* Or preceded by whitespace */
1150                    break;
1151                }
1152            }
1153            lp++;
1154        }
1155        if (lp > lp2)
1156          lp--;                         /* Back up over the NUL */
1157
1158        /* Now trim any space that preceded the comment */
1159
1160        while ((*lp == SP || *lp == HT) && lp >= lp2) {
1161            *lp = NUL;
1162            if (lp <= lp2)
1163              break;
1164            lp--;
1165        }
1166        debug(F110,"getnct comment trimmed",lp2,0);
1167
1168        len = strlen(lp2);              /* Length after trimming */
1169
1170        if (n - len < 2) {              /* Check remaining space */
1171            debug(F111,"getnct command too long",s2,buflen);
1172            printf("?Line too long, maximum length: %d.\n",buflen);
1173            free(lp2);
1174            lp2 = NULL;
1175            return(-4);
1176        }
1177        ccl = (len > 0) ? lp2[len-1] : 0; /* Last character in line */
1178
1179        lp = lp2;
1180        while (*s++ = *lp++)            /* Copy result to target buffer */
1181          n--;                          /* accounting for length */
1182        s--;                            /* Back up over the NUL */
1183
1184        /* Check whether this line is continued */
1185
1186        if (flag)                       /* No line continuation when flag=1 */
1187          break;                        /* So break out of read-lines loop */
1188
1189        debug(F000,"getnct first char","",*lp3);
1190        debug(F000,"getnct last char","",ccl);
1191
1192        if (bc > 0 && *lp3 == '}')      /* First char on line is '}' */
1193          bc--;                         /* Decrement block counter */
1194
1195        if (bc == 0 &&                  /* Line is continued if bc > 0 */
1196#ifdef COMMENT
1197            /* Not supported as of C-Kermit 6.0 */
1198            ccl != CMDQ &&              /* or line ends with CMDQ */
1199#endif /* COMMENT */
1200            ccl != '-'  &&              /* or line ends with dash */
1201            ccl != '{')                 /* or line ends with opening brace */
1202          break;                        /* None of those, we're done. */
1203
1204        if (ccl == '{') {               /* Last char on line is '{'? */
1205            bc++;                       /* Count the block opener. */
1206        } else if (ccl == '-'           /* Explicit continue? */
1207#ifdef COMMENT
1208/* Not supported as of C-Kermit 6.0. */
1209                   || ccl == CMDQ
1210#endif /* COMMENT */
1211                   ) {
1212            s--;                        /* Yes, back up over terminators */
1213            n++;                        /* and over continuation character */
1214        } else {                        /* None of those but (bc > 0) */
1215            lastcomma = s;
1216            *s++ = ',';                 /* and insert a comma */
1217            n--;
1218        }
1219        debug(F101,"getnct bc","",bc);
1220        debug(F100,"getnct continued","",0);
1221    } /* read-lines while loop */
1222
1223    if (lastcomma)
1224      *lastcomma = SP;
1225    if (!flag)                          /* Tack line terminator back on */
1226      *s++ = c;
1227    *s++ = NUL;                         /* Terminate the string */
1228    untab(s2);                          /* Done, convert tabs to spaces */
1229    debug(F110,"getnct return",s2,0);
1230    free(lp2);                          /* Free temporary storage */
1231    return(0);                          /* Return success */
1232}
1233
1234/*  P A R S E R  --  Top-level interactive command parser.  */
1235 
1236/*
1237  Call with:
1238    m = 0 for normal behavior: keep parsing and executing commands
1239          until an action command is parsed, then return with a
1240          Kermit start-state as the value of this function.
1241    m = 1 to parse only one command, can also be used to call parser()
1242          recursively.
1243    m = 2 to read but do not execute one command.
1244  In all cases, parser() returns:
1245    0     if no Kermit protocol action required
1246    > 0   with a Kermit protocol start-state.
1247    < 0   upon error.
1248*/
1249int
1250parser(m) int m; {
1251    int tfcode, xx, yy, zz;             /* Workers */
1252
1253#ifndef NOSPL
1254    int inlevel;                        /* Level we were called at */
1255#endif /* NOSPL */
1256    char *cbp;                          /* Command buffer pointer */
1257#ifdef MAC
1258    extern char *lfiles;                /* Fake extern cast */
1259#endif /* MAC */
1260
1261#ifdef AMIGA
1262    reqres();                   /* restore AmigaDOS requestors */
1263#endif /* AMIGA */
1264
1265#ifdef OS2
1266    if ( cursor_save > -1 ) {           /* restore cursor if it was */
1267        cursorena[VCMD] = cursor_save ; /* turned off in file xfer  */
1268        cursor_save = -1 ;              /* mode */
1269    }
1270#endif /* OS2 */
1271
1272    what = W_COMMAND;           /* Now we're parsing commands. */
1273    moving = 0;                 /* We're not MOVE'ing */
1274    if (                        /* If at top (interactive) level ... */
1275#ifndef NOSPL
1276        cmdlvl == 0
1277#else
1278        tlevel < 0
1279#endif /* NOSPL */
1280        )
1281        concb((char)escape);    /* ... put console in 'cbreak' mode. */
1282
1283#ifdef CK_TMPDIR
1284/* If we were cd'd temporarily to another device or directory ... */
1285    if (f_tmpdir) {
1286        int x;
1287        x = zchdir((char *) savdir);    /* ... restore previous directory */
1288        f_tmpdir = 0;                   /* and remember we did it. */
1289        debug(F111,"parser tmpdir restoring",savdir,x);
1290    }
1291#endif /* CK_TMPDIR */
1292
1293#ifndef NOSPL
1294    inlevel = cmdlvl;           /* Current macro level */
1295    debug(F101,"&parser entry maclvl","",maclvl);
1296    debug(F101,"&parser entry inlevel","",inlevel);
1297    debug(F101,"&parser entry tlevel","",tlevel);
1298    debug(F101,"&parser entry cmdlvl","",cmdlvl);
1299    debug(F101,"&parser entry m","",m);
1300#endif /* NOSPL */
1301
1302/*
1303  sstate becomes nonzero when a command has been parsed that requires some
1304  action from the protocol module.  Any non-protocol actions, such as local
1305  directory listing or terminal emulation, are invoked directly from below.
1306*/
1307    sstate = 0;                         /* Start with no start state. */
1308#ifndef NOFRILLS
1309    rmailf = rprintf = 0;               /* MAIL and PRINT modifiers for SEND */
1310    *optbuf = NUL;                      /* MAIL and PRINT options */
1311#endif /* NOFRILLS */
1312#ifndef NOSPL
1313    query = 0;                          /* QUERY not active */
1314#endif /* NOSPL */
1315
1316    while (sstate == 0) {               /* Parse cmds until action requested */
1317#ifdef WHAT_THE_HECK_IS_THIS
1318        int nnn;
1319        debug(F100,"top of parse loop","",0);
1320        nnn = ttchk();
1321        debug(F101,"APC ttchk p1","",nnn);
1322#endif /* WHAT_THE_HECK_IS_THIS */
1323
1324        remfile = 0;                    /* Clear these in case REMOTE */
1325        remappd = 0;                    /* command was interrupted... */
1326        rempipe = 0;
1327
1328    /* Take requested action if there was an error in the previous command */
1329
1330#ifndef MAC
1331        conint(trap,stptrap);           /* In case we were just fg'd */
1332        bgchk();                        /* Check background status */
1333#endif /* MAC */
1334
1335     debug(F101,"tlevel","",tlevel);
1336
1337#ifndef NOSPL
1338        if (success == 0) {
1339            if (cmdstk[cmdlvl].src == CMD_TF && takerr[cmdlvl]) {
1340                printf("Command file terminated by error.\n");
1341                popclvl();
1342                if (cmdlvl == 0) return(0);
1343            }
1344            if (cmdstk[cmdlvl].src == CMD_MD && merror[cmdlvl]) {
1345                printf("Command error: macro terminated.\n");
1346                popclvl();
1347                if (m && (cmdlvl < inlevel))
1348                  return((int) sstate);
1349            }
1350        }
1351
1352        nulcmd = (m == 2);
1353#else
1354        if (success == 0 && tlevel > -1 && takerr[tlevel]) {
1355            printf("Command file terminated by error.\n");
1356            popclvl();
1357            cmini(ckxech);              /* Clear the cmd buffer. */
1358            if (tlevel < 0)             /* Just popped out of cmd files? */
1359              return(0);                /* End of init file or whatever. */
1360        }
1361#endif /* NOSPL */
1362
1363#ifdef MAC
1364        /* Check for TAKE initiated by menu. */
1365        if ((tlevel == -1) && lfiles)
1366            startlfile();
1367#endif /* MAC */
1368
1369        /* If in TAKE file, check for EOF */
1370#ifndef NOSPL
1371#ifdef MAC
1372        if
1373#else
1374        while
1375#endif /* MAC */
1376          ((cmdstk[cmdlvl].src == CMD_TF)  /* If end of take file */
1377               && (tlevel > -1)
1378               && feof(tfile[tlevel])) {
1379            popclvl();                  /* pop command level */
1380            cmini(ckxech);              /* and clear the cmd buffer. */
1381            if (cmdlvl == 0) {          /* Just popped out of all cmd files? */
1382                if (
1383#ifdef NT
1384                    StartedFromDialer &&
1385#endif /* NT */
1386                    cfilef) {           /* Delete startup file? */
1387                    if (DeleteStartupFile) {
1388                        debug(F101,"DeleteStartupFile",cmdfil,0);
1389                        zdelet(cmdfil);
1390                    }
1391                }
1392                return(0);              /* End of init file or whatever. */
1393            }
1394        }
1395#ifdef MAC
1396        miniparser(1);
1397        if (sstate == 'a') {            /* if cmd-. cancel */
1398            debug(F100, "parser: cancel take due to sstate", "", sstate);
1399            sstate = '\0';
1400            dostop();
1401            return(0);                  /* End of init file or whatever. */
1402        }
1403#endif /*  MAC */
1404
1405#else /* NOSPL */
1406        if ((tlevel > -1) && feof(tfile[tlevel])) { /* If end of take */
1407            popclvl();                  /* Pop up one level. */
1408            cmini(ckxech);              /* and clear the cmd buffer. */
1409            if (tlevel < 0)             /* Just popped out of cmd files? */
1410              return(0);                /* End of init file or whatever. */
1411        }
1412#endif /* NOSPL */
1413
1414#ifndef NOSPL
1415        if (cmdstk[cmdlvl].src == CMD_MD) { /* Executing a macro? */
1416            debug(F100,"parser macro","",0);
1417            maclvl = cmdstk[cmdlvl].lvl; /* Get current level */
1418            debug(F101,"parser maclvl","",maclvl);
1419            cbp = cmdbuf;               /* Copy next cmd to command buffer. */
1420            *cbp = NUL;
1421            if (*savbuf) {              /* In case then-part of 'if' command */
1422                strcpy(cbp,savbuf);     /* was saved, restore it. */
1423                *savbuf = '\0';
1424            } else {                    /* Else get next cmd from macro def */
1425                if (getncm(cbp,CMDBL) < 0) {
1426                    if (m && (cmdlvl < inlevel))
1427                      return((int) sstate);
1428                    else /* if (!m) */ continue;
1429                }
1430            }
1431            debug(F110,"cmdbuf from macro",cmdbuf,0);
1432
1433        } else if (cmdstk[cmdlvl].src == CMD_TF)
1434#else
1435          if (tlevel > -1) 
1436#endif /* NOSPL */
1437          {
1438#ifndef NOSPL
1439            if (*savbuf) {              /* In case THEN-part of IF command */
1440                strcpy(cmdbuf,savbuf);  /* was saved, restore it. */
1441                *savbuf = '\0';
1442            } else
1443#endif /* NOSPL */
1444
1445              /* Get next line from TAKE file */
1446
1447              if ((tfcode = getnct(cmdbuf,CMDBL,tfile[tlevel],0)) < 0) {
1448                  if (tfcode < -1) {    /* Error */
1449                      printf("?Error in TAKE command file: %s\n",
1450                             (tfcode == -2) ? "Memory allocation failure" :
1451                             "Line too long or contains NUL characters"
1452                             );
1453                      dostop();
1454                  }
1455                  continue;             /* -1 means EOF */
1456              }     
1457
1458        /* If interactive, get next command from user. */
1459
1460        } else {                        /* User types it in. */
1461            if (pflag) prompt(xxstring);
1462            cmini(ckxech);
1463        }
1464
1465    /* Now we know where next command is coming from. Parse and execute it. */
1466
1467        repars = 1;                     /* 1 = command needs parsing */
1468        displa = 0;                     /* Assume no file transfer display */
1469
1470        while (repars) {                /* Parse this cmd until entered. */
1471            debug(F101,"parser top of while loop","",0);
1472            cmres();                    /* Reset buffer pointers. */
1473
1474#ifdef OS2
1475#ifdef COMMENT
1476            /* we check to see if a macro is waiting to be executed */
1477            /* if so, we call domac on it */
1478            if (cmdmac) {
1479                strncpy(cmdbuf, cmdmac, CMDBL);
1480                free(cmdmac);
1481                cmdmac = NULL;
1482            }
1483#endif /* COMMENT */
1484#endif /* OS2 */
1485            bye_active = 0;
1486            xx = cmkey2(cmdtab,ncmd,"Command","",toktab,xxstring,1);
1487            debug(F101,"top-level cmkey2","",xx);
1488            if (xx == -5) {
1489                yy = chktok(toktab);
1490                debug(F101,"top-level cmkey token","",yy);
1491                ungword();
1492                switch (yy) {
1493                  case '#': xx = XXCOM; break; /* Comment */
1494                  case ';': xx = XXCOM; break; /* Comment */
1495#ifndef NOSPL
1496                  case ':': xx = XXLBL; break; /* GOTO label */
1497#endif /* NOSPL */
1498
1499#ifndef NOPUSH
1500#ifdef CK_REDIR           
1501                  case '<':
1502#endif /* CK_REDIR */     
1503                  case '@':
1504                  case '!':                   
1505                    if (!nopush) {
1506                        switch(yy) {
1507#ifdef CK_REDIR
1508                          case '<': xx = XXFUN; break; /* REDIRECT */
1509#endif /* CK_REDIR */
1510                          case '@':
1511                          case '!': xx = XXSHE; break; /* Shell escape */
1512                        }
1513                    }
1514                    break;
1515#endif /* NOPUSH */
1516                  default:
1517                    printf("\n?Invalid - %s\n",cmdbuf);
1518                    if (tlevel > -1) {
1519                        printf("Command file: %s, line %d\n",
1520                               tfnam[tlevel] ? tfnam[tlevel] : "",
1521                               tfline[tlevel]
1522                               );
1523                    }
1524                    xx = -2;
1525                }
1526            }
1527
1528#ifndef NOSPL
1529            /* Special handling for IF..ELSE */
1530
1531            if (ifcmd[cmdlvl])          /* Count stmts after IF */
1532              ifcmd[cmdlvl]++;
1533            if (ifcmd[cmdlvl] > 2 && xx != XXELS && xx != XXCOM)
1534              ifcmd[cmdlvl] = 0;
1535
1536            /* Execute the command and take action based on return code. */
1537
1538            if (nulcmd) {               /* Ignoring this command? */
1539                xx = XXCOM;             /* Make this command a comment. */
1540            }
1541#endif /* NOSPL */
1542
1543            zz = docmd(xx);             /* Parse rest of command & execute. */
1544            debug(F101,"docmd returns","",zz);
1545            debug(F110,"cmdbuf",cmdbuf,"");
1546            debug(F110,"atmbuf",atmbuf,"");
1547#ifdef MAC
1548            if (tlevel > -1) {
1549                if (sstate == 'a') {    /* if cmd-. cancel */
1550                    debug(F110, "parser: cancel take, sstate:", "a", 0);
1551                    sstate = '\0';
1552                    dostop();
1553                    return(0);          /* End of init file or whatever. */
1554                }
1555            }
1556#endif /* MAC */
1557            switch (zz) {
1558              case -4:                  /* EOF (e.g. on redirected stdin) */
1559                doexit(GOOD_EXIT,xitsta); /* ...exit successfully */
1560              case -1:                  /* Reparse needed */
1561                repars = 1;             /* Just set reparse flag and... */
1562                continue;
1563#ifdef OS2
1564              case -7:                  /* They typed a disk letter */
1565                if (!zchdir((char *)cmdbuf)) {
1566                    perror((char *)cmdbuf);
1567                    success = 0;
1568                } else success = 1;
1569                repars = 0;
1570                continue;
1571               
1572#endif /* OS2 */
1573              case -6:                  /* Invalid command given w/no args */
1574              case -2:                  /* Invalid command given w/args */
1575#ifdef COMMENT
1576#ifndef NOSPL
1577                    /* This is going to be really ugly... */
1578                    yy = mlook(mactab,atmbuf,nmac); /* Look in macro table */
1579                    if (yy > -1) {                  /* If it's there */
1580                        if (zz == -2) {             /* insert "do" */
1581                            char *mp;
1582                            mp = malloc((int)strlen(cmdbuf) + 5);
1583                            if (!mp) {
1584                                printf("?malloc error 1\n");
1585                                return(-2);
1586                            }
1587                            sprintf(mp,"do %s ",cmdbuf);
1588                            strcpy(cmdbuf,mp);
1589                            free(mp);
1590                            mp = NULL;
1591                        } else sprintf(cmdbuf,"do %s %c",atmbuf, CR);
1592                        if (ifcmd[cmdlvl] == 2) /* This one doesn't count! */
1593                          ifcmd[cmdlvl]--;
1594                        debug(F111,"stuff cmdbuf",cmdbuf,zz);
1595                        repars = 1;     /* Go for reparse */
1596                        continue;
1597                    } else {
1598                        char *p;
1599                        int n;
1600                        p = cmdbuf;
1601                        lp = line;     
1602                        n = LINBUFSIZ;
1603                        if (cmflgs == 0) printf("\n");
1604                        if (zzstring(p,&lp,&n) > -1)
1605                          printf("?Invalid: %s\n",line);
1606                        else
1607                          printf("?Invalid: %s\n",cmdbuf);
1608                    } /* (fall thru...) */
1609#else
1610                    printf("?Invalid: %s\n",cmdbuf);
1611#endif /* NOSPL */
1612#else /* Not COMMENT */
1613                    printf("?Invalid: %s\n",cmdbuf);
1614#endif /* COMMENT */
1615
1616                case -9:                /* Bad, error message already done */
1617                    success = 0;
1618                    debug(F110,"top-level cmkey failed",cmdbuf,0);
1619                    /* If in background w/ commands coming stdin, terminate */
1620                    if (pflag == 0 && tlevel < 0)
1621                      fatal("Kermit command error in background execution");
1622/*
1623  Command retry feature, edit 190.  If we're at interactive prompting level,
1624  reprompt the user with as much of the command as didn't fail.
1625*/
1626#ifdef CK_RECALL
1627                    if (cm_retry &&     /* If command retry enabled... */
1628#ifndef NOSPL
1629                        (cmdlvl == 0)   /* and at top (interactive) level... */
1630                       
1631#else
1632                        (tlevel < 0)
1633#endif /* NOSPL */
1634                        ) {
1635                        int len;
1636                        char *p, *s;
1637                        len = strlen(cmdbuf); /* Length of command buffer */
1638                        p = malloc(len + 1);  /* Allocate space for copy */
1639                        if (p) {              /* If we got the space */
1640                            strcpy(p,cmdbuf); /* copy the command buffer. */
1641                            /* Chop off final field, the one that failed. */
1642                            s = p + len - 1;          /* Point to end */
1643                            while (*s == SP && s > p) /* Trim blanks */
1644                              s--;
1645                            while (*s != SP && s > p) /* Trim last field */
1646                              s--;
1647                            if (s > p)        /* Keep the space */
1648                              s++;            /* after last good field */
1649                            if (s >= p)       /* Cut off remainder */
1650                              *s = NUL;
1651                            cmini(ckxech);    /* Reinitialize the parser */
1652                            strcpy(cmdbuf,p); /* Copy truncated cmd back */
1653                            free(p);          /* Free temporary storage */
1654                            p = NULL;
1655                            prompt(xxstring); /* Reprint the prompt */
1656                            printf("%s",cmdbuf); /* Reprint partial command */
1657                            repars = 1;          /* Force reparse */
1658                            continue;
1659                        }
1660                    } else
1661#endif /* CK_RECALL */
1662                      if (tlevel > -1) {
1663                          printf("Command file: %s, line %d\n",
1664                                 tfnam[tlevel] ? tfnam[tlevel] : "",
1665                                 tfline[tlevel]
1666                                 );
1667                      }
1668                      cmini(ckxech);    /* (fall thru) */
1669
1670                case -3:                /* Empty command OK at top level */
1671                    repars = 0;         /* Don't need to reparse. */
1672                    continue;           /* Go back and get another command. */
1673
1674                default:                /* Command was successful. */
1675#ifndef NOSPL
1676                    debug(F101,"parser preparing to continue","",maclvl);
1677#endif /* NOSPL */
1678                    repars = 0;         /* Don't need to reparse. */
1679                    continue;           /* Go back and get another command. */
1680                }
1681        }
1682#ifndef NOSPL
1683        debug(F101,"parser breaks out of while loop","",maclvl);
1684        if (m && (cmdlvl < inlevel))  return((int) sstate);
1685#endif /* NOSPL */
1686    }
1687
1688/* Got an action command, return start state. */
1689 
1690    return((int) sstate);
1691}
1692
1693#ifndef NOSPL
1694/*
1695  OUTPUT command.
1696  Buffering and pacing added by L.I. Kirby, 5A(189), June 1993.
1697*/
1698#define OBSIZE 80                       /* Size of local character buffer */
1699
1700static int obn;                         /* Buffer offset (high water mark) */
1701static char obuf[OBSIZE+1];             /* OUTPUT buffer. */
1702static char *obp;                       /* Pointer to output buffer. */
1703_PROTOTYP( static int oboc, (char) );
1704_PROTOTYP( static int xxout, (char *, int) );
1705
1706static int
1707#ifdef CK_ANSIC
1708xxout(char *obuf, int obsize)
1709#else
1710xxout(obuf, obsize) char *obuf; int obsize;
1711#endif /* CK_ANSIC */
1712/* xxout */ {                           /* OUTPUT command's output function */
1713    int i, rc;
1714
1715    debug(F101,"xxout obsize","",obsize);
1716    debug(F101,"xxout pacing","",pacing);
1717    debug(F111,"xxout string",obuf,strlen(obuf));
1718
1719    rc = 0;                             /* Initial return code. */
1720    if (!obuf || (obsize <= 0))         /* Nothing to output. */
1721      goto xxout_x;                     /* Return successfully */
1722
1723    rc = -1;                              /* Now assume failure */
1724    if (pacing == 0) {                    /* Is pacing enabled? */
1725        if ((local ?                      /* No, write entire string at once */
1726             ttol((CHAR *)obuf, obsize) : /* to communications device */
1727             conxo(obsize, obuf))         /* or to console */
1728            != obsize)
1729          goto xxout_x;
1730    } else {
1731        for (i = 0; i < obsize; i++) {  /* Write individual chars */
1732            if ((local ? ttoc(obuf[i]) : conoc(obuf[i])) < 0)
1733              goto xxout_x;
1734            msleep(pacing);
1735        }
1736    }
1737    rc = 0;                             /* Success */
1738  xxout_x:
1739    obn = 0;                            /* Reset count */
1740    obp = obuf;                         /* and pointers */
1741    return(rc);                         /* return our return code */
1742}
1743
1744#ifdef COMMENT
1745/*
1746  Macros for OUTPUT command execution, to make it go faster.
1747*/
1748#define obfls() ((xxout(obuf,obn)<0)?-1:0)
1749#define oboc(c) ((*obp++=(char)(c)),*obp=0,(((++obn)>=OBSIZE)?obfls():0))
1750
1751#else /* The macros cause some compilers to generate bad code. */
1752
1753static int
1754#ifdef CK_ANSIC
1755oboc(char c)
1756#else
1757oboc(c) char c;
1758#endif /* CK_ANSIC */
1759/* oboc */ {                            /* OUTPUT command's output function */
1760
1761    *obp++ = c;                         /* Deposit character */
1762    *obp = NUL;                         /* Flush buffer if it's now full */
1763
1764    return(((++obn) >= OBSIZE) ? xxout(obuf,obn) : 0);
1765}
1766#endif /* COMMENT */
1767#endif /* NOSPL */
1768
1769
1770#ifndef NOSPL
1771
1772/*  Routines for handling local variables -- also see popclvl().  */
1773
1774VOID
1775freelocal(m) int m; {                   /* Free local variables */
1776    struct localvar * v, * tv;          /* at macro level m... */
1777    debug(F101,"freelocal level","",m);
1778    if (m < 0) return;
1779    v = localhead[m];                   /* List head for level m */
1780    while (v) {
1781        if (v->lv_name)                 /* Variable name */
1782          free(v->lv_name);
1783        if (v->lv_value)                /* Value */
1784          free(v->lv_value);
1785        tv = v;                         /* Save pointer to this node */
1786        v = v->lv_next;                 /* Get next one */
1787        if (tv)                         /* Free this one */
1788          free(tv);
1789    }
1790    localhead[m] = (struct localvar *) NULL; /* Done, set list head to NULL */
1791}
1792
1793int
1794dolocal() {                             /* Do the LOCAL command */
1795    int i, x, z, len;
1796    char * s, * p;
1797    char * list[65];                    /* Up to 64 variables per line */
1798    struct localvar * v, *prev;
1799
1800    if ((x = cmtxt("Variable name(s)","",&s,NULL) < 0))
1801      return(x);
1802
1803    xwords(s,64,list,0);                /* Break up line into "words" */
1804/*
1805  loop thru variable list.
1806  if variable is defined, allocate a node for it,
1807  copy its value to the node,
1808  and undefine it.
1809*/
1810    if (v = localhead[cmdlvl]) {        /* Already have some at this level? */
1811        while (v) {                     /* Find end of list */
1812            prev = v;
1813            v = v->lv_next;
1814        }
1815    }
1816    for (i = 1; i < 10 && list[i]; i++) { /* Go through the list */
1817        if (*(list[i]) == CMDQ)  {
1818            if (parsevar(list[i],&x,&z) < 0) /* Check for valid name */
1819              continue;
1820            sprintf(tmpbuf,"\\fcontents(%s)",list[i]); /* Get definition */
1821        } else {                        /* Macro */
1822            sprintf(tmpbuf,"\\fdefinition(%s)",list[i]); /* Get def */
1823        }
1824        s = line;                       /* Point to destination buffer */
1825        x = LINBUFSIZ;                  /* Length of destination buffer */
1826        zzstring(tmpbuf,&s,&x);         /* Get definition */
1827
1828/* Name is in list[i], definition is in line[] */
1829
1830        v = (struct localvar *) malloc(sizeof(struct localvar));
1831        if (!v) {
1832            printf("?Failure to allocate storage for local variables");
1833            return(-9);
1834        }
1835        if (!localhead[cmdlvl])         /* If first, set list head */
1836          localhead[cmdlvl] = v;
1837        else                            /* Otherwise link previous to this */
1838          prev->lv_next = v;
1839        prev = v;                       /* And make this previous */
1840        v->lv_next = (struct localvar *) NULL; /* No next yet */
1841
1842        if (!(v->lv_name = (char *) malloc((int) strlen(list[i]) + 1)))
1843          goto localbad;         
1844        strcpy(v->lv_name, list[i]);    /* Copy name into new node */
1845
1846        if (*line) {
1847            if (!(v->lv_value = (char *) malloc((int) strlen(line) + 1)))
1848              goto localbad;
1849            strcpy(v->lv_value, line);  /* Copy value into new node */
1850        } else
1851          v->lv_value = NULL;
1852
1853        delmac(list[i]);                /* Delete the original macro */
1854    }
1855    return(success = 1);
1856
1857  localbad:
1858    printf("?Failure to allocate storage for local variables");
1859    freelocal(cmdlvl);
1860    return(-9);
1861}
1862#endif /* NOSPL */
1863
1864#ifndef NOSPL
1865/*  D O O U T P U T  --  Returns 0 on failure, 1 on success */
1866
1867int
1868dooutput(s) char *s; {
1869
1870    int x, xx, y, quote;                /* Workers */
1871
1872    debug(F111,"dooutput s",s,(int)strlen(s));
1873
1874#ifndef NOLOCAL
1875    if (local) {                        /* Condition external line */
1876        y = ttvt(speed,flow);
1877        if (y < 0) return(0);
1878    }
1879#endif /* NOLOCAL */
1880    if (!cmdgquo()) {                   /* COMMAND QUOTING OFF */
1881        x = strlen(s);                  /* Just send the string literally */
1882        xx = local ? ttol((CHAR *)s,x) : conxo(x,s);
1883        return(success = (xx == x) ? 1 : 0);
1884    }
1885    quote = 0;                          /* Initialize backslash (\) quote */
1886    obn = 0;                            /* Reset count */
1887    obp = obuf;                         /* and pointers */
1888
1889    while (x = *s++) {                  /* Loop through the string */
1890        y = 0;                          /* Error code, 0 = no error. */
1891        debug(F000,"dooutput","",x);
1892        if (quote) {                    /* This character is quoted */
1893#ifndef NOKVERBS
1894#define K_BUFLEN 30
1895#define SEND_BUFLEN 255
1896#define sendbufd(x) { sendbuf[sendndx++] = x;\
1897 if (sendndx == SEND_BUFLEN) {dooutput(s); sendndx = 0;}}
1898
1899           if (x == 'k' || x == 'K') { /* \k or \K */
1900               extern struct keytab kverbs[];
1901               extern int nkverbs;
1902               extern char * keydefptr;
1903               extern int keymac;
1904               extern int keymacx;     
1905               int x, y, brace = 0;
1906               int pause;
1907               char * p, * b;
1908               char kbuf[K_BUFLEN + 1]; /* Key verb name buffer */
1909               char sendbuf[SEND_BUFLEN +1];
1910               int  sendndx = 0;
1911
1912               if (xxout(obuf,obn) < 0) /* Flush buffer */
1913                 goto outerr;
1914               debug(F100,"OUTPUT KVERB","",0); /* Send a KVERB */
1915               {                        /* Have K verb? */
1916                   if (!*s) {
1917                       break;
1918                   }
1919/*
1920  We assume that the verb name is {braced}, or it extends to the end of the
1921  string, s, or it ends with a space, control character, or backslash.
1922*/
1923                   p = kbuf;            /* Copy verb name into local buffer */
1924                   x = 0;
1925                   while ((x++ < K_BUFLEN) && (*s > SP) && (*s != CMDQ)) {
1926                       if (brace && *s == '}') {
1927                           break;
1928                       }
1929                       *p++ = *s++;
1930                   }
1931                   if (*s && !brace)    /* If we broke because of \, etc, */
1932                     s--;               /*  back up so we get another look. */
1933                   brace = 0;
1934                   *p = NUL;            /* Terminate. */
1935                   p = kbuf;            /* Point back to beginning */
1936                   debug(F110,"dooutput kverb",p,0);
1937                   y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
1938                   debug(F101,"dooutput lookup",0,y);
1939                   if (y > -1) {
1940                       if ( sendndx ) {
1941                           dooutput( sendbuf );
1942                           sendndx = 0;
1943                       }
1944                       dokverb(VCMD,y);     
1945#ifndef NOSPL
1946                   } else {             /* Is it a macro? */
1947                       y = mxlook(mactab,p,nmac);
1948                       if (y > -1) {
1949                           cmpush();
1950                           keymac = 1;  /* Flag for key macro active */
1951                           keymacx = y; /* Key macro index */
1952                           keydefptr = s; /* Where to resume next time */
1953                           debug(F111,"dooutput mxlook",keydefptr,y);
1954                           parser(1);
1955                           cmpop();
1956                       }
1957#endif /* NOSPL */
1958                   }
1959               }
1960               quote = 0;
1961               continue;
1962           } else
1963#endif /* NOKVERBS */
1964             if (x == 'n' || x == 'N') { /* \n or \N */
1965                 if (xxout(obuf,obn) < 0) /* Flush buffer */
1966                   goto outerr;
1967                 debug(F100,"OUTPUT NUL","",0); /* Send a NUL */
1968                 if (local)
1969                   ttoc(NUL);
1970                 else
1971                   conoc(NUL);
1972                 quote = 0;
1973                 continue;
1974
1975             } else if (x == 'b' || x == 'B') { /* \b or \B */
1976
1977                if (xxout(obuf,obn) < 0) /* Flush buffer first */
1978                  goto outerr;
1979                debug(F100,"OUTPUT BREAK","",0);
1980#ifndef NOLOCAL
1981                ttsndb();               /* Send BREAK signal */
1982#else
1983                 if (local)
1984                   ttoc(NUL);
1985                 else
1986                   conoc(NUL);
1987#endif /* NOLOCAL */
1988                quote = 0;              /* Turn off quote flag */
1989                continue;               /* and not the b or B */
1990#ifdef CK_LBRK
1991             } else if (x == 'l' || x == 'L') { /* \l or \L */
1992                 if (xxout(obuf,obn) < 0) /* Flush buffer first */
1993                   goto outerr;
1994                 debug(F100,"OUTPUT Long BREAK","",0);
1995#ifndef NOLOCAL
1996                 ttsndlb();             /* Send Long BREAK signal */
1997#else
1998                 if (local)
1999                   ttoc(NUL);
2000                 else
2001                   conoc(NUL);
2002#endif /* NOLOCAL */
2003                 quote = 0;             /* Turn off quote flag */
2004                 continue;              /* and not the l or L */
2005#endif /* CK_LBRK */
2006
2007             } else if (x == CMDQ) {    /* Backslash itself */
2008                 debug(F100,"OUTPUT CMDQ","",0);
2009                 xx = oboc(dopar(CMDQ)); /* Output the backslash. */
2010                 if (xx < 0)
2011                   goto outerr;
2012                 quote = 0;
2013                 continue;
2014
2015             } else {                   /* if \ not followed by b or B */
2016                /* Note: Atari ST compiler won't allow macro call in "if ()" */
2017                 xx = oboc(dopar(CMDQ)); /* Output the backslash. */
2018                 if (xx < 0)
2019                   goto outerr;
2020                 quote = 0;             /* Turn off quote flag */
2021             }
2022        } else if (x == CMDQ) {         /* This is the quote character */
2023            quote = 1;                  /* Go back and get next character */
2024            continue;                   /* which is quoted */
2025        }
2026        xx = oboc(dopar((char)x));      /* Output this character */
2027        debug(F111,"dooutput",obuf,obn);
2028        if (xx < 0)
2029          goto outerr;
2030        if (seslog && duplex)           /* Log the character if log is on */
2031          if (zchout(ZSFILE,(char)x) < 0) /* and connection is half duplex */
2032            seslog = 0;
2033        if (x == '\015') {              /* String contains carriage return */
2034            int stuff = -1, stuff2 = -1;
2035            if (tnlm) {                 /* TERMINAL NEWLINE ON */
2036                stuff = LF;             /* Stuff LF */
2037        }
2038#ifdef TNCODE
2039        /* TELNET NEWLINE ON/OFF/RAW */
2040            if (network && (ttnproto == NP_TELNET)) {
2041            switch (me_binary ? tn_b_nlm : tn_nlm) { /* NVT or BINARY */
2042                case TNL_CR:
2043                    break;
2044                case TNL_CRNUL:
2045                    stuff2 = stuff;
2046                    stuff  = NUL;
2047                    break;
2048                case TNL_CRLF:
2049                    stuff2 = stuff;
2050                    stuff = LF;
2051                    break;
2052                }
2053            }
2054#endif /* TNCODE */
2055            if (stuff > -1) {           /* Stuffing another character... */
2056                xx = oboc(dopar((CHAR)stuff));
2057                if (xx < 0)
2058                  goto outerr;
2059                if (seslog && duplex)   /* Log stuffed char if appropriate */
2060                  if (zchout(ZSFILE, (CHAR)stuff) < 0)
2061                    seslog = 0;
2062            }
2063            if (stuff2 > -1) {          /* Stuffing another character... */
2064                xx = oboc(dopar((CHAR)stuff2));
2065                if (xx < 0)
2066                  goto outerr;
2067                if (seslog && duplex)   /* Log stuffed char if appropriate */
2068                  if (zchout(ZSFILE, (CHAR)stuff2) < 0)
2069                    seslog = 0;
2070            }
2071            if (xxout(obuf,obn) < 0)    /* Flushing is required here! */
2072              goto outerr;
2073        }
2074    }
2075    if (quote == 1)                     /* String ended with backslash */
2076      xx = oboc(dopar(CMDQ));
2077
2078    if (obn > 0)                        /* OUTPUT done */
2079      if (xxout(obuf,obn) < 0)          /* Flush the buffer if necessary. */
2080        goto outerr;
2081    return(1);
2082
2083outerr:                                 /* OUTPUT command error handler */
2084    if (msgflg) printf("OUTPUT error\n");
2085    return(0);
2086
2087/* Remove "local" OUTPUT macro defininitions */
2088
2089#ifdef COMMENT
2090/* No more macros ... */
2091#undef oboc
2092#undef obfls
2093#endif /* COMMENT */
2094}
2095#endif /* NOSPL */
2096
2097/* Display version herald and initial prompt */
2098
2099VOID
2100herald() {
2101    int x = 0;
2102
2103    if (noherald || bgset > 0 || (bgset != 0 && backgrd != 0)) x = 1;
2104    debug(F101,"herald","",backgrd);
2105    if (x == 0) {
2106#ifdef datageneral
2107        printf("%s, for%s\n",versio,ckxsys);
2108#else
2109#ifdef OSK
2110        printf("%s, for%s\n",versio,ckxsys);
2111#else
2112        printf("%s, for%s\n\r",versio,ckxsys);
2113#endif /* OSK */
2114#endif /* datageneral */
2115        printf(" Copyright (C) 1985, 1996,\n");
2116        printf("  Trustees of Columbia University in the City of New York.\n");
2117
2118#ifdef OS2
2119       shoreg();
2120#endif /* OS2 */
2121
2122        if (!quiet && !backgrd) {
2123            char *s = NULL;
2124            switch (binary) {
2125              case XYFT_T: s = "TEXT";         break;
2126#ifdef VMS
2127              case XYFT_B: s = "BINARY FIXED"; break;
2128              case XYFT_I: s = "IMAGE";        break;
2129              case XYFT_L: s = "LABELED";      break;
2130              case XYFT_U: s = "BINARY UNDEF"; break;
2131#else
2132#ifdef MAC
2133              case XYFT_B: s = "BINARY";       break;
2134              case XYFT_M: s = "MACBINARY";    break;
2135#else
2136              case XYFT_B: s = "BINARY";       break;
2137#ifdef CK_LABELED
2138              case XYFT_L: s = "LABELED";      break;
2139#endif /* CK_LABELED */
2140#endif /* MAC */
2141#endif /* VMS */
2142            }
2143            if (s) printf("Default file-transfer mode is %s\n", s);
2144#ifdef COMMENT
2145#ifdef NT
2146            printf("\n");
2147            printf("StartedFromDialer = %d\n",StartedFromDialer);
2148            printf("Window Handle = %ld\n",DialerHandle);
2149            printf("\n");
2150#endif /* NT */
2151#endif /* COMMENT */
2152            printf("Type ? or HELP for help.\n");
2153        }
2154    }
2155}
2156
2157#ifndef NOSPL
2158/*  M L O O K  --  Lookup the macro name in the macro table  */
2159 
2160/*
2161 Call this way:  v = mlook(table,word,n);
2162 
2163   table - a 'struct mtab' table.
2164   word  - the target string to look up in the table.
2165   n     - the number of elements in the table.
2166 
2167 The keyword table must be arranged in ascending alphabetical order, and
2168 all letters must be lowercase.
2169 
2170 Returns the table index, 0 or greater, if the name was found, or:
2171 
2172  -3 if nothing to look up (target was null),
2173  -2 if ambiguous,
2174  -1 if not found.
2175 
2176 A match is successful if the target matches a keyword exactly, or if
2177 the target is a prefix of exactly one keyword.  It is ambiguous if the
2178 target matches two or more keywords from the table.
2179*/
2180int
2181mlook(table,cmd,n) struct mtab table[]; char *cmd; int n; {
2182 
2183    int i, v, cmdlen;
2184 
2185/* Lowercase & get length of target, if it's null return code -3. */
2186 
2187    if ((((cmdlen = lower(cmd))) == 0) || (n < 1)) return(-3);
2188 
2189/* Not null, look it up */
2190 
2191    for (i = 0; i < n-1; i++) {
2192        if (!strcmp(table[i].kwd,cmd) ||
2193           ((v = !strncmp(table[i].kwd,cmd,cmdlen)) &&
2194             strncmp(table[i+1].kwd,cmd,cmdlen))) {
2195                return(i);
2196             }
2197        if (v) return(-2);
2198    }   
2199 
2200/* Last (or only) element */
2201 
2202    if (!strncmp(table[n-1].kwd,cmd,cmdlen)) {
2203        return(n-1);
2204    } else return(-1);
2205}
2206
2207/* mxlook is like mlook, but an exact full-length match is required */
2208
2209int
2210mxlook(table,cmd,n) char *cmd; struct mtab table[]; int n; {
2211    int i, cmdlen;
2212    if ((((cmdlen = lower(cmd))) == 0) || (n < 1)) return(-3);
2213    for (i = 0; i < n; i++)
2214      if (((int)strlen(table[i].kwd) == cmdlen) &&
2215          (!strncmp(table[i].kwd,cmd,cmdlen))) return(i);
2216    return(-1);
2217}
2218
2219/*
2220  This routine is for the benefit of those compilers that can't handle
2221  long string constants or continued lines within them.  Long predefined
2222  macros like FOR, WHILE, and XIF have their contents broken up into
2223  arrays of string pointers.  This routine concatenates them back into a
2224  single string again, and then calls the real addmac() routine to enter
2225  the definition into the macro table.
2226*/
2227int
2228addmmac(nam,s) char *nam, *s[]; {       /* Add a multiline macro definition */
2229    int i, x, y; char *p;
2230    x = 0;                              /* Length counter */
2231    for (i = 0; (y = (int)strlen(s[i])) > 0; i++) { /* Add up total length */
2232        debug(F111,"addmmac line",s[i],y);     
2233        x += y;
2234    }
2235    debug(F101,"addmmac lines","",i);
2236    debug(F101,"addmmac loop exit","",y);
2237    debug(F111,"addmmac length",nam,x);
2238    if (x < 0) return(-1);
2239
2240    p = malloc(x+1);                    /* Allocate space for all of it. */
2241    if (!p) {
2242        printf("?addmmac malloc error: %s\n",nam);
2243        debug(F110,"addmmac malloc error",nam,0);
2244        return(-1);
2245    }
2246    *p = '\0';                          /* Start off with null string. */
2247    for (i = 0; *s[i]; i++)             /* Concatenate them all together. */
2248      strcat(p,s[i]);
2249    y = (int)strlen(p);                 /* Final precaution. */
2250    debug(F111,"addmmac constructed string",p,y);
2251    if (y == x) {
2252        y = addmac(nam,p);              /* Add result to the macro table. */
2253    } else {
2254        debug(F100,"addmmac length mismatch","",0);
2255        printf("\n!addmmac internal error!\n");
2256        y = -1;
2257    }
2258    free(p);                            /* Free the temporary copy. */
2259    return(y); 
2260}
2261
2262/* Here is the real addmac routine. */
2263
2264/* Returns -1 on failure, 0 on success. */
2265
2266int
2267addmac(nam,def) char *nam, *def; {      /* Add a macro to the macro table */
2268    int i, x, y, z, namlen, deflen;
2269    char * p = NULL, c;
2270
2271    if (!nam) return(-1);
2272    namlen = (int)strlen(nam);          /* Get argument lengths */
2273    debug(F111,"addmac nam",nam,namlen);
2274    if (!def) {                         /* Watch out for null pointer */
2275        deflen = 0;
2276        debug(F111,"addmac def","(null pointer)",deflen);
2277    } else {
2278        deflen = (int)strlen(def);
2279        debug(F111,"addmac def",def,deflen);
2280    }
2281    if (deflen < 0) return(-1);         /* strlen() failure, fail. */
2282    if (namlen < 1) return(-1);         /* No name given, fail. */
2283
2284    if (*nam == CMDQ) nam++;            /* Backslash quote? */
2285    if (*nam == '%') {                  /* Yes, if it's a variable name, */
2286        delmac(nam);                    /* Delete any old value. */
2287        if (!(c = *(nam + 1))) return(-1); /* Variable name letter or digit */
2288        if (deflen < 1) {               /* Null definition */
2289            p = NULL;                   /* Better not malloc or strcpy! */
2290        } else {                        /* A substantial definition */
2291            p = malloc(deflen + 1);     /* Allocate space for it */
2292            if (!p) {
2293                printf("?addmac malloc error 2\n");
2294                return(-1);
2295            } else strcpy(p,def);       /* Copy definition into new space */
2296        }
2297
2298        /* Now p points to the definition, or is a null pointer */
2299
2300        if (p)
2301          debug(F110,"addmac p",p,0);
2302        else
2303          debug(F110,"addmac p","(null pointer)",0);
2304
2305        if (c >= '0' && c <= '9') {     /* Digit variable */
2306            if (maclvl < 0) {           /* Are we calling or in a macro? */
2307                g_var[c] = p;           /* No, it's a global "top level" one */
2308                debug(F101,"addmac numeric global maclvl","",maclvl);
2309            } else {                    /* Yes, it's a macro argument */
2310                char **q;
2311                m_arg[maclvl][c - '0'] = p; /* Assign the value */
2312                debug(F101,"addmac macro arg maclvl","",maclvl);
2313                q = a_ptr[0];           /* Copy pointer to macro arg vector */
2314                q[c - '0'] = p;
2315            }
2316        } else {                        /* It's a global variable */
2317            if (c < 33 || c > GVARS) return(-1);
2318            if (isupper(c)) c = (char) tolower(c);
2319            g_var[c] = p;               /* Put pointer in global-var table */
2320            debug(F100,"addmac global","",0);
2321        }
2322        return(0);
2323    } else if (*nam == '&') {           /* An array reference? */
2324        char **q;
2325        if ((y = arraynam(nam,&x,&z)) < 0) /* If syntax is bad */
2326          return(-1);                   /* return -1. */
2327        if (chkarray(x,z) < 0)          /* If array not declared or */
2328          return(-2);                   /* subscript out of range, ret -2 */
2329        delmac(nam);                    /* Delete any current definition. */
2330        x -= ARRAYBASE;                 /* Convert name letter to index. */
2331        if ((q = a_ptr[x]) == NULL)     /* If array not declared, */
2332          return(-3);                   /* return -3. */
2333        if (deflen > 0) {
2334            if ((p = malloc(deflen+1)) == NULL) { /* Allocate space */
2335                printf("addmac macro error 7: %s\n",nam);
2336                return(-4);             /* for new def, return -4 on fail. */
2337            }
2338            strcpy(p,def);              /* Copy definition into new space. */
2339        } else p = NULL;
2340        q[z] = p;                       /* Store pointer to it. */
2341        return(0);                      /* Done. */
2342    } else debug(F110,"addmac macro def",nam,0);
2343
2344/* Not a macro argument or a variable, so it's a macro definition */
2345
2346    lower(nam);                         /* Lowercase the name */
2347    if (mxlook(mactab,nam,nmac) > -1)   /* Look up, requiring exact match */
2348      delmac(nam);                      /* if it's there, delete it. */
2349    if (deflen < 1)
2350      return(0);
2351    debug(F111,"addmac table size",nam,nmac);
2352    for (y = 0;                         /* Find the alphabetical slot */
2353         y < MAC_MAX && mactab[y].kwd != NULL && strcmp(nam,mactab[y].kwd) > 0;
2354         y++);
2355    if (y == MAC_MAX) {                 /* No more room. */
2356        debug(F101,"addmac table overflow","",y);
2357        return(-1);
2358    } else debug(F111,"addmac position",nam,y);
2359    if (mactab[y].kwd != NULL) {        /* Must insert */
2360        for (i = nmac; i > y; i--) {    /* Move the rest down one slot */
2361            mactab[i].kwd = mactab[i-1].kwd;
2362            mactab[i].mval = mactab[i-1].mval;
2363            mactab[i].flgs = mactab[i-1].flgs;
2364        }
2365    }
2366    p = malloc(namlen + 1);             /* Allocate space for name */
2367    if (!p) {
2368        printf("?addmac malloc error 3: %s\n",nam);
2369        return(-1);
2370    }
2371    strcpy(p,nam);                      /* Copy name into new space */
2372    mactab[y].kwd = p;                  /* Add pointer to table */
2373
2374    if (deflen > 0) {                   /* Same deal for definition */
2375        p = malloc(deflen + 1);         /* but watch out for null pointer */
2376        if (p == NULL) {
2377            printf("?addmac malloc error 5: %s\n", nam);
2378            if (mactab[y].kwd) {
2379                free(mactab[y].kwd);
2380                mactab[y].kwd = NULL;
2381            }
2382            return(-1);
2383        } else strcpy(p,def);           /* Copy the definition */
2384    } else p = NULL;
2385    mactab[y].mval = p;
2386    mactab[y].flgs = 0;
2387    nmac++;                             /* Count this macro */
2388    return(y);
2389}
2390
2391int
2392delmac(nam) char *nam; {                /* Delete the named macro */
2393    int i, x, z;
2394    char *p, c;
2395
2396    if (!nam) return(0);                /* Watch out for null pointer */
2397    debug(F110,"delmac nam",nam,0);
2398    if (*nam == CMDQ) nam++;
2399    if (*nam == '%') {                  /* If it's a variable name */
2400        if (!(c = *(nam+1))) return(0); /* Get variable name letter or digit */
2401        p = (char *)0;                  /* Initialize value pointer */
2402        if (maclvl > -1 && c >= '0' && c <= '9') { /* Digit? */
2403            p = m_arg[maclvl][c - '0']; /* Get pointer from macro-arg table */
2404            m_arg[maclvl][c - '0'] = NULL; /* Zero the table pointer */
2405        } else {                        /* It's a global variable */
2406            if (c < 33 || c > GVARS) return(0);
2407            p = g_var[c];               /* Get pointer from global-var table */
2408            g_var[c] = NULL;            /* Zero the table entry */
2409        }
2410        if (p) {
2411            debug(F110,"delmac def",p,0);
2412            free(p);                    /* Free the storage */
2413            p = NULL;
2414        } else debug(F110,"delmac def","(null pointer)",0);
2415        return(0);
2416    }
2417           
2418    if (*nam == '&') {                  /* An array reference? */
2419        char **q;
2420        if (arraynam(nam,&x,&z) < 0)    /* If syntax is bad */
2421          return(-1);                   /* return -1. */
2422        x -= ARRAYBASE;                 /* Convert name to number. */
2423        if ((q = a_ptr[x]) == NULL)     /* If array not declared, */
2424          return(-2);                   /* return -2. */
2425        if (z > a_dim[x])               /* If subscript out of range, */
2426          return(-3);                   /* return -3. */
2427        if (q[z]) {                     /* If there is an old value, */
2428            debug(F110,"delman def",q[z],0);
2429            if (x != 0)                 /* Macro arg vector is just a copy */
2430              free(q[z]);               /* Others are real so free them */
2431            q[z] = NULL;
2432        } else debug(F110,"delmac def","(null pointer)",0);
2433    }
2434
2435   /* Not a variable or an array, so it must be a macro. */
2436
2437    if ((x = mlook(mactab,nam,nmac)) < 0) { /* Look it up */
2438        debug(F111,"delmac mlook",nam,x);
2439        return(x);
2440    }
2441    if (mactab[x].kwd) {                /* Free the storage for the name */
2442        free(mactab[x].kwd);
2443        mactab[x].kwd = NULL;
2444    }
2445    if (mactab[x].mval) {               /* and for the definition */
2446        free(mactab[x].mval);
2447        mactab[x].mval = NULL;
2448    }
2449    for (i = x; i < nmac; i++) {        /* Now move up the others. */
2450        mactab[i].kwd = mactab[i+1].kwd;
2451        mactab[i].mval = mactab[i+1].mval;
2452        mactab[i].flgs = mactab[i+1].flgs;
2453    }
2454    nmac--;                             /* One less macro */
2455    mactab[nmac].kwd = NULL;            /* Delete last item from table */
2456    mactab[nmac].mval = NULL;
2457    mactab[nmac].flgs = 0;
2458    return(0);
2459}
2460
2461VOID
2462initmac() {                             /* Init macro & variable tables */
2463    int i, j;
2464
2465    nmac = 0;                           /* No macros */
2466    for (i = 0; i < MAC_MAX; i++) {     /* Initialize the macro table */
2467        mactab[i].kwd = NULL;
2468        mactab[i].mval = NULL;
2469        mactab[i].flgs = 0;
2470    }
2471    for (i = 0; i < MACLEVEL; i++) {    /* Init the macro argument tables */
2472        mrval[i] = NULL;
2473        for (j = 0; j < 10; j++) {
2474            m_arg[i][j] = NULL;
2475        }
2476    }
2477    for (i = 0; i < GVARS; i++) {       /* And the global variables table */
2478        g_var[i] = NULL;
2479    }
2480    /* And the table of arrays */
2481    for (i = 0; i < (int) 'z' - ARRAYBASE + 1; i++) {
2482        a_ptr[i] = (char **) NULL;      /* Null pointer for each */
2483        a_dim[i] = 0;                   /* and a dimension of zero */
2484    }
2485}
2486
2487int
2488popclvl() {                             /* Pop command level, return cmdlvl */
2489    struct localvar * v;
2490    debug(F101,"popclvl cmdlvl","",cmdlvl);
2491    if (cmdlvl > 0) {
2492        if (v = localhead[cmdlvl]) { /* Did we save any variables? */
2493            while (v) {                 /* Yes */
2494                if (v->lv_value)        /* Copy old ones back */
2495                  addmac(v->lv_name,v->lv_value);
2496                else
2497                  delmac(v->lv_name);
2498                v = v->lv_next;
2499            }
2500            freelocal(cmdlvl);  /* Free local storage */
2501        }
2502    }
2503    if (cmdlvl < 1) {                   /* If we're already at top level */
2504        cmdlvl = 0;                     /* just make sure all the */
2505        tlevel = -1;                    /* stack pointers are set right */
2506        maclvl = -1;                    /* and return */
2507    } else if (cmdstk[cmdlvl].src == CMD_TF) { /* Reading from TAKE file? */
2508        debug(F101,"popclvl tlevel","",tlevel);
2509        if (tlevel > -1) {              /* Yes, */
2510            fclose(tfile[tlevel]);      /* close it */
2511            if (tfnam[tlevel]) {        /* free storage for name */
2512                free(tfnam[tlevel]);
2513                tfnam[tlevel] = NULL;
2514            }
2515            tlevel--;                   /* and pop take level */
2516            cmdlvl--;                   /* and command level */
2517        } else tlevel = -1;
2518    } else if (cmdstk[cmdlvl].src == CMD_MD) { /* In a macro? */
2519        debug(F101,"popclvl maclvl","",maclvl);
2520        if (maclvl > -1) {              /* Yes, */
2521            int i;
2522            char **q;
2523            debug(F111,"popclvl mac 1",macx[maclvl],maclvl);
2524            debug(F111,"popclvl mac 2",macp[maclvl],maclvl);
2525            macp[maclvl] = "";          /* set macro pointer to null string */
2526            debug(F111,"popclvl mac 3",macp[maclvl],maclvl);
2527            *cmdbuf = '\0';             /* clear the command buffer */
2528            debug(F111,"popclvl mac 4",mrval[maclvl+1],maclvl);
2529            if (mrval[maclvl+1]) {      /* Free any deeper return values. */
2530                free(mrval[maclvl+1]);
2531                mrval[maclvl+1] = NULL;
2532            }
2533            debug(F111,"popclvl mac 6",mrval[maclvl+1],maclvl);
2534            maclvl--;                   /* Pop macro level */
2535            cmdlvl--;                   /* and command level */
2536            q = a_ptr[0];
2537            debug(F101,"popclvl mac 7","",maclvl);
2538            if (maclvl > -1)
2539              for (i = 0; i < 10; i++)  /* Restore previous arg vector */
2540                q[i] = m_arg[maclvl][i];
2541            debug(F111,"popclvl mac 8",
2542                  (maclvl > -1 && macx[maclvl]) ? macx[maclvl] : "",maclvl);
2543        } else maclvl = -1;
2544    }
2545#ifndef MAC
2546    if (cmdlvl < 1) {                   /* If back at top level */
2547        conint(trap,stptrap);           /* Fix interrupts */
2548        bgchk();                        /* Check background status */
2549        concb((char)escape);            /* Go into cbreak mode */
2550    }
2551#endif /* MAC */
2552    return(cmdlvl < 1 ? 0 : cmdlvl);    /* Return command level */
2553}
2554#else /* No script programming language */
2555int popclvl() {                         /* Just close current take file. */
2556    if (tlevel > -1) {                  /* if any... */
2557        if (tfnam[tlevel]) {
2558            free(tfnam[tlevel]);
2559            tfnam[tlevel] = NULL;
2560        }
2561        fclose(tfile[tlevel--]);
2562    }
2563    if (tlevel == -1) {                 /* And if back at top level */
2564        conint(trap,stptrap);           /* check and set interrupts */
2565        bgchk();                        /* and background status */
2566        concb((char)escape);            /* and go back into cbreak mode. */
2567    }
2568    return(tlevel + 1);
2569}
2570#endif /* NOSPL */
2571
2572/* STOP - get back to C-Kermit prompt, no matter where from. */
2573
2574int
2575dostop() {
2576    while (popclvl()) ;         /* Pop all macros & take files */
2577#ifndef NOSPL
2578    while (cmpop() > -1);       /* And all recursive cmd pkg invocations */
2579#endif /* NOSPL */
2580    cmini(ckxech);              /* Clear the command buffer. */
2581    return(0);
2582}
2583
2584
2585/* Close the given log */
2586
2587int
2588doclslog(x) int x; {
2589    int y;
2590    switch (x) {
2591#ifdef DEBUG
2592        case LOGD:
2593            if (deblog <= 0) {
2594                printf("?Debugging log wasn't open\n");
2595                return(0);
2596            }
2597            debug(F100,"Debug Log Closed","",0L);
2598            *debfil = '\0';
2599            deblog = 0;
2600            return(zclose(ZDFILE));
2601#endif /* DEBUG */
2602
2603        case LOGP:
2604            if (pktlog <= 0) {
2605                printf("?Packet log wasn't open\n");
2606                return(0);
2607            }
2608            *pktfil = '\0';
2609            pktlog = 0;
2610            return(zclose(ZPFILE));
2611 
2612#ifndef NOLOCAL
2613        case LOGS:
2614            if (seslog <= 0) {
2615                printf("?Session log wasn't open\n");
2616                return(0);
2617            }
2618            *sesfil = '\0';
2619            seslog = 0;
2620            return(zclose(ZSFILE));
2621#endif /* NOLOCAL */
2622 
2623#ifdef TLOG
2624        case LOGT:
2625            if (tralog <= 0) {
2626                printf("?Transaction log wasn't open\n");
2627                return(0);
2628            }
2629            tlog(F100,"Transaction Log Closed","",0L);
2630            *trafil = '\0';
2631            tralog = 0;
2632            return(zclose(ZTFILE));
2633#endif /* TLOG */
2634 
2635#ifndef NOSPL
2636          case LOGW:                    /* WRITE file */
2637          case LOGR:                    /* READ file */
2638            y = (x == LOGR) ? ZRFILE : ZWFILE;
2639            if (chkfn(y) < 1)           /* If no file to close */
2640              return(1);                /* succeed silently. */
2641            return(zclose(y));          /* Otherwise, close the file. */
2642#endif /* NOSPL */
2643
2644        default:
2645            printf("\n?Unexpected log designator - %d\n", x);
2646            return(0);
2647        }
2648}
2649
2650static char *nm[] =  { "disabled", "local only", "remote only", "enabled" };
2651
2652static int slc = 0;                     /* Screen line count */
2653
2654#ifndef NOSHOW
2655char *
2656showoff(x) int x; {
2657    return( x ? "on" : "off");
2658}
2659
2660#ifndef NOFRILLS
2661#define xxdiff(v,sys) strncmp(v,sys,strlen(sys))
2662VOID
2663shover() {
2664    extern long xvernum;
2665    extern char *ck_ver;
2666    printf("\nVersions:\n %s\n Numeric: %ld",versio,vernum);
2667    if (verwho) printf("-%d",verwho);
2668    printf("\n");
2669    if (xvernum)
2670      printf("C-Kermit %s\n",ck_ver);
2671    printf(xxdiff(ckxv,ckxsys) ? " %s for%s\n" : " %s\n",ckxv,ckxsys);
2672    printf(xxdiff(ckzv,ckzsys) ? " %s for%s\n" : " %s\n",ckzv,ckzsys);
2673    printf(" %s\n",protv);
2674    printf(" %s\n",fnsv);
2675    printf(" %s\n %s\n",cmdv,userv);
2676#ifndef NOCSETS
2677    printf(" %s\n",xlav);
2678#endif /* NOCSETS */
2679#ifndef MAC
2680    printf(" %s\n",connv);
2681#endif /* MAC */
2682#ifndef NODIAL
2683    printf(" %s\n",dialv);
2684#endif /* NODIAL */
2685#ifndef NOSCRIPT
2686    printf(" %s\n",loginv);
2687#endif /* NOSCRIPT */
2688#ifdef NETCONN
2689    printf(" %s\n",cknetv);
2690#ifdef OS2
2691    printf(" %s\n",ckonetv);
2692#ifdef CK_NETBIOS
2693    printf(" %s\n",ckonbiv);
2694#endif /* CK_NETBIOS */
2695#ifdef OS2MOUSE
2696    printf(" %s\n",ckomouv);
2697#endif /* OS2MOUSE */
2698#endif /* OS2 */
2699#endif /* NETCONN */
2700    printf("\n");
2701}
2702
2703VOID
2704shofea() {
2705    int flag = 0;
2706    int lines = 5;
2707#ifdef OS2
2708#ifdef NT
2709    if (isWin95())
2710      printf("\nWindows 95.\n");
2711    else
2712      printf("\nWindows NT.\n");
2713    lines++;
2714#else /* NT */
2715#ifdef M_I286
2716    printf("\nOS/2 16-bit.\n");
2717#else
2718    printf("\nOS/2 32-bit.\n");
2719#endif /* M_I286 */
2720    lines++;
2721#endif /* NT */
2722#endif /* OS2 */
2723    printf("\nMajor optional features included:\n");
2724    lines++;
2725#ifdef NETCONN
2726    printf(" Network support (type SHOW NET for further info)\n");
2727    lines++;
2728#endif /* NETCONN */
2729#ifdef CK_RTSCTS
2730    printf(" Hardware flow control\n");
2731    lines++;
2732#endif /* CK_RTSCTS */
2733
2734#ifdef CK_XYZ
2735#ifdef XYZ_INTERNAL
2736    printf(" Built-in XYZMODEM protocols\n");
2737#else
2738    printf(" External XYZMODEM protocol support\n");
2739#endif /* XYZ_INTERNAL */
2740    lines++;
2741#endif /* CK_XYZ */
2742
2743#ifndef NOCSETS
2744    printf(" Latin-1 (West European) character-set translation\n");
2745    lines++;
2746#ifdef LATIN2
2747    printf(" Latin-2 (East European) character-set translation\n");
2748    lines++;
2749#endif /* LATIN2 */
2750#ifdef CYRILLIC
2751    printf(" Cyrillic (Russian, Ukrainian, etc) character-set translation\n");
2752    lines++;
2753#endif /* CYRILLIC */
2754#ifdef HEBREW
2755    printf(" Hebrew character-set translation\n");
2756    lines++;
2757#endif /* HEBREW */
2758#ifdef KANJI
2759    printf(" Kanji (Japanese) character-set translation\n");
2760    lines++;
2761#endif /* KANJI */
2762#ifdef CKOUNI
2763    if (isunicode())
2764      printf(" Unicode support for ISO-2022 Terminal Emulation\n");
2765    else
2766      printf(" Unicode translation for Terminal Character-Sets\n");
2767#endif /* CKOUNI */
2768#endif /* NOCSETS */
2769
2770#ifdef CK_REDIR
2771    printf(" REDIRECT command\n");
2772    lines++;
2773#endif /* CK_REDIR */
2774#ifdef CK_RESEND
2775    printf(" RESEND command\n");
2776    lines++;
2777#endif /* CK_RESEND */
2778
2779#ifdef CK_CURSES
2780    printf(" Fullscreen file transfer display\n");
2781    lines++;
2782#endif /* CK_CURSES */
2783
2784#ifdef CK_SPEED
2785    printf(" Control-character unprefixing\n");
2786    lines++;
2787#endif /* CK_SPEED */
2788
2789#ifdef OS2MOUSE
2790    printf(" Mouse support\n");
2791    lines++;
2792#endif /* OS2MOUSE */
2793
2794#ifdef CK_REXX
2795    printf(" REXX script language interface\n");
2796    lines++;
2797#endif /* CK_REXX */
2798
2799    printf("\nMajor optional features not included:\n");
2800    lines++;
2801#ifndef CK_CURSES
2802#ifndef MAC
2803    printf(" No fullscreen file transfer display\n");
2804    lines++;
2805    flag = 1;
2806#endif /* MAC */
2807#endif /* CK_CURSES */
2808#ifdef NOSERVER
2809    printf(" No server mode\n");
2810    lines++;
2811    flag = 1;
2812#endif /* NOSERVER */
2813#ifdef NODEBUG
2814    printf(" No debugging\n");
2815    lines++;
2816    flag = 1;
2817#endif /* NODEBUG */
2818#ifdef NOTLOG
2819    printf(" No transaction log\n");
2820    lines++;
2821    flag = 1;
2822#endif /* NOTLOG */
2823#ifdef NOHELP
2824    printf(" No built-in help\n");
2825    lines++;
2826    flag = 1;
2827#endif /* NOHELP */
2828#ifndef NETCONN
2829    printf(" No network support\n");
2830    lines++;
2831    flag = 1;
2832#endif /* NETCONN */
2833#ifdef NOMSEND
2834    printf(" No MSEND command\n");
2835    lines++;
2836    flag = 1;
2837#endif /* NOMSEND */
2838#ifdef NODIAL
2839    printf(" No DIAL command\n");
2840    lines++;
2841    flag = 1;
2842#else
2843#ifdef MINIDIAL
2844    printf(
2845         " No DIAL command for modems other than Hayes, CCITT, and Unknown\n");
2846    lines++;
2847    flag = 1;
2848#endif /* MINIDIAL */
2849#ifndef CK_RTSCTS
2850#ifndef MAC
2851    printf(" No hardware flow control\n");
2852    lines++;
2853    flag = 1;
2854#endif /* MAC */
2855#endif /* CK_RTSCTS */
2856#endif /* NODIAL */
2857#ifdef NOXMIT
2858    printf(" No TRANSMIT command\n");
2859    lines++;
2860    flag = 1;
2861#endif /* NOXMIT */
2862#ifdef NOSCRIPT
2863    printf(" No SCRIPT command\n");
2864    lines++;
2865    flag = 1;
2866#endif /* NOSCRIPT */
2867#ifdef NOSPL
2868    printf(" No script programming features\n");
2869    lines++;
2870    flag = 1;
2871#endif /* NOSPL */
2872#ifndef CK_XYZ
2873    printf(" No built-in XYZMODEM protocols\n");
2874    lines++;
2875    flag = 1;
2876#endif /* CK_XYZ */
2877#ifdef NOCSETS
2878    printf(" No character-set translation\n");
2879    lines++;
2880    flag = 1;
2881#else
2882#ifndef LATIN2
2883    printf(" No Latin-2 character-set translation\n");
2884    lines++;
2885    flag = 1;
2886#endif /* LATIN2 */
2887#ifdef NOHEBREW
2888    printf(" No Hebrew character-set translation\n");
2889    lines++;
2890    flag = 1;
2891#endif /* NOHEBREW */
2892#ifdef NOCYRIL
2893    printf(" No Cyrillic character-set translation\n");
2894    lines++;
2895    flag = 1;
2896#endif /* NOCYRIL */
2897#ifndef KANJI
2898    printf(" No Kanji character-set translation\n");
2899    lines++;
2900    flag = 1;
2901#endif /* KANJI */
2902#endif /* NOCSETS */
2903#ifdef NOCMDL
2904    printf(" No command-line arguments\n");
2905    lines++;
2906    flag = 1;
2907#endif /* NOCMDL */
2908#ifdef NOFRILLS
2909    printf(" No frills\n");
2910    lines++;
2911    flag = 1;
2912#endif /* NOFRILLS */
2913#ifdef NOPUSH
2914    printf(" No escape to system\n");
2915    lines++;
2916    flag = 1;
2917#endif /* NOPUSH */
2918#ifdef NOJC
2919#ifdef UNIX
2920    printf(" No UNIX job control\n");
2921    lines++;
2922    flag = 1;
2923#endif /* UNIX */
2924#endif /* NOJC */
2925#ifdef NOSETKEY
2926    printf(" No SET KEY command\n");
2927    lines++;
2928    flag = 1;
2929#endif /* NOSETKEY */
2930#ifndef PARSENSE
2931    printf(" No automatic parity detection\n");
2932    lines++;
2933    flag = 1;
2934#endif /* PARSENSE */
2935#ifndef CK_SPEED
2936    printf(" No control-character unprefixing\n");
2937    lines++;
2938    flag = 1;
2939#endif /* CK_SPEED */
2940#ifndef CK_REDIR
2941    printf(" No REDIRECT command\n");
2942    lines++;
2943    flag = 1;
2944#endif /* CK_REDIR */
2945#ifndef CK_RESEND
2946    printf(" No RESEND command\n");
2947    lines++;
2948    flag = 1;
2949#endif /* CK_RESEND */
2950#ifdef OS2
2951#ifdef __32BIT__
2952#ifndef OS2MOUSE
2953    printf(" No Mouse support\n");
2954    lines++;
2955    flag = 1;
2956#endif /* __32BIT__ */
2957#endif /* OS2 */
2958#endif /* OS2MOUSE */
2959#ifdef OS2
2960#ifndef NT
2961#ifndef CK_REXX
2962    printf(" No REXX script language interface\n");
2963    lines++;
2964    flag = 1;
2965#endif /* CK_REXX */
2966#endif /* NT */
2967#endif /* OS2 */
2968
2969    if (flag == 0) { printf(" None\n"); lines++; }
2970/*
2971  Print compile-time (-D) options, as well as C preprocessor
2972  predefined symbols that might affect us...
2973*/
2974#ifdef __DATE__                         /* GNU and other ANSI */
2975#ifdef __TIME__
2976    printf("\nCompiled %s %s, options:\n", __DATE__, __TIME__);
2977#else
2978    printf("\nCompiled %s, options:\n", __DATE__);
2979#endif /* __TIME__ */
2980#else /* !__DATE__ */
2981    printf("\nCompiler options:\n");
2982#endif /* __DATE__ */
2983    lines++;
2984
2985#ifdef MAC
2986#ifdef MPW
2987    if (!prtopt(&lines,"MPW")) return;
2988#else
2989#ifdef THINK_C
2990    if (!prtopt(&lines,"THINK_C")) return;
2991#endif /* THINK_C */
2992#endif /* MPW */
2993#endif /* MAC */
2994
2995#ifdef __386__
2996    if (!prtopt(&lines,"__386__")) return;
2997#endif /* __386__ */
2998
2999#ifdef DEBUG
3000#ifdef IFDEBUG
3001    if (!prtopt(&lines,"IFDEBUG")) return;
3002#else
3003    if (!prtopt(&lines,"DEBUG")) return;
3004#endif /* IFDEBUG */
3005#endif /* DEBUG */
3006#ifdef TLOG
3007    if (!prtopt(&lines,"TLOG")) return;
3008#endif /* TLOG */
3009#ifdef BIGBUFOK
3010    if (!prtopt(&lines,"BIGBUFOK")) return;
3011#endif /* BIGBUFOK */
3012#ifdef XFRCAN
3013    if (!prtopt(&lines,"XFRCAN")) return;
3014#endif /* XFRCAN */
3015#ifdef CK_SPEED
3016    if (!prtopt(&lines,"CK_SPEED")) return;
3017#endif /* CK_SPEED */
3018#ifdef CK_APC
3019    if (!prtopt(&lines,"CK_APC")) return;
3020#endif /* CK_APC */
3021#ifdef CK_AUTODL
3022    if (!prtopt(&lines,"CK_AUTODL")) return;
3023#endif /* CK_AUTODL */
3024#ifdef CK_MKDIR
3025    if (!prtopt(&lines,"CK_MKDIR")) return;
3026#endif /* CK_MKDIR */
3027#ifdef NOMKDIR
3028    if (!prtopt(&lines,"NOMKDIR")) return;
3029#endif /* NOMKDIR */
3030#ifdef CK_LABELED
3031    if (!prtopt(&lines,"CK_LABELED")) return;
3032#endif /* CK_LABELED */
3033#ifdef NODIAL
3034    if (!prtopt(&lines,"NODIAL")) return;
3035#endif /* NODIAL */
3036#ifdef MINIDIAL
3037    if (!prtopt(&lines,"MINIDIAL")) return;
3038#endif /* MINIDIAL */
3039#ifdef WHATAMI
3040    if (!prtopt(&lines,"WHATAMI")) return;
3041#endif /* WHATAMI */
3042#ifdef DYNAMIC
3043    if (!prtopt(&lines,"DYNAMIC")) return;
3044#endif /* IFDEBUG */
3045#ifndef NOSPL
3046    sprintf(line,"CMDDEP=%d",CMDDEP);
3047    if (!prtopt(&lines,line)) return;
3048#endif /* NOSPL */
3049
3050    sprintf(line,"CKMAXPATH=%d",CKMAXPATH);
3051    if (!prtopt(&lines,line)) return;
3052
3053#ifdef MAXGETPATH
3054    sprintf(line,"MAXGETPATH=%d",MAXGETPATH);
3055    if (!prtopt(&lines,line)) return;
3056#endif /* MAXGETPATH */
3057
3058#ifdef CMDBL
3059    sprintf(line,"CMDBL=%d",CMDBL);
3060    if (!prtopt(&lines,line)) return;
3061#endif /* CMDBL */
3062
3063#ifdef VNAML
3064    sprintf(line,"VNAML=%d",VNAML);
3065    if (!prtopt(&lines,line)) return;
3066#endif /* VNAML */
3067
3068#ifdef ARRAYREFLEN
3069    sprintf(line,"ARRAYREFLEN=%d",ARRAYREFLEN);
3070    if (!prtopt(&lines,line)) return;
3071#endif /* ARRAYREFLEN */
3072
3073#ifdef FORDEPTH
3074    sprintf(line,"FORDEPTH=%d",FORDEPTH);
3075    if (!prtopt(&lines,line)) return;
3076#endif /* FORDEPTH */
3077
3078#ifdef MAXTAKE
3079    sprintf(line,"MAXTAKE=%d",MAXTAKE);
3080    if (!prtopt(&lines,line)) return;
3081#endif /* MAXTAKE */
3082
3083#ifdef MACLEVEL
3084    sprintf(line,"MACLEVEL=%d",MACLEVEL);
3085    if (!prtopt(&lines,line)) return;
3086#endif /* MACLEVEL */
3087
3088#ifdef MAC_MAX
3089    sprintf(line,"MAC_MAX=%d",MAC_MAX);
3090    if (!prtopt(&lines,line)) return;
3091#endif /* MAC_MAX */
3092
3093#ifdef MINPUTMAX
3094    sprintf(line,"MINPUTMAX=%d",MINPUTMAX);
3095    if (!prtopt(&lines,line)) return;
3096#endif /* MINPUTMAX */
3097
3098#ifdef MSENDMAX
3099    sprintf(line,"MSENDMAX=%d",MSENDMAX);
3100    if (!prtopt(&lines,line)) return;
3101#endif /* MSENDMAX  */
3102
3103#ifdef MAXDDIR
3104    sprintf(line,"MAXDDIR=%d",MAXDDIR);
3105    if (!prtopt(&lines,line)) return;
3106#endif /* MAXDDIR  */
3107
3108#ifdef MAXDNUMS
3109    sprintf(line,"MAXDNUMS=%d",MAXDNUMS);
3110    if (!prtopt(&lines,line)) return;
3111#endif /* MAXDNUMS  */
3112
3113#ifdef UNIX
3114    if (!prtopt(&lines,"UNIX")) return;
3115#endif /* UNIX */
3116#ifdef VMS
3117    if (!prtopt(&lines,"VMS")) return;
3118#ifdef __VMS_VER
3119    sprintf(line,"__VMS_VER=%d",__VMS_VER);
3120    if (!prtopt(&lines,line)) return;
3121#endif /* __VMS_VER */
3122#ifdef VMSV70
3123    if (!prtopt(&lines,"VMSV70")) return;
3124#endif /* VMSV70 */
3125#endif /* VMS */
3126#ifdef OLD_VMS
3127    if (!prtopt(&lines,"OLD_VMS")) return;
3128#endif /* OLD_VMS */
3129#ifdef vms
3130    if (!prtopt(&lines,"vms")) return;
3131#endif /* vms */
3132#ifdef VMSSHARE
3133    if (!prtopt(&lines,"VMSSHARE")) return;
3134#endif /* VMSSHARE */
3135#ifdef datageneral
3136    if (!prtopt(&lines,"datageneral")) return;
3137#endif /* datageneral */
3138#ifdef apollo
3139    if (!prtopt(&lines,"apollo")) return;
3140#endif /* apollo */
3141#ifdef aegis
3142    if (!prtopt(&lines,"aegis")) return;
3143#endif /* aegis */
3144#ifdef A986
3145    if (!prtopt(&lines,"A986")) return;
3146#endif /* A986 */
3147#ifdef AMIGA
3148    if (!prtopt(&lines,"AMIGA")) return;
3149#endif /* AMIGA */
3150#ifdef CONVEX9
3151    if (!prtopt(&lines,"CONVEX9")) return;
3152#endif /* CONVEX9 */
3153#ifdef CONVEX10
3154    if (!prtopt(&lines,"CONVEX10")) return;
3155#endif /* CONVEX9 */
3156#ifdef MAC
3157    if (!prtopt(&lines,"MAC")) return;
3158#endif /* MAC */
3159#ifdef AUX
3160    if (!prtopt(&lines,"AUX")) return;
3161#endif /* AUX */
3162#ifdef OS2
3163    if (!prtopt(&lines,"OS2")) return;
3164#ifdef NT
3165    if (!prtopt(&lines,"NT")) return;
3166#endif /* NT */
3167#endif /* OS2 */
3168#ifdef OSK
3169    if (!prtopt(&lines,"OS9")) return;
3170#endif /* OSK */
3171#ifdef MSDOS
3172    if (!prtopt(&lines,"MSDOS")) return;
3173#endif /* MSDOS */
3174#ifdef DIRENT
3175    if (!prtopt(&lines,"DIRENT")) return;
3176#endif /* DIRENT */
3177#ifdef SDIRENT
3178    if (!prtopt(&lines,"SDIRENT")) return;
3179#endif /* SDIRENT */
3180#ifdef NDIR
3181    if (!prtopt(&lines,"NDIR")) return;
3182#endif /* NDIR */
3183#ifdef XNDIR
3184    if (!prtopt(&lines,"XNDIR")) return;
3185#endif /* XNDIR */
3186#ifdef MATCHDOT
3187    if (!prtopt(&lines,"MATCHDOT")) return;
3188#endif /* MATCHDOT */
3189#ifdef SAVEDUID
3190    if (!prtopt(&lines,"SAVEDUID")) return;
3191#endif /* SAVEDUID */
3192#ifdef RENAME
3193    if (!prtopt(&lines,"RENAME")) return;
3194#endif /* RENAME */
3195#ifdef CK_TMPDIR
3196    if (!prtopt(&lines,"CK_TMPDIR")) return;
3197#endif /* CK_TMPDIR */
3198#ifdef NOCCTRAP
3199    if (!prtopt(&lines,"NOCCTRAP")) return;
3200#endif /* NOCCTRAP */
3201#ifdef CK_NEED_SIG
3202    if (!prtopt(&lines,"CK_NEED_SIG")) return;
3203#endif /* CK_NEED_SIG */
3204#ifdef CK_TTYFD
3205    if (!prtopt(&lines,"CK_TTYFD")) return;
3206#endif /* CK_TTYFD */
3207#ifdef NETCONN
3208    if (!prtopt(&lines,"NETCONN")) return;
3209#endif /* NETCONN */
3210#ifdef TCPSOCKET
3211    if (!prtopt(&lines,"TCPSOCKET")) return;
3212#ifdef NOTCPOPTS
3213    if (!prtopt(&lines,"NOTCPOPTS")) return;
3214#endif /* NOTCPOPTS */
3215#ifdef NOLISTEN
3216    if (!prtopt(&lines,"NOLISTEN")) return;
3217#endif /* NOLISTEN */
3218#ifdef SOL_SOCKET
3219    if (!prtopt(&lines,"SOL_SOCKET")) return;
3220#endif /* SOL_SOCKET */
3221#ifdef TCP_NODELAY
3222    if (!prtopt(&lines,"TDP_NODELAY")) return;
3223#endif /* TCP_NODELAY */
3224#ifdef HADDRLIST
3225    if (!prtopt(&lines,"HADDRLIST")) return;
3226#endif /* HADDRLIST */
3227#ifdef CK_SOCKS
3228    if (!prtopt(&lines,"CK_SOCKS")) return;
3229#endif /* CK_SOCKS */
3230#ifdef RLOGCODE
3231    if (!prtopt(&lines,"RLOGCODE")) return;
3232#endif /* RLOGCODE */
3233#ifdef CONGSPD
3234    if (!prtopt(&lines,"CONGSPD")) return;
3235#endif /* CONGSPDCK_SOCKS */
3236#endif /* TCPSOCKET */
3237#ifdef SUNX25
3238    if (!prtopt(&lines,"SUNX25")) return;
3239#endif /* SUNX25 */
3240#ifdef DECNET
3241    if (!prtopt(&lines,"DECNET")) return;
3242#endif /* DECNET */
3243#ifdef SUPERLAT
3244   if (!prtopt(&lines,"SUPERLAT")) return;
3245#endif /* SUPERLAT */
3246#ifdef NPIPE
3247    if (!prtopt(&lines,"NPIPE")) return;
3248#endif /* NPIPE */
3249#ifdef CK_NETBIOS
3250    if (!prtopt(&lines,"CK_NETBIOS")) return;
3251#endif /* CK_NETBIOS */
3252#ifdef ATT7300
3253    if (!prtopt(&lines,"ATT7300")) return;
3254#endif /* ATT7300 */
3255#ifdef ATT6300
3256    if (!prtopt(&lines,"ATT6300")) return;
3257#endif /* ATT6300 */
3258#ifdef HDBUUCP
3259    if (!prtopt(&lines,"HDBUUCP")) return;
3260#endif /* HDBUUCP */
3261#ifdef NOUUCP
3262    if (!prtopt(&lines,"NOUUCP")) return;
3263#endif /* NOUUCP */
3264#ifdef LONGFN
3265    if (!prtopt(&lines,"LONGFN")) return;
3266#endif /* LONGFN */
3267#ifdef RDCHK
3268    if (!prtopt(&lines,"RDCHK")) return;
3269#endif /* RDCHK */
3270#ifdef SELECT
3271    if (!prtopt(&lines,"SELECT")) return;
3272#endif /* SELECT */
3273#ifdef USLEEP
3274    if (!prtopt(&lines,"USLEEP")) return;
3275#endif /* USLEEP */
3276#ifdef NAP
3277    if (!prtopt(&lines,"NAP")) return;
3278#endif /* NAP */
3279#ifdef NAPHACK
3280    if (!prtopt(&lines,"NAPHACK")) return;
3281#endif /* NAPHACK */
3282#ifdef CK_POLL
3283    if (!prtopt(&lines,"CK_POLL")) return;
3284#endif /* CK_POLL */
3285#ifdef NOIEXTEN
3286    if (!prtopt(&lines,"NOIEXTEN")) return;
3287#endif /* NOIEXTEN */
3288#ifdef EXCELAN
3289    if (!prtopt(&lines,"EXCELAN")) return;
3290#endif /* EXCELAN */
3291#ifdef INTERLAN
3292    if (!prtopt(&lines,"INTERLAN")) return;
3293#endif /* INTERLAN */
3294#ifdef NOFILEH
3295    if (!prtopt(&lines,"NOFILEH")) return;
3296#endif /* NOFILEH */
3297#ifdef NOSYSIOCTLH
3298    if (!prtopt(&lines,"NOSYSIOCTLH")) return;
3299#endif /* NOSYSIOCTLH */
3300#ifdef DCLPOPEN
3301    if (!prtopt(&lines,"DCLPOPEN")) return;
3302#endif /* DCLPOPEN */
3303#ifdef NOSETBUF
3304    if (!prtopt(&lines,"NOSETBUF")) return;
3305#endif /* NOSETBUF */
3306#ifdef NOFDZERO
3307    if (!prtopt(&lines,"NOFDZERO")) return;
3308#endif /* NOFDZERO */
3309#ifdef NOPOPEN
3310    if (!prtopt(&lines,"NOPOPEN")) return;
3311#endif /* NOPOPEN */
3312#ifdef NOPARTIAL
3313    if (!prtopt(&lines,"NOPARTIAL")) return;
3314#endif /* NOPARTIAL */
3315#ifdef NOKVERBS
3316    if (!prtopt(&lines,"NOKVERBS")) return;
3317#endif /* NOKVERBS */
3318#ifdef NOSETREU
3319    if (!prtopt(&lines,"NOSETREU")) return;
3320#endif /* NOSETREU */
3321#ifdef _POSIX_SOURCE
3322    if (!prtopt(&lines,"_POSIX_SOURCE")) return;
3323#endif /* _POSIX_SOURCE */
3324#ifdef LCKDIR
3325    if (!prtopt(&lines,"LCKDIR")) return;
3326#endif /* LCKDIR */
3327#ifdef ACUCNTRL
3328    if (!prtopt(&lines,"ACUCNTRL")) return;
3329#endif /* ACUCNTRL */
3330#ifdef BSD4
3331    if (!prtopt(&lines,"BSD4")) return;
3332#endif /* BSD4 */
3333#ifdef BSD44
3334    if (!prtopt(&lines,"BSD44")) return;
3335#endif /* BSD44 */
3336#ifdef BSD41
3337    if (!prtopt(&lines,"BSD41")) return;
3338#endif /* BSD41 */
3339#ifdef BSD43
3340    if (!prtopt(&lines,"BSD43")) return;
3341#endif /* BSD43 */
3342#ifdef BSD29
3343    if (!prtopt(&lines,"BSD29")) return;
3344#endif /* BSD29 */
3345#ifdef BSDI
3346    if (!prtopt(&lines,"BSDI")) return;
3347#endif /* BSDI */
3348#ifdef __bsdi__
3349    if (!prtopt(&lines,"__bsdi__")) return;
3350#endif /* __bsdi__ */
3351#ifdef __NetBSD__
3352    if (!prtopt(&lines,"__NetBSD__")) return;
3353#endif /* __NetBSD__ */
3354#ifdef __FreeBSD__
3355    if (!prtopt(&lines,"__FreeBSD__")) return;
3356#endif /* __FreeBSD__ */
3357#ifdef __linux__
3358    if (!prtopt(&lines,"__linux__")) return;
3359#endif /* __linux__ */
3360#ifdef LINUX_HI_SPD
3361    if (!prtopt(&lines,"LINUX_HI_SPD")) return;
3362#endif /* LINUX_HI_SPD */
3363#ifdef LYNXOS
3364    if (!prtopt(&lines,"LYNXOS")) return;
3365#endif /* LYNXOS */
3366#ifdef V7
3367    if (!prtopt(&lines,"V7")) return;
3368#endif /* V7 */
3369#ifdef AIX370
3370    if (!prtopt(&lines,"AIX370")) return;
3371#endif /* AIX370 */
3372#ifdef RTAIX
3373    if (!prtopt(&lines,"RTAIX")) return;
3374#endif /* RTAIX */
3375#ifdef HPUX
3376    if (!prtopt(&lines,"HPUX")) return;
3377#endif /* HPUX */
3378#ifdef HPUXPRE65
3379    if (!prtopt(&lines,"HPUXPRE65")) return;
3380#endif /* HPUXPRE65 */
3381#ifdef DGUX
3382    if (!prtopt(&lines,"DGUX")) return;
3383#endif /* DGUX */
3384#ifdef DGUX430
3385    if (!prtopt(&lines,"DGUX430")) return;
3386#endif /* DGUX430 */
3387#ifdef DGUX540
3388    if (!prtopt(&lines,"DGUX540")) return;
3389#endif /* DGUX540 */
3390#ifdef sony_news
3391    if (!prtopt(&lines,"sony_news")) return;
3392#endif /* sony_news */
3393#ifdef CIE
3394    if (!prtopt(&lines,"CIE")) return;
3395#endif /* CIE */
3396#ifdef XENIX
3397    if (!prtopt(&lines,"XENIX")) return;
3398#endif /* XENIX */
3399#ifdef SCO_XENIX
3400    if (!prtopt(&lines,"SCO_XENIX")) return;
3401#endif /* SCO_XENIX */
3402#ifdef ISIII
3403    if (!prtopt(&lines,"ISIII")) return;
3404#endif /* ISIII */
3405#ifdef I386IX
3406    if (!prtopt(&lines,"I386IX")) return;
3407#endif /* I386IX */
3408#ifdef RTU
3409    if (!prtopt(&lines,"RTU")) return;
3410#endif /* RTU */
3411#ifdef PROVX1
3412    if (!prtopt(&lines,"PROVX1")) return;
3413#endif /* PROVX1 */
3414#ifdef PYRAMID
3415    if (!prtopt(&lines,"PYRAMID")) return;
3416#endif /* PYRAMID */
3417#ifdef TOWER1
3418    if (!prtopt(&lines,"TOWER1")) return;
3419#endif /* TOWER1 */
3420#ifdef UTEK
3421    if (!prtopt(&lines,"UTEK")) return;
3422#endif /* UTEK */
3423#ifdef ZILOG
3424    if (!prtopt(&lines,"ZILOG")) return;
3425#endif /* ZILOG */
3426#ifdef TRS16
3427    if (!prtopt(&lines,"TRS16")) return;
3428#endif /* TRS16 */
3429#ifdef MINIX
3430    if (!prtopt(&lines,"MINIX")) return;
3431#endif /* MINIX */
3432#ifdef C70
3433    if (!prtopt(&lines,"C70")) return;
3434#endif /* C70 */
3435#ifdef AIXPS2
3436    if (!prtopt(&lines,"AIXPS2")) return;
3437#endif /* AIXPS2 */
3438#ifdef AIXRS
3439    if (!prtopt(&lines,"AIXRS")) return;
3440#endif /* AIXRS */
3441#ifdef UTSV
3442    if (!prtopt(&lines,"UTSV")) return;
3443#endif /* UTSV */
3444#ifdef ATTSV
3445    if (!prtopt(&lines,"ATTSV")) return;
3446#endif /* ATTSV */
3447#ifdef SVR3
3448    if (!prtopt(&lines,"SVR3")) return;
3449#endif /* SVR3 */
3450#ifdef SVR4
3451    if (!prtopt(&lines,"SVR4")) return;
3452#endif /* SVR4 */
3453#ifdef DELL_SVR4
3454    if (!prtopt(&lines,"DELL_SVR4")) return;
3455#endif /* DELL_SVR4 */
3456#ifdef ICL_SVR4
3457    if (!prtopt(&lines,"ICL_SVR4")) return;
3458#endif /* ICL_SVR4 */
3459#ifdef OSF
3460    if (!prtopt(&lines,"OSF")) return;
3461#endif /* OSF */
3462#ifdef OSF1
3463    if (!prtopt(&lines,"OSF1")) return;
3464#endif /* OSF1 */
3465#ifdef __OSF
3466    if (!prtopt(&lines,"__OSF")) return;
3467#endif /* __OSF */
3468#ifdef __OSF__
3469    if (!prtopt(&lines,"__OSF__")) return;
3470#endif /* __OSF__ */
3471#ifdef __osf__
3472    if (!prtopt(&lines,"__osf__")) return;
3473#endif /* __osf__ */
3474#ifdef __OSF1
3475    if (!prtopt(&lines,"__OSF1")) return;
3476#endif /* __OSF1 */
3477#ifdef __OSF1__
3478    if (!prtopt(&lines,"__OSF1__")) return;
3479#endif /* __OSF1__ */
3480#ifdef PTX
3481    if (!prtopt(&lines,"PTX")) return;
3482#endif /* PTX */
3483#ifdef POSIX
3484    if (!prtopt(&lines,"POSIX")) return;
3485#endif /* POSIX */
3486#ifdef Plan9
3487    if (!prtopt(&lines,"Plan9")) return;
3488#endif /* Plan9 */
3489#ifdef SOLARIS
3490    if (!prtopt(&lines,"SOLARIS")) return;
3491#endif /* SOLARIS */
3492#ifdef SUNOS4
3493    if (!prtopt(&lines,"SUNOS4")) return;
3494#endif /* SUNOS4 */
3495#ifdef SUN4S5
3496    if (!prtopt(&lines,"SUN4S5")) return;
3497#endif /* SUN4S5 */
3498#ifdef ENCORE
3499    if (!prtopt(&lines,"ENCORE")) return;
3500#endif /* ENCORE */
3501#ifdef ultrix
3502    if (!prtopt(&lines,"ultrix")) return;
3503#endif
3504#ifdef sxaE50
3505    if (!prtopt(&lines,"sxaE50")) return;
3506#endif
3507#ifdef mips
3508    if (!prtopt(&lines,"mips")) return;
3509#endif
3510#ifdef MIPS
3511    if (!prtopt(&lines,"MIPS")) return;
3512#endif
3513#ifdef vax
3514    if (!prtopt(&lines,"vax")) return;
3515#endif
3516#ifdef VAX
3517    if (!prtopt(&lines,"VAX")) return;
3518#endif
3519#ifdef alpha
3520    if (!prtopt(&lines,"alpha")) return;
3521#endif
3522#ifdef ALPHA
3523    if (!prtopt(&lines,"ALPHA")) return;
3524#endif
3525#ifdef __ALPHA
3526    if (!prtopt(&lines,"__ALPHA")) return;
3527#endif
3528#ifdef __alpha
3529    if (!prtopt(&lines,"__alpha")) return;
3530#endif
3531#ifdef __AXP
3532    if (!prtopt(&lines,"__AXP")) return;
3533#endif
3534#ifdef AXP
3535    if (!prtopt(&lines,"AXP")) return;
3536#endif
3537#ifdef axp
3538    if (!prtopt(&lines,"axp")) return;
3539#endif
3540#ifdef __ALPHA__
3541    if (!prtopt(&lines,"__ALPHA__")) return;
3542#endif
3543#ifdef __alpha__
3544    if (!prtopt(&lines,"__alpha__")) return;
3545#endif
3546#ifdef sun
3547    if (!prtopt(&lines,"sun")) return;
3548#endif
3549#ifdef sun3
3550    if (!prtopt(&lines,"sun3")) return;
3551#endif
3552#ifdef sun386
3553    if (!prtopt(&lines,"sun386")) return;
3554#endif
3555#ifdef _SUN
3556    if (!prtopt(&lines,"_SUN")) return;
3557#endif
3558#ifdef sun4
3559    if (!prtopt(&lines,"sun4")) return;
3560#endif
3561#ifdef sparc
3562    if (!prtopt(&lines,"sparc")) return;
3563#endif
3564#ifdef _CRAY
3565    if (!prtopt(&lines,"_CRAY")) return;
3566#endif /* _CRAY */
3567#ifdef NEXT33
3568    if (!prtopt(&lines,"NEXT33")) return;
3569#endif
3570#ifdef NEXT
3571    if (!prtopt(&lines,"NEXT")) return;
3572#endif
3573#ifdef NeXT
3574    if (!prtopt(&lines,"NeXT")) return;
3575#endif
3576#ifdef MACH
3577    if (!prtopt(&lines,"MACH")) return;
3578#endif
3579#ifdef sgi
3580    if (!prtopt(&lines,"sgi")) return;
3581#endif
3582#ifdef M_SYS5
3583    if (!prtopt(&lines,"M_SYS5")) return;
3584#endif
3585#ifdef __SYSTEM_FIVE
3586    if (!prtopt(&lines,"__SYSTEM_FIVE")) return;
3587#endif
3588#ifdef sysV
3589    if (!prtopt(&lines,"sysV")) return;
3590#endif
3591#ifdef M_XENIX                          /* SCO Xenix V and UNIX/386 */
3592    if (!prtopt(&lines,"M_XENIX")) return;
3593#endif
3594#ifdef M_UNIX                           /* SCO UNIX */
3595    if (!prtopt(&lines,"M_UNIX")) return;
3596#endif
3597#ifdef _M_UNIX                          /* SCO UNIX 3.2v4 = ODT 2.0 */
3598    if (!prtopt(&lines,"_M_UNIX")) return;
3599#endif
3600#ifdef M_I586
3601    if (!prtopt(&lines,"M_I586")) return;
3602#endif
3603#ifdef _M_I586
3604    if (!prtopt(&lines,"_M_I586")) return;
3605#endif
3606#ifdef i586
3607    if (!prtopt(&lines,"i586")) return;
3608#endif
3609#ifdef M_I486
3610    if (!prtopt(&lines,"M_I486")) return;
3611#endif
3612#ifdef _M_I486
3613    if (!prtopt(&lines,"_M_I486")) return;
3614#endif
3615#ifdef i486
3616    if (!prtopt(&lines,"i486")) return;
3617#endif
3618#ifdef M_I386
3619    if (!prtopt(&lines,"M_I386")) return;
3620#endif
3621#ifdef _M_I386
3622    if (!prtopt(&lines,"_M_I386")) return;
3623#endif
3624#ifdef i386
3625    if (!prtopt(&lines,"i386")) return;
3626#endif
3627#ifdef i286
3628    if (!prtopt(&lines,"i286")) return;
3629#endif
3630#ifdef M_I286
3631    if (!prtopt(&lines,"M_I286")) return;
3632#endif
3633#ifdef mc68000
3634    if (!prtopt(&lines,"mc68000")) return;
3635#endif
3636#ifdef mc68010
3637    if (!prtopt(&lines,"mc68010")) return;
3638#endif
3639#ifdef mc68020
3640    if (!prtopt(&lines,"mc68020")) return;
3641#endif
3642#ifdef mc68030
3643    if (!prtopt(&lines,"mc68030")) return;
3644#endif
3645#ifdef mc68040
3646    if (!prtopt(&lines,"mc68040")) return;
3647#endif
3648#ifdef M_68000
3649    if (!prtopt(&lines,"M_68000")) return;
3650#endif
3651#ifdef M_68010
3652    if (!prtopt(&lines,"M_68010")) return;
3653#endif
3654#ifdef M_68020
3655    if (!prtopt(&lines,"M_68020")) return;
3656#endif
3657#ifdef M_68030
3658    if (!prtopt(&lines,"M_68030")) return;
3659#endif
3660#ifdef M_68040
3661    if (!prtopt(&lines,"M_68040")) return;
3662#endif
3663#ifdef m68k
3664    if (!prtopt(&lines,"m68k")) return;
3665#endif
3666#ifdef m88k
3667    if (!prtopt(&lines,"m88k")) return;
3668#endif
3669#ifdef pdp11
3670    if (!prtopt(&lines,"pdp11")) return;
3671#endif
3672#ifdef iAPX
3673    if (!prtopt(&lines,"iAPX")) return;
3674#endif
3675#ifdef __hp9000s800
3676    if (!prtopt(&lines,"__hp9000s800")) return;
3677#endif
3678#ifdef __hp9000s700
3679    if (!prtopt(&lines,"__hp9000s700")) return;
3680#endif
3681#ifdef __hp9000s500
3682    if (!prtopt(&lines,"__hp9000s500")) return;
3683#endif
3684#ifdef __hp9000s300
3685    if (!prtopt(&lines,"__hp9000s300")) return;
3686#endif
3687#ifdef __hp9000s200
3688    if (!prtopt(&lines,"__hp9000s200")) return;
3689#endif
3690#ifdef AIX
3691    if (!prtopt(&lines,"AIX")) return;
3692#endif
3693#ifdef _AIXFS
3694    if (!prtopt(&lines,"_AIXFS")) return;
3695#endif
3696#ifdef u370
3697    if (!prtopt(&lines,"u370")) return;
3698#endif
3699#ifdef u3b
3700    if (!prtopt(&lines,"u3b")) return;
3701#endif
3702#ifdef u3b2
3703    if (!prtopt(&lines,"u3b2")) return;
3704#endif
3705#ifdef multimax
3706    if (!prtopt(&lines,"multimax")) return;
3707#endif
3708#ifdef balance
3709    if (!prtopt(&lines,"balance")) return;
3710#endif
3711#ifdef ibmrt
3712    if (!prtopt(&lines,"ibmrt")) return;
3713#endif
3714#ifdef _IBMRT
3715    if (!prtopt(&lines,"_IBMRT")) return;
3716#endif
3717#ifdef ibmrs6000
3718    if (!prtopt(&lines,"ibmrs6000")) return;
3719#endif
3720#ifdef _AIX
3721    if (!prtopt(&lines,"_AIX")) return;
3722#endif /* _AIX */
3723#ifdef _IBMR2
3724    if (!prtopt(&lines,"_IBMR2")) return;
3725#endif
3726#ifdef UNIXWARE
3727    if (!prtopt(&lines,"UNIXWARE")) return;
3728#endif
3729#ifdef QNX
3730    if (!prtopt(&lines,"QNX")) return;
3731#ifdef __QNX__
3732    if (!prtopt(&lines,"__QNX__")) return;
3733#ifdef __16BIT__
3734    if (!prtopt(&lines,"__16BIT__")) return;
3735#endif
3736#ifdef CK_QNX16
3737    if (!prtopt(&lines,"CK_QNX16")) return;
3738#endif
3739#ifdef __32BIT__
3740    if (!prtopt(&lines,"__32BIT__")) return;
3741#endif
3742#ifdef CK_QNX32
3743    if (!prtopt(&lines,"CK_QNX32")) return;
3744#endif
3745#endif /* __QNX__ */
3746#endif /* QNX */
3747
3748#ifdef __STRICT_BSD__
3749    if (!prtopt(&lines,"__STRICT_BSD__")) return;
3750#endif
3751#ifdef __STRICT_ANSI__
3752    if (!prtopt(&lines,"__STRICT_ANSI__")) return;
3753#endif
3754#ifdef _ANSI_C_SOURCE
3755    if (!prtopt(&lines,"_ANSI_C_SOURCE")) return;
3756#endif
3757#ifdef __STDC__
3758    if (!prtopt(&lines,"__STDC__")) return;
3759#endif
3760#ifdef __DECC
3761    if (!prtopt(&lines,"__DECC")) return;
3762#ifdef __DECC_VER
3763    sprintf(line,"__DECC_VER=%d",__DECC_VER);
3764    if (!prtopt(&lines,line)) return;
3765#endif /* __DECC_VER */
3766#endif /* __DECC */
3767#ifdef __GNUC__                         /* gcc in ansi mode */
3768    if (!prtopt(&lines,"__GNUC__")) return;
3769#endif
3770#ifdef GNUC                             /* gcc in traditional mode */
3771    if (!prtopt(&lines,"GNUC")) return;
3772#endif
3773#ifdef __WATCOMC__
3774    if (!prtopt(&lines,"__WATCOMC__")) return;
3775#endif
3776#ifdef CK_ANSIC
3777    if (!prtopt(&lines,"CK_ANSIC")) return;
3778#endif
3779#ifdef CK_ANSILIBS
3780    if (!prtopt(&lines,"CK_ANSILIBS")) return;
3781#endif
3782#ifdef _XOPEN_SOURCE
3783    if (!prtopt(&lines,"_XOPEN_SOURCE")) return;
3784#endif
3785#ifdef _ALL_SOURCE
3786    if (!prtopt(&lines,"_ALL_SOURCE")) return;
3787#endif
3788#ifdef _SC_JOB_CONTROL
3789    if (!prtopt(&lines,"_SC_JOB_CONTROL")) return;
3790#endif
3791#ifdef _POSIX_JOB_CONTROL
3792    if (!prtopt(&lines,"_POSIX_JOB_CONTROL")) return;
3793#endif
3794#ifdef CK_POSIX_SIG
3795    if (!prtopt(&lines,"CK_POSIX_SIG")) return;
3796#endif
3797#ifdef SVR3JC
3798    if (!prtopt(&lines,"SVR3JC")) return;
3799#endif
3800#ifdef _386BSD
3801    if (!prtopt(&lines,"_386BSD")) return;
3802#endif
3803#ifdef _BSD
3804    if (!prtopt(&lines,"_BSD")) return;
3805#endif
3806#ifdef TERMIOX
3807    if (!prtopt(&lines,"TERMIOX")) return;
3808#endif /* TERMIOX */
3809#ifdef STERMIOX
3810    if (!prtopt(&lines,"STERMIOX")) return;
3811#endif /* STERMIOX */
3812#ifdef CK_CURSES
3813    if (!prtopt(&lines,"CK_CURSES")) return;
3814#endif /* CK_CURSES */
3815#ifdef CK_NEWTERM
3816    if (!prtopt(&lines,"CK_NEWTERM")) return;
3817#endif /* CK_NEWTERM */
3818#ifdef CK_WREFRESH
3819    if (!prtopt(&lines,"CK_WREFRESH")) return;
3820#endif /* CK_WREFRESH */
3821#ifdef CK_PCT_BAR
3822    if (!prtopt(&lines,"CK_PCT_BAR")) return;
3823#endif /* CK_PCT_BAR */
3824#ifdef CK_DTRCD
3825    if (!prtopt(&lines,"CK_DTRCD")) return;
3826#endif /* CK_DTRCD */
3827#ifdef CK_DTRCTS
3828    if (!prtopt(&lines,"CK_DTRCTS")) return;
3829#endif /* CK_DTRCTS */
3830#ifdef CK_RTSCTS
3831    if (!prtopt(&lines,"CK_RTSCTS")) return;
3832#endif /* CK_RTSCTS */
3833#ifdef POSIX_CRTSCTS
3834    if (!prtopt(&lines,"POSIX_CRTSCTS")) return;
3835#endif /* POSIX_CRTSCTS */
3836#ifdef CK_DSYSINI
3837    if (!prtopt(&lines,"CK_DSYSINI")) return;
3838#endif /* CK_DSYSINI */
3839#ifdef CK_SYSINI
3840    if (!prtopt(&lines,"CK_SYSINI")) return;
3841#endif /* CK_SYSINI */
3842#ifdef CK_INI_A
3843    if (!prtopt(&lines,"CK_INI_A")) return;
3844#endif /* CK_INI_A */
3845#ifdef CK_INI_B
3846    if (!prtopt(&lines,"CK_INI_B")) return;
3847#endif /* CK_INI_B */
3848#ifdef CK_TTGWSIZ
3849    if (!prtopt(&lines,"CK_TTGWSIZ")) return;
3850#endif /* CK_TTGWSIZ */
3851#ifdef CK_NAWS
3852    if (!prtopt(&lines,"CK_NAWS")) return;
3853#endif /* CK_NAWS */
3854#ifdef DCMDBUF
3855    if (!prtopt(&lines,"DCMDBUF")) return;
3856#endif /* DCMDBUF */
3857#ifdef CK_RECALL
3858    if (!prtopt(&lines,"CK_RECALL")) return;
3859#endif /* CK_RECALL */
3860#ifdef CLSOPN
3861    if (!prtopt(&lines,"CLSOPN")) return;
3862#endif /* CLSOPN */
3863#ifdef STRATUS
3864    if (!prtopt(&lines,"STRATUS")) return;
3865#endif /* STRATUS */
3866#ifdef __VOS__
3867    if (!prtopt(&lines,"__VOS__")) return;
3868#endif /* __VOS__ */
3869#ifdef STRATUSX25
3870    if (!prtopt(&lines,"STRATUSX25")) return;
3871#endif /* STRATUSX25 */
3872#ifdef OS2MOUSE
3873    if (!prtopt(&lines,"OS2MOUSE") ) return;
3874#endif /* OS2MOUSE */
3875#ifdef CK_REXX
3876    if (!prtopt(&lines,"CK_REXX") ) return;
3877#endif /* CK_REXX */
3878#ifdef CK_TIMERS
3879    if (!prtopt(&lines,"CK_TIMERS") ) return;
3880#endif /* CK_TIMERS */
3881    if (!prtopt(&lines,(char *)0)) return;
3882    printf("\n\n");
3883}
3884#endif /* NOFRILLS */
3885
3886#ifdef CK_LABELED
3887VOID
3888sholbl() {
3889#ifdef VMS
3890    printf("VMS Labeled File Features:\n");
3891    printf(" acl %s (ACL info %s)\n",
3892           showoff(lf_opts & LBL_ACL),
3893           lf_opts & LBL_ACL ? "preserved" : "discarded");
3894    printf(" backup-date %s (backup date/time %s)\n",
3895           showoff(lf_opts & LBL_BCK),
3896           lf_opts & LBL_BCK ? "preserved" : "discarded");
3897    printf(" name %s (original filename %s)\n",
3898           showoff(lf_opts & LBL_NAM),
3899           lf_opts & LBL_NAM ? "preserved" : "discarded");
3900    printf(" owner %s (original file owner id %s)\n",
3901           showoff(lf_opts & LBL_OWN),
3902           lf_opts & LBL_OWN ? "preserved" : "discarded");
3903    printf(" path %s (original file's disk:[directory] %s)\n",
3904           showoff(lf_opts & LBL_PTH),
3905           lf_opts & LBL_PTH ? "preserved" : "discarded");
3906#else
3907#ifdef OS2
3908    printf("OS/2 Labeled File features (attributes):\n");
3909    printf(" archive:   %s\n", showoff(lf_opts & LBL_ARC));
3910    printf(" extended:  %s\n", showoff(lf_opts & LBL_EXT));
3911    printf(" hidden:    %s\n", showoff(lf_opts & LBL_HID));
3912    printf(" read-only: %s\n", showoff(lf_opts & LBL_RO ));
3913    printf(" system:    %s\n", showoff(lf_opts & LBL_SYS));
3914#endif /* OS2 */
3915#endif /* VMS */
3916}
3917#endif /* CK_LABELED */
3918
3919VOID
3920shotcs(csl,csr) int csl, csr; {         /* Show terminal character set */
3921#ifndef NOCSETS
3922#ifdef OS2
3923    extern struct _vtG G[4], *GL, *GR;
3924
3925    printf(" Terminal character-sets:\n");
3926#ifndef CKOUNI
3927    printf("    Local: %s\n",
3928        csl == FC_TRANSP ? "transparent" : fcsinfo[csl].keyword );
3929    printf("   Remote: %sG0: %s (%s)\n",
3930        GL == &G[0] ? "GL->" : GR == &G[0] ? "GR->" : "    ",
3931        G[0].designation == FC_TRANSP ? "transparent" :
3932        G[0].designation == FC_DECSPEC ? "dec-special" :
3933        G[0].designation == FC_DECTECH ? "dec-technical" :
3934        fcsinfo[G[0].designation].keyword,
3935        G[0].designation == FC_TRANSP ? "" :
3936        G[0].size == cs94 ? "94 chars" :
3937        G[0].size == cs96 ? "96 chars" : "multi-byte" );
3938    printf("           %sG1: %s (%s)\n",
3939        GL == &G[1] ? "GL->" : GR == &G[1] ? "GR->" : "    ",
3940        G[1].designation == FC_TRANSP ? "transparent" :
3941        G[1].designation == FC_DECSPEC ? "dec-special" :
3942        G[1].designation == FC_DECTECH ? "dec-technical" :
3943        fcsinfo[G[1].designation].keyword,
3944        G[1].designation == FC_TRANSP ? "" :
3945        G[1].size == cs94 ? "94 chars" :
3946        G[1].size == cs96 ? "96 chars" : "multi-byte" );
3947    printf("           %sG2: %s (%s)\n",
3948        GL == &G[2] ? "GL->" : GR == &G[2] ? "GR->" : "    ",
3949        G[2].designation == FC_TRANSP ? "transparent" :
3950        G[2].designation == FC_DECSPEC ? "dec-special" :
3951        G[2].designation == FC_DECTECH ? "dec-technical" :
3952        fcsinfo[G[2].designation].keyword,
3953        G[2].designation == FC_TRANSP ? "" :
3954        G[2].size == cs94 ? "94 chars" :
3955        G[2].size == cs96 ? "96 chars" : "multi-byte" );
3956    printf("           %sG3: %s (%s)\n",
3957        GL == &G[3] ? "GL->" : GR == &G[3] ? "GR->" : "    ",
3958        G[3].designation == FC_TRANSP ? "transparent" :
3959        G[3].designation == FC_DECSPEC ? "dec-special" :
3960        G[3].designation == FC_DECTECH ? "dec-technical" :
3961        fcsinfo[G[3].designation].keyword,
3962        G[3].designation == FC_TRANSP ? "" :
3963        G[3].size == cs94 ? "94 chars" :
3964        G[3].size == cs96 ? "96 chars" : "multi-byte" );
3965#else /* CKOUNI */
3966    printf("    Local: %s\n",
3967           isunicode() ? "Unicode" :
3968           csl == TX_TRANSP ? "transparent" :
3969           csl == TX_UNDEF ? "undefined" : txrinfo[csl]->keywd );
3970    printf("   Remote: %sG0: %s (%s)\n",
3971           GL == &G[0] ? "GL->" : GR == &G[0] ? "GR->" : "    ",
3972           txrinfo[G[0].designation]->keywd,
3973           G[0].size == cs94 ? "94 chars" :
3974           G[0].size == cs96 ? "96 chars" : "multi-byte" );
3975    printf("           %sG1: %s (%s)\n",
3976           GL == &G[1] ? "GL->" : GR == &G[1] ? "GR->" : "    ",
3977           txrinfo[G[1].designation]->keywd,
3978           G[1].size == cs94 ? "94 chars" :
3979           G[1].size == cs96 ? "96 chars" : "multi-byte" );
3980    printf("           %sG2: %s (%s)\n",
3981           GL == &G[2] ? "GL->" : GR == &G[2] ? "GR->" : "    ",
3982           txrinfo[G[2].designation]->keywd,
3983           G[2].size == cs94 ? "94 chars" :
3984           G[2].size == cs96 ? "96 chars" : "multi-byte" );
3985    printf("           %sG3: %s (%s)\n",
3986           GL == &G[3] ? "GL->" : GR == &G[3] ? "GR->" : "    ",
3987           txrinfo[G[3].designation]->keywd,
3988           G[3].size == cs94 ? "94 chars" :
3989           G[3].size == cs96 ? "96 chars" : "multi-byte" );
3990#endif /* CKOUNI */
3991#else /* OS2 */
3992#ifndef MAC
3993    char *s;
3994#ifdef CK_ANSIC
3995    int gettcs(int, int);
3996#else
3997    int gettcs();
3998#endif /* CK_ANSIC */
3999
4000    printf(" Terminal character-set: ");
4001    if (csl == csr) {                   /* No translation */
4002        printf("transparent\n");
4003    } else {                            /* Translation */
4004        printf("%s (remote) %s (local)\n",
4005               fcsinfo[csr].keyword,fcsinfo[csl].keyword);
4006        if (csr != csl) {
4007            switch(gettcs(csr,csl)) {
4008              case TC_USASCII:  s = "ascii";        break;
4009              case TC_1LATIN:   s = "latin1-iso";   break;
4010              case TC_2LATIN:   s = "latin2-iso";   break;
4011              case TC_CYRILL:   s = "cyrillic-iso"; break;
4012              case TC_JEUC:     s = "japanese-euc"; break;
4013              case TC_HEBREW:   s = "hebrew-iso";   break;
4014              default:          s = "transparent";  break;
4015            }
4016            if (strcmp(s,fcsinfo[csl].keyword) &&
4017                strcmp(s,fcsinfo[csr].keyword))
4018              printf("                         (via %s)\n",s);
4019        }
4020    }
4021#endif /* MAC */
4022#endif /* OS2 */
4023#endif /* NOCSETS */
4024}
4025#endif /* NOSHOW */
4026
4027#ifndef NOSETKEY
4028VOID
4029shostrdef(s) CHAR * s; {
4030    CHAR ch;
4031        while (ch = *s++)
4032          if (ch < 32 || ch == 127
4033/*
4034  Systems whose native character sets have graphic characters in C1...
4035*/
4036#ifndef NEXT                            /* NeXT */
4037#ifndef AUX                             /* Macintosh */
4038#ifndef XENIX                           /* IBM PC */
4039#ifndef OS2                             /* IBM PC */
4040              || (ch > 127 && ch < 160)
4041#endif /* OS2 */
4042#endif /* XENIX */
4043#endif /* AUX */
4044#endif /* NEXT */
4045              )
4046            printf("\\{%d}",ch);        /* Display control characters */
4047          else putchar((char) ch);      /* in backslash notation */
4048}
4049
4050VOID
4051shokeycode(c) int c; {
4052    KEY ch;
4053    CHAR *s;
4054#ifdef NEWMAPKEY
4055    con_event km;
4056#else /* NEWMAPKEY */
4057    int km;
4058#endif /* NEWMAPKEY */
4059
4060#ifdef OS2
4061    extern int mskkeys;
4062
4063    if (c >= KMSIZE) {
4064        bleep(BP_FAIL);
4065        return;
4066    }
4067    s = keyname(c);
4068    printf(" Key code \\%d %s => ", mskkeys ? cktomsk(c) : c,
4069            s == NULL ? "" : s);
4070#else /* OS2 */
4071    printf(" Key code \\%d => ", c);
4072#endif /* OS2 */
4073
4074#ifndef NEWMAPKEY
4075    km = mapkey(c);
4076
4077#ifndef NOKVERBS
4078    if (IS_KVERB(km)) {                 /* \Kverb? */
4079        int i, kv;
4080        kv = km & ~(F_KVERB);
4081        printf("Verb: ");
4082        for (i = 0; i < nkverbs; i++)
4083          if (kverbs[i].kwval == kv) {
4084              printf("\\K%s",kverbs[i].kwd);
4085              break;
4086          }
4087        printf("\n");
4088    } else
4089#endif /* NOKVERBS */
4090      if (IS_CSI(km)) {
4091          int xkm = km & 0xFF;
4092          if (xkm <= 32 || xkm >= 127)
4093            printf("String: \\{27}[\\{%d}\n",xkm);
4094          else
4095            printf("String: \\{27}[%c\n",xkm);
4096      } else if (IS_ESC(km)) {
4097          int xkm = km & 0xFF;
4098          if (xkm <= 32 || xkm >= 127)
4099            printf("String: \\{27}\\{%d}\n",xkm);
4100          else
4101            printf("String: \\{27}%c\n",xkm);
4102      } else if (macrotab[c]) {         /* See if there's a macro */
4103          printf("String: ");           /* If so, display its definition */
4104          s = macrotab[c];
4105          shostrdef(s);
4106          printf("\n");
4107#ifndef NOKVERBS
4108    } else if (km >= 0x100) {           /* This means "undefined" */
4109        printf("Undefined\n");
4110#endif /* NOKVERBS */
4111    } else {                            /* No macro, show single character */
4112        printf("Character: ");
4113        ch = km;
4114        if (ch < 32 || ch == 127 || ch > 255
4115#ifndef NEXT
4116#ifndef AUX
4117#ifndef XENIX
4118#ifndef OS2
4119            || (ch > 127 && ch < 160)
4120#endif /* OS2 */
4121#endif /* XENIX */
4122#endif /* AUX */
4123#endif /* NEXT */
4124            )
4125/*
4126  These used to be %d, but gcc 1.93 & later complain about type mismatches.
4127  %u is supposed to be totally portable.
4128*/
4129          printf("\\%u",(unsigned int) ch);
4130        else printf("%c \\%u",(CHAR) (ch & 0xff),(unsigned int) ch);
4131        if (ch == (KEY) c)
4132          printf(" (self, no translation)\n");
4133        else
4134          printf("\n");
4135    }
4136#else /* NEWMAPKEY */
4137    km = mapkey(c);
4138
4139    switch (km.type) {
4140#ifndef NOKVERBS
4141      case kverb: {
4142          int i, kv;
4143          kv = km.kverb.id & ~(F_KVERB);
4144          printf("Verb: ");
4145          for (i = 0; i < nkverbs; i++) {
4146              if (kverbs[i].kwval == kv) {
4147                  printf("\\K%s",kverbs[i].kwd);
4148                  break;
4149              }
4150          }
4151          printf("\n");
4152          break;
4153      }
4154#endif /* NOKVERBS */
4155      case csi: {
4156          int xkm = km.csi.key & 0xFF;
4157          if (xkm <= 32 || xkm >= 127)
4158            printf("String: \\{27}[\\{%d}\n",xkm);
4159          else
4160            printf("String: \\{27}[%c\n",xkm);
4161          break;
4162      }
4163      case esc: {
4164          int xkm = km.esc.key & 0xFF;
4165          if (xkm <= 32 || xkm >= 127)
4166            printf("String: \\{27}\\{%d}\n",xkm);
4167          else
4168            printf("String: \\{27}%c\n",xkm);
4169          break;
4170      }
4171      case macro: {
4172          printf("String: ");           /* Macro, display its definition */
4173          shostrdef(km.macro.string);
4174          printf("\n");
4175          break;
4176      }
4177      case error: {
4178          printf("Undefined\n");
4179          break;
4180      }
4181      case key: {
4182          printf("Character: ");
4183          ch = km.key.scancode;
4184          if (ch < 32 || ch == 127 || ch > 255
4185#ifndef NEXT
4186#ifndef AUX
4187#ifndef XENIX
4188#ifndef OS2
4189              || (ch > 127 && ch < 160)
4190#endif /* OS2 */
4191#endif /* XENIX */
4192#endif /* AUX */
4193#endif /* NEXT */
4194              )
4195/*
4196  These used to be %d, but gcc 1.93 & later complain about type mismatches.
4197  %u is supposed to be totally portable.
4198*/
4199            printf("\\%u",(unsigned int) ch);
4200          else printf("%c \\%u",(CHAR) (ch & 0xff),(unsigned int) ch);
4201          if (ch == (KEY) c)
4202            printf(" (self, no translation)\n");
4203          else
4204            printf("\n");
4205          break;
4206      }
4207    }
4208#endif /* NEWMAPKEY */
4209}
4210#endif /* NOSETKEY */
4211
4212#ifndef NOSHOW
4213#ifndef NOLOCAL
4214#ifdef OS2
4215extern char htab[];
4216void
4217shotabs()
4218{
4219    int i;
4220
4221    printf("Tab Stops:\n\n");
4222    for ( i = 1; i <= 70; i++ )   
4223        printf("%c",htab[i]=='T'?'T':'-');
4224    printf("\n1.......10........20........30........40........50........60\
4225........70\n\n");
4226    for ( ; i <= 140; i++ )
4227        printf("%c",htab[i]=='T'?'T':'-');
4228    printf("\n........80........90.......100.......110.......120.......130\
4229.......140\n\n");
4230    for ( ; i <= 210; i++ )
4231        printf("%c",htab[i]=='T'?'T':'-');
4232    printf("\n.......150.......160.......170.......180.......190.......200\
4233.......210\n\n");
4234    for ( ; i <= 255; i++ )
4235        printf("%c",htab[i]=='T'?'T':'-');
4236    printf("\n.......220.......230.......240.......250..255\n");
4237}
4238
4239#endif /* OS2 */
4240#endif /* NOLOCAL */
4241#endif /* NOSHOW */
4242
4243#ifndef NOSHOW
4244#ifndef NOLOCAL
4245VOID
4246shotrm() {
4247    char *s;
4248
4249#ifdef PCFONTS
4250    int i;
4251    char *font;
4252
4253    if ( IsOS2FullScreen() ) {          /* Determine the font name */
4254        if ( !os2LoadPCFonts() ) {
4255            for ( i=0; i <ntermfont; i++ ) {
4256                if ( tt_font == termfont[i].kwval ) {
4257                    font = termfont[i].kwd;
4258                    break;
4259                }       
4260            }
4261        } else {
4262            font = "(DLL not available)";
4263        }
4264    } else {
4265        font =     "(full screen only)";
4266    }
4267#endif /* PCFONTS */
4268
4269#ifndef OS2
4270    printf("\n");
4271#endif /* OS2 */
4272
4273    printf("Terminal parameters:\n");
4274    printf(" %19s: %1d%-12s  %13s: %1d%-14s\n",
4275           "Bytesize: Command",
4276           (cmdmsk == 0377) ? 8 : 7,
4277           " bits","Terminal",
4278           (cmask == 0377) ? 8 : 7," bits");
4279#ifdef OS2
4280    printf(" %19s: %-13s","Type",
4281           (tt_type >= 0 && tt_type <= max_tt) ?
4282           tt_info[tt_type].x_name :
4283           "unknown" );
4284    if (tt_type >= 0 && tt_type <= max_tt)
4285      if (strlen(tt_info[tt_type].x_id))
4286        printf("  %13s: <ESC>%s","ID",tt_info[tt_type].x_id);
4287    printf("\n");
4288#else
4289    s = getenv("TERM");
4290    printf(" %19s: %-13s\n","Type", s ? s : "(unknown)");
4291#endif /* OS2 */
4292    printf(" %19s: %-13s  %13s: %-15s\n","Echo",
4293           duplex ? "local" : "remote","Locking-shift",showoff(sosi));
4294    printf(" %19s: %-13s  %13s: %-15s\n","Newline-mode",
4295           showoff(tnlm),"Cr-display",tt_crd ? "crlf" : "normal");
4296#ifdef OS2
4297    printf(" %19s: %-13s  %13s: %-15s\n","Cursor",
4298           (tt_cursor == 2) ? "full" :
4299           (tt_cursor == 1) ? "half" : "underline",
4300#ifdef CK_AUTODL           
4301           "autodownload",autodl ? "on" : "off"
4302#else /* CK_AUTODL */
4303           "", ""
4304#endif /* CK_AUTODL */
4305           );
4306#endif /* OS2 */
4307#ifdef OS2
4308    printf(" %19s: %-13s  %13s: %-15s\n","Arrow-keys",
4309           tt_arrow ? "application" : "cursor",
4310           "Keypad-mode", tt_keypad ? "application" : "numeric"
4311           );
4312
4313    /* Just to make sure we are using current info */
4314    updanswerbk();
4315
4316    /*
4317       This line doesn't end with '\n' because the answerback string
4318       is terminated with a newline
4319    */
4320    printf(" %19s: %-13s  %13s: %-15s","Answerback",
4321           showoff(tt_answer),"response",answerback);
4322    switch ( tt_bell ) {
4323      case XYB_NONE:
4324        s = "none";
4325        break;
4326      case XYB_VIS:
4327        s= "visible";
4328        break;
4329      case XYB_AUD | XYB_BEEP:
4330        s="beep";
4331        break;
4332      case XYB_AUD | XYB_SYS:
4333        s="system sounds";
4334        break;
4335      default:
4336        s="(unknown)";
4337    }
4338    printf(" %19s: %-13s  %13s: %-15s\n","Bell",s,
4339           "Wrap",showoff(tt_wrap));
4340    printf(" %19s: %-13d  %13s: %-15d\n","Transmit-timeout",tt_ctstmo,
4341           "Output-pacing",tt_pacing);
4342    printf(" %19s: %-13s  %13s: %-15d\n","Roll-mode",
4343           tt_roll[VTERM]?"insert":"overwrite","Scrollback", tt_scrsize[VTERM]
4344           );
4345#endif /* OS2 */
4346
4347#ifdef CK_APC
4348    if (apcstatus == APC_ON) s = "on";
4349    else if (apcstatus == APC_OFF) s = "off";
4350    else if (apcstatus == APC_UNCH) s = "unchecked";
4351    printf(" %19s: %-13s  %13s: %-15s\n",
4352           "APC", s,
4353#ifdef OS2
4354#ifdef PCFONTS
4355           "Font",font
4356#else /* PCFONTS */
4357           "",""
4358#endif /* PCFONTS */
4359#else
4360#ifdef CK_AUTODL
4361           "Autodownload", autodl ? "on" : "off"
4362#else
4363           "",""
4364#endif /* CK_AUTODL */
4365#endif /* OS2 */
4366           );
4367#endif /* CK_APC */
4368
4369#ifdef OS2                               
4370    {
4371        char cpbuf[50];
4372        int cplist[8], cps;
4373        cps = os2getcplist(cplist, sizeof(cplist));
4374        sprintf(cpbuf,"%3d,%3d,%3d,%3d",
4375                cps > 1 ? cplist[1] : 0, cps > 2 ? cplist[2] : 0,
4376                cps > 3 ? cplist[3] : 0, cps > 4 ? cplist[4] : 0 );
4377        printf(" %19s: %-13d  %13s: %-15s\n","Code-page: active",
4378               os2getcp(),"available",cpbuf);
4379    }
4380#endif /* OS2 */
4381
4382#ifdef CK_TTGWSIZ                       /* Console terminal screen size */
4383#ifdef OS2
4384    if ( tt_cols[VTERM] < 0 || tt_rows[VTERM] < 0 )
4385      ttgwsiz();                        /* Try to get latest size */
4386    printf(" %19s: %-13d  %13s: %-15d\n","Height",tt_rows[VTERM],
4387           "Width",tt_cols[VTERM]);
4388#else /* OS2 */
4389    ttgwsiz();                          /* Try to get latest size */
4390    printf(" %19s: %-13d  %13s: %-15d\n","Height",tt_rows, "Width", tt_cols);
4391#endif /* OS2 */
4392#else
4393#endif /* CK_TTGWSIZ */
4394
4395#ifdef OS2
4396    if (updmode == tt_updmode)
4397      if (updmode == TTU_FAST)
4398        s = "fast (fast)";
4399      else
4400        s = "smooth (smooth)";
4401    else
4402      if (updmode == TTU_FAST)
4403        s = "fast (smooth)";
4404      else
4405        s = "smooth (fast)";
4406
4407    printf(" %19s: %-13s  %13s: %-15d\n","Screen-update: mode",s,
4408           "update freq",tt_update);
4409#endif /* OS2 */
4410    printf(" %19s: %-13s  %13s: %-15s\n","Debug",
4411           showoff(debses),"Session log", seslog? sesfil : "(none)" );
4412#ifdef OS2
4413    {
4414        USHORT row, col;
4415        char * colors[16] = {
4416            "black","blue","green","cyan","red","magenta","brown","lgray",
4417            "dgray","lblue","lgreen","lcyan","lred","lmagent","yellow","white"
4418        };
4419        printf("\n Color:");
4420#ifndef ONETERMUPD
4421        GetCurPos( &row, &col );
4422        WrtCharStrAtt("border",    6, row, 9, &colorborder );
4423        WrtCharStrAtt("debug",     5, row, 17, &colordebug );
4424        WrtCharStrAtt("helptext",  8, row, 25, &colorhelp );
4425        WrtCharStrAtt("reverse",   7, row, 34, &colorreverse );
4426        WrtCharStrAtt("select",    6, row, 42, &colorselect );
4427        WrtCharStrAtt("status",    6, row, 50, &colorstatus );
4428        WrtCharStrAtt("terminal",  8, row, 58, &colornormal );
4429        WrtCharStrAtt("underline",  9, row, 67, &colorunderline );
4430#endif /* ONETERMUPD */
4431        row = VscrnGetCurPos(VCMD)->y+1;
4432        VscrnWrtCharStrAtt(VCMD, "border",    6, row, 9, &colorborder );
4433        VscrnWrtCharStrAtt(VCMD, "debug",     5, row, 17, &colordebug );
4434        VscrnWrtCharStrAtt(VCMD, "helptext",  8, row, 25, &colorhelp );
4435        VscrnWrtCharStrAtt(VCMD, "reverse",   7, row, 34, &colorreverse );
4436        VscrnWrtCharStrAtt(VCMD, "select",    6, row, 42, &colorselect );
4437        VscrnWrtCharStrAtt(VCMD, "status",    6, row, 50, &colorstatus );
4438        VscrnWrtCharStrAtt(VCMD, "terminal",  8, row, 58, &colornormal );
4439        VscrnWrtCharStrAtt(VCMD, "underline",  9, row, 67, &colorunderline );
4440        printf( "\n" );
4441
4442        /* Foreground color names */
4443        printf("%6s: %-8s%-8s%-9s%-8s%-8s%-8s%-9s%-9s\n","fore",
4444                "",
4445                colors[colordebug&0x0F],
4446                colors[colorhelp&0x0F],
4447                colors[colorreverse&0x0F],
4448                colors[colorselect&0x0F],
4449                colors[colorstatus&0x0F],
4450                colors[colornormal&0x0F],
4451                colors[colorunderline&0x0F] );
4452
4453        /* Background color names */
4454        printf("%6s: %-8s%-8s%-9s%-8s%-8s%-8s%-9s%-9s\n","back",
4455                colors[colorborder],
4456                colors[colordebug>>4],
4457                colors[colorhelp>>4],
4458                colors[colorreverse>>4],
4459                colors[colorselect>>4],
4460                colors[colorstatus>>4],
4461                colors[colornormal>>4],
4462                colors[colorunderline>>4] );
4463    }
4464#endif /* OS2 */
4465    printf("\n");
4466    printf(" CONNECT-mode escape character: %d (Ctrl-%c, %s): %s\n",
4467           escape,ctl(escape),(escape == 127 ? "DEL" : ccntab[escape]),
4468           nm[tt_escape]
4469           );
4470#ifdef OS2
4471    printf(" See SHOW CHARACTER-SETS for character-set info\n");
4472#else /* OS2 */
4473#ifndef NOCSETS
4474    shotcs(tcsl,tcsr);          /* Show terminal character sets */
4475#endif /* NOCSETS */
4476#endif /* OS2 */
4477
4478#ifdef UNIX
4479#ifndef NOJC
4480    printf(" %19s: %-13s\n\n","Suspend", showoff(suspend));
4481#endif /* NOJC */
4482#endif /* UNIX */
4483}
4484#endif /* NOLOCAL */
4485#endif /* NOSHOW */
4486
4487#ifndef NOSHOW
4488#ifndef NOLOCAL
4489#ifdef OS2MOUSE
4490
4491void
4492shomou() {
4493    int button, event, id, i;
4494    char * name = "";
4495
4496    printf("Mouse settings:\n");
4497    printf("   Active:         %s\n\n",showoff(tt_mouse));
4498
4499    for ( button = 0; button < MMBUTTONMAX; button++ )
4500      for ( event = 0; event < MMEVENTSIZE; event++ )
4501        if ( mousemap[button][event].type != error )
4502          switch ( mousemap[button][event].type ) {
4503            case key:
4504              printf("   %s = Character: %c \\%d\n",
4505                     mousename(button,event),
4506                     mousemap[button][event].key.scancode,
4507                     mousemap[button][event].key.scancode );
4508              break;
4509            case kverb:
4510              id = mousemap[button][event].kverb.id & ~(F_KVERB);
4511              if ( id != K_IGNORE ) {
4512                  for ( i = 0; i< nkverbs; i++)
4513                    if ( id == kverbs[i].kwval ) {
4514                        name = kverbs[i].kwd;
4515                        break;
4516                    }
4517                  printf("   %s = Kverb: \\K%s\n",
4518                         mousename(button,event),
4519                         name
4520                         );
4521              }
4522              break;
4523            case macro:
4524              printf("   %s = Macro: ",
4525                     mousename(button,event) );
4526              shostrdef(mousemap[button][event].macro.string);
4527              printf("\n");
4528              break;
4529          }
4530}
4531#endif /* OS2MOUSE */
4532#endif /* NOLOCAL */
4533#endif /* NOSHOW */
4534
4535#ifndef NOSHOW
4536#ifdef OS2
4537static struct keytab shokeytab[] = {    /* SHOW KEY modes */
4538    "all",    1, 0,
4539    "one",    0, 0
4540};
4541static int nshokey = (sizeof(shokeytab) / sizeof(struct keytab));
4542#endif /* OS2 */
4543
4544int
4545doshow(x) int x; {
4546    int y, i; long zz;
4547    char *s;
4548#ifdef OS2
4549    extern int os2gks;
4550#endif /* OS2 */
4551
4552#ifndef NOSETKEY
4553    if (x == SHKEY) {                   /* SHOW KEY */
4554        int c;
4555#ifdef OS2
4556        if ((x = cmkey(shokeytab,nshokey,"How many keys should be shown?",
4557                        "one",xxstring)) < 0) return(x);
4558#endif /* OS2 */
4559        if ((y = cmcfm()) < 0) return(y);
4560#ifdef MAC
4561        printf("Not implemented\n");
4562        return(0);
4563#else /* Not MAC */
4564#ifdef OS2
4565        if ( x ) {
4566#ifndef NEWMAPKEY
4567            extern KEY * keymap;
4568            for ( c = 0; c < KMSIZE; c++ )
4569              if ( mapkey(c) != c || macrotab[c] )
4570                shokeycode(c);
4571#else /* NEWMAPKEY */
4572            con_event evt;
4573            for (c = 0; c < KMSIZE; c++) {
4574                evt = mapkey(c);
4575                if (evt.type != error) {
4576                    shokeycode(c);
4577                }
4578            }
4579#endif /* NEWMAPKEY */
4580        } else {
4581#endif /* OS2 */
4582            printf(" Press key: ");
4583#ifdef UNIX
4584#ifdef NOSETBUF
4585            fflush(stdout);
4586#endif /* NOSETBUF */
4587#endif /* UNIX */
4588            conbin((char)escape);       /* Put terminal in binary mode */
4589#ifdef OS2
4590            os2gks = 0;                 /* Turn off Kverb preprocessing */
4591#endif /* OS2 */
4592            c = congks(0);              /* Get character or scan code */
4593#ifdef OS2
4594            os2gks = 1;                 /* Turn on Kverb preprocessing */
4595#endif /* OS2 */
4596            concb((char)escape);        /* Restore terminal to cbreak mode */
4597            if (c < 0) {                /* Check for error */
4598                printf("?Error reading key\n");
4599                return(0);
4600            }
4601#ifndef OS2
4602/*
4603  Do NOT mask when it can be a raw scan code, perhaps > 255
4604*/
4605            c &= cmdmsk;                /* Apply command mask */
4606#endif /* OS2 */
4607            printf("\n");
4608            shokeycode(c);
4609#ifdef OS2
4610        }
4611#endif /* OS2 */
4612        return(1);
4613#endif /* MAC */
4614    }
4615#ifndef NOKVERBS
4616    if (x == SHKVB) {                   /* SHOW KVERBS */
4617        if ((y = cmcfm()) < 0) return(y);           
4618        printf("\nThe following %d keyboard verbs are available:\n\n",nkverbs);
4619        kwdhelp(kverbs,nkverbs,"","\\K","",3);
4620        printf("\n");
4621        return(1);
4622    }
4623#ifdef OS2
4624    if (x == SHUDK) {                   /* SHOW UDKs */
4625        extern void showudk(void);
4626        if ((y = cmcfm()) < 0) return(y);
4627        showudk();
4628        return(1);
4629    }
4630#endif /* OS2 */
4631#endif /* NOKVERBS */
4632#endif /* NOSETKEY */
4633
4634#ifndef NOSPL
4635    if (x == SHMAC) {                   /* SHOW MACRO */
4636        x = cmfld("Macro name, or carriage return to see them all","",&s,
4637                  NULL);
4638        if (x == -3)                    /* This means they want see all */
4639          *line = '\0';
4640        else if (x < 0)                 /* Otherwise negative = parse error */
4641          return(x);
4642        else                            /* 0 or greater */
4643          strcpy(line,s);               /* means they typed something */
4644        if ((y = cmcfm()) < 0) return(y); /* Get confirmation */
4645        if (*line) {
4646            slc = 0;                    /* Initial SHO MAC line number */
4647            x = mlook(mactab,s,nmac);   /* Look up what they typed */
4648            switch (x) {
4649              case -3:                  /* Nothing to look up */
4650                return(0);
4651              case -1:                  /* Not found */
4652                printf("%s - not found\n",s);
4653                return(0);
4654              case -2:                  /* Ambiguous, matches more than one */
4655                y = (int)strlen(line);
4656                slc = 1;
4657                for (x = 0; x < nmac; x++)
4658                  if (!strncmp(mactab[x].kwd,line,y))
4659                    if (shomac(mactab[x].kwd,mactab[x].mval) < 0) break;
4660                return(1);
4661              default:                  /* Matches one exactly */
4662                shomac(mactab[x].kwd,mactab[x].mval);
4663                return(1);
4664            }
4665        } else {                        /* They want to see them all */
4666            printf("Macros:\n");
4667            slc = 1;
4668            for (y = 0; y < nmac; y++)
4669              if (shomac(mactab[y].kwd,mactab[y].mval) < 0) break;
4670            return(1);
4671        }
4672    }
4673#endif /* NOSPL */
4674
4675/*
4676  Other SHOW commands only have two fields.  Get command confirmation here,
4677  then handle with big switch() statement.
4678*/
4679    if ((y = cmcfm()) < 0) return(y);
4680    switch (x) {
4681
4682#ifdef ANYX25
4683      case SHPAD:
4684        shopad();
4685        break;
4686#endif /* ANYX25 */
4687
4688#ifdef NETCONN
4689      case SHNET:
4690        shonet();
4691        break;
4692#endif /* NETCONN */
4693
4694      case SHPAR:
4695        shopar();
4696        break;
4697 
4698      case SHATT:
4699        shoatt();
4700        break;
4701 
4702#ifndef NOSPL
4703      case SHCOU:
4704        printf(" %d\n",count[cmdlvl]);
4705        break;
4706#endif /* NOSPL */
4707
4708#ifndef NOSERVER
4709      case SHSER:                       /* Show Server */
4710        i = 0;
4711#ifndef NOFRILLS
4712        printf("Function           Status:\n");
4713        i++;
4714        printf(" GET                %s\n",nm[en_get]);
4715        i++;
4716        printf(" RETRIEVE           %s\n",nm[en_ret]);
4717        i++;
4718        printf(" SEND               %s\n",nm[en_sen]);
4719        i++;
4720        printf(" MAIL               %s\n",nm[en_mai]);
4721        i++;
4722        printf(" PRINT              %s\n",nm[en_pri]);
4723        i++;
4724#ifndef NOSPL
4725        printf(" REMOTE ASSIGN      %s\n",nm[en_asg]);
4726        i++;
4727#endif /* NOSPL */
4728        printf(" REMOTE CD/CWD      %s\n",nm[en_cwd]);
4729        i++;
4730#ifdef ZCOPY
4731        printf(" REMOTE COPY        %s\n",nm[en_cpy]);
4732        i++;
4733#endif /* ZCOPY */
4734        printf(" REMOTE DELETE      %s\n",nm[en_del]);
4735        printf(" REMOTE DIRECTORY   %s\n",nm[en_dir]);
4736        printf(" REMOTE HOST        %s\n",nm[en_hos]);
4737        i += 3;
4738#ifndef NOSPL
4739        printf(" REMOTE QUERY       %s\n",nm[en_que]);
4740        i++;
4741#endif /* NOSPL */
4742        printf(" REMOTE RENAME      %s\n",nm[en_ren]);
4743        printf(" REMOTE SET         %s\n",nm[en_set]);     
4744        printf(" REMOTE SPACE       %s\n",nm[en_spa]);     
4745        printf(" REMOTE TYPE        %s\n",nm[en_typ]);     
4746        printf(" REMOTE WHO         %s\n",nm[en_who]);
4747        printf(" BYE                %s\n",nm[en_bye]);
4748        printf(" FINISH             %s\n",nm[en_fin]);
4749        i += 7;
4750#endif /* NOFRILLS */
4751        printf("Server timeout:     %d\n",srvtim);
4752        printf("Server display:     %s\n", showoff(srvdis));
4753        printf("Server login:       ");
4754        if (!x_user) {
4755            printf("(none)\n");
4756        } else {
4757            char *s;
4758            printf("\"%s\", \"%s\", \"%s\"\n",
4759                   x_user,
4760                   x_passwd ? x_passwd : "",
4761                   x_acct ? x_acct : ""
4762                   );
4763        }           
4764        printf("Server get-path:");
4765        if (ngetpath == 0) {
4766            printf("    (none)\n");
4767        } else {
4768            printf("\n");
4769            i += 3;
4770            for (x = 0; x < ngetpath; x++) {
4771                if (getpath[x]) printf(" %d. %s\n", x, getpath[x]);
4772                if (++i > (cmd_rows - 3)) { /* More than a screenful... */
4773                    if (!askmore())
4774                      break;
4775                    else
4776                      i = 0;
4777                }
4778            }
4779        }
4780        break;
4781#endif /* NOSERVER */
4782
4783      case SHSTA:                       /* Status of last command */
4784        printf( " %s\n", success ? "SUCCESS" : "FAILURE" );
4785        return(0);                      /* Don't change it */
4786
4787#ifdef MAC
4788      case SHSTK: {                     /* Stack for MAC debugging */
4789          long sp;
4790
4791          sp = -1;
4792          loadA0 ((char *)&sp);         /* set destination address */
4793          SPtoaA0();                    /* move SP to destination */
4794          printf("Stack at 0x%x\n", sp);
4795          show_queue();                 /* more debugging */
4796          break;
4797      }
4798#endif /* MAC */
4799
4800#ifndef NOLOCAL
4801#ifdef OS2
4802      case SHTAB:                       /* SHOW TABS */
4803        shotabs();
4804        break;
4805#endif /* OS2 */
4806
4807      case SHTER:                       /* SHOW TERMINAL */
4808        shotrm();
4809        break;
4810
4811#ifdef OS2
4812      case SHVSCRN:                     /* SHOW Virtual Screen - for debug */
4813        shovscrn();
4814        break;
4815#endif /* OS2 */
4816
4817#ifdef OS2MOUSE
4818      case SHMOU:                       /* SHOW MOUSE */
4819        shomou();
4820        break;
4821#endif /* OS2MOUSE */
4822#endif /* NOLOCAL */
4823
4824#ifndef NOFRILLS
4825      case SHVER:
4826        shover();
4827        break;
4828#endif /* NOFRILLS */
4829 
4830#ifndef NOSPL
4831      case SHBUI:                       /* Built-in variables */
4832      case SHFUN:                       /* or built-in functions */
4833#ifdef CK_TTGWSIZ
4834#ifdef OS2
4835        if (tt_cols[VTERM] < 0 || tt_rows[VTERM] < 0)
4836          ttgwsiz();
4837#else /* OS2 */
4838        if (ttgwsiz() > 0) {            /* Get current screen size */
4839            if (tt_rows > 0 && tt_cols > 0) {
4840                cmd_rows = tt_rows;
4841                cmd_cols = tt_cols;
4842            }
4843        }
4844#endif /* OS2 */
4845#endif /* CK_TTGWSIZ */
4846
4847        if (x == SHFUN) {               /* Functions */
4848            printf("\nThe following functions are available:\n\n");
4849            kwdhelp(fnctab,nfuncs,"","\\F","()",3);
4850            printf("\n");
4851            break;
4852        } else {                        /* Variables */
4853            i = 0;
4854            for (y = 0; y < nvars; y++) {
4855                char *s;
4856                if ((vartab[y].flgs & CM_INV))
4857                  continue;
4858                s = nvlook(vartab[y].kwd);
4859                printf(" \\v(%s) = ",vartab[y].kwd);
4860                if (vartab[y].kwval == VN_NEWL) { /* \v(newline) */
4861                    while (*s)          /* Show control chars symbolically */
4862                      printf("\\{%d}",*s++);
4863                    printf("\n");
4864                } else if ( vartab[y].kwval == VN_IBUF ||  /* \v(input) */
4865                           vartab[y].kwval == VN_QUE  ||  /* \v(query) */
4866#ifdef OS2
4867                            vartab[y].kwval == VN_SELCT || /* \v(select) */
4868#endif /* OS2 */
4869                           (vartab[y].kwval >= VN_M_AAA && /* modem ones */
4870                            vartab[y].kwval <= VN_M_ZZZ)
4871                           ) {
4872                    int r = 12; /* This one can wrap around */
4873                    char buf[10];
4874                    while (*s) {
4875                        if (isprint(*s)) {
4876                            buf[0] = *s;
4877                            buf[1] = NUL;
4878                            r++;
4879                        } else {
4880                            sprintf(buf,"\\{%d}",*s);
4881                            r += (int) strlen(buf);
4882                        }
4883                        if (r >= cmd_cols - 1) {
4884                            printf("\n");
4885                            r = 0;
4886                            i++;
4887                        }
4888                        printf("%s",buf);
4889                        s++;
4890                    }
4891                    printf("\n");
4892                } else
4893                  printf("%s\n",s);
4894                if (++i > (cmd_rows - 3)) {     /* More than a screenful... */
4895                    if ((y >= nvars - 1) || !askmore())
4896                      break;
4897                    else
4898                      i = 0;
4899                }
4900            }
4901        }
4902        break;
4903
4904      case SHVAR:                       /* Global variables */
4905        x = 0;                          /* Variable count */
4906        slc = 1;                        /* Screen line count for "more?" */
4907        for (y = 33; y < GVARS; y++)
4908          if (g_var[y]) {
4909              if (x++ == 0) printf("Global variables:\n");
4910              sprintf(line," \\%%%c",y);
4911              if (shomac(line,g_var[y]) < 0) break;
4912          }
4913        if (!x) printf(" No variables defined\n");
4914        break;
4915
4916      case SHARG:                       /* Args */
4917        if (maclvl > -1) {
4918            printf("Macro arguments at level %d\n",maclvl);
4919            for (y = 0; y < 10; y++)
4920              if (m_arg[maclvl][y])
4921                printf(" \\%%%d = %s\n",y,m_arg[maclvl][y]);
4922        } else {
4923            printf(" No macro arguments at top level\n");
4924        }
4925        break;
4926
4927      case SHARR:                       /* Arrays */
4928        x = 0;
4929        for (y = 0; y < (int) 'z' - ARRAYBASE + 1; y++)
4930          if (a_ptr[y]) {
4931              if (x == 0) printf("Declared arrays:\n");
4932              x = 1;
4933              printf(" \\&%c[%d]\n",
4934                     (y == 1) ? 64 : y + ARRAYBASE, a_dim[y]);
4935          }
4936        if (!x) printf(" No arrays declared\n");
4937        break;
4938#endif /* NOSPL */
4939
4940      case SHPRO:                       /* Protocol parameters */
4941        shoparp();
4942        if (protocol == PROTO_K) {
4943#ifdef XFRCAN
4944            printf("\n Cancellation: %s",showoff(xfrcan));
4945            if (xfrcan) printf(" %d %d\n", xfrchr, xfrnum);
4946            else printf("\n");
4947#endif /* XFRCAN */
4948            printf(" Send / Receive Pause:   %d (msec)\n\n",pktpaus);
4949        }
4950        break;
4951
4952      case SHCOM:                       /* Communication parameters */
4953        printf("\n");
4954        shoparc();
4955#ifdef OS2
4956        {
4957            int i;
4958            char *s = "(unknown)";
4959            for (i = 0; i < nprty; i++)
4960              if (prtytab[i].kwval == priority) {
4961                  s = prtytab[i].kwd;
4962                  break;
4963              }
4964            printf(" Priority: %s\n", s );
4965        }
4966#endif /* OS2 */
4967
4968        printf("\n");
4969#ifdef NETCONN
4970        if (!network) {
4971#endif /* NETCONN */
4972            shomdm();
4973            printf("\n");
4974#ifdef NETCONN
4975        }
4976#endif /* NETCONN */
4977
4978#ifdef COMMENT                          /* No more space for this! */
4979#ifndef NODIAL
4980        printf("\n");
4981#ifdef NETCONN
4982        if (!network)
4983#endif /* NETCONN */
4984          shodial();
4985#endif /* NODIAL */
4986#else
4987#ifndef NODIAL
4988        printf("Type SHOW DIAL to see DIAL-related items\n");
4989#endif /* NODIAL */
4990#endif /* COMMENT */
4991        break;
4992
4993      case SHFIL:                       /* File parameters */
4994        shoparf();
4995        /* printf("\n"); */             /* (out o' space) */
4996        break;
4997
4998#ifndef NOCSETS
4999      case SHLNG:                       /* Languages */
5000        shoparl();
5001        break;
5002#endif /* NOCSETS */
5003
5004#ifndef NOSPL
5005      case SHSCR:                       /* Scripts */
5006        printf(" Command Quoting:     %s\n", showoff(cmdgquo()));
5007        printf(" Take  Echo:          %s\n", showoff(techo));
5008        printf(" Take  Error:         %s\n", showoff(takerr[cmdlvl]));
5009        printf(" Macro Echo:          %s\n", showoff(mecho));
5010        printf(" Macro Error:         %s\n", showoff(merror[cmdlvl]));
5011        printf(" Input Case:          %s\n", inpcas[cmdlvl] ?
5012               "Observe" : "Ignore");
5013        printf(" Input Buffer-length: %d\n", inbufsize);
5014        printf(" Input Echo:          %s\n", showoff(inecho));
5015        printf(" Input Silence:       %d (seconds)\n", insilence);
5016        printf(" Input Timeout:       %s\n", intime[cmdlvl] ?
5017               "quit" : "proceed");
5018        if (instatus < 0)
5019          printf(" Last INPUT:          -1 (INPUT command not yet given)\n");
5020        else
5021          printf(" Last INPUT:          %d (%s)\n", instatus,i_text[instatus]);
5022        printf(" Output Pacing:       %d (milliseconds)\n",pacing);
5023#ifndef NOSCRIPT
5024        printf(" Script Echo:         %s\n", showoff(secho));
5025#endif /* NOSCRIPT */
5026        printf(" Command buffer:      %d\n", CMDBL);
5027        printf(" Atom buffer:         %d\n", ATMBL);
5028
5029        break;
5030#endif /* NOSPL */
5031
5032#ifndef NOXMIT
5033      case SHXMI:
5034        printf(" File type: %s\n", binary ? "binary" : "text");
5035#ifndef OS2
5036        printf(" See SHOW CHARACTER-SETS for character-set info\n");
5037#else /* OS2 */
5038#ifndef NOCSETS
5039        shotcs(tcsl,tcsr);
5040#endif /* NOCSETS */
5041#endif /* OS2 */
5042        printf(" Terminal echo: %s\n", duplex ? "local" : "remote");
5043        printf(" Transmit EOF: ");
5044        if (*xmitbuf == NUL) {
5045            printf("none\n");
5046        } else {
5047            char *p;
5048            p = xmitbuf;
5049            while (*p) {
5050                if (*p < SP)
5051                  printf("^%c",ctl(*p));
5052                else
5053                  printf("%c",*p);
5054                p++;
5055            }
5056            printf("\n");
5057        }
5058        if (xmitf)
5059          printf(" Transmit Fill: %d (fill character for blank lines)\n",
5060                 xmitf);
5061        else
5062          printf(" Transmit Fill: none\n");
5063        printf(" Transmit Linefeed: %s\n",
5064               xmitl ? "on (send linefeeds too)" : "off");
5065        if (xmitp)
5066          printf(" Transmit Prompt: %d (host line end character)\n",xmitp);
5067        else
5068          printf(" Transmit Prompt: none\n");
5069        printf(" Transmit Echo: %s\n", showoff(xmitx));
5070        printf(" Transmit Locking-Shift: %s\n", showoff(xmits));
5071        printf(" Transmit Pause: %d milliseconds\n", xmitw);
5072        break;
5073#endif /* NOXMIT */
5074
5075#ifndef NODIAL
5076      case SHMOD:                       /* SHOW MODEM */
5077        shomodem();                     /* Show SET MODEM items */
5078        break;
5079#endif /* NODIAL */
5080
5081#ifndef MAC
5082      case SHDFLT:
5083        zsyscmd(PWDCMD);
5084        break;
5085#endif /* MAC */
5086
5087#ifndef NOLOCAL
5088      case SHESC:
5089        printf(" Escape character: Ctrl-%c (ASCII %d, %s): %s\r\n",
5090               ctl(escape), escape, (escape == 127 ? "DEL" : ccntab[escape]),
5091           nm[tt_escape]
5092           );
5093        break;
5094#endif /* NOLOCAL */
5095
5096#ifndef NODIAL
5097      case SHDIA:                       /* SHOW DIAL */
5098        shmdmlin();
5099        printf(", speed: ");
5100        if ((zz = ttgspd()) < 0) {
5101            printf("unknown");
5102        } else {
5103            if (zz == 8880) printf("75/1200"); else printf("%ld",zz);
5104        }
5105        if (carrier == CAR_OFF) s = "off";
5106        else if (carrier == CAR_ON) s = "on";
5107        else if (carrier == CAR_AUT) s = "auto";
5108        else s = "unknown";
5109        printf(", carrier: %s", s);
5110        if (carrier == CAR_ON) {
5111            if (cdtimo) printf(", timeout: %d sec", cdtimo);
5112            else printf(", timeout: none");
5113        }
5114        printf("\n");
5115        doshodial();
5116        if (local
5117#ifdef NETCONN
5118            && !network
5119#endif /* NETCONN */
5120            ) {
5121            printf("Type SHOW MODEM to see modem settings.\n");
5122            printf("Type SHOW COMMUNICATIONS to see modem signals.\n");
5123        }
5124        break;
5125#endif /* NODIAL */
5126
5127#ifdef CK_LABELED
5128      case SHLBL:                       /* Labeled file info */
5129        sholbl();
5130        break;
5131#endif /* CK_LABELED */
5132
5133      case SHCSE:                       /* Character sets */
5134#ifdef NOCSETS
5135        printf(
5136" Character set translation is not supported in this version of C-Kermit\n");
5137#else
5138        shocharset();
5139        printf("\n Unknown-Char-Set: %s\n",
5140               unkcs ? "Keep" : "Discard");
5141#ifdef OS2
5142        printf("\n");
5143#endif /* OS2 */
5144        shotcs(tcsl,tcsr);
5145        printf("\n");
5146#endif /* NOCSETS */
5147        break;
5148
5149#ifndef NOFRILLS
5150      case SHFEA:                       /* Features */
5151        shofea();
5152        break;
5153#endif /* NOFRILLS */
5154
5155#ifdef CK_SPEED
5156      case SHCTL:                       /* Control-Prefix table */
5157        shoctl();
5158        break;
5159#endif /* CK_SPEED */
5160
5161      case SHEXI:
5162        printf("\n Exit warning %s\n", xitwarn ?
5163               (xitwarn == 1 ? "on" : "always") : "off");
5164        printf(" Exit on-disconnect: %s\n", showoff(exitonclose));
5165        printf(" Current exit status: %d\n\n", xitsta);
5166        break;
5167
5168      case SHPRT:
5169        printf("Printer: %s%s\n",
5170               printpipe ? "| " : "",
5171               printfile ? printfile :
5172#ifdef OS2
5173               "PRN"
5174#else
5175               "(default)"
5176#endif /* OS2 */
5177               );
5178        break;
5179
5180      case SHCMD:
5181        printf(" Command bytesize: %d bits\n",
5182               (cmdmsk == 0377) ? 8 : 7);
5183#ifdef CK_RECALL
5184        printf(" Command recall-buffer-size: %d\n",cm_recall);
5185#else
5186        printf(" Command recall-buffer not available in this version\n");
5187#endif /* CK_RECALL */
5188#ifdef CK_RECALL
5189        printf(" Command retry: %s\n",cm_retry ? "on" : "off");
5190#else
5191        printf(" Command retry not available in this version\n");
5192#endif /* CK_RECALL */
5193        printf(" Command quoting: %s\n", showoff(cmdgquo()));
5194        printf(" Command more-prompting: %s\n", showoff(xaskmore));
5195        printf(" Command height: %d\n", cmd_rows);
5196        printf(" Command width:  %d\n", cmd_cols);
5197        printf(" Maximum command length: %d\n", CMDBL);
5198#ifndef NOSPL
5199        printf(" Maximum number of macros: %d\n", MAC_MAX);
5200        printf(" Macros defined: %d\n", nmac);
5201        printf(" Maximum macro depth: %d\n", MACLEVEL);
5202        printf(" Maximum TAKE depth: %d\n", MAXTAKE);
5203#endif /* NOSPL */
5204#ifdef UNIX
5205#ifndef NOJC
5206        printf(" Suspend: %s\n", showoff(suspend));
5207#endif /* NOJC */
5208#endif /* UNIX */
5209        break;
5210
5211#ifndef NOSPL
5212      case SHALRM:
5213        if (ck_alarm)
5214          printf("Alarm at %s %s\n",alrm_date,alrm_time);
5215        else
5216          printf("(no alarm set)\n");
5217        break;
5218#endif /* NOSPL */
5219
5220#ifndef NOMSEND
5221      case SHSFL: {
5222          extern struct filelist * filehead;
5223          if (!filehead) {
5224              printf("send-list is empty\n");
5225          } else {
5226              struct filelist * flp;
5227              char * s;
5228              flp = filehead;
5229              while (flp) {
5230                  s = flp->fl_alias;
5231                  if (!s) s = "(none)";
5232                  printf("%s, mode: %s, alias: %s\n",
5233                         flp->fl_name,
5234                         gfmode(flp->fl_mode),
5235                         s
5236                         );
5237                  flp = flp->fl_next;
5238              }
5239          }
5240      }
5241      break;
5242
5243#endif /* NOMSEND */
5244
5245      default:
5246        printf("\nNothing to show...\n");
5247        return(-2);
5248    }
5249    return(success = 1);
5250}
5251#endif /* NOSHOW */
5252
5253VOID
5254shmdmlin() {                            /* Briefly show modem & line */
5255#ifndef NODIAL
5256    int i;
5257#ifndef MINIDIAL
5258#ifdef OLDTBCODE
5259    extern int tbmodel;
5260    _PROTOTYP( char * gtbmodel, (void) );
5261#endif /* OLDTBCODE */
5262#endif /* MINIDIAL */
5263#endif /* NODIAL */
5264    if (local)
5265#ifdef OS2
5266      printf(" Port: %s, Modem type: ",ttname);
5267#else
5268      printf(" Line: %s, Modem type: ",ttname);
5269#endif /* OS2 */
5270    else
5271      printf(
5272#ifdef OS2
5273" Communication device not yet selected with SET PORT\n Modem type: "
5274#else
5275" Communication device not yet selected with SET LINE\n Modem type: "
5276#endif /* OS2 */
5277             );
5278#ifndef NODIAL
5279    printf("%s",gmdmtyp());
5280#ifndef MINIDIAL
5281#ifdef OLDTBCODE
5282    if (tbmodel) printf(" (%s)",gtbmodel()); /* Telebit model info */
5283#endif /* OLDTBCODE */
5284#endif /* MINIDIAL */
5285#else
5286    printf("(disabled)");
5287#endif /* NODIAL */
5288}
5289
5290#ifdef GEMDOS
5291isxdigit(c) int c; {
5292    return(isdigit(c) ||
5293           (c >= 'a' && c <= 'f') ||
5294           (c >= 'A' && c <= 'F'));
5295}
5296#endif /* GEMDOS */
5297
5298#ifndef NOSHOW
5299#ifndef NOSPL
5300int                                     /* SHO MACROS */
5301shomac(s1, s2) char *s1, *s2; {
5302    int x, n, pp;
5303    pp = 0;                             /* Parenthesis counter */
5304
5305    if (!s1)
5306      return(0);
5307    else
5308      printf("\n%s = ",s1);             /* Print blank line and macro name */
5309    slc++;                              /* Count the line */
5310    n = (int)strlen(s1) + 4;            /* Width of current line */
5311    if (!s2) s2 = "(null definition)";
5312
5313    while (x = *s2++) {                 /* Loop thru definition */
5314        if (x == '(') pp++;             /* Treat commas within parens */
5315        if (x == ')') pp--;             /* as ordinary text */
5316        if (pp < 0) pp = 0;             /* Outside parens, */
5317        if (x == ',' && pp == 0) {      /* comma becomes comma-dash-NL. */
5318            putchar(',');
5319            putchar('-');
5320            x = '\n';
5321        }
5322        putchar(x);                     /* Output the character */
5323        if (x == '\n') {                /* If it was a newline */
5324#ifdef UNIX
5325#ifdef NOSETBUF
5326            fflush(stdout);
5327#endif /* NOSETBUF */
5328#endif /* UNIX */
5329            putchar(' ');               /* Indent the next line 1 space */
5330            while(*s2 == ' ') s2++;     /* skip past leading blanks */
5331            n = 2;                      /* restart the character counter */
5332            slc++;                      /* and increment the line counter. */
5333        } else if (++n > (cmd_cols - 1)) { /* If line is too wide */
5334            putchar('-');               /* output a dash */
5335            putchar(NL);                /* and a newline */
5336#ifdef UNIX
5337#ifdef NOSETBUF
5338            fflush(stdout);
5339#endif /* NOSETBUF */
5340#endif /* UNIX */
5341            n = 1;                      /* and restart the char counter */
5342            slc++;                      /* and increment the line counter */
5343        }
5344        if (n < 3 && slc > (cmd_rows - 3)) { /* If new line and screen full */
5345            if (!askmore()) return(-1); /* ask if they want more. */
5346            n = 1;                      /* They do, start a new line */
5347            slc = 0;                    /* and restart line counter */
5348        }
5349    }
5350    putchar(NL);                        /* End of definition */
5351    if (++slc > (cmd_rows - 3)) {
5352        if (!askmore()) return(-1);
5353        slc = 0;
5354    }
5355    return(0);
5356}
5357#endif /* NOSPL */
5358#endif /* NOSHOW */
5359
5360#ifndef NOSHOW
5361int
5362shoatt() {
5363    printf("Attributes: %s\n", showoff(atcapr));
5364    if (!atcapr) return(0);
5365    printf(" Blocksize: %s\n", showoff(atblki));
5366    printf(" Date: %s\n", showoff(atdati));
5367    printf(" Disposition: %s\n", showoff(atdisi));
5368    printf(" Encoding (Character Set): %s\n", showoff(atenci));
5369    printf(" Length: %s\n", showoff(atleni));
5370    printf(" Type (text/binary): %s\n", showoff(attypi));
5371    printf(" System ID: %s\n", showoff(atsidi));
5372    printf(" System Info: %s\n", showoff(atsysi));
5373#ifdef STRATUS
5374    printf(" Format: %s\n", showoff(atfrmi));
5375    printf(" Creator: %s\n", showoff(atcrei));
5376    printf(" Account: %s\n", showoff(atacti));
5377#endif /* STRATUS */
5378    return(0);
5379}
5380#endif /* NOSHOW */
5381
5382int x_ifnum = 0;                        /* Flag for IF NUMERIC active */
5383
5384#ifndef NOSPL
5385/* Evaluate an arithmetic expression. */
5386/* Code adapted from ev, by Howie Kaye of Columbia U & others. */
5387
5388static int xerror;
5389static char *cp;
5390static long tokval;
5391static char curtok;
5392static long expval;
5393
5394#define LONGBITS (8*sizeof (long))
5395#define NUMBER 'N'
5396#define N_EOT 'E'
5397
5398/*
5399 Replacement for strchr() and index(), neither of which seem to be universal.
5400*/
5401
5402static char *
5403#ifdef CK_ANSIC
5404windex(char * s, char c)
5405#else
5406windex(s,c) char *s, c;
5407#endif /* CK_ANSIC */
5408/* windex */ {
5409    while (*s != NUL && *s != c) s++;
5410    if (*s == c) return(s); else return(NULL);
5411}
5412
5413/*
5414 g e t t o k
5415
5416 Returns the next token.  If token is a NUMBER, sets tokval appropriately.
5417*/
5418static char
5419gettok() {
5420
5421    while (isspace(*cp))                /* Skip past leading spaces */
5422      cp++;
5423
5424    switch (*cp) {
5425      case '$':                         /* ??? */
5426      case '+':                         /* Add */
5427      case '-':                         /* Subtract or Negate */
5428      case '@':                         /* Greatest Common Divisor */
5429      case '*':                         /* Multiply */
5430      case '/':                         /* Divide */
5431      case '%':                         /* Modulus */
5432      case '<':                         /* Left shift */
5433      case '>':                         /* Right shift */
5434      case '&':                         /* And */
5435      case '|':                         /* Or */
5436      case '#':                         /* Exclusive Or */
5437      case '~':                         /* Not */
5438      case '^':                         /* Exponent */
5439      case '!':                         /* Factorial */
5440      case '(':                         /* Parens for grouping */
5441      case ')': return(*cp++);          /* operator, just return it */
5442      case '\n':
5443      case '\0': return(N_EOT);         /* End of line, return that */
5444    }
5445    if (isxdigit(*cp)) {                /* Digit, must be a number */
5446        char tbuf[80],*tp;              /* Buffer to accumulate number */
5447        int radix = 10;                 /* Default radix */
5448        for (tp = tbuf; isxdigit(*cp); cp++)
5449          *tp++ = (char) (isupper(*cp) ? tolower(*cp) : *cp);
5450        *tp = '\0';                     /* End number */
5451        switch(isupper(*cp) ? tolower(*cp) : *cp) { /* Examine break char */
5452          case 'h':
5453          case 'x': radix = 16; cp++; break; /* if radix signifier... */
5454          case 'o':
5455          case 'q': radix = 8; cp++; break;
5456          case 't': radix = 2; cp++; break;
5457        }
5458        for (tp = tbuf, tokval = 0; *tp != '\0'; tp++)  {
5459            int dig;
5460            dig = *tp - '0';            /* Convert number */
5461            if (dig > 10) dig -= 'a'-'0'-10;
5462            if (dig >= radix) {
5463                xerror = 1;
5464                if (cmdlvl == 0 && !x_ifnum)
5465                  printf("invalid digit '%c' in number\n",*tp);
5466                return(NUMBER);
5467            }
5468            tokval = radix*tokval + dig;
5469        }
5470        return(NUMBER);
5471    }
5472    if (cmdlvl == 0 && !x_ifnum)
5473      printf("Invalid character '%c' in input\n",*cp);
5474    xerror = 1;
5475    cp++;
5476    return(gettok());
5477}
5478
5479static long
5480#ifdef CK_ANSIC
5481expon(long x, long y)
5482#else
5483expon(x,y) long x,y;
5484#endif /* CK_ANSIC */
5485/* expon */ {
5486    long result = 1;
5487    int sign = 1;
5488    if (y < 0) return(0);
5489    if (x < 0) {
5490        x = -x;
5491        if (y & 1) sign = -1;
5492    }
5493    while (y != 0) {
5494        if (y & 1) result *= x;
5495        y >>= 1;
5496        if (y != 0) x *= x;
5497  }
5498  return(result * sign);
5499}
5500
5501/*
5502 * factor ::= simple | simple ^ factor
5503 *
5504 */
5505_PROTOTYP( static VOID simple, (void) );
5506
5507static VOID
5508factor() {
5509    long oldval;
5510    simple();
5511    if (curtok == '^') {
5512        oldval = expval;
5513        curtok = gettok();
5514        factor();
5515        expval = expon(oldval,expval);
5516    }
5517}
5518
5519/*
5520 * termp ::= NULL | {*,/,%,&} factor termp
5521 *
5522 */
5523static VOID
5524termp() {
5525    while (curtok == '*' || curtok == '/' || curtok == '%' || curtok == '&') {
5526        long oldval;
5527        char op;
5528        op = curtok;
5529        curtok = gettok();              /* skip past operator */
5530        oldval = expval;
5531        factor();
5532        switch(op) {
5533          case '*': expval = oldval * expval; break;
5534          case '/':
5535            if (expval == 0) expval = -1; /* don't divide by 0 */
5536            else expval = oldval / expval; break;
5537          case '%': expval = oldval % expval; break;
5538          case '&': expval = oldval & expval; break;
5539        }
5540    }
5541}
5542
5543static long
5544#ifdef CK_ANSIC
5545fact(long x)
5546#else
5547fact(x) long x;
5548#endif /* CK_ANSIC */
5549/* fact */ {                            /* factorial */
5550    long result = 1;
5551    while (x > 1)
5552      result *= x--;
5553    return(result);
5554}
5555
5556/*
5557 * term ::= factor termp
5558 *
5559 */
5560static VOID
5561term() {
5562    factor();
5563    termp();
5564}
5565
5566static long
5567#ifdef CK_ANSIC
5568gcd(long x, long y)
5569#else
5570gcd(x,y) long x,y;
5571#endif /* CK_ANSIC */
5572/* gcd */ {                             /* Greatest Common Divisor */
5573    int nshift = 0;
5574    if (x < 0) x = -x;
5575    if (y < 0) y = -y;                  /* validate arguments */
5576    if (x == 0 || y == 0) return(x + y);    /* this is bogus */
5577   
5578    while (!((x & 1) | (y & 1))) {      /* get rid of powers of 2 */
5579        nshift++;
5580        x >>= 1;
5581        y >>= 1;
5582    }
5583    while (x != 1 && y != 1 && x != 0 && y != 0) {
5584        while (!(x & 1)) x >>= 1;       /* eliminate unnecessary */
5585        while (!(y & 1)) y >>= 1;       /* powers of 2 */
5586        if (x < y) {                    /* force x to be larger */
5587            long t;
5588            t = x;
5589            x = y;
5590            y = t;
5591        }
5592        x -= y;
5593    }
5594    if (x == 0 || y == 0) return((x + y) << nshift); /* gcd is non-zero one */
5595    else return((long) 1 << nshift);    /* else gcd is 1 */
5596}
5597
5598/*
5599 * exprp ::= NULL | {+,-,|,...} term exprp
5600 *
5601 */
5602static VOID
5603exprp() {
5604    while (windex("+-|<>#@",curtok) != NULL) {
5605        long oldval;
5606        char op;
5607        op = curtok;
5608        curtok = gettok();              /* skip past operator */
5609        oldval = expval;
5610        term();
5611        switch(op) {
5612          case '+' : expval = oldval + expval; break;
5613          case '-' : expval = oldval - expval; break;
5614          case '|' : expval = oldval | expval; break;
5615          case '#' : expval = oldval ^ expval; break;
5616          case '@' : expval = gcd(oldval,expval); break;
5617          case '<' : expval = oldval << expval; break;
5618          case '>' : expval = oldval >> expval; break;
5619        }
5620    }
5621}
5622
5623/*
5624 * expr ::= term exprp
5625 *
5626 */
5627static VOID
5628expr() {
5629    term();
5630    exprp();
5631}
5632
5633static long
5634xparse() {
5635    curtok = gettok();
5636    expr();
5637#ifdef COMMENT
5638    if (curtok == '$') {
5639        curtok = gettok();
5640        if (curtok != NUMBER) {
5641            if (cmdlvl == 0 && !x_ifnum)
5642              printf("illegal radix\n");
5643            return(0);
5644        }
5645        curtok = gettok();
5646    }
5647#endif /* COMMENT */
5648    if (curtok != N_EOT) {
5649        if (cmdlvl == 0 && !x_ifnum)
5650          printf("extra characters after expression\n");
5651        xerror = 1;
5652    }
5653    return(expval);
5654}
5655
5656char *
5657evala(s) char *s; {
5658    char *p;                            /* Return pointer */
5659    long v;                             /* Numeric value */
5660
5661    if (!s) return("");
5662    xerror = 0;                         /* Start out with no error */
5663    cp = s;                             /* Make the argument global */
5664    v = xparse();                       /* Parse the string */
5665    p = numbuf;                         /* Convert long number to string */
5666    sprintf(p,"%ld",v);
5667    return(xerror ? "" : p);            /* Return empty string on error */
5668}
5669
5670/*
5671 * simplest ::= NUMBER | ( expr )
5672 *
5673 */
5674static VOID
5675simplest() {
5676    if (curtok == NUMBER) expval = tokval;
5677    else if (curtok == '(') {
5678        curtok = gettok();              /* skip over paren */
5679        expr();
5680        if (curtok != ')') {
5681            if (cmdlvl == 0 && !x_ifnum)
5682              printf("missing right parenthesis\n");
5683            xerror = 1;
5684        }
5685    } else {
5686        if (cmdlvl == 0 && !x_ifnum)
5687          printf("operator unexpected\n");
5688        xerror = 1;
5689    }
5690    curtok = gettok();
5691}
5692
5693/*
5694 * simpler ::= simplest | simplest !
5695 *
5696 */
5697static VOID
5698simpler() {
5699    simplest();
5700    if (curtok == '!') {
5701        curtok = gettok();
5702        expval = fact(expval);
5703    }
5704}
5705
5706/*
5707 * simple ::= {-,~} simpler | simpler
5708 *
5709 */
5710
5711static VOID
5712simple() {
5713    if (curtok == '-' || curtok == '~') {
5714        int op = curtok;
5715        curtok = gettok();              /* skip over - sign */
5716        simpler();                      /* parse the factor again */
5717        expval = op == '-' ? -expval : ~expval;
5718    } else simpler();
5719}
5720#endif /* NOSPL */
5721
5722#ifndef NOSPL
5723/*  D C L A R R A Y  --  Declare an array  */
5724
5725int                                     /* Declare an array of size n */
5726#ifdef CK_ANSIC
5727dclarray(char a, int n)
5728#else
5729dclarray(a,n) char a; int n;
5730#endif /* CK_ANSIC */
5731/* dclarray */ {
5732    char **p; int i, n2;
5733
5734    if (a > 63 && a < 91) a += 32;      /* Convert letters to lowercase */
5735    if (a < ARRAYBASE || a > 122)       /* Verify name */
5736      return(-1);
5737    a -= ARRAYBASE;                     /* Convert name to number */
5738    if ((p = a_ptr[a]) != NULL) {       /* Delete old array of same name */
5739        n2 = a_dim[a];
5740        for (i = 0; i <= n2; i++) {     /* First delete its elements */
5741            if (p[i]) {
5742                free(p[i]);
5743                p[i] = NULL;
5744            }
5745        }
5746        free(a_ptr[a]);                 /* Then the element list */
5747        a_ptr[a] = (char **) NULL;      /* Remove pointer to element list */
5748        a_dim[a] = 0;                   /* Set dimension at zero. */
5749    }
5750    if (n == 0) return(0);              /* If dimension 0, just deallocate. */
5751
5752    p = (char **) malloc((n+1) * sizeof(char **)); /* Allocate for new array */
5753    if (p == NULL) return(-1);          /* Check */
5754    a_ptr[a] = p;                       /* Save pointer to member list */
5755    a_dim[a] = n;                       /* Save dimension */
5756    for (i = 0; i <= n; i++)            /* Initialize members to null */
5757      p[i] = NULL;
5758    return(0);
5759}
5760
5761/*  A R R A Y N A M  --  Parse an array name  */
5762
5763/*
5764  Call with pointer to string that starts with the array reference.
5765  String may begin with either \& or just &.
5766  On success,
5767    Returns letter ID (always lowercase) in argument c,
5768      which can also be accent grave (` = 96; '@' is converted to grave);
5769    Dimension or subscript in argument n;
5770    IMPORTANT: These arguments must be provided by the caller as addresses
5771    of ints (not chars), for example:
5772      char *s; int x, y;
5773      arraynam(s,&x,&y);
5774  On failure, returns a negative number, with args n and c set to zero.
5775*/
5776int
5777arraynam(ss,c,n) char *ss; int *c; int *n; {
5778    int i, y, pp;
5779    char x;
5780    char *s, *p, *sx, *vnp;
5781    /* On stack to allow for recursive calls... */
5782    char vnbuf[ARRAYREFLEN+1];          /* Entire array reference */
5783    char ssbuf[ARRAYREFLEN+1];          /* Subscript in "plain text" */
5784    char sxbuf[16];                     /* Evaluated subscript */
5785
5786    *c = *n = 0;                        /* Initialize return values */
5787    for (i = 0; i < (int)strlen(ss); i++) /* Check length */
5788      if (ss[i] == ']')
5789        break;
5790    if (i > ARRAYREFLEN) {
5791        printf("?Array reference too long - %s\n",ss);
5792        return(-9);
5793    }
5794    strncpy(vnbuf,ss,ARRAYREFLEN);
5795    vnp = vnbuf;
5796    if (vnbuf[0] == CMDQ && vnbuf[1] == '&') vnp++;
5797    if (*vnp != '&') {
5798        printf("?Not an array - %s\n",vnbuf);
5799        return(-9);
5800    }
5801    x = *(vnp + 1);                     /* Fold case of array name */
5802    /* We don't use isupper & tolower here on purpose because these */
5803    /* would produce undesired effects with accented letters. */
5804    if (x > 63 && x < 91) x  = *(vnp + 1) = (char) (x + 32);
5805    if ((x < ARRAYBASE) || (x > 122) || (*(vnp+2) != '[')) {
5806        printf("?Invalid format for array name - %s\n",vnbuf);
5807        return(-9);
5808    }
5809    *c = x;                             /* Return the array name */
5810    s = vnp+3;                          /* Get dimension */
5811    p = ssbuf;   
5812    pp = 1;                             /* Bracket counter */
5813    for (i = 0; i < ARRAYREFLEN && *s != NUL; i++) { /* Copy up to ] */
5814        if (*s == '[') pp++;
5815        if (*s == ']' && --pp == 0) break;
5816        *p++ = *s++;
5817    }
5818    if (*s != ']') {
5819        printf("?No closing bracket on array dimension - %s\n",vnbuf);
5820        return(-9);
5821    }
5822    *p--;                               /* Trim whitespace from end */
5823    while (*p == SP || *p == HT)
5824      p--;
5825    p++;
5826    *p = NUL;                           /* Terminate subscript with null */
5827    p = ssbuf;                          /* Point to beginning of subscript */
5828    while (*p == SP || *p == HT)        /* Trim whitespace from beginning */
5829      p++;
5830    sx = sxbuf;                         /* Where to put expanded subscript */
5831    y = 16;
5832    zzstring(p,&sx,&y);                 /* Convert variables, etc. */
5833
5834    p = evala(sxbuf);                   /* Run it thru \fneval()... */
5835    if (p) if (*p) strcpy(sxbuf,p);     /* We know it has to be a number. */
5836
5837    if (!chknum(sxbuf)) {               /* Make sure it's all digits */
5838        printf("?Array dimension or subscript must be numeric - %s\n",sxbuf);
5839        return(-9);
5840    }
5841    if ((y = atoi(sxbuf)) < 0) {
5842        if (cmflgs == 0) printf("\n");
5843        printf("?Array dimension or subscript must be positive or zero - %s\n",
5844               sxbuf);
5845        return(-9);
5846    }
5847    *n = y;                             /* Return the subscript or dimension */
5848    return(0);
5849}
5850
5851int
5852chkarray(a,i) int a, i; {               /* Check if array is declared */
5853    int x;                              /* and if subscript is in range */
5854    if (a == 64) a = 96;                /* Convert atsign to grave accent */
5855    x = a - ARRAYBASE;                  /* Values must be in range 95-122 */
5856    if (x < 0 || x > 'z' - ARRAYBASE)   /* Not in range */
5857      return(-2);
5858    if (a_ptr[x] == NULL) return(-1);   /* Not declared */
5859    if (i > a_dim[x]) return(-2);       /* Declared but out of range. */
5860    return(a_dim[x]);                   /* All ok, return dimension */
5861}
5862
5863#ifdef COMMENT                          /* This isn't used. */
5864char *
5865arrayval(a,i) int a, i; {               /* Return value of \&a[i] */
5866    int x; char **p;                    /* (possibly NULL) */
5867    if (a == 64) a = 96;                /* Convert atsign to grave accent */
5868    x = a - ARRAYBASE;                  /* Values must be in range 95-122 */
5869    if (x < 0 || x > 27) return(NULL);  /* Not in range */
5870    if ((x > 0) && (p = a_ptr[x]) == NULL) /* Array not declared */
5871      return(NULL);
5872    if (i > a_dim[x])                   /* Subscript out of range. */
5873      return(NULL);
5874    return(p[i]);                       /* All ok, return pointer to value. */
5875}
5876#endif /* COMMENT */
5877#endif /* NOSPL */
5878
5879#ifndef NOSPL
5880/*  P A R S E V A R  --  Parse a variable name or array reference.  */
5881/*
5882 Call with:
5883   s  = pointer to candidate variable name or array reference.
5884   *c = address of integer in which to return variable ID.
5885   *i = address of integer in which to return array subscript.
5886 Returns:
5887   -2:  syntax error in variable name or array reference.
5888    1:  successful parse of a simple variable, with ID in c.
5889    2:  successful parse of an array reference, w/ID in c and subscript in i.
5890*/
5891int
5892parsevar(s,c,i) char *s; int *c, *i; {
5893    char *p;
5894    int x,y,z;
5895
5896    p = s;
5897    if (*s == CMDQ) s++;                /* Point after backslash */
5898
5899    if (*s != '%' && *s != '&') {       /* Make sure it's % or & */
5900        printf("?Not a variable name - %s\n",p);
5901        return(-9);
5902    }
5903    if ((int)strlen(s) < 2) {
5904        printf("?Incomplete variable name - %s\n",p);
5905        return(-9);
5906    }
5907    if (*s == '%' && *(s+2) != '\0') {
5908        printf("?Only one character after '%%' in variable name, please\n");
5909        return(-9);
5910    }
5911    if (*s == '&' && *(s+2) != '[') {
5912        printf("?Array subscript expected - %s\n",p);
5913        return(-9);
5914    }
5915    if (*s == '%') {                    /* Simple variable. */
5916        y = *(s+1);                     /* Get variable ID letter/char */
5917        if (isupper(y)) y -= ('a'-'A'); /* Convert upper to lower case */
5918        *c = y;                         /* Set the return values. */
5919        *i = -1;                        /* No array subscript. */
5920        return(1);                      /* Return 1 = simple variable */
5921    }
5922    if (*s == '&') {                    /* Array reference. */
5923        if (arraynam(s,&x,&z) < 0) { /* Go parse it. */
5924            printf("?Invalid array reference - %s\n",p);
5925            return(-9);
5926        }
5927        if (chkarray(x,z) < 0) {        /* Check if declared, etc. */
5928            printf("?Array not declared or subscript out of range\n");
5929            return(-9);
5930        }
5931        *c = x;                         /* Return array letter */
5932        *i = z;                         /* and subscript. */
5933        return(2);
5934    }   
5935    return(-2);                         /* None of the above. */
5936}
5937
5938#define VALN 20
5939
5940/* Get the numeric value of a variable */
5941/*
5942  Call with pointer to variable name, pointer to int for return value.
5943  Returns:
5944    0 on success with second arg containing the value.
5945   -1 on failure (bad variable syntax, variable not defined or not numeric).
5946*/
5947int
5948varval(s,v) char *s; int *v; {
5949    char valbuf[VALN+1];                /* s is pointer to variable name */
5950    char name[256];
5951    char *p;
5952    int y;
5953
5954    if (*s != CMDQ) {                   /* Handle macro names too */
5955        sprintf(name,"\\m(%s)", s);
5956        s = name;
5957    }
5958    p = valbuf;                         /* Expand variable into valbuf. */
5959    y = VALN;
5960    if (zzstring(s,&p,&y) < 0) return(-1);
5961    p = valbuf;                         /* Make sure value is numeric */
5962    if (chknum(p)) {                    /* Convert numeric string to int */
5963        *v = atoi(p);                   /* OK */
5964    } else {                            /* Not OK */
5965        p = evala(p);                   /* Maybe it's an expression */
5966        if (!chknum(p))                 /* Did it evaluate? */
5967          return(-1);                   /* No, failure. */
5968        else                            /* Yes, */
5969          *v = atoi(p);                 /* success */
5970    }
5971    return(0);   
5972}
5973
5974/* Increment or decrement a variable */
5975/* Returns -1 on failure, 0 on success */
5976
5977int
5978incvar(s,x,z) char *s; int x; int z; {  /* Increment a numeric variable */
5979    char valbuf[VALN+1];                /* s is pointer to variable name */
5980                                        /* x is amount to increment by */
5981    int n;                              /* z != 0 means add */
5982                                        /* z = 0 means subtract */
5983
5984    if (varval(s,&n) < 0)               /* Convert numeric string to int */
5985      return(-1);
5986    if (z)                              /* Increment it by the given amount */
5987      n += x;
5988    else                                /* or decrement as requested. */
5989      n -= x;
5990    sprintf(valbuf,"%d",n);             /* Convert back to numeric string */
5991    addmac(s,valbuf);                   /* Replace old variable */
5992    return(0);
5993}
5994#endif /* NOSPL */
5995
5996/* Functions moved here from ckuusr.c to even out the module sizes... */
5997
5998/*
5999  Breaks up string s -- IN PLACE! -- into a list of up to max words.
6000  Pointers to each word go into the array list[].
6001  max is the maximum number of words (pointers).
6002  If list is NULL, then they are added to the macro table.
6003  flag = 0 means the last field is to be one word, like all the other fields,
6004         so anything after it is discarded.
6005  flag = 1 means the last field extends to the end of the string, even if
6006         there are lots of words left, so the last field contains the
6007         remainder of the string.
6008*/
6009VOID
6010xwords(s,max,list,flag) char *s; int max; char *list[]; int flag; {
6011    char *p;
6012    int b, i, k, y, z;
6013#ifndef NOSPL
6014    int macro;
6015    macro = (list == NULL);
6016    debug(F101,"xwords macro","",macro);
6017#endif /* NOSPL */
6018
6019#ifdef XWORDSDEBUG
6020    printf("XWORDS max=%d\n",max);
6021#endif /* XWORDSDEBUG */
6022    p = s;                              /* Pointer to beginning of string */
6023    b = 0;                              /* Flag for outer brace removal */
6024    k = 0;                              /* Flag for in-word */
6025    y = 0;                              /* Brace nesting level */
6026    z = 0;                              /* "Word" counter, 0 thru max */
6027
6028    if (list)
6029      for (i = 0; i <= max; i++)        /* Initialize pointers */
6030        list[i] = NULL;
6031
6032    if (flag) max--;
6033
6034    while (1) {                         /* Go thru word list */
6035        if (!s || (*s == '\0')) {       /* No more characters? */
6036            if (k != 0) {               /* Was I in a word? */
6037                if (z == max) break;    /* Yes, only go up to max. */
6038                z++;                    /* Count this word. */
6039#ifdef XWORDSDEBUG
6040                printf("1 z++ = %d\n", z);
6041#endif /* XWORDSDEBUG */
6042#ifndef NOSPL
6043                if (macro) {            /* Doing macro args */
6044                    varnam[1] = (char) (z + '0'); /* Assign last argument */
6045                    addmac(varnam,p);
6046                } else {                /* Not doing macro args */
6047#endif /* NOSPL */
6048                    list[z] = p;        /* Assign pointer. */
6049#ifdef XWORDSDEBUG
6050                    printf("[1]LIST[%d]=\"%s\"\n",z,list[z]);
6051#endif /* XWORDSDEBUG */
6052#ifndef NOSPL
6053                }
6054#endif /* NOSPL */
6055                break;                  /* And get out. */
6056            } else break;               /* Was not in a word */
6057        }
6058        if (k == 0 && (*s == SP || *s == HT)) { /* Eat leading blanks */
6059            s++;
6060            continue;
6061        } else if (*s == '{') {         /* An opening brace */
6062            if (k == 0 && y == 0) {     /* If leading brace */
6063                p = s+1;                /* point past it */
6064                b = 1;                  /* and flag that we did this */
6065            }
6066            k = 1;                      /* Flag that we're in a word */
6067            y++;                        /* Count the brace. */
6068        } else if (*s == '}') {         /* A closing brace. */
6069            y--;                        /* Count it. */
6070            if (y == 0 && b != 0) {     /* If it matches the leading brace */
6071                *s = SP;                /* change it to a space */
6072                b = 0;                  /* and we're not in braces any more */
6073            } else if (y < 0) k = 1;    /* otherwise just start a new word. */
6074        } else if (*s != SP && *s != HT) { /* Nonspace means we're in a word */
6075            if (k == 0) {               /* If we weren't in a word before, */
6076                p = s;                  /* Mark the beginning */
6077                if (flag && z == max) { /* Want last word to be remainder? */
6078                    z++;
6079#ifdef XWORDSDEBUG
6080                    printf("1 z++ = %d\n", z);
6081#endif /* XWORDSDEBUG */
6082                    list[z] = p;        /* Yes, point to it */
6083#ifdef XWORDSDEBUG
6084                    printf("[4]LIST[%d]=\"%s\"\n",z,list[z]);
6085#endif /* XWORDSDEBUG */
6086                    break;              /* and quit */
6087                }
6088                k = 1;                  /* Set in-word flag */
6089            }
6090        }
6091        /* If we're not inside a braced quantity, and we are in a word, and */
6092        /* we have hit whitespace, then we have a word. */
6093        if ((y < 1) && (k != 0) && (*s == SP || *s == HT)) {
6094            if (!flag || z < max)       /* if we don't want to keep rest */
6095              *s = '\0';                /* terminate the arg with null */
6096            k = 0;                      /* say we're not in a word any more */
6097            y = 0;                      /* start braces off clean again */
6098            if (z == max) break;        /* Only go up to max. */
6099            z++;                        /* count this arg */
6100#ifdef XWORDSDEBUG
6101            printf("1 z++ = %d\n", z);
6102#endif /* XWORDSDEBUG */
6103
6104#ifndef NOSPL
6105            if (macro) {
6106                varnam[1] = (char) (z + '0');   /* compute its name */
6107                addmac(varnam,p);       /* add it to the macro table */
6108            } else {
6109#endif /* NOSPL */
6110                list[z] = p;
6111#ifdef XWORDSDEBUG
6112                printf("[2]LIST[%d]=\"%s\"\n",z,list[z]);
6113#endif /* XWORDSDEBUG */
6114#ifndef NOSPL
6115            }
6116#endif /* NOSPL */
6117            p = s+1;
6118        }
6119        s++;                            /* Point past this character */
6120    }
6121    if ((z == 0) && (y > 1)) {          /* Extra closing brace(s) at end */
6122        z++;
6123#ifndef NOSPL
6124        if (macro) {
6125            varnam[1] = z + '0';        /* compute its name */
6126            addmac(varnam,p);           /* Add rest of line to last arg */
6127        } else {
6128#endif /* NOSPL */
6129            list[z] = p;
6130#ifdef XWORDSDEBUG
6131            printf("[3]LIST[%d]=\"%s\"\n",z,list[z]);
6132#endif /* XWORDSDEBUG */
6133#ifndef NOSPL
6134        }
6135#endif /* NOSPL */
6136    }
6137#ifndef NOSPL
6138    if (macro)
6139      macargc[maclvl] = z + 1;          /* Set \v(argc) variable */
6140#endif /* NOSPL */
6141    return;
6142}
6143
6144#ifndef NOSPL
6145/* D O D O  --  Do a macro */
6146
6147/*
6148  Call with x = macro table index, s = pointer to arguments.
6149  Returns 0 on failure, 1 on success.
6150*/
6151
6152int
6153dodo(x,s,flags) int x; char *s; int flags; {
6154    int y;
6155
6156    debug(F101,"dodo maclvl","",maclvl);
6157    if (++maclvl > MACLEVEL) {          /* Make sure we have storage */
6158        debug(F101,"dodo maclvl too deep","",maclvl);
6159        --maclvl;
6160        printf("Macros nested too deeply\n");
6161        return(0);
6162    }
6163    macp[maclvl] = mactab[x].mval;      /* Point to the macro body */
6164    macx[maclvl] = mactab[x].mval;      /* Remember where the beginning is */
6165    debug(F111,"do macro",macp[maclvl],maclvl);
6166
6167    cmdlvl++;                           /* Entering a new command level */
6168    if (cmdlvl > CMDSTKL) {             /* Too many macros + TAKE files? */
6169        debug(F101,"dodo cmdlvl too deep","",cmdlvl);
6170        cmdlvl--;
6171        printf("?TAKE files and DO commands nested too deeply\n");
6172        return(0);
6173    }
6174#ifdef VMS
6175    conres();                           /* So Ctrl-C, etc, will work. */
6176#endif /* VMS */
6177    ifcmd[cmdlvl] = 0;
6178    iftest[cmdlvl] = 0;
6179    count[cmdlvl] = count[cmdlvl-1];    /* Inherit COUNT from previous level */
6180    intime[cmdlvl] = intime[cmdlvl-1];  /* Inherit previous INPUT TIMEOUT */
6181    inpcas[cmdlvl] = inpcas[cmdlvl-1];  /*   and INPUT CASE */
6182    takerr[cmdlvl] = takerr[cmdlvl-1];  /*   and TAKE ERROR */
6183    merror[cmdlvl] = merror[cmdlvl-1];  /*   and MACRO ERROR */
6184    cmdstk[cmdlvl].src = CMD_MD;        /* Say we're in a macro */
6185    cmdstk[cmdlvl].lvl = maclvl;        /* and remember the macro level */
6186    cmdstk[cmdlvl].ccflgs = flags;      /* set flags */
6187    mrval[maclvl] = NULL;               /* Initialize return value */
6188
6189    debug(F110,"do macro",mactab[x].kwd,0);
6190
6191/* Clear old %0..%9 arguments */
6192
6193    addmac("%0",mactab[x].kwd);         /* Define %0 = name of macro */
6194    varnam[0] = '%';
6195    varnam[2] = '\0';
6196    for (y = 1; y < 10; y++) {          /* Clear args %1..%9 */
6197        varnam[1] = (char) (y + '0');
6198        delmac(varnam);
6199    }   
6200
6201/* Assign the new args one word per arg, allowing braces to group words */
6202
6203    xwords(s,9,NULL,0);
6204    return(1);
6205}
6206
6207/* Insert "literal" quote around each comma-separated command to prevent */
6208/* its premature expansion.  Only do this if object command is surrounded */
6209/* by braces. */
6210
6211static char* flit = "\\flit(";
6212
6213int
6214litcmd(src,dest) char **src, **dest; {
6215    int bc = 0, pp = 0;
6216    char *s, *lp, *ss;
6217    char * ppp;
6218
6219    s = *src;
6220    lp = *dest;
6221    ppp = *dest;
6222
6223    debug(F110,"litcmd",s,0);
6224
6225    while (*s == SP) s++;               /* strip extra leading spaces */
6226    debug(F110,"litcmd2",s,0);
6227
6228    if (*s == '{') {
6229
6230        pp = 0;                         /* paren counter */
6231        bc = 1;                         /* count leading brace */
6232        *lp++ = *s++;                   /* copy it */
6233        debug(F110,"litcmd3",s,0);
6234        while (*s == SP) s++;           /* strip interior leading spaces */
6235        debug(F110,"litcmd4",s,0);
6236        ss = flit;                      /* point to "\flit(" */
6237        while (*lp++ = *ss++);          /* copy it */
6238
6239        debug(F110,"litcmd5",s,0);
6240
6241        lp--;                           /* back up over null */
6242
6243        while (*s) {                    /* go thru rest of text */
6244            ss = flit;                  /* point back to start of "\flit(" */
6245            if (*s == '{') bc++;        /* count brackets */
6246            if (*s == '(') pp++;        /* and parens */
6247            if (*s == ')') pp--;
6248            if (*s == '}') {            /* Closing brace. */
6249                if (--bc == 0) {        /* Final one? */
6250                    *lp++ = ')';        /* Add closing paren for "\flit()" */
6251                    *lp++ = *s++;
6252                    break;
6253                }
6254            }
6255            *lp = NUL;
6256            debug(F110,"litcmd6",s,0);
6257
6258#ifdef COMMENT
6259/* This was from before \flit() stopped breaking on commas... */
6260            if (*s == ',' && pp == 0) { /* comma not inside of parens */
6261                *lp++ = ')';            /* closing ) of \flit( */
6262                *lp++ = ',';            /* insert the comma */
6263                while (*lp++ = *ss++);  /* start new "\flit(" */
6264                lp--;                   /* back up over null */
6265                s++;                    /* skip over comma in source string */
6266                while (*s++ == SP);     /* eat leading spaces again. */
6267                s--;                    /* back up over nonspace */
6268                continue;
6269            }
6270#endif /* COMMENT */
6271            *lp++ = *s++;               /* Copy anything but comma here. */
6272        }
6273        *lp = NUL;
6274        debug(F110,"litcmd7",s,0);
6275
6276    } else {                            /* No brackets around, */
6277        while (*lp++ = *s++)            /* just copy. */
6278          ;
6279        lp--;
6280        debug(F110,"litcmd8",s,0);
6281    }
6282    debug(F110,"litcmd9",s,0);
6283
6284    *src = s;
6285    *dest = lp;
6286    if (bc) return(-1);
6287    else return(0);
6288}
6289#endif /* NOSPL */
6290
6291int
6292docd() {                                /* Do the CD command */
6293    int x;
6294    extern int quiet;
6295    char *s;
6296#ifdef MAC
6297    char temp[34];
6298#endif /* MAC */
6299
6300#ifdef GEMDOS
6301    if ((x = cmdir("Name of local directory, or carriage return",homdir,&s,
6302                   NULL)) < 0 )
6303      return(x);
6304#else
6305#ifdef OS2
6306    if ((x = cmdir("Name of PC disk and/or directory,\n\
6307       or press the Enter key for the default",homdir,&s,
6308                   xxstring)) < 0 )
6309      return(x);
6310#else
6311#ifdef MAC
6312    strncpy(temp,homdir,32);
6313    x = strlen(temp);
6314    if (x > 0) if (temp[x-1] != ':') { temp[x] = ':'; temp[x+1] = NUL; }
6315    if ((x = cmtxt("Name of Macintosh volume and/or folder,\n\
6316 or press the Return key for the desktop on the boot disk",
6317                   temp,&s, xxstring)) < 0 )
6318      return(x);
6319#else
6320    if ((x = cmdir("Name of local directory, or carriage return",homdir,&s,
6321                   xxstring)) < 0 )
6322      return(x);
6323#endif /* MAC */
6324#endif /* OS2 */
6325#endif /* GEMDOS */
6326#ifndef MAC
6327    if (x == 2) {
6328        printf("?Wildcards not allowed in directory name\n");
6329        return(-9);
6330    }
6331#endif /* MAC */
6332    strcpy(line,s);                     /* Make a safe copy */
6333    s = line;
6334#ifndef MAC
6335    if ((x = cmcfm()) < 0)              /* Get confirmation */
6336      return(x);
6337#endif /* MAC */
6338
6339#ifdef datageneral
6340    x = strlen(line);                   /* homdir ends in colon, */
6341    if (line[x-1] == ':')               /* and "dir" doesn't like that... */
6342      line[x-1] = NUL;
6343#endif /* datageneral */
6344
6345#ifdef MAC
6346    cwdf = 1;
6347    if (! zchdir(s)) {
6348        cwdf = 0;
6349        if (*s != ':') {                /* If it failed, */
6350            char *p;                    /* supply leading colon */
6351            p = malloc((int)strlen(s) + 2); /* and try again... */
6352            if (p) {
6353                strcpy(p,":");
6354                strcat(p,s);
6355                if (zchdir(p))
6356                  cwdf = 1;
6357                free(p);
6358                p = NULL;
6359            }
6360        }
6361    }
6362    if (!cwdf)
6363      perror(s);
6364#else
6365    if (! zchdir(s)) {
6366        cwdf = 0;
6367        perror(s);
6368    } else cwdf = 1;
6369#endif /* MAC */
6370    if (!quiet &&
6371#ifndef NOSPL
6372        cmdlvl == 0
6373#else
6374        tlevel == -1
6375#endif /* NOSPL */
6376        )
6377      printf("%s\n", zgtdir());
6378    return(cwdf);
6379}
6380
6381VOID
6382fixcmd() {                      /* Fix command parser after interruption */
6383    dostop();                   /* Back to top level (also calls conint()). */
6384    bgchk();                    /* Check background status */
6385    if (*psave) {               /* If old prompt saved, */
6386        cmsetp(psave);          /* restore it. */
6387        *psave = NUL;
6388    }
6389    success = 0;                /* Tell parser last command failed */
6390}
6391
6392int
6393prtopt(lines,s) int * lines; char *s; { /* Print an option */
6394    static int x = 0;                   /* (used by SHOW FEATURES) */
6395    int y, i;                           /* Does word wrap. */
6396    if (!s) { x = 0; return(1); }       /* Call with null pointer to */
6397    y = (int)strlen(s) + 1;             /* reset horizontal position. */
6398    i = *lines;
6399    x += y;
6400    if (
6401#ifdef OS2
6402        x > ((cmd_cols > 40) ? (cmd_cols - 1) : 79)
6403#else /* OS2 */
6404        x > ((tt_cols > 40) ? (tt_cols - 1) : 79)
6405#endif /* OS2 */
6406        ) {
6407        printf("\n");
6408        if (++i > (cmd_rows - 3)) {
6409            if (!askmore())
6410              return(0);
6411            else
6412              *lines = 0;
6413        }
6414        printf(" %s",s);
6415        x = y;
6416    } else printf(" %s",s);
6417    return(1);
6418}
6419#endif /* NOICP */
Note: See TracBrowser for help on using the repository browser.