standards-version: 3.8.4
[ckermit.git] / ckuus5.c
1 #include "ckcsym.h"
2
3 int xcmdsrc = 0;
4
5 #ifdef NOICP
6 int cmdsrc() { return(0); }
7 #endif /* NOICP */
8
9 /*  C K U U S 5 --  "User Interface" for C-Kermit, part 5  */
10
11 /*
12   Authors:
13     Frank da Cruz <fdc@columbia.edu>,
14       The Kermit Project, Columbia University, New York City
15     Jeffrey E Altman <jaltman@secure-endpoints.com>
16       Secure Endpoints Inc., New York City
17
18   Copyright (C) 1985, 2004,
19     Trustees of Columbia University in the City of New York.
20     All rights reserved.  See the C-Kermit COPYING.TXT file or the
21     copyright text in the ckcmai.c module for disclaimer and permissions.
22 */
23
24 /* Includes */
25
26 #include "ckcdeb.h"
27 #include "ckcasc.h"
28 #include "ckcker.h"
29 #include "ckuusr.h"
30
31 #ifdef DCMDBUF
32 char *line;                             /* Character buffer for anything */
33 char *tmpbuf;
34 #else
35 char line[LINBUFSIZ+1];
36 char tmpbuf[TMPBUFSIZ+1];               /* Temporary buffer */
37 #endif /* DCMDBUF */
38
39 #ifndef NOICP
40
41 #include "ckcnet.h"
42 #ifndef NOCSETS
43 #include "ckcxla.h"
44 #endif /* NOCSETS */
45 #ifdef MAC
46 #include "ckmasm.h"
47 #endif /* MAC */
48 #ifdef CK_SSL
49 #include "ck_ssl.h"
50 #endif /* CK_SSL */
51
52 #ifdef OS2
53 #include "ckoetc.h"
54 #ifndef NT
55 #define INCL_NOPM
56 #define INCL_VIO /* Needed for ckocon.h */
57 #include <os2.h>
58 #undef COMMENT
59 #else /* NT */
60 #include <windows.h>
61 #define TAPI_CURRENT_VERSION 0x00010004
62 #include <tapi.h>
63 #include <mcx.h>
64 #include "ckntap.h"
65 #define APIRET ULONG
66 extern int DialerHandle;
67 extern int StartedFromDialer;
68 #endif /* NT */
69 #include "ckocon.h"
70 #include "ckokey.h"
71 #ifdef KUI
72 #include "ikui.h"
73 #endif /* KUI */
74 #ifdef putchar
75 #undef putchar
76 #endif /* putchar */
77 #define putchar(x) conoc(x)
78 extern int cursor_save ;
79 extern bool cursorena[] ;
80 #endif /* OS2 */
81
82 /* For formatted screens, "more?" prompting, etc. */
83
84 #ifdef FT18
85 #define isxdigit(c) isdigit(c)
86 #endif /* FT18 */
87
88 #ifdef STRATUS                          /* Stratus Computer, Inc.  VOS */
89 #ifdef putchar
90 #undef putchar
91 #endif /* putchar */
92 #define putchar(x) conoc(x)
93 #ifdef getchar
94 #undef getchar
95 #endif /* getchar */
96 #define getchar(x) coninc(0)
97 #endif /* STRATUS */
98
99 /* External variables */
100
101 extern int carrier, cdtimo, local, quiet, backgrd, bgset, sosi, xsuspend,
102   binary, escape, xargs, flow, cmdmsk, duplex, ckxech, seslog, what,
103   inserver, diractive, tlevel, cwdf, nfuncs, msgflg, remappd, hints, mdmtyp,
104   zincnt, cmask, rcflag, success, xitsta, pflag, tnlm, tn_nlm, xitwarn,
105   debses, xaskmore, parity, saveask, wasclosed, whyclosed, cdactive,
106   rcdactive, keepallchars;
107
108 #ifdef LOCUS
109 extern int locus, autolocus;
110 #endif /* LOCUS */
111
112 #ifndef NOMSEND
113 extern int addlist;
114 #endif /* NOMSEND */
115
116 #ifdef CK_SPEED
117 extern int prefixing;
118 #endif /* CK_SPEED */
119
120 extern int g_matchdot;
121
122 #ifdef RECURSIVE
123 extern int recursive;
124 #endif /* RECURSIVE */
125 extern int xfiletype;
126
127 #ifdef IKSDCONF
128 extern char * iksdconf;
129 extern int iksdcf;
130 #endif /* IKSDCONF */
131
132 #ifdef CK_RECALL
133 extern int on_recall;
134 #endif /* CK_RECALL */
135
136 extern int ngetpath, exitonclose;
137 extern char * getpath[];
138 extern CHAR * epktmsg;
139
140 extern char * snd_move;
141 extern char * snd_rename;
142 extern char * rcv_move;
143 extern char * rcv_rename;
144 extern char * g_snd_move;
145 extern char * g_snd_rename;
146 extern char * g_rcv_move;
147 extern char * g_rcv_rename;
148
149 extern char * nm[];
150
151 #ifdef CK_UTSNAME
152 extern char unm_mch[];
153 extern char unm_mod[];
154 extern char unm_nam[];
155 extern char unm_rel[];
156 extern char unm_ver[];
157 #endif /* CK_UTSNAME */
158
159 #ifndef NOPUSH
160 #ifndef NOFRILLS
161 extern char editor[];
162 extern char editfile[];
163 extern char editopts[];
164 #ifdef BROWSER
165 extern char browser[];
166 extern char browsopts[];
167 extern char browsurl[];
168 #endif /* BROWSER */
169 #endif /*  NOFRILLS */
170 #endif /* NOPUSH */
171
172 #ifndef NOSERVER
173 extern char * x_user, * x_passwd, * x_acct;
174 #endif /* NOSERVER */
175
176 #ifdef CKLOGDIAL
177 extern int dialog;
178 extern char diafil[];
179 #endif /* CKLOGDIAL */
180
181 #ifdef CKROOT
182 extern int ckrooterr;
183 #endif /* CKROOT */
184
185 #ifndef NOSPL
186 extern int cfilef, xxdot;
187 extern char cmdfil[];
188
189 struct localvar * localhead[CMDSTKL];
190 struct localvar * localtail = NULL;
191 struct localvar * localnext = NULL;
192
193 _PROTOTYP( VOID shosexp, (void) );
194 _PROTOTYP( static VOID shoinput, (void) );
195 _PROTOTYP( static char gettok,   (void) );
196 _PROTOTYP( static VOID factor,   (void) );
197 _PROTOTYP( static VOID term,     (void) );
198 _PROTOTYP( static VOID termp,    (void) );
199 _PROTOTYP( static VOID exprp,    (void) );
200 _PROTOTYP( static VOID expr,     (void) );
201 _PROTOTYP( static VOID simple,   (void) );
202 _PROTOTYP( static VOID simpler,  (void) );
203 _PROTOTYP( static VOID simplest, (void) );
204 _PROTOTYP( static long xparse,   (void) );
205 #endif /* NOSPL */
206 #ifndef NOSHOW
207 _PROTOTYP( int sho_iks, (void) );
208 #endif /* NOSHOW */
209
210 #ifdef MAC
211 char * ckprompt = "Mac-Kermit>";        /* Default prompt for Macintosh */
212 char * ikprompt = "IKSD>";
213 #else  /* Not MAC */
214 #ifdef NOSPL
215 #ifdef OS2
216 char * ckprompt = "K-95> ";             /* Default prompt for Win32 */
217 char * ikprompt = "IKSD> ";
218 #else
219 char * ckprompt = "C-Kermit>";
220 char * ikprompt = "IKSD>";
221 #endif /* NT */
222 #else  /* NOSPL */
223 #ifdef OS2
224 /* Default prompt for OS/2 and Win32 */
225 #ifdef NT
226 char * ckprompt = "[\\freplace(\\flongpath(\\v(dir)),/,\\\\)] K-95> ";
227 char * ikprompt = "[\\freplace(\\flongpath(\\v(dir)),/,\\\\)] IKSD> ";
228 #else  /* NT */
229 char * ckprompt = "[\\freplace(\\v(dir),/,\\\\)] K-95> ";
230 char * ikprompt = "[\\freplace(\\v(dir),/,\\\\)] IKSD> ";
231 #endif /* NT */
232 #else  /* OS2 */
233 #ifdef VMS
234 char * ckprompt = "\\v(dir) C-Kermit>"; /* Default prompt VMS */
235 char * ikprompt = "\\v(dir) IKSD>";
236 #else
237 char * ckprompt = "(\\v(dir)) C-Kermit>"; /* Default prompt for others */
238 char * ikprompt = "(\\v(dir)) IKSD>";
239 #endif /* VMS */
240 #endif /* NT */
241 #endif /* NOSPL */
242 #endif /* MAC */
243
244 #ifndef CCHMAXPATH
245 #define CCHMAXPATH 257
246 #endif /* CCHMAXPATH */
247 char inidir[CCHMAXPATH] = { NUL, NUL }; /* Directory INI file executed from */
248
249 #ifdef TNCODE
250 extern int tn_b_nlm;                    /* TELNET BINARY newline mode */
251 #endif /* TNCODE */
252
253 #ifndef NOKVERBS
254 extern struct keytab kverbs[];          /* Table of \Kverbs */
255 extern int nkverbs;                     /* Number of \Kverbs */
256 #endif /* NOKVERBS */
257
258 #ifndef NOPUSH
259 extern int nopush;
260 #endif /* NOPUSH */
261
262 #ifdef CK_RECALL
263 extern int cm_recall;
264 #endif /* CK_RECALL */
265
266 extern char *ccntab[];
267
268 /* Printer stuff */
269
270 extern char *printername;
271 extern int printpipe;
272 #ifdef BPRINT
273 extern int printbidi, pportparity, pportflow;
274 extern long pportspeed;
275 #endif /* BPRINT */
276
277 #ifdef OS2
278 _PROTOTYP (int os2getcp, (void) );
279 _PROTOTYP (int os2getcplist, (int *, int) );
280 #ifdef OS2MOUSE
281 extern int tt_mouse;
282 #endif /* OS2MOUSE */
283 extern int tt_update, tt_updmode, updmode, tt_utf8;
284 #ifndef IKSDONLY
285 extern int tt_status[];
286 #endif /* IKSDONLY */
287 #ifdef PCFONTS
288 extern struct keytab term_font[];
289 #else
290 #ifdef KUI
291 extern struct keytab * term_font;
292 #endif /* KUI */
293 #endif /* PCFONTS */
294 extern int ntermfont, tt_font, tt_font_size;
295 extern unsigned char colornormal, colorunderline, colorstatus,
296     colorhelp, colorselect, colorborder, colorgraphic, colordebug,
297     colorreverse, colorcmd, coloritalic;
298 extern int priority;
299 extern struct keytab prtytab[];
300 extern int nprty;
301 char * cmdmac = NULL;
302 #endif /* OS2 */
303
304 #ifdef VMS
305 _PROTOTYP (int zkermini, (char *, int, char *) );
306 #endif /* VMS */
307
308 extern long vernum;
309 extern int inecho, insilence, inbufsize, nvars, inintr;
310 extern char *protv, *fnsv, *cmdv, *userv, *ckxv, *ckzv, *ckzsys, *xlav,
311  *cknetv, *clcmds;
312 #ifdef OS2
313 extern char *ckyv;
314 #endif /* OS2 */
315 #ifdef CK_AUTHENTICATION
316 extern char * ckathv;
317 #endif /* CK_AUTHENTICATION */
318 #ifdef CK_SSL
319 extern char * cksslv;
320 #endif /* CK_SSL */
321 #ifdef CK_ENCRYPTION
322 #ifndef CRYPT_DLL
323 extern char * ckcrpv;
324 #endif /* CRYPT_DLL */
325 #endif /* CK_ENCRYPTION */
326
327 #ifdef SSHBUILTIN
328 extern char *cksshv;
329 #ifdef SFTP_BUILTIN
330 extern char *cksftpv;
331 #endif /* SFTP_BUILTIN */
332 #endif /* SSHBUILTIN */
333
334 #ifdef TNCODE
335 extern char *cktelv;
336 #endif /* TNCODE */
337 #ifndef NOFTP
338 #ifndef SYSFTP
339 extern char * ckftpv;
340 #endif /* SYSFTP */
341 #endif /* NOFTP */
342
343 extern int srvidl;
344
345 #ifdef OS2
346 extern char *ckonetv;
347 extern int interm;
348 #ifdef CK_NETBIOS
349 extern char *ckonbiv;
350 #endif /* CK_NETBIOS */
351 #ifdef OS2MOUSE
352 extern char *ckomouv;
353 #endif /* OS2MOUSE */
354 #endif /* OS2 */
355
356 #ifndef NOLOCAL
357 extern char *connv;
358 #endif /* NOLOCAL */
359 #ifndef NODIAL
360 extern char *dialv;
361 #endif /* NODIAL */
362 #ifndef NOSCRIPT
363 extern char *loginv;
364 extern int secho;
365 #endif /* NOSCRIPT */
366
367 #ifndef NODIAL
368 extern int nmdm, dirline;
369 extern struct keytab mdmtab[];
370 #endif /* NODIAL */
371
372 extern int network, nettype, ttnproto;
373
374 #ifdef OS2
375 #ifndef NOTERM
376 /* SET TERMINAL items... */
377 extern int tt_type, tt_arrow, tt_keypad, tt_wrap, tt_answer, tt_scrsize[];
378 extern int tt_bell, tt_roll[], tt_ctstmo, tt_cursor, tt_pacing, tt_type_mode;
379 extern char answerback[];
380 extern struct tt_info_rec tt_info[];    /* Indexed by terminal type */
381 extern int max_tt;
382 #endif /* NOTERM */
383 #endif /* OS2 */
384
385 _PROTOTYP( VOID shotrm, (void) );
386 _PROTOTYP( int shofea, (void) );
387
388 #ifdef OS2
389 extern int tt_rows[], tt_cols[];
390 #else /* OS2 */
391 extern int tt_rows, tt_cols;
392 #endif /* OS2 */
393 extern int cmd_rows, cmd_cols;
394
395 #ifdef CK_TMPDIR
396 extern int f_tmpdir;                    /* Directory changed temporarily */
397 extern char savdir[];                   /* Temporary directory */
398 #endif /* CK_TMPDIR */
399
400 #ifndef NOLOCAL
401 extern int tt_crd, tt_escape;
402 #endif /* NOLOCAL */
403
404 #ifndef NOCSETS
405 extern int language, nfilc, tcsr, tcsl, tcs_transp, fcharset;
406 extern struct keytab fcstab[];
407 extern struct csinfo fcsinfo[];
408 #ifndef MAC
409 extern struct keytab ttcstab[];
410 #endif /* MAC */
411 #endif /* NOCSETS */
412
413 extern long speed;
414
415 #ifndef NOXMIT
416 extern int xmitf, xmitl, xmitp, xmitx, xmits, xmitw, xmitt;
417 extern char xmitbuf[];
418 #endif /* NOXMIT */
419
420 extern char **xargv, *versio, *ckxsys, *dftty, *lp;
421
422 #ifdef DCMDBUF
423 extern char *cmdbuf, *atmbuf;           /* Command buffers */
424 #ifndef NOSPL
425 extern char *savbuf;                    /* Command buffers */
426 #endif /* NOSPL */
427 #else
428 extern char cmdbuf[], atmbuf[];         /* Command buffers */
429 #ifndef NOSPL
430 extern char savbuf[];                   /* Command buffers */
431 #endif /* NOSPL */
432 #endif /* DCMDBUF */
433
434 extern char toktab[], ttname[], psave[];
435 extern CHAR sstate, feol;
436 extern int cmflgs, techo, repars, ncmd;
437 extern struct keytab cmdtab[];
438
439 #ifndef NOSETKEY
440 KEY *keymap;
441 #ifndef OS2
442 #define mapkey(x) keymap[x]
443 #endif /* OS2 */
444 MACRO *macrotab;
445 _PROTOTYP( VOID shostrdef, (CHAR *) );
446 #endif /* NOSETKEY */
447
448 extern int cmdlvl;
449
450 #ifndef NOSPL
451 extern struct mtab *mactab;
452 extern struct keytab mackey[];
453 extern struct keytab vartab[], fnctab[], iftab[];
454 extern int maclvl, nmac, mecho, fndiags, fnerror, fnsuccess, nif;
455 #endif /* NOSPL */
456
457 FILE *tfile[MAXTAKE];                   /* TAKE file stack */
458 char *tfnam[MAXTAKE];
459 int tfline[MAXTAKE];
460
461 int topcmd = -1;                        /* cmdtab index of current command */
462 int havetoken = 0;
463 extern int dblquo;                      /* Doublequoting enabled */
464
465 #ifdef DCMDBUF                          /* Initialization filespec */
466 char *kermrc = NULL;
467 #else
468 char kermrcb[KERMRCL];
469 char *kermrc = kermrcb;
470 #endif /* DCMDBUF */
471
472 int noherald = 0;
473 int cm_retry = 1;                       /* Command retry enabled */
474 xx_strp xxstring = zzstring;
475
476 #ifndef NOXFER
477 extern int displa, bye_active, protocol, pktlog, remfile, rempipe, unkcs,
478   keep, lf_opts, fncnv, pktpaus, autodl, xfrcan, xfrchr, xfrnum, srvtim,
479   srvdis, query, retrans, streamed, reliable, crunched, timeouts,
480   fnrpath, autopath, rpackets, spackets, epktrcvd, srvping;
481
482 #ifdef CK_AUTODL
483 extern int inautodl, cmdadl;
484 #endif /* CK_AUTODL */
485
486 #ifndef NOSERVER
487 extern int en_asg, en_cwd, en_cpy, en_del, en_dir, en_fin, en_bye, en_ret,
488   en_get, en_hos, en_que, en_ren, en_sen, en_set, en_spa, en_typ, en_who,
489   en_mai, en_pri, en_mkd, en_rmd, en_xit, en_ena;
490 #endif /* NOSERVER */
491
492 extern int atcapr,
493   atenci, atenco, atdati, atdato, atleni, atleno, atblki, atblko,
494   attypi, attypo, atsidi, atsido, atsysi, atsyso, atdisi, atdiso;
495
496 #ifdef STRATUS
497 extern int atfrmi, atfrmo, atcrei, atcreo, atacti, atacto;
498 #endif /* STRATUS */
499
500 #ifdef CK_PERMS
501 extern int atlpri, atlpro, atgpri, atgpro;
502 #endif /* CK_PERMS */
503
504 #ifdef CK_LOGIN
505 extern char * anonfile;                 /* Anonymous login init file */
506 extern char * anonroot;                 /* Anonymous file-system root */
507 extern char * userfile;                 /* Forbidden user file */
508 extern int isguest;                     /* Flag for anonymous user */
509 #endif /* CK_LOGIN */
510 #endif /* NOXFER */
511
512 #ifdef DCMDBUF
513 int *xquiet = NULL;
514 #else
515 int xquiet[CMDSTKL];
516 #endif /* DCMDBUF */
517
518 char * prstring[CMDSTKL];
519
520 #ifndef NOSPL
521
522 extern long ck_alarm;
523 extern char alrm_date[], alrm_time[];
524
525 /* Local declarations */
526
527 static int nulcmd = 0;                  /* Flag for next cmd to be ignored */
528
529 /* Definitions for predefined macros */
530
531 /* First, the single-line macros, installed with addmac()... */
532
533 /* IBM-LINEMODE macro */
534 char *m_ibm = "set parity mark, set dupl half, set handsh xon, set flow none";
535
536 /* FATAL macro */
537 char *m_fat = "if def \\%1 echo \\%1, if not = \\v(local) 0 hangup, stop 1";
538
539 #ifdef CK_SPEED
540 #ifdef IRIX65
541 char *m_fast = "set win 30, set rec pack 4000, set prefix cautious";
542 #else
543 #ifdef IRIX
544 /* Because of bug in telnet server */
545 char *m_fast = "set window 30, set rec pack 4000, set send pack 4000,\
546  set pref cautious";
547 #else
548 #ifdef pdp11
549 char *m_fast = "set win 3, set rec pack 1024, set prefix cautious";
550 #else
551 #ifdef BIGBUFOK
552 char *m_fast = "set win 30, set rec pack 4000, set prefix cautious";
553 #else
554 char *m_fast = "set win 4, set rec pack 2200, set prefix cautious";
555 #endif /* BIGBUFOK */
556 #endif /* IRIX */
557 #endif /* IRIX65 */
558 #endif /* pdp11 */
559 #ifdef pdp11
560 char *m_cautious = "set win 2, set rec pack 512, set prefixing cautious";
561 #else
562 char *m_cautious = "set win 4, set rec pack 1000, set prefixing cautious";
563 #endif /* pdp11 */
564 char *m_robust = "set win 1, set rec pack 90, set prefixing all, \
565 set reliable off, set clearchannel off";
566 #else
567 #ifdef BIGBUFOK
568 #ifdef IRIX65
569 char *m_fast = "set win 30, set rec pack 4000";
570 #else
571 #ifdef IRIX
572 char *m_fast = "set win 30, set rec pack 4000, set send pack 4000";
573 #else
574 char *m_fast = "set win 30, set rec pack 4000";
575 #endif /* IRIX */
576 #endif /* IRIX65 */
577 #else /* Not BIGBUFOK */
578 char *m_fast = "set win 4, set rec pack 2200";
579 #endif /* BIGBUFOK */
580 char *m_cautious = "set win 4, set rec pack 1000";
581 char *m_robust = "set win 1, set rec pack 90, set reliable off";
582 #endif /* CK_SPEED */
583
584 #ifdef VMS
585 char *m_purge = "run purge \\%*";
586 #endif /* VMS */
587
588 #ifdef OS2
589 char *m_manual = "browse \\v(exedir)docs/manual/kermit95.htm";
590 #endif /* OS2 */
591
592 /* Now the multiline macros, defined with addmmac()... */
593
594 /* FOR macro for \%i-style loop variables (see dofor()...) */
595
596 char *for_def[] = { "_assign _for\\v(cmdlevel) { _getargs,",
597 "def \\\\\\%1 \\feval(\\%2),:_..top,if \\%5 \\\\\\%1 \\%3 goto _..bot,",
598 "\\%6,:_..inc,incr \\\\\\%1 \\%4,goto _..top,:_..bot,_putargs},",
599 "def break goto _..bot, def continue goto _..inc,",
600 "do _for\\v(cmdlevel) \\%1 \\%2 \\%3 \\%4 { \\%5 },_assign _for\\v(cmdlevel)",
601 ""};
602
603 /* This is the FOR macro when the loop variable is itself a macro */
604
605 char *foz_def[] = { "_assign _for\\v(cmdlevel) { _getargs,",
606 "def \\%1 \\feval(\\%2),:_..top,if \\%5 \\%1 \\%3 goto _..bot,",
607 "\\%6,:_..inc,incr \\%1 \\%4,goto _..top,:_..bot,_putargs},",
608 "def break goto _..bot, def continue goto _..inc,",
609 "do _for\\v(cmdlevel) \\%1 \\%2 \\%3 \\%4 { \\%5 },_assign _for\\v(cmdlevel)",
610 ""};
611
612 /* WHILE macro */
613 char *whil_def[] = { "_assign _whi\\v(cmdlevel) {_getargs,",
614 ":_..inc,\\%1,\\%2,goto _..inc,:_..bot,_putargs},",
615 "_def break goto _..bot, _def continue goto _..inc,",
616 "do _whi\\v(cmdlevel),_assign _whi\\v(cmdlevel)",
617 ""};
618
619 /* SWITCH macro */
620 char *sw_def[] = { "_assign _sw_\\v(cmdlevel) {_getargs,",
621 "_forward {\\%1},\\%2,:default,:_..bot,_putargs},_def break goto _..bot,",
622 "do _sw_\\v(cmdlevel),_assign _sw_\\v(cmdlevel)",
623 ""};
624
625 /* XIF macro */
626 char *xif_def[] = {
627 "_assign _if\\v(cmdlevel) {_getargs,\\%1,_putargs},",
628 "do _if\\v(cmdlevel),_assign _if\\v(cmdlevel)",
629 ""};
630
631 /*
632   Variables declared here for use by other ckuus*.c modules.
633   Space is allocated here to save room in ckuusr.c.
634 */
635 #ifdef DCMDBUF
636 struct cmdptr *cmdstk;
637 int
638   *ifcmd  = NULL,
639   *count  = NULL,
640   *iftest = NULL,
641   *intime = NULL,
642   *inpcas = NULL,
643   *takerr = NULL,
644   *merror = NULL;
645 #else
646 struct cmdptr cmdstk[CMDSTKL];
647 int ifcmd[CMDSTKL], count[CMDSTKL], iftest[CMDSTKL], intime[CMDSTKL],
648   inpcas[CMDSTKL], takerr[CMDSTKL], merror[CMDSTKL];
649 #endif /* DCMDBUF */
650
651 /* Macro stack */
652
653 #ifdef COMMENT
654 char *topline = NULL;                   /* Program invocation arg line */
655 char *m_line[MACLEVEL] = { NULL, NULL }; /* Stack of macro invocation lines */
656 #endif /* COMMENT */
657
658 char **m_xarg[MACLEVEL];                /* Pointers to arg vector arrays */
659 int n_xarg[MACLEVEL];                   /* Sizes of arg vector arrays */
660 char *m_arg[MACLEVEL][NARGS];           /* Args of each level */
661 int macargc[MACLEVEL];                  /* Argc of each level */
662 char *macp[MACLEVEL];                   /* Current position in each macro */
663 char *macx[MACLEVEL];                   /* Beginning of each macro def */
664 char *mrval[MACLEVEL];                  /* RETURN value at each level */
665 int lastcmd[MACLEVEL];                  /* Last command at each level */
666 int topargc = 0;                        /* Argc at top level */
667 char **topxarg = NULL;                  /* Argv at top level */
668 char *toparg[MAXARGLIST+2];
669
670 /* Global Variables */
671
672 char *g_var[GVARS+1];                   /* Global \%a..z pointers */
673 extern char varnam[];                   /* \%x variable name buffer */
674
675 /* Arrays -- Dimension must be 'z' - ARRAYBASE + 1 */
676 /* Note: a_link[x] < 0 means no link; >= 0 is a link */
677
678 char **a_ptr[32];                       /* Array pointers, for arrays a-z */
679 int a_dim[32];                          /* Dimensions for each array */
680 int a_link[32];                         /* Link (index of linked-to-array) */
681
682 char **aa_ptr[CMDSTKL][32];             /* Array stack for automatic arrays */
683 int aa_dim[CMDSTKL][32];                /* Dimensions for each array */
684
685 /* INPUT command buffers and variables */
686
687 char * inpbuf = NULL;                   /* Buffer for INPUT and REINPUT */
688 extern char * inpbp;                    /* Global/static pointer to it  */
689 char inchar[2] = { NUL, NUL };          /* Last character that was INPUT */
690 int  incount = 0;                       /* INPUT character count */
691 extern int instatus;                    /* INPUT status */
692 static char * i_text[] = {              /* INPUT status text */
693     "success", "timeout", "interrupted", "internal error", "i/o error"
694 };
695
696 char lblbuf[LBLSIZ];                    /* Buffer for labels */
697
698 #else  /* NOSPL */
699
700 int takerr[MAXTAKE];
701 #endif /* NOSPL */
702
703 static char *prevdir = NULL;
704
705 int pacing = 0;                         /* OUTPUT pacing */
706
707 char *tp;                               /* Temporary buffer pointer */
708
709 int timelimit = 0, asktimer = 0;        /* Timers for time-limited commands */
710
711 #ifdef CK_APC                           /* Application Program Command (APC) */
712 int apcactive = APC_INACTIVE;
713 int apcstatus = APC_OFF;                /* OFF by default everywhere */
714 #ifdef DCMDBUF
715 char *apcbuf;
716 #else
717 char apcbuf[APCBUFLEN];
718 #endif /* DCMDBUF */
719 #endif /* CK_APC */
720
721 extern char pktfil[],
722 #ifdef DEBUG
723   debfil[],
724 #endif /* DEBUG */
725 #ifdef TLOG
726   trafil[],
727 #endif /* TLOG */
728   sesfil[];
729
730 #ifndef NOFRILLS
731 extern int rmailf, rprintf;             /* REMOTE MAIL & PRINT items */
732 extern char optbuf[];
733 #endif /* NOFRILLS */
734
735 extern int noinit;                      /* Flat to skip init file */
736
737 #ifndef NOSPL
738 static struct keytab kcdtab[] = {       /* Symbolic directory names */
739 #ifdef NT
740     { "appdata",  VN_APPDATA,   0 },
741     { "common",   VN_COMMON,    0 },
742     { "desktop",  VN_DESKTOP,   0 },
743 #endif /* NT */
744     { "download", VN_DLDIR,     0 },
745 #ifdef OS2ORUNIX
746     { "exedir",   VN_EXEDIR,    0 },
747 #endif /* OS2ORUNIX */
748     { "home",     VN_HOME,      0 },
749     { "inidir",   VN_INI,       0 },
750 #ifdef UNIX
751     { "lockdir",  VN_LCKDIR,    0 },
752 #endif /* UNIX */
753 #ifdef NT
754     { "personal", VN_PERSONAL,  0 },
755 #endif /* NT */
756     { "startup",  VN_STAR,      0 },
757     { "textdir",  VN_TXTDIR,    0 },
758     { "tmpdir",   VN_TEMP,      0 }
759 };
760 static int nkcdtab = (sizeof(kcdtab) / sizeof(struct keytab));
761 #endif /* NOSPL */
762
763 #ifndef NOSPL
764 _PROTOTYP( VOID freelocal, (int) );
765 _PROTOTYP( static long expon, (long, long) );
766 _PROTOTYP( static long gcd, (long, long) );
767 _PROTOTYP( static long fact, (long) );
768
769 int                     /* Initialize macro data structures. */
770 macini() {              /* Allocate mactab and preset the first element. */
771     int i;
772     if (!(mactab = (struct mtab *) malloc(sizeof(struct mtab) * MAC_MAX)))
773       return(-1);
774     mactab[0].kwd = NULL;
775     mactab[0].mval = NULL;
776     mactab[0].flgs = 0;
777     for (i = 0; i < MACLEVEL; i++)
778       localhead[i] = NULL;
779     return(0);
780 }
781 #endif /* NOSPL */
782
783 /*  C M D S R C  --  Returns current command source  */
784
785 /*  0 = top level, 1 = file, 2 = macro, -1 = error (shouldn't happen) */
786
787 /*
788   As of 19 Aug 2000 this routine is obsolete.  The scalar global variable
789   xcmdsrc can be checked instead to save the overhead of a function call.
790 */
791 int
792 cmdsrc() {
793 #ifdef COMMENT
794     return(xcmdsrc);
795 #else
796 #ifndef NOSPL
797     if (cmdlvl == 0)
798       return(0);
799     else if (cmdstk[cmdlvl].src == CMD_MD)
800       return(2);
801     else if (cmdstk[cmdlvl].src == CMD_TF)
802       return(1);
803     else
804       return(-1);
805 #else
806     if (tlevel < 0)
807       return(0);
808     else
809       return(1);
810 #endif /* NOSPL */
811 #endif /* COMMENT */
812 }
813
814 /*  C M D I N I  --  Initialize the interactive command parser  */
815
816 static int cmdinited = 0;               /* Command parser initialized */
817 extern int cmdint;                      /* Interrupts are allowed */
818 #ifdef CK_AUTODL
819 int cmdadl = 1;                         /* Autodownload */
820 #else
821 int cmdadl = 0;
822 #endif /* CK_AUTODL */
823
824 char * k_info_dir = NULL;               /* Where to find text files */
825 #ifdef UNIX
826 static char * txtdir[] = {
827     "/usr/local/doc/",                  /* Linux, SunOS, ... */
828     "/usr/share/lib/",                  /* HP-UX 10.xx... */
829     "/usr/share/doc/",                  /* Other possibilities... */
830     "/usr/local/lib/",                  /* NOTE: Each of these is tried */
831     "/usr/local/share/",                /* as is, and also with a kermit */
832     "/usr/local/share/doc/",            /* subdirectory. */
833     "/usr/local/share/lib/",
834     "/opt/kermit/",                     /* Solaris */
835     "/opt/kermit/doc/",
836     "/opt/",
837     "/usr/doc/",
838     "/doc/",
839     ""
840 };
841 #endif /* UNIX */
842
843 /*
844   lookup() cache to speed up script execution.
845
846   This is a static cache.  Items are stored in decreasing frequency of
847   reference based on statistics from a range of scripts.  This gives
848   better performance than a dynamic cache, which would require a lot more
849   code and also would require system-dependent elements including system
850   calls (e.g. to get subsecond times for entry aging).
851 */
852 #ifdef USE_LUCACHE                      /* Set in ckuusr.h */
853 #define LUCACHE 32                      /* Change this to reduce cache size */
854 int lusize = 0;
855 char * lucmd[LUCACHE];
856 int luval[LUCACHE];
857 int luidx[LUCACHE];
858 struct keytab * lutab[LUCACHE];
859 #endif /* USE_LUCACHE */
860
861 static VOID
862 luinit() {                              /* Initialize lookup() cache */
863     int x, y;
864
865 #ifdef USE_LUCACHE
866     x = lookup(cmdtab,"if",ncmd,&y);
867     lucmd[lusize] = "if";
868     luval[lusize] = x;
869     luidx[lusize] = y;
870     lutab[lusize] = cmdtab;
871     if (++lusize > LUCACHE) return;
872
873     x = lookup(iftab,"not",nif,&y);
874     lucmd[lusize] = "not";
875     luval[lusize] = x;
876     luidx[lusize] = y;
877     lutab[lusize] = iftab;
878     if (++lusize > LUCACHE) return;
879
880     x = lookup(vartab,"cmdlevel",nvars,&y);
881     lucmd[lusize] = "cmdlevel";
882     luval[lusize] = x;
883     luidx[lusize] = y;
884     lutab[lusize] = vartab;
885     if (++lusize > LUCACHE) return;
886
887     x = lookup(cmdtab,"goto",ncmd,&y);
888     lucmd[lusize] = "goto";
889     luval[lusize] = x;
890     luidx[lusize] = y;
891     lutab[lusize] = cmdtab;
892     if (++lusize > LUCACHE) return;
893
894     x = lookup(iftab,">",nif,&y);
895     lucmd[lusize] = ">";
896     luval[lusize] = x;
897     luidx[lusize] = y;
898     lutab[lusize] = iftab;
899     if (++lusize > LUCACHE) return;
900
901     x = lookup(cmdtab,"incr",ncmd,&y);
902     lucmd[lusize] = "incr";
903     luval[lusize] = x;
904     luidx[lusize] = y;
905     lutab[lusize] = cmdtab;
906     if (++lusize > LUCACHE) return;
907
908     x = lookup(cmdtab,"def",ncmd,&y);
909     lucmd[lusize] = "def";
910     luval[lusize] = x;
911     luidx[lusize] = y;
912     lutab[lusize] = cmdtab;
913     if (++lusize > LUCACHE) return;
914
915     x = lookup(cmdtab,"_assign",ncmd,&y);
916     lucmd[lusize] = "_assign";
917     luval[lusize] = x;
918     luidx[lusize] = y;
919     lutab[lusize] = cmdtab;
920     if (++lusize > LUCACHE) return;
921
922     x = lookup(cmdtab,"echo",ncmd,&y);
923     lucmd[lusize] = "echo";
924     luval[lusize] = x;
925     luidx[lusize] = y;
926     lutab[lusize] = cmdtab;
927     if (++lusize > LUCACHE) return;
928
929     x = lookup(fnctab,"eval",nfuncs,&y);
930     lucmd[lusize] = "eval";
931     luval[lusize] = x;
932     luidx[lusize] = y;
933     lutab[lusize] = fnctab;
934     if (++lusize > LUCACHE) return;
935
936     x = lookup(fnctab,"lit",nfuncs,&y);
937     lucmd[lusize] = "lit";
938     luval[lusize] = x;
939     luidx[lusize] = y;
940     lutab[lusize] = fnctab;
941     if (++lusize > LUCACHE) return;
942
943     x = lookup(cmdtab,"do",ncmd,&y);
944     lucmd[lusize] = "do";
945     luval[lusize] = x;
946     luidx[lusize] = y;
947     lutab[lusize] = cmdtab;
948     if (++lusize > LUCACHE) return;
949
950     x = lookup(cmdtab,"_getargs",ncmd,&y);
951     lucmd[lusize] = "_getargs";
952     luval[lusize] = x;
953     luidx[lusize] = y;
954     lutab[lusize] = cmdtab;
955     if (++lusize > LUCACHE) return;
956
957     x = lookup(iftab,"<",nif,&y);
958     lucmd[lusize] = "<";
959     luval[lusize] = x;
960     luidx[lusize] = y;
961     lutab[lusize] = iftab;
962     if (++lusize > LUCACHE) return;
963
964     x = lookup(cmdtab,"_putargs",ncmd,&y);
965     lucmd[lusize] = "_putargs";
966     luval[lusize] = x;
967     luidx[lusize] = y;
968     lutab[lusize] = cmdtab;
969     if (++lusize > LUCACHE) return;
970
971     x = lookup(cmdtab,"asg",ncmd,&y);
972     lucmd[lusize] = "asg";
973     luval[lusize] = x;
974     luidx[lusize] = y;
975     lutab[lusize] = cmdtab;
976     if (++lusize > LUCACHE) return;
977
978     x = lookup(cmdtab,"else",ncmd,&y);
979     lucmd[lusize] = "else";
980     luval[lusize] = x;
981     luidx[lusize] = y;
982     lutab[lusize] = cmdtab;
983 #endif /* USE_LUCACHE */
984 }
985
986 VOID
987 cmdini() {
988     int i = 0, x = 0, y = 0, z = 0, skip = 0;
989     char * p;
990 #ifdef TTSPDLIST
991     long * ss = NULL;
992     extern int nspd;
993     extern struct keytab * spdtab;
994 #endif /* TTSPDLIST */
995
996 #ifndef NOSPL
997 /*
998   On stack to allow recursion!
999 */
1000     char vnambuf[VNAML];                /* Buffer for variable names */
1001 #endif /* NOSPL */
1002
1003     if (cmdinited)                      /* Already initialized */
1004       return;                           /* Don't do it again */
1005
1006     for (i = 0; i < CMDSTKL; i++)       /* Prompt strings for each */
1007       prstring[i] = NULL;               /* command level */
1008
1009 #ifndef NOCSETS
1010     p = getenv("K_CHARSET");            /* Set default file character set */
1011     if (p) {                            /* from environment */
1012         x = lookup(fcstab,p,nfilc,&y);
1013         if (x > -1)
1014           fcharset = x;
1015     }
1016 #endif /* NOCSETS */
1017
1018     p = getenv("K_INFO_DIRECTORY");     /* Find Kermit info directory */
1019     if (p && *p && strlen(p) <= CKMAXPATH)
1020       makestr(&k_info_dir,p);
1021     if (!k_info_dir) {
1022         p = getenv("K_INFO_DIR");
1023         if (p && *p && strlen(p) <= CKMAXPATH)
1024           makestr(&k_info_dir,p);
1025     }
1026 #ifdef UNIX
1027     if (k_info_dir) {                   /* Look for Kermit docs directory */
1028         if (zchki(k_info_dir) == -2) {
1029             char xbuf[CKMAXPATH+32], *s = "";
1030             if (ckrchar(k_info_dir) != '/')
1031               s = "/";
1032             ckmakmsg(xbuf,CKMAXPATH+32,k_info_dir,s,"ckubwr.txt",NULL);
1033             if (zchki(xbuf) < 0)
1034               makestr(&k_info_dir,NULL);
1035         }
1036     }
1037     if (!k_info_dir) {
1038         char xbuf[CKMAXPATH+32];
1039         int i;
1040         for (i = 0; *(txtdir[i]); i++) {
1041             ckmakmsg(xbuf,CKMAXPATH+32,txtdir[i],"ckubwr.txt",NULL,NULL);
1042             if (zchki(xbuf) > 0) {
1043                 makestr(&k_info_dir,txtdir[i]);
1044                 debug(F110,"k_info_dir 1",k_info_dir,0);
1045                 break;
1046             }
1047             ckmakmsg(xbuf,CKMAXPATH+32,
1048                      txtdir[i],"kermit/","ckubwr.txt",NULL);
1049             if (zchki(xbuf) > 0) {
1050                 ckmakmsg(xbuf,CKMAXPATH+32,txtdir[i],"kermit/",NULL,NULL);
1051                 makestr(&k_info_dir,xbuf);
1052                 debug(F110,"k_info_dir 2",k_info_dir,0);
1053                 break;
1054             }
1055             ckmakmsg(xbuf,CKMAXPATH+32,
1056                      txtdir[i],"ckermit/","ckubwr.txt",NULL);
1057             if (zchki(xbuf) > 0) {
1058                 ckmakmsg(xbuf,CKMAXPATH+32,txtdir[i],"ckermit/",NULL,NULL);
1059                 makestr(&k_info_dir,xbuf);
1060                 debug(F110,"k_info_dir 3",k_info_dir,0);
1061                 break;
1062             }
1063         }
1064         if (k_info_dir) {               /* Make sure it ends with "/" */
1065             if (ckrchar(k_info_dir) != '/') {
1066                 char xbuf[CKMAXPATH+32];
1067                 ckmakmsg(xbuf,CKMAXPATH+32,k_info_dir,"/",NULL,NULL);
1068                 makestr(&k_info_dir,xbuf);
1069             }
1070         }
1071     }
1072 #else
1073 #ifdef OS2
1074     {
1075         char xdir[CKMAXPATH+8], *s = "";
1076         extern char startupdir[];
1077         xdir[0] = NUL;
1078         if (ckrchar(startupdir) != '/')
1079           s = "/";
1080         if (strlen(s) + strlen(startupdir) + 5 < CKMAXPATH + 8 )
1081           ckmakmsg(xdir,CKMAXPATH+8,s,startupdir,"DOC/",NULL);
1082         makestr(&k_info_dir,xdir);
1083     }
1084 #endif /* OS2 */
1085 #endif /* UNIX */
1086
1087 #ifdef TTSPDLIST
1088     if (!spdtab && (ss = ttspdlist())) { /* Get speed list if necessary */
1089         int j, k, m = 0, n;             /* Create sorted keyword table */
1090         char buf[16];
1091         char * p;
1092         if ((spdtab =
1093              (struct keytab *) malloc(sizeof(struct keytab) * ss[0]))) {
1094             for (i = 1; i <= ss[0]; i++) { /* ss[0] = number of elements */
1095                 if (ss[i] < 1L) break;     /* Shouldn't happen */
1096                 buf[0] = NUL;              /* Make string */
1097                 sprintf(buf,"%ld",ss[i]);  /* SAFE */
1098                 if (ss[i] == 8880L)
1099                   ckstrncpy(buf,"75/1200",sizeof(buf));
1100                 if (ss[i] == 134L)
1101                   ckstrncat(buf,".5",16);
1102                 n = strlen(buf);
1103                 if ((n > 0) && (p = (char *)malloc(n+1))) {
1104                     if (m > 0) {        /* Have at least one in list */
1105                         for (j = 0;     /* Find slot */
1106                              j < m && strcmp(buf,spdtab[j].kwd) > 0;
1107                              j++
1108                              )
1109                           ;
1110                         if (j < m) {    /* Must insert */
1111                             for (k = m-1; k >= j; k--) { /* Move others down */
1112                                 spdtab[k+1].kwd = spdtab[k].kwd;
1113                                 spdtab[k+1].flgs = spdtab[k].flgs;
1114                                 spdtab[k+1].kwval = spdtab[k].kwval;
1115                             }
1116                         }
1117                     } else              /* First one */
1118                       j = 0;
1119                     ckstrncpy(p,buf,n+1); /* Add new speed */
1120                     spdtab[j].kwd = p;
1121                     spdtab[j].flgs = 0;
1122                     spdtab[j].kwval = (int) ss[i] / 10;
1123                     m++;                /* Count this one */
1124                 }
1125             }
1126         }
1127         nspd = m;
1128     }
1129 #endif /* TTSPDLIST */
1130
1131 #ifndef NOSPL
1132     /* Allocate INPUT command buffer */
1133     if (!inpbuf) {
1134         if (!(inpbuf = (char *) malloc(INPBUFSIZ+1)))
1135           fatal("cmdini: no memory for INPUT buffer");
1136     }
1137     for (x = 0; x < INPBUFSIZ; x++)     /* Initialize it */
1138       inpbuf[x] = NUL;
1139     inpbp = inpbuf;                     /* Initialize pointer */
1140     inbufsize = INPBUFSIZ;              /* and size. */
1141 #endif /* NOSPL */
1142
1143 #ifdef DCMDBUF
1144     if (cmsetup() < 0) fatal("Can't allocate command buffers!");
1145
1146 #ifndef NOSPL
1147     /* Allocate command stack allowing command parser to call itself */
1148
1149     if (!(cmdstk = (struct cmdptr *) malloc(sizeof(struct cmdptr)*CMDSTKL)))
1150       fatal("cmdini: no memory for cmdstk");
1151     if (!(ifcmd = (int *) malloc(sizeof(int)*CMDSTKL)))
1152       fatal("cmdini: no memory for ifcmd");
1153     if (!(count = (int *) malloc(sizeof(int)*CMDSTKL)))
1154       fatal("cmdini: no memory for count");
1155     if (!(iftest = (int *) malloc(sizeof(int)*CMDSTKL)))
1156       fatal("cmdini: no memory for iftest");
1157     if (!(intime = (int *) malloc(sizeof(int)*CMDSTKL)))
1158       fatal("cmdini: no memory for intime");
1159     if (!(inpcas = (int *) malloc(sizeof(int)*CMDSTKL)))
1160       fatal("cmdini: no memory for inpcas");
1161     if (!(takerr = (int *) malloc(sizeof(int)*CMDSTKL)))
1162       fatal("cmdini: no memory for takerr");
1163     if (!(merror = (int *) malloc(sizeof(int)*CMDSTKL)))
1164       fatal("cmdini: no memory for merror");
1165     if (!(xquiet = (int *) malloc(sizeof(int)*CMDSTKL)))
1166       fatal("cmdini: no memory for xquiet");
1167     if (!kermrc)
1168       if (!(kermrc = (char *) malloc(KERMRCL+1)))
1169         fatal("cmdini: no memory for kermrc");
1170 #ifdef CK_APC
1171 /* Application Program Command buffer */
1172     if (!(apcbuf = malloc(APCBUFLEN + 1)))
1173         fatal("cmdini: no memory for apcbuf");
1174 #endif /* CK_APC */
1175 #endif /* NOSPL */
1176
1177 /* line[] and tmpbuf[] are the two string buffers used by the command parser */
1178
1179     if (!(line = malloc(LINBUFSIZ + 1)))
1180         fatal("cmdini: no memory for line");
1181     if (!(tmpbuf = malloc(LINBUFSIZ + 1)))
1182         fatal("cmdini: no memory for tmpbuf");
1183 #endif /* DCMDBUF */
1184
1185 #ifndef NOSPL
1186 #ifdef CK_MINPUT
1187     {                                   /* Initialize MINPUT pointers */
1188         int i;
1189         extern char *ms[];
1190         for (i = 0; i < MINPMAX; i++)
1191           ms[i] = NULL;
1192     }
1193 #endif /* CK_MINPUT */
1194
1195     if (macini() < 0)                   /* Allocate macro buffers */
1196       fatal("Can't allocate macro buffers!");
1197
1198     ifcmd[0] = 0;                       /* Command-level related variables. */
1199     iftest[0] = 0;                      /* Initialize variables at top level */
1200     count[0] = 0;                       /* of stack... */
1201     intime[0] = 0;
1202     inpcas[0] = 0;
1203     takerr[0] = 0;
1204     merror[0] = 0;
1205     xquiet[0] = quiet;
1206 #endif /* NOSPL */
1207
1208 #ifndef NOSPL
1209     cmdlvl = 0;                         /* Initialize the command stack */
1210     xcmdsrc = CMD_KB;
1211     cmdstk[cmdlvl].src = CMD_KB;        /* Source is console */
1212     cmdstk[cmdlvl].lvl = 0;             /* Level is 0 */
1213     cmdstk[cmdlvl].ccflgs = 0;          /* No flags */
1214 #endif /* NOSPL */
1215
1216     tlevel = -1;                        /* Take file level = keyboard */
1217     for (i = 0; i < MAXTAKE; i++)       /* Initialize command file names */
1218       tfnam[i] = NULL;
1219
1220     cmsetp(ckprompt);                   /* Set up C-Kermit's prompt */
1221                                         /* Can't set IKSD prompt here since */
1222                                         /* we do not yet know if we are IKSD */
1223 #ifndef NOSPL
1224
1225     initmac();                          /* Initialize macro table */
1226
1227 /* Predefine built-in one-line macros */
1228
1229     addmac("ibm-linemode",m_ibm);       /* IBM-LINEMODE */
1230     addmac("fatal",m_fat);              /* FATAL macro */
1231     y = addmac("fast",m_fast);          /* FAST macro */
1232     addmac("cautious",m_cautious);      /* CAUTIOUS macro */
1233     addmac("robust",m_robust);          /* ROBUST macro */
1234 #ifdef OS2
1235     addmac("manual",m_manual);          /* MANUAL macro */
1236 #endif /* OS2 */
1237 #ifdef VMS
1238     addmac("purge",m_purge);            /* PURGE macro */
1239 #endif /* VMS */
1240
1241 /*
1242   Predefine built-in multiline macros; these are top-level commands
1243   that are implemented internally as macros.  NOTE: When adding a new
1244   one of these, remember to update the END and RETURN commands to
1245   account for it, or else END and RETURN from within it won't work right.
1246 */
1247     x = addmmac("_forx",for_def);       /* FOR macro */
1248     if (x > -1) mactab[x].flgs = CM_INV;
1249     x = addmmac("_forz",foz_def);       /* Other FOR macro */
1250     if (x > -1) mactab[x].flgs = CM_INV;
1251     x = addmmac("_xif",xif_def);        /* XIF macro */
1252     if (x > -1) mactab[x].flgs = CM_INV;
1253     x = addmmac("_while",whil_def);     /* WHILE macro */
1254     if (x > -1) mactab[x].flgs = CM_INV;
1255     x = addmmac("_switx",sw_def);       /* SWITCH macro */
1256     if (x > -1) mactab[x].flgs = CM_INV;
1257
1258 /* Fill in command-line argument vector */
1259
1260     sprintf(vnambuf,"\\&@[%d]",xargs);  /* SAFE */
1261     if (inserver) {                     /* But hidden in IKSD */
1262         y = -1;
1263         xargs = 0;
1264     } else
1265       y = arraynam(vnambuf,&x,&z);      /* goes in array \&@[] */
1266
1267     tmpbuf[0] = NUL;
1268     if (y > -1) {
1269         int j = -1;
1270         int yy = 0;
1271         dclarray((char)x,z);            /* Declare the array */
1272 #ifndef NOTAKEARGS
1273         /* Macro argument vector */
1274         sprintf(vnambuf,"\\&_[%d]",z);  /* SAFE */
1275         yy = arraynam(vnambuf,&x,&z);   /* goes in array \&_[] */
1276         if (yy > -1)                    /* Name is OK */
1277           dclarray((char)x,z);          /* Declare the array */
1278 #endif /* NOTAKEARGS */
1279         skip = 0;
1280         for (i = 0; i < xargs; i++) {   /* Fill the arrays */
1281             sprintf(vnambuf,"\\&@[%d]",i); /* SAFE */
1282             addmac(vnambuf,xargv[i]);
1283             if (cfilef && i == 0)
1284               continue;
1285 #ifdef KERBANG
1286             if (skip) {
1287                 j = 0;
1288                 skip = 0;
1289                 continue;
1290             }
1291 #endif /* KERBANG */
1292             if (j < 0 &&                /* Assign items after "=" or "--"*/
1293                 (!strcmp(xargv[i],"=") || !strcmp(xargv[i],"--"))
1294                 ) {
1295                 j = 0;                  /* to \%1..\%9 */
1296 #ifdef KERBANG
1297             } else if (j < 0 &&
1298                        (!strcmp(xargv[i],"+") ||
1299                         !strncmp(xargv[i],"+ ",2) ||
1300                         !strncmp(xargv[i],"+\t",2))
1301                         ) {
1302                 skip = 1;
1303                 continue;
1304 #endif /* KERBANG */
1305             } else if (j > -1) {
1306                 j++;
1307                 if (j <= 9) {
1308                     vnambuf[0] = '\\';
1309                     vnambuf[1] = '%';
1310                     vnambuf[2] = (char)(j+'0');
1311                     vnambuf[3] = NUL;
1312                     addmac(vnambuf,xargv[i]);
1313                 }
1314                 if (yy > -1) {
1315                     char c, * p;
1316                     int flag = 0;
1317                     p = xargv[i];
1318                     makestr(&(toparg[j]),p);
1319                     while ((c = *p++)) { if (c == SP) { flag++; break; } }
1320                     if (flag)
1321                       ckstrncat(tmpbuf,"\"",TMPBUFSIZ);
1322                     ckstrncat(tmpbuf,xargv[i],TMPBUFSIZ);
1323                     if (flag)
1324                       ckstrncat(tmpbuf,"\"",TMPBUFSIZ);
1325                     ckstrncat(tmpbuf," ",TMPBUFSIZ);
1326                 }
1327             }
1328         }
1329         if (cfilef) {
1330             addmac("\\%0",cmdfil);
1331             if (yy > -1)
1332               makestr(&(toparg[0]),cmdfil);
1333         } else {
1334             addmac("\\%0",xargv[0]);
1335             if (yy > -1)
1336               makestr(&(toparg[0]),xargv[0]);
1337         }
1338         if (yy > -1) {
1339             topargc = (j < 0) ? 1 : j + 1;
1340             topxarg = toparg;
1341 #ifdef COMMENT
1342             /* This needs work */
1343             if (!cfilef)
1344               makestr(&topline,tmpbuf);
1345 #endif /* COMMENT */
1346         } else {
1347             topargc = 0;
1348             topxarg = NULL;
1349         }
1350         a_dim[0] = topargc - 1;
1351         a_ptr[0] = topxarg;
1352         debug(F111,"a_dim[0]","A",a_dim[0]);
1353     }
1354     *vnambuf = NUL;
1355 #endif /* NOSPL */
1356
1357     luinit();                           /* Initialize lookup() cache */
1358
1359 /* Get our home directory now.  This needed in lots of places. */
1360
1361     cmdinited = 1;
1362 }
1363
1364 #ifdef NT
1365 _PROTOTYP(char * GetAppData,(int));
1366 #endif /* NT */
1367
1368 VOID
1369 doinit() {
1370 #ifdef CKROOT
1371 extern int ckrooterr;
1372 #endif /* CKROOT */
1373     int x = 0, ok = 0;
1374 #ifdef OS2
1375     char * ptr = 0;
1376 #endif /* OS2 */
1377
1378     if (!cmdinited)
1379       cmdini();
1380
1381 #ifdef MAC
1382     return;                             /* Mac Kermit has no init file */
1383
1384 #else /* !MAC */
1385
1386 /* If skipping init file ('-Y' on Kermit command line), return now. */
1387
1388     if (noinit) {
1389         kermrc[0] = '\0';
1390         inidir[0] = '\0';
1391 /*
1392   But returning from here results in inidir[] never being set to anything.
1393   Instead it should be set to wherever the init file *would* have been
1394   executed from.  So this bit of code should be removed, and then we should
1395   sprinkle "if (noinit)" tests throughout the following code until we have
1396   set inidir[], and then return without actually taking the init file.
1397 */
1398         return;
1399     }
1400
1401 #ifdef OS2
1402 /*
1403   The -y init file must be fully specified or in the current directory.
1404   KERMRC is looked for via INIT, DPATH and PATH in that order.  Finally, our
1405   own executable file path is taken and the .EXE suffix is replaced by .INI
1406   and this is tried as the initialization file.
1407 */
1408 #ifdef CK_LOGIN
1409     debug(F101,"doinit inserver","",inserver);
1410     debug(F101,"doinit isguest","",isguest);
1411     debug(F110,"doinit anonfile",anonfile,0);
1412
1413     if (isguest && anonfile) {
1414       ckstrncpy(line, anonfile, LINBUFSIZ+1);
1415     } else
1416 #endif /* CK_LOGIN */
1417       if (rcflag) {
1418           ckstrncpy(line,kermrc,LINBUFSIZ+1);
1419 #ifdef CK_LOGIN
1420       } else if (inserver) {
1421           char * appdata = NULL;
1422 #ifdef NT
1423           appdata = GetAppData(1);
1424           if ( appdata ) {
1425               ckmakmsg(line,LINBUFSIZ+1,appdata,
1426                         "Kermit 95/k95.ini",NULL,NULL);
1427               if ( zchki(line) < 0 )
1428                   line[0] = '\0';
1429           }
1430           if (line[0] == 0) {
1431               appdata = GetAppData(0);
1432               if ( appdata ) {
1433                   ckmakmsg(line,LINBUFSIZ+1,appdata,
1434                             "Kermit 95/k95.ini",NULL,NULL);
1435                   if ( zchki(line) < 0 )
1436                       line[0] = '\0';
1437               }
1438           }
1439 #endif /* NT */
1440           if (line[0] == 0) {
1441               appdata = zhome();
1442               if ( appdata ) {
1443                   ckmakmsg(line,LINBUFSIZ+1,appdata,
1444 #ifdef NT
1445                           "k95.ini",
1446 #else /* NT */
1447                           "k2.ini",
1448 #endif /* NT */
1449                            NULL,NULL);
1450                   if ( zchki(line) < 0 )
1451                       line[0] = '\0';
1452               }
1453           }
1454           debug(F110,"doinit inserver inifile",line,0);
1455 #endif /* CK_LOGIN */
1456     } else {
1457         char * env = 0;
1458 #ifdef NT
1459         env = getenv("K95.KSC");
1460 #else
1461         env = getenv("K2.KSC");
1462 #endif /* NT */
1463         if (!env) {
1464 #ifdef NT
1465             env = getenv("K95.INI");
1466 #else
1467             env = getenv("K2.INI");
1468 #endif /* NT */
1469         }
1470         if (!env)
1471           env = getenv("CKERMIT.INI");
1472         if (!env)
1473           env = getenv("CKERMIT_INI");
1474         line[0] = '\0';
1475
1476         debug(F110,"doinit env",env,0);
1477         if (env)
1478           ckstrncpy(line,env,LINBUFSIZ+1);
1479
1480 #ifdef NT
1481         if (line[0] == 0) {
1482             env = GetAppData(1);
1483             if ( env ) {
1484                 ckmakmsg(line,LINBUFSIZ+1,env,"Kermit 95/k95.ini",NULL,NULL);
1485                 if ( zchki(line) < 0 )
1486                     line[0] = '\0';
1487             }
1488         }
1489         if (line[0] == 0) {
1490             env = GetAppData(0);
1491             if ( env ) {
1492                 ckmakmsg(line,LINBUFSIZ+1,env,"Kermit 95/k95.ini",NULL,NULL);
1493                 if ( zchki(line) < 0 )
1494                     line[0] = '\0';
1495             }
1496         }
1497 #endif /* NT */
1498
1499         if (line[0] == 0) {
1500             env = zhome();
1501             if ( env ) {
1502                 ckmakmsg(line,LINBUFSIZ+1,env,
1503 #ifdef NT
1504                           "k95.ini",
1505 #else /* NT */
1506                           "k2.ini",
1507 #endif /* NT */
1508                           NULL,NULL);
1509                 if ( zchki(line) < 0 )
1510                     line[0] = '\0';
1511             }
1512         }
1513
1514         if (line[0] == 0)
1515           _searchenv(kermrc,"INIT",line);
1516         if (line[0] == 0)
1517           _searchenv(kermrc,"DPATH",line);
1518         if (line[0] == 0)
1519           _searchenv(kermrc,"PATH",line);
1520         if (line[0] == 0) {
1521             char *pgmptr = GetLoadPath();
1522             if (pgmptr && strlen(pgmptr) < LINBUFSIZ-8) {
1523                 lp = strrchr(pgmptr, '\\');
1524                 if (lp) {
1525                     strncpy(line, pgmptr, lp - pgmptr);
1526 #ifdef NT
1527                     strcpy(line + (lp - pgmptr), "/k95.ini");
1528 #else /* NT */
1529                     strcpy(line + (lp - pgmptr), "/k2.ini");
1530 #endif /* NT */
1531                 } else {
1532                     lp = strrchr(pgmptr, '.');
1533                     if (lp) {
1534                         strncpy(line, pgmptr, lp - pgmptr);
1535                         strcpy(line + (lp - pgmptr), ".ini");
1536                     }
1537                 }
1538             }
1539         }
1540     }
1541
1542 #ifdef CKROOT
1543     if (!zinroot(line)) {
1544         debug(F110,"doinit setroot violation",line,0);
1545         return;
1546     }
1547 #endif /* CKROOT */
1548
1549     debug(F110,"doinit fopen()",line,0);
1550     if ((tfile[0] = fopen(line,"r")) != NULL) {
1551         ok = 1;
1552         tlevel = 0;
1553         tfline[tlevel] = 0;
1554         if (tfnam[tlevel] = malloc(strlen(line)+1))
1555           strcpy(tfnam[tlevel],line);   /* safe */
1556 #ifndef NOSPL
1557         cmdlvl++;
1558         xcmdsrc = CMD_TF;
1559         cmdstk[cmdlvl].src = CMD_TF;
1560         cmdstk[cmdlvl].lvl = tlevel;
1561         cmdstk[cmdlvl].ccflgs = 0;
1562         ifcmd[cmdlvl] = 0;
1563         iftest[cmdlvl] = 0;
1564         count[cmdlvl] =  count[cmdlvl-1]; /* Inherit from previous level */
1565         intime[cmdlvl] = intime[cmdlvl-1];
1566         inpcas[cmdlvl] = inpcas[cmdlvl-1];
1567         takerr[cmdlvl] = takerr[cmdlvl-1];
1568         merror[cmdlvl] = merror[cmdlvl-1];
1569         xquiet[cmdlvl] = quiet;
1570 #endif /* NOSPL */
1571         debug(F110,"doinit init file",line,0);
1572     } else {
1573         debug(F100,"doinit no init file","",0);
1574     }
1575     ckstrncpy(kermrc,line,KERMRCL);
1576     for (ptr = kermrc; *ptr; ptr++)     /* Convert backslashes to slashes */
1577        if (*ptr == '\\')
1578          *ptr = '/';
1579 #else /* not OS2 */
1580     lp = line;
1581     lp[0] = '\0';
1582     debug(F101,"doinit rcflag","",rcflag);
1583 #ifdef GEMDOS
1584     zkermini(line, rcflag, kermrc);
1585 #else
1586 #ifdef VMS
1587     {
1588         int x;
1589         x = zkermini(line,LINBUFSIZ,kermrc);
1590         debug(F111,"CUSTOM zkermini",line,x);
1591         if (x == 0)
1592           line[0] = NUL;
1593     }
1594 #else /* not VMS */
1595 #ifdef CK_LOGIN
1596     debug(F101,"doinit isguest","",isguest);
1597     if (isguest)
1598       ckstrncpy(lp, anonfile ? anonfile : kermrc, LINBUFSIZ);
1599     else
1600 #endif /* CK_LOGIN */
1601       if (rcflag) {                     /* If init file name from cmd line */
1602           ckstrncpy(lp,kermrc,LINBUFSIZ); /* use it, */
1603       } else {                          /* otherwise... */
1604 #ifdef CK_INI_A                         /* If we've a system-wide init file */
1605           /* And it takes precedence over the user's... */
1606           ckstrncpy(lp,CK_SYSINI,KERMRCL); /* Use it */
1607           if (zchki(lp) < 0) {          /* (if it exists...) */
1608 #endif /* CK_INI_A */
1609               char * homdir;
1610               char * env = 0;
1611               line[0] = NUL;
1612
1613               /* Add support for environment variable */
1614               env = getenv("CKERMIT.INI");
1615               if (!env)
1616                 env = getenv("CKERMIT_INI");
1617               if (env)
1618                 ckstrncpy(lp,env,KERMRCL);
1619
1620               if (lp[0] == 0) {
1621                   homdir = zhome();
1622                   if (homdir) {         /* Home directory for init file. */
1623                       ckstrncpy(lp,homdir,KERMRCL);
1624 #ifdef STRATUS
1625                       ckstrncat(lp,">",KERMRCL);/* VOS dirsep */
1626 #else
1627                       if (lp[0] == '/') ckstrncat(lp,"/",KERMRCL);
1628 #endif /* STRATUS */
1629                   }
1630                   ckstrncat(lp,kermrc,KERMRCL);/* Append default file name */
1631               }
1632 #ifdef CK_INI_A
1633           }
1634 #endif /* CK_INI_A */
1635 #ifdef CK_INI_B                         /* System-wide init defined? */
1636           /* But user's ini file takes precedence */
1637           if (zchki(lp) < 0)            /* If user doesn't have her own, */
1638             ckstrncpy(lp,CK_SYSINI,KERMRCL); /* use system-wide one. */
1639 #endif /* CK_INI_B */
1640       }
1641 #endif /* VMS */
1642 #endif /* GEMDOS */
1643
1644 #ifdef AMIGA
1645     reqoff();                           /* Disable requestors */
1646 #endif /* AMIGA */
1647
1648 #ifdef USE_CUSTOM
1649     /* If no init file was found, execute the customization file */
1650     debug(F110,"CUSTOM 1",line,0);
1651     if (!line[0] || zchki(line) < 0) {
1652         int x;
1653 #ifdef OS2
1654         x = ckmakestr(line,LINBUFSIZ,GetAppData(1),"/","K95CUSTOM.INI",NULL);
1655         debug(F111,"CUSTOM 2",line,x);
1656         if (zchki(line) < 0) {
1657             x = ckmakestr(line,LINBUFSIZ,GetAppData(0),"/","K95USER.INI",NULL);
1658             debug(F111,"CUSTOM 3",line,x);
1659         }
1660 #else  /* OS2 */
1661         x = ckstrncpy(line,zhome(),LINBUFSIZ);
1662 #ifndef VMS
1663         /* VMS zhome() returns "SYS$LOGIN:" */
1664         if (line[x-1] != DIRSEP) {
1665             line[x++] = DIRSEP;
1666             line[x] = NUL;
1667         }
1668 #endif /* VMS */
1669         x = ckstrncat(line,MYCUSTOM,LINBUFSIZ);
1670         debug(F111,"CUSTOM 4",line,x);
1671 #endif /* OS2 */
1672     }
1673     debug(F110,"CUSTOM 5",line,0);
1674 #endif /* USE_CUSTOM */
1675
1676 #ifdef CKROOT
1677     if (!zinroot(line)) {
1678         debug(F110,"doinit setroot violation",line,0);
1679         return;
1680     }
1681 #endif /* CKROOT */
1682
1683     debug(F110,"doinit ini file is",line,0);
1684     if ((tfile[0] = fopen(line,"r")) != NULL) { /* Try to open init file. */
1685         ok = 1;
1686         tlevel = 0;
1687         tfline[tlevel] = 0;
1688         if ((tfnam[tlevel] = malloc(strlen(line)+1)))
1689           strcpy(tfnam[tlevel],line);   /* safe */
1690
1691         ckstrncpy(kermrc,line,KERMRCL);
1692
1693 #ifndef NOSPL
1694         cmdlvl++;
1695         ifcmd[cmdlvl] = 0;
1696         iftest[cmdlvl] = 0;
1697         count[cmdlvl] =  count[cmdlvl-1]; /* Inherit from previous level */
1698         intime[cmdlvl] = intime[cmdlvl-1];
1699         inpcas[cmdlvl] = inpcas[cmdlvl-1];
1700         takerr[cmdlvl] = takerr[cmdlvl-1];
1701         merror[cmdlvl] = merror[cmdlvl-1];
1702         xquiet[cmdlvl] = quiet;
1703         debug(F101,"doinit open ok","",cmdlvl);
1704         xcmdsrc = CMD_TF;
1705         cmdstk[cmdlvl].src = CMD_TF;
1706         cmdstk[cmdlvl].lvl = tlevel;
1707         cmdstk[cmdlvl].ccflgs = 0;
1708 #endif /* NOSPL */
1709     } else if (rcflag) {
1710         /* Print an error message only if a specific file was asked for. */
1711         printf("?%s - %s\n", ck_errstr(), line);
1712     }
1713
1714 #ifdef datageneral
1715 /* If CKERMIT.INI not found in home directory, look in searchlist */
1716     if (/* homdir && */ (tlevel < 0)) {
1717         ckstrncpy(lp,kermrc,LINBUFSIZ);
1718         if ((tfile[0] = fopen(line,"r")) != NULL) {
1719             ok = 1;
1720             tlevel = 0;
1721             tfline[tlevel] = 0;
1722             if (tfnam[tlevel] = malloc(strlen(line)+1))
1723               strcpy(tfnam[tlevel],line); /* safe */
1724 #ifndef NOSPL
1725             cmdlvl++;
1726             xcmdsrc = CMD_TF;
1727             cmdstk[cmdlvl].src = CMD_TF;
1728             cmdstk[cmdlvl].lvl = tlevel;
1729             cmdstk[cmdlvl].ccflgs = 0;
1730             ifcmd[cmdlvl] = 0;
1731             iftest[cmdlvl] = 0;
1732             count[cmdlvl] =  count[cmdlvl-1]; /* Inherit from previous level */
1733             intime[cmdlvl] = intime[cmdlvl-1];
1734             inpcas[cmdlvl] = inpcas[cmdlvl-1];
1735             takerr[cmdlvl] = takerr[cmdlvl-1];
1736             merror[cmdlvl] = merror[cmdlvl-1];
1737             xquiet[cmdlvl] = quiet;
1738 #endif /* NOSPL */
1739         }
1740     }
1741 #endif /* datageneral */
1742
1743 #ifdef AMIGA                            /* Amiga... */
1744     reqpop();                           /* Restore requestors */
1745 #endif /* AMIGA */
1746 #endif /* OS2 */
1747 #endif /* MAC */
1748
1749     /* Assign value to inidir */
1750
1751     if (!ok) {
1752         inidir[0] = NUL;
1753     } else {
1754         ckstrncpy(inidir, kermrc, CCHMAXPATH);
1755         x = strlen(inidir);
1756         if (x > 0) {
1757             int i;
1758             for (i = x - 1; i > 0; i-- ) {
1759                 if (ISDIRSEP(inidir[i])) {
1760                     inidir[i+1] = NUL;
1761                     break;
1762                 }
1763             }
1764         }
1765 #ifdef NT
1766         GetShortPathName(inidir,inidir,CCHMAXPATH);
1767 #endif /* NT */
1768     }
1769 }
1770
1771 VOID
1772 doiksdinit() {
1773 #ifdef CK_SSL
1774     /* IKSD doesn't request client certs */
1775     ssl_verify_flag = SSL_VERIFY_NONE;
1776 #endif /* CK_SSL */
1777
1778     if (!cmdinited)
1779       cmdini();
1780
1781 #ifdef IKSDCONF
1782 #ifdef OS2
1783     line[0] = '\0';
1784     _searchenv(iksdconf,"INIT",line);
1785     if (line[0] == 0)
1786       _searchenv(iksdconf,"DPATH",line);
1787     if (line[0] == 0)
1788       _searchenv(iksdconf,"PATH",line);
1789     if (line[0] == 0) {
1790         char *pgmptr = GetLoadPath();
1791         if (pgmptr && strlen(pgmptr) < LINBUFSIZ-8) {
1792             lp = strrchr(pgmptr, '\\');
1793             if (lp) {
1794                 strncpy(line, pgmptr, lp - pgmptr);
1795                 strcpy(line + (lp - pgmptr), "\\");
1796                 strcpy(line + (lp - pgmptr + 1), iksdconf);
1797             } else {
1798                 lp = strrchr(pgmptr, '.');
1799                 if (lp) {
1800                     strncpy(line, pgmptr, lp - pgmptr);
1801                     strcpy(line + (lp - pgmptr), ".ksc");
1802                 }
1803             }
1804         }
1805     }
1806     debug(F110,"doiksdinit() line",line,0);
1807     tfile[0] = fopen(line,"r");
1808 #else /* OS2 */
1809     tfile[0] = fopen(iksdconf,"r");
1810 #endif /* OS2 */
1811     if (tfile[0] != NULL) {
1812         tlevel = 0;
1813         tfline[tlevel] = 0;
1814 #ifdef OS2
1815         if (tfnam[tlevel] = malloc(strlen(line)+1))
1816           strcpy(tfnam[tlevel],line);
1817 #else /* OS2 */
1818         if ((tfnam[tlevel] = malloc(strlen(iksdconf)+1)))
1819           strcpy(tfnam[tlevel],iksdconf);
1820 #endif /* OS2 */
1821 #ifndef NOSPL
1822         cmdlvl++;
1823         xcmdsrc = CMD_TF;
1824         cmdstk[cmdlvl].src = CMD_TF;
1825         cmdstk[cmdlvl].lvl = tlevel;
1826         cmdstk[cmdlvl].ccflgs = 0;
1827         ifcmd[cmdlvl]  = 0;
1828         iftest[cmdlvl] = 0;
1829         count[cmdlvl]  = count[cmdlvl-1]; /* Inherit from previous level */
1830         intime[cmdlvl] = intime[cmdlvl-1];
1831         inpcas[cmdlvl] = inpcas[cmdlvl-1];
1832         takerr[cmdlvl] = takerr[cmdlvl-1];
1833         merror[cmdlvl] = merror[cmdlvl-1];
1834         xquiet[cmdlvl] = quiet;
1835 #endif /* NOSPL */
1836         debug(F110,"doiksdinit file ok",tfnam[tlevel],0);
1837     } else {
1838         debug(F110,"doiksdinit open failed",tfnam[tlevel],0);
1839     }
1840 #endif /* IKSDCONF */
1841 }
1842
1843 #ifndef NOSPL
1844 /*
1845   G E T N C M
1846
1847   Get next command from current macro definition.  Command is copied
1848   into string pointed to by argument s, max length n.   Returns:
1849    0 if a string was copied;
1850   -1 if there was no string to copy.
1851 */
1852 int
1853 getncm(s,n) char *s; int n; {
1854     int y = 0;                          /* Character counter */
1855     int quote = 0;
1856     int kp = 0;                         /* Brace up-down counter */
1857     int pp = 0;                         /* Parenthesis up-down counter */
1858 #ifndef NODQMACRO
1859     int dq = 0;                         /* Doublequote counter */
1860 #endif /* NODQMACRO */
1861     char *s2;                           /* Copy of destination pointer */
1862
1863     s2 = s;                             /* Initialize string pointers */
1864     *s = NUL;                           /* and destination buffer */
1865
1866     /* debug(F010,"getncm entry",macp[maclvl],0); */
1867
1868     for (y = 0;                         /* Loop for n bytes max */
1869          macp[maclvl] && *macp[maclvl] && y < n;
1870          y++, s++, macp[maclvl]++) {
1871
1872         *s = *macp[maclvl];             /* Get next char from macro def */
1873
1874 #ifndef COMMENT
1875 /*
1876   This is to allow quoting of parentheses, commas, etc, in function
1877   arguments, but it breaks just about everything else.  DON'T REMOVE THIS
1878   COMMENT!  (Otherwise you'll wind up adding the same code again and breaking
1879   everything again.)  <-- The preceding warning should be obsolete since the
1880   statements below have been fixed, but in case of fire, remove the "n" from
1881   the <#>ifndef above.  NEW WARNING: code added 12 Apr 2002 to exempt the
1882   opening brace in \{nnn} from being treated as a quoted brace.
1883 */
1884         if (!quote && *s == CMDQ) {
1885             quote = 1;
1886             continue;
1887         }
1888         if (quote) {
1889             int notquote = 0;
1890             quote = 0;
1891             if (*s == '{') {            /* Check for \{nnn} (8.0.203) */
1892                 char c, * p;
1893                 p = macp[maclvl] + 1;
1894                 while ((c = *p++)) {
1895                     if (isdigit(c))
1896                       continue;
1897                     else if (c == '}') {
1898                         notquote++;
1899                         break;
1900                     } else {
1901                         break;
1902                     }
1903                 }
1904             }
1905             if (notquote == 0)
1906               continue;
1907         }
1908 #endif /* COMMENT */
1909
1910 /*
1911   Allow braces around macro definition to prevent commas from being turned to
1912   end-of-lines and also treat any commas within parens as text so that
1913   multiple-argument functions won't cause the command to break prematurely.
1914   19 Oct 2001: Similar treatment was added for doublequotes, so
1915
1916      define foo { echo "one, two, three" }
1917
1918   would work as expected.  This doesn't seem to have broken anything but
1919   if something comes up later, rebuild with NODQMACRO defined.
1920 */
1921         if (*s == '{') kp++;            /* Count braces */
1922         if (*s == '}' && kp > 0) kp--;
1923         if (*s == '(') pp++;            /* Count parentheses. */
1924         if (*s == ')' && pp > 0) pp--;
1925 #ifndef NODQMACRO
1926 #ifndef COMMENT
1927         /* Too many false positives */
1928         /* No, not really -- this is indeed the best we can do */
1929         /* Reverted to this method Sun May 11 18:43:45 2003 */
1930         if (*s == '"') dq = 1 - dq;     /* Account for doublequotes */
1931 #else  /* Fri Apr  4 13:21:29 2003 */
1932         /* The code below breaks the SWITCH statement */
1933         /* There is no way to make this work -- it would require */
1934         /* building in all the knowledge of command parser. */
1935         if (dblquo && (*s == '"')) {    /* Have doublequote */
1936             if (dq == 1) {              /* Close quote only if... */
1937                 if ((*(macp[maclvl]+1) == SP) || /* followed by space or... */
1938                     (!*(macp[maclvl]+1)) ||      /* at end or ... */
1939                     /* Next char is command separator... */
1940                     /* Sun May 11 17:24:12 2003 */
1941                     (kp < 1 && pp < 1 && (*(macp[maclvl]+1) == ','))
1942                     )                
1943                   dq = 0;               /* Close the quote */
1944             } else if (dq == 0) {
1945                 /* Open quote only if at beginning or preceded by space */
1946                 if (s > s2) {
1947                     if (*(s-1) == SP)
1948                       dq = 1;
1949                 } else if (s == s2) {
1950                       dq = 1;
1951                 }
1952             }
1953         }
1954 #endif /* COMMENT */
1955 #endif /* NODQMACRO */
1956         if (*s == ',' && pp <= 0 && kp <= 0
1957 #ifndef NODQMACRO
1958             && dq == 0
1959 #endif /* NODQMACRO */
1960             ) {
1961             macp[maclvl]++;             /* Comma not in {} or () */
1962             /* debug(F110,"next cmd",s,0); */
1963             kp = pp = 0;                /* so we have the next command */
1964             break;
1965         }
1966     }                                   /* Reached end. */
1967 #ifdef COMMENT
1968     /* DON'T DO THIS - IT BREAKS EVERYTHING */
1969     *s = NUL;
1970 #endif /* COMMENT */
1971     if (*s2 == NUL) {                   /* If nothing was copied, */
1972         /* debug(F100,"XXX getncm eom","",0); */
1973         popclvl();                      /* pop command level. */
1974         return(-1);
1975     } else {                            /* otherwise, tack CR onto end */
1976         *s++ = CR;
1977         *s = '\0';
1978         /* debug(F110,"XXX getncm OK",s,0); */
1979         if (mecho && pflag)             /* If MACRO ECHO ON, echo the cmd */
1980           printf("%s\n",s2);
1981     }
1982     return(0);
1983 }
1984
1985 /*  D O M A C  --  Define and then execute a macro */
1986
1987 int
1988 domac(name, def, flags) char *name, *def; int flags; {
1989     int x, m;
1990 #ifndef NOLOCAL
1991 #ifdef OS2
1992     extern int term_io;
1993     int term_io_sav = term_io;
1994     term_io = 0;                        /* Disable Terminal Emulator I/O */
1995 #endif /* OS2 */
1996 #endif /* NOLOCAL */
1997     m = maclvl;                         /* Current macro stack level */
1998     x = addmac(name, def);              /* Define a new macro */
1999     if (x > -1) {                       /* If successful, */
2000         dodo(x,NULL,flags);             /* start it (increments maclvl). */
2001         while (maclvl > m) {            /* Keep going till done with it, */
2002             debug(F101,"domac loop maclvl 1","",maclvl);
2003             sstate = (CHAR) parser(1);  /* parsing & executing each command, */
2004             debug(F101,"domac loop maclvl 2","",maclvl);
2005             if (sstate) proto();        /* including protocol commands. */
2006         }
2007         debug(F101,"domac loop exit maclvl","",maclvl);
2008     }
2009 #ifndef NOLOCAL
2010 #ifdef OS2
2011     term_io = term_io_sav;
2012 #endif /* OS2 */
2013 #endif /* NOLOCAL */
2014     return(success);
2015 }
2016 #endif /* NOSPL */
2017
2018 /*
2019   G E T N C T
2020
2021   Get next command from TAKE (command) file.
2022
2023   Call with:
2024    s     Pointer to buffer to read into
2025    n     Length of buffer
2026    f     File descriptor of file to read from
2027    flag  0 == keep line terminator on and allow continuation
2028          1 == discard line terminator and don't allow continuation
2029
2030   Call with flag == 0 to read a command from a TAKE file;
2031   Call with flag != 0 to read a line from a dialing or network directory.
2032
2033   In both cases, trailing comments and/or trailing whitespace is/are stripped.
2034   If flag == 0, continued lines are combined into one line.  A continued line
2035   is one that ends in hypen, or any line in a "block", which starts with "{"
2036   at the end of a line and ends with a matching "}" at the beginning of a
2037   subsequent line; blocks may be nested.
2038
2039   Returns:
2040    0 if a string was copied,
2041   -1 on EOF,
2042   -2 on malloc failure
2043   -3 if line is not properly terminated
2044   -4 if (possibly continued) line is too long.
2045 */
2046 static int lpxlen = 0;
2047
2048 int
2049 getnct(s,n,f,flag) char *s; int n; FILE *f; int flag; {
2050     int i = 0, len = 0, buflen = 0;
2051     char c = NUL, cc = NUL, ccl = NUL, ccx = NUL, *s2 = NULL;
2052     char *lp = NULL, *lpx = NULL, *lp2 = NULL, *lp3 = NULL, *lastcomma = NULL;
2053     char * prev = NULL;
2054     int bc = 0;                         /* Block counter */
2055
2056     s2 = s;                             /* Remember original pointer */
2057     prev = s2;
2058     buflen = n;                         /* Remember original buffer length */
2059
2060     if (n < 0)
2061       return(-2);
2062
2063     /* Allocate a line buffer only if we don't have one that's big enough */
2064
2065     debug(F111,"getnct",ckitoa(lpxlen),n);
2066
2067     if (lpx && (n > lpxlen)) {          /* Have one already */
2068         debug(F101,"getnct new buffer","",lpxlen);
2069         free(lpx);                      /* But it's not big enough */
2070         lpx = NULL;                     /* Free current one */
2071         lpxlen = 0;
2072     }
2073     if (!lpx) {                         /* Get new one */
2074         if (!(lpx = (char *) malloc(n))) {
2075             debug(F101,"getnct malloc failure","",0);
2076             printf("?Memory allocation failure [getnct]\n");
2077             return(-2);
2078         }
2079         lpxlen = n;
2080     }
2081     lp2 = lpx;
2082 #ifdef KLUDGE
2083     /* NOTE: No longer used as of 14 Aug 2000 */
2084     lp2++;
2085 #endif /* KLUDGE */
2086
2087     while (1) {                         /* Loop to read lines from file */
2088         debug(F101,"getnct while (1)","",n);
2089         if (fgets(lp2,n,f) == NULL) {   /* Read a line into lp2 */
2090             debug(F110,"getnct EOF",s2,0); /* EOF */
2091             free(lpx);                  /* Free temporary storage */
2092             lpx = NULL;
2093             *s = NUL;                   /* Make destination be empty */
2094             return(-1);                 /* Return failure code */
2095         }
2096 #ifndef NODIAL
2097         if (flag)                       /* Count this line */
2098           dirline++;
2099         else
2100 #endif /* NODIAL */
2101           tfline[tlevel]++;
2102         len = strlen(lp2) - 1;          /* Position of line terminator */
2103         if (len == 0 && lp2[0] != '\n') { /* Last line in file has one char */
2104             lp2[++len] = '\n';          /* that is not a newline */
2105             lp2[len] = NUL;
2106         }
2107         debug(F010,"getnct",lp2,0);
2108         if (len < 0)
2109           len = 0;
2110         if (techo && pflag)             /* If TAKE ECHO ON, */
2111           printf("%3d. %s",             /* echo it this line. */
2112 #ifndef NODIAL
2113                  flag ? dirline :
2114 #endif /* NODIAL */
2115                  tfline[tlevel],
2116                  lp2
2117                  );
2118         lp3 = lp2;                      /* Working pointer */
2119         i = len;                        /* Get first nonwhitespace character */
2120         while (i > 0 && (*lp3 == SP || *lp3 == HT)) {
2121             i--;
2122             lp3++;
2123         }
2124         if (i == 0 && bc > 0)           /* Blank line in {...} block */
2125           continue;
2126
2127         /* Isolate, remove, and check terminator */
2128
2129         c = lp2[len];                   /* Value of line terminator */
2130         /* debug(F101,"getnct terminator","",c); */
2131         if (c < LF || c > CR) {         /* It's not a terminator */
2132             /* debug(F111,"getnct bad line",lp2,c); */
2133             if (feof(f) && len > 0 && len < n) {
2134                 /* Kludge Alert... */
2135                 if (!quiet)
2136                   printf("WARNING: Last line of %s lacks terminator\n",
2137                          s2 == cmdbuf ? "command file" : "directory file");
2138                 c = lp2[++len] = '\n';  /* No big deal - supply one. */
2139             } else {                    /* Something's wrong, fail. */
2140                 free(lpx);
2141                 lpx = NULL;
2142                 return(-3);
2143             }
2144         }
2145         /* Trim trailing whitespace */
2146
2147         for (i = len - 1; i > -1 && lp2[i] <= SP; i--) /* Trim */
2148           ;
2149         /* debug(F101,"getnct i","",i); */
2150         lp2[i+1] = NUL;                 /* Terminate the string */
2151         /* debug(F110,"getnct lp2",lp2,0); */
2152         lp = lp2;                       /* Make a working pointer */
2153
2154         /* Remove trailing or full-line comment */
2155
2156         while ((cc = *lp)) {
2157             if (cc == ';' || cc == '#') { /* Comment introducer? */
2158                 if (lp == lp2) {        /* First char on line */
2159                     *lp = NUL;
2160                     break;
2161                 } else if (*(lp - 1) == SP || *(lp - 1) == HT) {
2162                     lp--;
2163                     *lp = NUL;  /* Or preceded by whitespace */
2164                     break;
2165                 }
2166             }
2167             lp++;
2168         }
2169         if (lp > lp2)
2170           lp--;                         /* Back up over the NUL */
2171
2172         /* Now trim any space that preceded the comment */
2173
2174         while ((*lp == SP || *lp == HT) && lp >= lp2) {
2175             *lp = NUL;
2176             if (lp <= lp2)
2177               break;
2178             lp--;
2179         }
2180         /* debug(F110,"getnct comment trimmed",lp2,0); */
2181
2182         len = strlen(lp2);              /* Length after trimming */
2183
2184         if (n - len < 2) {              /* Check remaining space */
2185             debug(F111,"getnct command too long",s2,buflen);
2186             printf("?Line too long, maximum length: %d.\n",buflen);
2187             free(lpx);
2188             return(-4);
2189         }
2190         ccl = (len > 0) ? lp2[len-1] : 0;     /* Last character in line */
2191         ccx = (len > 1) ? lp2[len-2] : 0;     /* Penultimate char in line */
2192
2193 #ifdef COMMENT
2194         /* Line containing only whitespace and ,- */
2195         if ((len > 1) && (lp3 == lp2+len-2) && (ccl == '-') && (ccx == ','))
2196           continue;
2197 #endif /* COMMENT */
2198
2199 #ifdef KLUDGE
2200 /*
2201   If it is a command and it begins with a token (like ! or .) that is not
2202   followed by a space, insert a space now; otherwise cmkey() can get mighty
2203   confused.
2204 */
2205         if (s == s2 && !flag) {
2206             char *p = toktab;
2207             while (*p) {
2208                 if (*p == *lp3 && *(p+1) != SP) {
2209                     debug(F110,"getnct token",p,0);
2210                     *lp3-- = SP;
2211                     *lp3 = *p;
2212                     if (lp3 < lp2) {
2213                         lp2--;
2214                         len++;
2215                     }
2216                     break;
2217                 } else
2218                   p++;
2219             }
2220         }
2221 #endif /* KLUDGE */
2222         lp = lp2;
2223
2224         while ((*s++ = *lp++))          /* Copy result to target buffer */
2225           n--;                          /* accounting for length */
2226         s--;                            /* Back up over the NUL */
2227
2228         /* Check whether this line is continued */
2229
2230         if (flag)                       /* No line continuation when flag=1 */
2231           break;                        /* So break out of read-lines loop */
2232
2233 #ifdef COMMENT
2234         debug(F000,"getnct first char","",*lp3);
2235         debug(F000,"getnct last char","",ccl);
2236         debug(F000,"getnct next-to-last char","",ccx);
2237 #endif /* COMMENT */
2238
2239         if (bc > 0 && *lp3 == '}') {    /* First char on line is '}' */
2240             bc--;                               /* Decrement block counter */
2241         }
2242
2243         if (bc == 0 &&                  /* Line is continued if bc > 0 */
2244 #ifdef COMMENT
2245             /* Not supported as of C-Kermit 6.0 */
2246             ccl != CMDQ &&              /* or line ends with CMDQ */
2247 #endif /* COMMENT */
2248             ccl != '-'  &&              /* or line ends with dash */
2249             ccl != '{')                 /* or line ends with opening brace */
2250           break;                        /* None of those, we're done. */
2251
2252         if (ccl == '-' || ccl == '{')   /* Continuation character */
2253           if (ccx == CMDQ)              /* But it's quoted */
2254             break;                      /* so ignore it */
2255
2256         if (ccl == '{') {               /* Last char on line is '{'? */
2257             bc++;                       /* Count the block opener. */
2258         } else if (ccl == '-') {        /* Explicit continue? */
2259             char c, * ss;
2260             int state = 0, nn;
2261             s--;                        /* Yes, back up over terminators */
2262             n++;                        /* and over continuation character */
2263             nn = n;                     /* Save current count */
2264             ss = s;                     /* and pointer */
2265             s--;                        /* Back up over dash */
2266             n++;
2267             while (state < 2 && s >= prev) { /* Check for "{,-" */
2268                 n++;
2269                 c = *s--;
2270                 if (c <= SP)
2271                   continue;
2272                 if (c != ',' && c != '{')
2273                   break;
2274                 switch (state) {
2275                   case 0:               /* Looking for comma */
2276                     if (c == ',')
2277                       state = 1;
2278                     break;
2279                   case 1:               /* Looking for left brace */
2280                     if (c == '{') {
2281                         state = 2;
2282                         s += 2;
2283                         *s = NUL;
2284                         bc++;
2285                     }
2286                     break;
2287                 }
2288             }
2289             if (state != 2) { s = ss; n = nn; }
2290             *s = NUL;
2291         } else {                        /* None of those but (bc > 0) */
2292             lastcomma = s;
2293             *s++ = ',';                 /* and insert a comma */
2294             n--;
2295         }
2296 #ifdef COMMENT
2297         debug(F101,"getnct bc","",bc);
2298         debug(F100,"getnct continued","",0);
2299 #endif /* COMMENT */
2300
2301         *s = NUL;
2302         prev = s;
2303
2304     } /* read-lines while loop */
2305
2306     if (lastcomma)
2307       *lastcomma = SP;
2308     if (!flag)                          /* Tack line terminator back on */
2309       *s++ = c;
2310     *s++ = NUL;                         /* Terminate the string */
2311     untab(s2);                          /* Done, convert tabs to spaces */
2312 #ifdef DEBUG
2313     if (!flag) {
2314         debug(F010,"CMD(F)",s2,0);
2315     }
2316 #endif /* DEBUG */
2317     free(lpx);                          /* Free temporary storage */
2318     return(0);                          /* Return success */
2319 }
2320
2321 VOID
2322 shostack() {                            /* Dump the command stack */
2323     int i;
2324     char *p;
2325 #ifndef NOSPL
2326     for (i = cmdlvl; i > 0; i--) {
2327         if (cmdstk[i].src == CMD_TF) {
2328             p = tfnam[cmdstk[i].lvl];
2329             if (zfnqfp(p,TMPBUFSIZ,tmpbuf))
2330               p = tmpbuf;
2331             printf(" %2d. File  : %s (line %d)\n",
2332                    i,
2333                    p,
2334                    tfline[cmdstk[i].lvl]
2335                    );
2336         } else if (cmdstk[i].src == CMD_MD) {
2337             char * m;
2338             m = m_arg[cmdstk[i].lvl][0]; /* Name of this macro */
2339             if (i > 0) {                 /* Special handling for 2-level */
2340                 char *s;                 /* built-in macros... */
2341                 s = m_arg[cmdstk[i-1].lvl][0]; /* Name next level up */
2342                 if (s && cmdstk[i-1].src == CMD_MD) {
2343                     if (!strcmp(s,"_forx"))
2344                       m = "FOR";
2345                     else if (!strcmp(s,"_xif"))
2346                       m = "XIF";
2347                     else if (!strcmp(s,"_while"))
2348                       m = "WHILE";
2349                     else if (!strcmp(s,"_switx"))
2350                       m = "SWITCH";
2351                 }
2352             }
2353             printf(" %2d. Macro : %s\n",i,m);
2354         } else if (cmdstk[i].src == CMD_KB) {
2355             printf(" %2d. Prompt:\n",i);
2356         } else {
2357             printf(" %2d. ERROR : Command source unknown\n",i);
2358         }
2359     }
2360 #else
2361     for (i = tlevel; i > -1; i--) {
2362         p = tfnam[i];
2363         if (zfnqfp(p,TMPBUFSIZ,tmpbuf))
2364           p = tmpbuf;
2365         printf(" %2d. File  : %s (line %d)\n",
2366                i,
2367                p,
2368                tfline[i]
2369                );
2370     }
2371 #endif /* NOSPL */
2372     if (i == 0)
2373       printf(" %2d. Prompt: (top level)\n",0);
2374 }
2375
2376
2377 /*  P A R S E R  --  Top-level interactive command parser.  */
2378
2379 /*
2380   Call with:
2381     m = 0 for normal behavior: keep parsing and executing commands
2382           until an action command is parsed, then return with a
2383           Kermit start-state as the value of this function.
2384     m = 1 to parse only one command, can also be used to call parser()
2385           recursively.
2386     m = 2 to read but do not execute one command.
2387   In all cases, parser() returns:
2388     0     if no Kermit protocol action required
2389     > 0   with a Kermit protocol start-state.
2390     < 0   upon error.
2391 */
2392 int
2393 parser(m) int m; {
2394     int tfcode, xx, yy, zz;             /* Workers */
2395     int is_tn = 0;
2396     int cdlost = 0;
2397
2398 #ifndef NOSPL
2399     int inlevel;                        /* Level we were called at */
2400     extern int askflag;
2401 #endif /* NOSPL */
2402     char *cbp;                          /* Command buffer pointer */
2403 #ifdef MAC
2404     extern char *lfiles;                /* Fake extern cast */
2405 #endif /* MAC */
2406     extern int interrupted;
2407 #ifndef NOXFER
2408     extern int sndcmd, getcmd, fatalio, clearrq;
2409 #endif /* NOXFER */
2410
2411     debok = 1;                          /* Undisable debugging */
2412
2413 #ifdef AMIGA
2414     reqres();                           /* Restore AmigaDOS requestors */
2415 #endif /* AMIGA */
2416
2417 #ifdef OS2
2418     if (cursor_save > -1) {             /* Restore cursor if it was */
2419         cursorena[VCMD] = cursor_save;  /* turned off during file transfer */
2420         cursor_save = -1;
2421     }
2422 #endif /* OS2 */
2423
2424 #ifdef IKSDB
2425     if (ikdbopen) slotstate(what,"COMMAND PROMPT","",""); /* IKSD database */
2426 #endif /* IKSDB */
2427
2428     is_tn = (local && network && IS_TELNET()) ||
2429       (!local && sstelnet);
2430
2431     if (!xcmdsrc)                       /* If at top (interactive) level ... */
2432       concb((char)escape);              /* put console in 'cbreak' mode. */
2433
2434 #ifdef CK_TMPDIR
2435 /* If we were cd'd temporarily to another device or directory ... */
2436     if (f_tmpdir) {
2437         int x;
2438         x = zchdir((char *) savdir);    /* ... restore previous directory */
2439         f_tmpdir = 0;                   /* and remember we did it. */
2440         debug(F111,"parser tmpdir restoring",savdir,x);
2441     }
2442 #endif /* CK_TMPDIR */
2443
2444 #ifndef NOSPL
2445     inlevel = cmdlvl;           /* Current macro level */
2446 #ifdef DEBUG
2447     if (deblog) {
2448         debug(F101,"&parser entry maclvl","",maclvl);
2449         debug(F101,"&parser entry inlevel","",inlevel);
2450         debug(F101,"&parser entry tlevel","",tlevel);
2451         debug(F101,"&parser entry cmdlvl","",cmdlvl);
2452         debug(F101,"&parser entry m","",m);
2453     }
2454 #endif /* DEBUG */
2455 #endif /* NOSPL */
2456
2457 #ifndef NOXFER
2458     ftreset();                          /* Reset global file settings */
2459 #endif /* NOXFER */
2460 /*
2461   sstate becomes nonzero when a command has been parsed that requires some
2462   action from the protocol module.  Any non-protocol actions, such as local
2463   directory listing or terminal emulation, are invoked directly from below.
2464 */
2465     sstate = 0;                         /* Start with no start state. */
2466
2467 #ifndef NOXFER
2468 #ifndef NOSPL
2469     query = 0;                          /* QUERY not active */
2470 #endif /* NOSPL */
2471 #ifndef NOHINTS
2472     if (!success) {
2473         if (local && !network && carrier != CAR_OFF) {
2474             int x;                      /* Serial connection */
2475             x = ttgmdm();               /* with carrier checking */
2476             if (x > -1) {
2477                 if (!(x & BM_DCD)) {
2478                     cdlost = 1;
2479                     fatalio = 1;
2480                 }
2481             }
2482         }
2483     }
2484 #ifdef DEBUG
2485     if (deblog) {
2486         debug(F101,"parser top what","",what);
2487         debug(F101,"parser top interrupted","",interrupted);
2488         debug(F101,"parser top cdlost","",cdlost);
2489         debug(F101,"parser top sndcmd","",sndcmd);
2490         debug(F101,"parser top getcmd","",getcmd);
2491     }
2492 #endif /* DEBUG */
2493     if (cdlost && !interrupted && (sndcmd || getcmd)) {
2494         printf("?Connection broken (carrier signal lost)\n");
2495     }
2496     if (sndcmd && !success && hints && !interrupted && !fatalio && !xcmdsrc) {
2497         int x = 0, n = 0;
2498         printf("\n*************************\n");
2499         printf("SEND-class command failed.\n");
2500         printf(" Packets sent: %d\n", spackets);
2501         printf(" Retransmissions: %d\n",retrans);
2502         printf(" Timeouts: %d\n", timeouts);
2503         printf(" Damaged packets: %d\n", crunched);
2504         if (epktrcvd) {
2505             printf(" Transfer canceled by receiver.\n");
2506             printf(" Receiver's message: \"%s\"\n",(char *)epktmsg);
2507             n++;
2508         } else {
2509             if (epktmsg) if (*epktmsg) {
2510                 printf(" Fatal Kermit Protocol Error: %s\n",epktmsg);
2511                 n++;
2512             }
2513         }
2514         if (local && !network && carrier != CAR_OFF) {
2515             int xx;                     /* Serial connection */
2516             xx = ttgmdm();              /* with carrier checking */
2517             if (xx > -1) {
2518                 if (!(xx & BM_DCD))
2519                   cdlost = 1;
2520             }
2521         }
2522
2523 #ifdef UNIX
2524         if (errno != 0)
2525 #endif /* UNIX */
2526           {
2527               printf(" Most recent local OS error: \"%s\"\n",ck_errstr());
2528               n++;
2529           }
2530         printf(
2531    "\nHINTS... If the preceding error message%s not explain the failure:\n",
2532                (n > 1) ? "s do" : " does"
2533                );
2534 #ifndef NOLOCAL
2535         if (local) {
2536             if (rpackets == 0) {
2537                 printf(" . Did you start a Kermit receiver on the far end?\n");
2538             } else {
2539                 printf(
2540                 " . Try changing the remote Kermit's FLOW-CONTROL setting.\n");
2541                 if (!network && mdmtyp > 0)
2542                   if ((3 * crunched) > spackets)
2543                     printf(
2544                 " . Try placing a new call to get a cleaner connection.\n");
2545             }
2546         } else if (rpackets > 0) {
2547             if (flow == FLO_NONE)
2548              printf(" . Give me a SET FLOW XON/XOFF command and try again.\n");
2549             else
2550              printf(" . Give me a SET FLOW NONE command and try again.\n");
2551         }
2552         x++;
2553 #endif /* NOLOCAL */
2554
2555         if ((3 * timeouts) > spackets)
2556           printf(" . Adjust the timeout method (see HELP SET SEND).\n");
2557         if ((3 * retrans) > spackets)
2558           printf(" . Increase the retry limit (see HELP SET RETRY).\n");
2559
2560 #ifdef CK_SPEED
2561         if (prefixing != PX_ALL && rpackets > 2) {
2562             printf(" . Try it again with SET PREFIXING ALL.\n");
2563             x++;
2564         }
2565 #endif /* CK_SPEED */
2566 #ifdef STREAMING
2567         if (streamed) {
2568             printf(" . Try it again with SET STREAMING OFF.\n");
2569             x++;
2570         } else if (reliable) {
2571             printf(" . Try it again with SET RELIABLE OFF.\n");
2572             x++;
2573         }
2574 #endif /* STREAMING */
2575
2576 #ifdef CK_SPEED
2577         if (clearrq > 0 && prefixing == PX_NON) {
2578             printf(" . Try it again with SET CLEAR-CHANNEL OFF.\n");
2579             x++;
2580         }
2581 #endif /* CK_SPEED */
2582         if (!parity) {
2583             printf(" . Try it again with SET PARITY SPACE.\n");
2584             x++;
2585         }
2586         printf(" . %sive a ROBUST command and try again.\n",
2587                (x > 0) ? "As a last resort, g" : "G"
2588                );
2589         printf("Also:\n");
2590         printf(" . Be sure the source file has read permission.\n");
2591         printf(" . Be sure the target directory has write permission.\n");
2592         printf("(Use SET HINTS OFF to suppress hints.)\n");
2593         printf("*************************\n\n");
2594     }
2595     debug(F101,"topcmd","",topcmd);
2596     if (getcmd && !success && hints && !interrupted && !fatalio && !xcmdsrc) {
2597         int x = 0;
2598         extern int urpsiz, wslotr;
2599         printf("\n*************************\n");
2600         printf("RECEIVE- or GET-class command failed.\n");
2601         printf(" Packets received: %d\n", rpackets);
2602         printf(" Damaged packets: %d\n", crunched);
2603         printf(" Timeouts: %d\n", timeouts);
2604         if (rpackets > 0)
2605           printf(" Packet length: %d\n", urpsiz);
2606         if (epktrcvd) {
2607             printf(" Transfer canceled by sender.\n");
2608             printf(" Sender's message: \"%s\"\n",(char *)epktmsg);
2609         }
2610 #ifdef UNIX
2611         if (errno != 0)
2612 #endif /* UNIX */
2613           printf(" Most recent local error: \"%s\"\n",ck_errstr());
2614         printf(
2615    "\nHINTS... If the preceding error message%s not explain the failure:\n",
2616                epktrcvd ? "s do" : " does"
2617                );
2618 #ifndef NOLOCAL
2619         if (local) {
2620             if (topcmd == XXGET)
2621               printf(" . Did you start a Kermit SERVER on the far end?\n");
2622             if (rpackets == 0) {
2623                 if (topcmd != XXGET)
2624                   printf(" . Did you start a Kermit SENDer on the far end?\n");
2625             } else {
2626                 printf(
2627                 " . Choose a different FLOW-CONTROL setting and try again.\n");
2628             }
2629         } else if (topcmd == XXGET)
2630           printf(" . Is the other Kermit in (or does it have) SERVER mode?\n");
2631         if (rpackets > 0 && urpsiz > 90)
2632           printf(" . Try smaller packets (SET RECEIVE PACKET-LENGTH).\n");
2633         if (rpackets > 0 && wslotr > 1 && !streamed)
2634           printf(" . Try a smaller window size (SET WINDOW).\n");
2635         if (!local && rpackets > 0) {
2636             if (flow == FLO_NONE)
2637              printf(" . Give me a SET FLOW XON/XOFF command and try again.\n");
2638             else
2639              printf(" . Give me a SET FLOW NONE command and try again.\n");
2640         }
2641         x++;
2642 #endif /* NOLOCAL */
2643 #ifdef STREAMING
2644         if (streamed) {
2645             printf(" . Try it again with SET STREAMING OFF.\n");
2646             x++;
2647         } else if (reliable && local) {
2648             printf(" . Try it again with SET RELIABLE OFF.\n");
2649             x++;
2650         } else
2651 #endif /* STREAMING */
2652         if (!parity) {
2653             printf(" . Try it again with SET PARITY SPACE.\n");
2654             x++;
2655         }
2656         printf((x > 0) ?
2657                " . As a last resort, give a ROBUST command and try again.\n" :
2658                " . Give a ROBUST command and try again.\n"
2659                );
2660         printf("Also:\n");
2661         printf(" . Be sure the target directory has write permission.\n");
2662         printf(" . Try telling the %s to SET PREFIXING ALL.\n",
2663                topcmd == XXGET ? "server" : "sender"
2664                );
2665         printf(" . Try giving a ROBUST command to the %s.\n",
2666                topcmd == XXGET ? "server" : "sender"
2667                );
2668         printf("(Use SET HINTS OFF to suppress hints.)\n");
2669         printf("*************************\n\n");
2670     }
2671 #endif /* NOHINTS */
2672     getcmd = 0;
2673     sndcmd = 0;
2674     interrupted = 0;
2675 #endif /* NOXFER */
2676
2677     while (sstate == 0) {               /* Parse cmds until action requested */
2678         debug(F100,"parse top","",0);
2679         what = W_COMMAND;               /* Now we're parsing commands. */
2680         rcdactive = 0;                  /* REMOTE CD not active */
2681         keepallchars = 0;               /* MINPUT not active */
2682
2683 #ifdef OS2
2684         if (apcactive == APC_INACTIVE)
2685           WaitCommandModeSem(-1);
2686 #endif /* OS2 */
2687 #ifdef IKS_OPTION
2688         if ((local &&
2689              !xcmdsrc &&
2690              is_tn &&
2691              TELOPT_ME(TELOPT_KERMIT) &&
2692              TELOPT_SB(TELOPT_KERMIT).kermit.me_start) ||
2693             (!local &&
2694              !cmdadl &&
2695              TELOPT_ME(TELOPT_KERMIT) &&
2696              TELOPT_SB(TELOPT_KERMIT).kermit.me_start)
2697             ) {
2698             tn_siks(KERMIT_STOP);
2699         }
2700 #endif /* IKS_OPTION */
2701
2702 #ifndef NOXFER
2703         if (autopath) {
2704             fnrpath = PATH_AUTO;
2705             autopath = 0;
2706         }
2707         remfile = 0;                    /* Clear these in case REMOTE */
2708         remappd = 0;                    /* command was interrupted... */
2709         rempipe = 0;
2710         makestr(&snd_move,g_snd_move);  /* Restore these */
2711         makestr(&rcv_move,g_rcv_move);
2712         makestr(&snd_rename,g_snd_rename);
2713         makestr(&rcv_rename,g_rcv_rename);
2714 #endif /* NOXFER */
2715         xaskmore = saveask;             /* Restore global more-prompting */
2716         diractive = 0;
2717         cdactive = 0;
2718
2719 #ifndef NOSPL
2720         askflag = 0;
2721 #endif /* NOSPL */
2722
2723     /* Take requested action if there was an error in the previous command */
2724
2725         setint();
2726         debug(F101,"parser tlevel","",tlevel);
2727         debug(F101,"parser cmd_rows","",cmd_rows);
2728
2729 #ifndef NOLOCAL
2730         debug(F101,"parser wasclosed","",wasclosed);
2731         if (wasclosed) {                /* If connection was just closed */
2732 #ifndef NOSPL
2733             int k;
2734             k = mlook(mactab,"on_close",nmac); /* Look up "on_close" */
2735             if (k >= 0) {               /* If found, */
2736                 /* printf("ON_CLOSE CMD LOOP\n"); */
2737                 dodo(k,ckitoa(whyclosed),0); /* Set it up */
2738             }
2739 #endif /* NOSPL */
2740             whyclosed = WC_REMO;
2741             wasclosed = 0;
2742         }
2743 #endif /* NOLOCAL */
2744
2745 #ifndef NOSPL
2746         xxdot = 0;                      /* Clear this... */
2747
2748         debug(F101,"parser success","",success);
2749         if (success == 0) {
2750             if (cmdstk[cmdlvl].src == CMD_TF && takerr[cmdlvl]) {
2751                 printf("Command file terminated by error.\n");
2752                 popclvl();
2753                 if (cmdlvl == 0) return(0);
2754             }
2755             if (cmdstk[cmdlvl].src == CMD_MD && merror[cmdlvl]) {
2756                 printf("Command error: macro terminated.\n");
2757                 popclvl();
2758                 if (m && (cmdlvl < inlevel))
2759                   return((int) sstate);
2760             }
2761         }
2762         nulcmd = (m == 2);
2763         debug(F101,"parser nulcmd","",nulcmd);
2764 #else
2765         if (success == 0 && tlevel > -1 && takerr[tlevel]) {
2766             printf("Command file terminated by error.\n");
2767             popclvl();
2768             cmini(ckxech);              /* Clear the cmd buffer. */
2769             if (tlevel < 0)             /* Just popped out of cmd files? */
2770               return(0);                /* End of init file or whatever. */
2771         }
2772 #endif /* NOSPL */
2773
2774 #ifdef MAC
2775         /* Check for TAKE initiated by menu. */
2776         if ((tlevel == -1) && lfiles)
2777             startlfile();
2778 #endif /* MAC */
2779
2780         /* If in TAKE file, check for EOF */
2781 #ifndef NOSPL
2782 #ifdef MAC
2783         if
2784 #else
2785         while
2786 #endif /* MAC */
2787           ((cmdstk[cmdlvl].src == CMD_TF)  /* If end of take file */
2788                && (tlevel > -1)
2789                && feof(tfile[tlevel])) {
2790             popclvl();                  /* pop command level */
2791             cmini(ckxech);              /* and clear the cmd buffer. */
2792             if (cmdlvl == 0) {          /* Just popped out of all cmd files? */
2793                 return(0);              /* End of init file or whatever. */
2794             }
2795         }
2796 #ifdef MAC
2797         miniparser(1);
2798         if (sstate == 'a') {            /* if cmd-. cancel */
2799             debug(F100, "parser: cancel take due to sstate", "", sstate);
2800             sstate = '\0';
2801             dostop();
2802             return(0);                  /* End of init file or whatever. */
2803         }
2804 #endif /*  MAC */
2805
2806 #else /* NOSPL */
2807         if ((tlevel > -1) && feof(tfile[tlevel])) { /* If end of take */
2808             popclvl();                  /* Pop up one level. */
2809             cmini(ckxech);              /* and clear the cmd buffer. */
2810             if (tlevel < 0)             /* Just popped out of cmd files? */
2811               return(0);                /* End of init file or whatever. */
2812         }
2813 #endif /* NOSPL */
2814
2815
2816 #ifndef NOSPL
2817         debug(F101,"parser cmdlvl","",cmdlvl);
2818         debug(F101,"parser cmdsrc","",cmdstk[cmdlvl].src);
2819
2820         if (cmdstk[cmdlvl].src == CMD_MD) { /* Executing a macro? */
2821             debug(F100,"parser macro","",0);
2822             maclvl = cmdstk[cmdlvl].lvl; /* Get current level */
2823             debug(F101,"parser maclvl","",maclvl);
2824             cbp = cmdbuf;               /* Copy next cmd to command buffer. */
2825             *cbp = NUL;
2826             if (*savbuf) {              /* In case then-part of 'if' command */
2827                 ckstrncpy(cbp,savbuf,CMDBL); /* was saved, restore it. */
2828                 *savbuf = '\0';
2829             } else {                    /* Else get next cmd from macro def */
2830                 if (getncm(cbp,CMDBL) < 0) {
2831 #ifdef DEBUG
2832                     if (deblog) {
2833                         debug(F101,"parser end of macro m","",m);
2834                         debug(F101,"parser end of macro cmdlvl","",cmdlvl);
2835                         debug(F101,"parser end of macro inlevel","",inlevel);
2836                     }
2837 #endif /* DEBUG */
2838                     if (m && (cmdlvl < inlevel))
2839                       return((int) sstate);
2840                     else /* if (!m) */ continue;
2841                 }
2842             }
2843             debug(F010,"CMD(M)",cmdbuf,0);
2844
2845         } else if (cmdstk[cmdlvl].src == CMD_TF)
2846 #else
2847           if (tlevel > -1)
2848 #endif /* NOSPL */
2849           {
2850 #ifndef NOSPL
2851             debug(F111,"parser savbuf",savbuf,tlevel);
2852             if (*savbuf) {              /* In case THEN-part of IF command */
2853                 ckstrncpy(cmdbuf,savbuf,CMDBL); /* was saved, restore it. */
2854                 *savbuf = '\0';
2855             } else
2856 #endif /* NOSPL */
2857
2858               /* Get next line from TAKE file */
2859
2860               if ((tfcode = getnct(cmdbuf,CMDBL,tfile[tlevel],0)) < 0) {
2861                   debug(F111,"parser tfcode",tfile[tlevel],tfcode);
2862                   if (tfcode < -1) {    /* Error */
2863                       printf("?Error in TAKE command file: %s\n",
2864                              (tfcode == -2) ? "Memory allocation failure" :
2865                              "Line too long or contains NUL characters"
2866                              );
2867                       dostop();
2868                   }
2869                   continue;             /* -1 means EOF */
2870               }
2871
2872         /* If interactive, get next command from user. */
2873
2874         } else {                        /* User types it in. */
2875             if (pflag) prompt(xxstring);
2876             cmini(ckxech);
2877         }
2878
2879     /* Now we know where next command is coming from. Parse and execute it. */
2880
2881         repars = 1;                     /* 1 = command needs parsing */
2882 #ifndef NOXFER
2883         displa = 0;                     /* Assume no file transfer display */
2884 #endif /* NOXFER */
2885
2886         while (repars) {                /* Parse this cmd until entered. */
2887
2888             debug(F101,"parser top of while loop","",0);
2889
2890 #ifdef RECURSIVE
2891             /* In case of "send /recursive ./?<Ctrl-U>" etc */
2892             recursive = 0;              /* This is never sticky */
2893 #endif /* RECURSIVE */
2894             xfiletype = -1;             /* Reset this between each command */
2895 #ifndef NOMSEND
2896             addlist = 0;
2897 #endif /* NOMSEND */
2898 #ifdef CK_RECALL
2899             on_recall = 1;
2900 #endif /* CK_RECALL */
2901             /* This might have been changed by a switch */
2902             if (g_matchdot > -1) {
2903                 matchdot = g_matchdot;
2904                 g_matchdot = -1;
2905             }
2906             cmres();                    /* Reset buffer pointers. */
2907
2908 #ifdef OS2
2909 #ifdef COMMENT
2910             /* we check to see if a macro is waiting to be executed */
2911             /* if so, we call domac on it */
2912             if (cmdmac) {
2913                 ckstrncpy(cmdbuf, cmdmac, CMDBL);
2914                 free(cmdmac);
2915                 cmdmac = NULL;
2916             }
2917 #endif /* COMMENT */
2918 #endif /* OS2 */
2919 #ifndef NOXFER
2920             bye_active = 0;
2921 #endif /* NOXFER */
2922             havetoken = 0;
2923             xx = cmkey2(cmdtab,ncmd,"Command","",toktab,xxstring,1);
2924             debug(F101,"top-level cmkey2","",xx);
2925             if (xx == -5) {
2926                 yy = chktok(toktab);
2927                 debug(F101,"top-level cmkey token","",yy);
2928 #ifndef COMMENT
2929                 /* Either way makes absolutely no difference */
2930                 debug(F110,"NO UNGWORD",atmbuf,0);
2931                 /* ungword(); */
2932 #else
2933                 debug(F110,"TOKEN UNGWORD",atmbuf,0);
2934                 ungword();
2935 #endif /* COMMENT */
2936                 switch (yy) {
2937                   case '#': xx = XXCOM; break; /* Comment */
2938                   case ';': xx = XXCOM; break; /* Comment */
2939 #ifndef NOSPL
2940                   case '.': xx = XXDEF; xxdot = 1; break; /* Assignment */
2941                   case ':': xx = XXLBL; break; /* GOTO label */
2942 #endif /* NOSPL */
2943
2944 #ifndef NOPUSH
2945 #ifdef CK_REDIR
2946                   case '<':
2947 #endif /* CK_REDIR */
2948                   case '@':
2949                   case '!':
2950                     if (nopush) {
2951                         char *s; int x;
2952                         if ((x = cmtxt("Text to be ignored","",&s,NULL)) < 0)
2953                           return(x);
2954                         success = 0;
2955                         xx = XXCOM;
2956                     } else {
2957                         switch(yy) {
2958 #ifdef CK_REDIR
2959                           case '<': xx = XXFUN; break; /* REDIRECT */
2960 #endif /* CK_REDIR */
2961                           case '@':
2962                           case '!': xx = XXSHE; break; /* Shell escape */
2963                         }
2964                     }
2965                     break;
2966 #endif /* NOPUSH */
2967 #ifdef CK_RECALL
2968                   case '^': xx = XXREDO;  break;
2969 #endif /* CK_RECALL */
2970 #ifndef NOSPL
2971                   case '{': xx = XXMACRO; break;
2972                   case '(': xx = XXSEXP;  break;
2973 #endif /* NOSPL */
2974
2975                   default:
2976                     if (!quiet) {
2977                         printf("\n?Invalid - \"%s\"\n",cmdbuf);
2978 #ifdef COMMENT
2979 #ifndef NOSPL
2980                         if (maclvl > -1 && xcmdsrc == 2)
2981                           printf("Macro: %s; ",
2982                                  m_arg[maclvl][0] ?
2983                                  m_arg[maclvl][0] : "");
2984 #endif /* NOSPL */
2985                         if (tlevel > -1) {
2986                             printf("Command file: %s, line %d\n",
2987                                    tfnam[tlevel] ? tfnam[tlevel] : "",
2988                                    tfline[tlevel]
2989                                    );
2990                         }
2991 #else
2992                         if (xcmdsrc > 0) {
2993                             printf("Command stack:\n");
2994                             shostack();
2995                         }
2996 #endif /* COMMENT */
2997
2998                     }
2999                     xx = -2;
3000                 }
3001                 havetoken = 1;
3002                 debug(F101,"HAVE TOKEN","",xx);
3003             }
3004             if (xx > -1) {
3005                 topcmd = xx;            /* Top-level command index */
3006 #ifndef NOSPL
3007                 if (maclvl > -1)
3008                   lastcmd[maclvl] = xx;
3009 #endif /* NOSPL */
3010                 debug(F101,"topcmd","",topcmd);
3011                 debug(F101,"cmflgs","",cmflgs);
3012             }
3013
3014 #ifndef NOSPL
3015             /* Special handling for IF..ELSE */
3016
3017             debug(F101,"cmdlvl","",cmdlvl);
3018             debug(F101,"ifcmd[cmdlvl]","",ifcmd[cmdlvl]);
3019
3020             if (ifcmd[cmdlvl])          /* Count stmts after IF */
3021               ifcmd[cmdlvl]++;
3022             if (ifcmd[cmdlvl] > 2 && xx != XXELS && xx != XXCOM)
3023               ifcmd[cmdlvl] = 0;
3024
3025             /* Execute the command and take action based on return code. */
3026
3027             if (nulcmd) {               /* Ignoring this command? */
3028                 xx = XXCOM;             /* Make this command a comment. */
3029             }
3030             fnsuccess = 1;              /* For catching \function() errors */
3031 #endif /* NOSPL */
3032
3033             debug(F101,"calling docmd()","",xx);
3034             zz = docmd(xx);             /* Parse rest of command & execute. */
3035
3036 #ifndef NOSPL
3037             if (fnerror && !fnsuccess)
3038               success = 0;
3039 #endif /* NOSPL */
3040             debug(F101,"docmd returns","",zz);
3041             /* debug(F011,"cmdbuf",cmdbuf,30); */
3042             /* debug(F011,"atmbuf",atmbuf,30); */
3043 #ifdef MAC
3044             if (tlevel > -1) {
3045                 if (sstate == 'a') {    /* if cmd-. cancel */
3046                     debug(F110, "parser: cancel take, sstate:", "a", 0);
3047                     sstate = '\0';
3048                     dostop();
3049                     return(0);          /* End of init file or whatever. */
3050                 }
3051             }
3052 #endif /* MAC */
3053             switch (zz) {
3054               case -4:                  /* EOF (e.g. on redirected stdin) */
3055                 doexit(GOOD_EXIT,xitsta); /* ...exit successfully */
3056               case -1:                  /* Reparse needed */
3057                 repars = 1;             /* Just set reparse flag and... */
3058                 continue;
3059 #ifdef OS2
3060               case -7:                  /* They typed a disk letter */
3061                 if (!zchdir((char *)cmdbuf)) {
3062                     perror((char *)cmdbuf);
3063                     success = 0;
3064                 } else success = 1;
3065                 repars = 0;
3066                 continue;
3067
3068 #endif /* OS2 */
3069               case -6:                  /* Invalid command given w/no args */
3070               case -2:                  /* Invalid command given w/args */
3071 #ifdef COMMENT
3072 #ifndef NOSPL
3073                     /* This is going to be really ugly... */
3074                     yy = mlook(mactab,atmbuf,nmac); /* Look in macro table */
3075                     if (yy > -1) {                  /* If it's there */
3076                         if (zz == -2) {             /* insert "do" */
3077                             char *mp;
3078                             mp = malloc((int)strlen(cmdbuf) + 5);
3079                             if (!mp) {
3080                                 printf("?malloc error 1\n");
3081                                 return(-2);
3082                             }
3083                             sprintf(mp,"do %s ",cmdbuf); /* SAFE (checked) */
3084                             ckstrncpy(cmdbuf,mp,CMDBL);
3085                             free(mp);
3086                             mp = NULL;
3087                         } else {
3088                             if (((int)strlen(atmbuf) + 5) < CMDBL)
3089                               sprintf(cmdbuf,"do %s %c",atmbuf, CR); /* SAFE */
3090                             else
3091                               ckstrncpy(cmdbuf,"echo ?Too long\r",CMDBL);
3092                         }
3093                         if (ifcmd[cmdlvl] == 2) /* This one doesn't count! */
3094                           ifcmd[cmdlvl]--;
3095                         debug(F111,"stuff cmdbuf",cmdbuf,zz);
3096                         repars = 1;     /* Go for reparse */
3097                         continue;
3098                     } else {
3099                         char *p;
3100                         int n;
3101                         p = cmdbuf;
3102                         lp = line;
3103                         n = LINBUFSIZ;
3104                         if (cmflgs == 0) printf("\n");
3105                         if (zzstring(p,&lp,&n) > -1)
3106                           printf("?Invalid: %s\n",line);
3107                         else
3108                           printf("?Invalid: %s\n",cmdbuf);
3109                     } /* (fall thru...) */
3110 #else
3111                     printf("?Invalid: %s\n",cmdbuf);
3112 #endif /* NOSPL */
3113 #else /* Not COMMENT */
3114                     printf("?Invalid: %s\n",cmdbuf);
3115 #endif /* COMMENT */
3116
3117                 case -9:                /* Bad, error message already done */
3118                     success = 0;
3119                     debug(F110,"top-level cmkey failed",cmdbuf,0);
3120                     /* If in background w/ commands coming stdin, terminate */
3121                     if (pflag == 0 && tlevel < 0)
3122                       fatal("Kermit command error in background execution");
3123 /*
3124   Command retry feature, edit 190.  If we're at interactive prompting level,
3125   reprompt the user with as much of the command as didn't fail.
3126 */
3127 #ifdef CK_RECALL
3128                     if (cm_retry && !xcmdsrc) { /* If at top level */
3129                         int len;
3130                         char *p, *s;
3131                         len = strlen(cmdbuf); /* Length of command buffer */
3132                         p = malloc(len + 1);  /* Allocate space for copy */
3133                         if (p) {              /* If we got the space copy */
3134                             strcpy(p,cmdbuf); /* the command buffer (SAFE). */
3135                             /* Chop off final field, the one that failed. */
3136                             s = p + len - 1;          /* Point to end */
3137                             while (*s == SP && s > p) /* Trim blanks */
3138                               s--;
3139                             while (*s != SP && s > p) /* Trim last field */
3140                               s--;
3141                             if (s > p)        /* Keep the space */
3142                               s++;            /* after last good field */
3143                             if (s >= p)       /* Cut off remainder */
3144                               *s = NUL;
3145                             cmini(ckxech);    /* Reinitialize the parser */
3146                             ckstrncpy(cmdbuf,p,CMDBL); /* Copy result back */
3147                             free(p);          /* Free temporary storage */
3148                             p = NULL;
3149                             prompt(xxstring); /* Reprint the prompt */
3150                             printf("%s",cmdbuf); /* Reprint partial command */
3151                             repars = 1;          /* Force reparse */
3152                             continue;
3153                         }
3154                     } else
3155 #endif /* CK_RECALL */
3156                       if (!quiet) {
3157 #ifdef COMMENT
3158 #ifndef NOSPL
3159                           if (maclvl > -1)
3160                             printf("Macro: %s; ",
3161                                    m_arg[maclvl][0] ?
3162                                    m_arg[maclvl][0] : "");
3163 #endif /* NOSPL */
3164                           if (tlevel > -1)
3165                             printf("Command file: %s, line %d\n",
3166                                    tfnam[tlevel] ? tfnam[tlevel] : "",
3167                                    tfline[tlevel]
3168                                    );
3169 #else
3170                           if (xcmdsrc > 0) {
3171                               printf("Command stack:\n");
3172                               shostack();
3173                           }
3174 #endif /* COMMENT */
3175                       }
3176                       cmini(ckxech);    /* (fall thru) */
3177
3178                 case -3:                /* Empty command OK at top level */
3179                     repars = 0;         /* Don't need to reparse. */
3180                     continue;           /* Go back and get another command. */
3181
3182                 default:                /* Command was successful. */
3183 #ifndef NOSPL
3184                     debug(F101,"parser preparing to continue","",maclvl);
3185 #endif /* NOSPL */
3186                     debug(F101,"parser success","",success);
3187                     repars = 0;         /* Don't need to reparse. */
3188                     continue;           /* Go back and get another command. */
3189                 }
3190         }
3191 #ifndef NOSPL
3192         debug(F101,"parser breaks out of while loop","",maclvl);
3193         if (m && (cmdlvl < inlevel))  return((int) sstate);
3194 #endif /* NOSPL */
3195     }
3196
3197 /* Got an action command, return start state. */
3198
3199     return((int) sstate);
3200 }
3201
3202 #ifndef NOSPL
3203 /*
3204   OUTPUT command.
3205   Buffering and pacing added by L.I. Kirby, 5A(189), June 1993.
3206 */
3207 #define OBSIZE 80                       /* Size of local character buffer */
3208
3209 static int obn;                         /* Buffer offset (high water mark) */
3210 static char obuf[OBSIZE+1];             /* OUTPUT buffer. */
3211 static char *obp;                       /* Pointer to output buffer. */
3212 _PROTOTYP( static int oboc, (char) );
3213 _PROTOTYP( static int xxout, (char *, int) );
3214
3215 static int
3216 #ifdef CK_ANSIC
3217 xxout(char *obuf, int obsize)
3218 #else
3219 xxout(obuf, obsize) char *obuf; int obsize;
3220 #endif /* CK_ANSIC */
3221 /* xxout */ {                           /* OUTPUT command's output function */
3222     int i, rc;
3223
3224     debug(F101,"xxout obsize","",obsize);
3225     debug(F101,"xxout pacing","",pacing);
3226     debug(F111,"xxout string",obuf,strlen(obuf));
3227
3228     rc = 0;                             /* Initial return code. */
3229     if (!obuf || (obsize <= 0))         /* Nothing to output. */
3230       goto xxout_x;                     /* Return successfully */
3231
3232     rc = -1;                              /* Now assume failure */
3233     if (pacing == 0) {                    /* Is pacing enabled? */
3234         if ((local ?                      /* No, write entire string at once */
3235              ttol((CHAR *)obuf, obsize) : /* to communications device */
3236              conxo(obsize, obuf))         /* or to console */
3237             != obsize)
3238           goto xxout_x;
3239     } else {
3240         for (i = 0; i < obsize; i++) {  /* Write individual chars */
3241             if ((local ? ttoc(obuf[i]) : conoc(obuf[i])) < 0)
3242               goto xxout_x;
3243             msleep(pacing);
3244         }
3245     }
3246     if (duplex) {
3247 #ifdef OS2
3248         if (inecho && local) {
3249 #ifndef NOLOCAL
3250             for (i = 0; i < obsize; i++) { /* Write to emulator */
3251                 scriptwrtbuf((USHORT)obuf[i]); /* which also logs session */
3252             }
3253 #endif /* NOLOCAL */
3254             conxo(obsize,obuf);
3255         } else if (seslog) {            /* or log session here */
3256             logstr((char *) obuf, obsize);
3257         }
3258 #else /* OS2 */
3259         if (seslog) {
3260             logstr((char *) obuf, obsize);
3261         }
3262         if (inecho && local) {
3263             conxo(obsize,obuf);
3264         }
3265 #endif /* OS2 */
3266     }
3267     rc = 0;                             /* Success */
3268   xxout_x:
3269     obn = 0;                            /* Reset count */
3270     obp = obuf;                         /* and pointers */
3271     return(rc);                         /* return our return code */
3272 }
3273
3274 #ifdef COMMENT
3275 /*
3276   Macros for OUTPUT command execution, to make it go faster.
3277 */
3278 #define obfls() ((xxout(obuf,obn)<0)?-1:0)
3279 #define oboc(c) ((*obp++=(char)(c)),*obp=0,(((++obn)>=OBSIZE)?obfls():0))
3280
3281 #else /* The macros cause some compilers to generate bad code. */
3282
3283 static int
3284 #ifdef CK_ANSIC
3285 oboc(char c)
3286 #else
3287 oboc(c) char c;
3288 #endif /* CK_ANSIC */
3289 /* oboc */ {                            /* OUTPUT command's output function */
3290
3291     *obp++ = c;                         /* Deposit character */
3292     *obp = NUL;                         /* Flush buffer if it's now full */
3293
3294     return(((++obn) >= OBSIZE) ? xxout(obuf,obn) : 0);
3295 }
3296 #endif /* COMMENT */
3297
3298 /*  Routines for handling local variables -- also see popclvl().  */
3299
3300 VOID
3301 freelocal(m) int m; {                   /* Free local variables */
3302     struct localvar * v, * tv;          /* at macro level m... */
3303     debug(F101,"freelocal level","",m);
3304     if (m < 0) return;
3305     v = localhead[m];                   /* List head for level m */
3306     while (v) {
3307         if (v->lv_name)                 /* Variable name */
3308           free(v->lv_name);
3309         if (v->lv_value)                /* Value */
3310           free(v->lv_value);
3311         tv = v;                         /* Save pointer to this node */
3312         v = v->lv_next;                 /* Get next one */
3313         if (tv)                         /* Free this one */
3314           free((char *)tv);
3315     }
3316     localhead[m] = (struct localvar *) NULL; /* Done, set list head to NULL */
3317 }
3318
3319 #define MAXLOCALVAR 64
3320
3321 /* Return a pointer to the definition of a user-defined variable */
3322
3323 static char *
3324 vardef(s,isarray,x1,x2) char * s; int * isarray, * x1, * x2; {
3325     char * p;
3326     char c;
3327     *isarray = 0;
3328     if (!s) return(NULL);
3329     if (!*s) return(NULL);
3330     p = s;
3331     if (*s == CMDQ) {
3332         p++;
3333         if (!*p)
3334           return(NULL);
3335         if ((c = *p) == '%') {          /* Scalar variable. */
3336             c = *++p;                   /* Get ID character. */
3337             p = "";                     /* Assume definition is empty */
3338             if (!c)
3339               return(NULL);
3340             if (c >= '0' && c <= '9') { /* Digit for macro arg */
3341                 if (maclvl < 0)         /* Digit variables are global */
3342                   return(g_var[c]);     /* if no macro is active */
3343                 else                    /* otherwise */
3344                   return(m_arg[maclvl][c - '0']); /* they're on the stack */
3345             } else if (isalpha(c)) {
3346                 if (isupper(c)) c -= ('a'-'A');
3347                 return(g_var[c]);           /* Letter for global variable */
3348             } else
3349               return(NULL);
3350         } else if (c == '&') {          /* Array reference. */
3351             int x, vbi, d;
3352             x = arraynam(p,&vbi,&d);    /* Get name and subscript */
3353             if (x > -1 || d == -17) {
3354                 *isarray = 1;
3355                 *x1 = vbi;
3356                 *x2 = (d == -17) ? 0 : d;
3357             }
3358             if (x < 0)
3359               return(NULL);
3360             if (chkarray(vbi,d) > 0) {  /* Array is declared? */
3361                 vbi -= ARRAYBASE;       /* Convert name to index */
3362                 if (a_dim[vbi] >= d) {  /* If subscript in range */
3363                     char **ap;
3364                     ap = a_ptr[vbi];
3365                     return((ap) ? ap[d] : NULL);
3366                 }
3367             }
3368         }
3369         return(NULL);
3370     } else {
3371         int k;
3372         k = mxlook(mactab,s,nmac);
3373         return((k > -1) ? mactab[k].mval : NULL);
3374     }
3375 }
3376
3377
3378 int
3379 addlocal(p) char * p; {
3380     int x, z, isarray = 0;
3381     char * s;
3382     struct localvar * v, *prev = (struct localvar *)NULL;
3383     extern int tra_asg; int tra_tmp;
3384
3385     tra_tmp = tra_asg;
3386
3387     s = vardef(p,&isarray,&x,&z);       /* Get definition of variable */
3388     if (isarray) {                      /* Arrays are handled specially */
3389         pusharray(x,z);
3390         return(0);
3391     }
3392     if (!s) s = "";
3393     if ((v = localhead[cmdlvl])) {      /* Already have some at this level? */
3394         while (v) {                     /* Find end of list */
3395             prev = v;
3396             v = v->lv_next;
3397         }
3398     }
3399     v = (struct localvar *) malloc(sizeof(struct localvar));
3400     if (!v) {
3401         printf("?Failure to allocate storage for local variables");
3402         return(-9);
3403     }
3404     if (!localhead[cmdlvl])             /* If first, set list head */
3405       localhead[cmdlvl] = v;
3406     else                                /* Otherwise link previous to this */
3407       prev->lv_next = v;
3408     prev = v;                           /* And make this previous */
3409     v->lv_next = (struct localvar *) NULL; /* No next yet */
3410
3411     if (!(v->lv_name = (char *) malloc((int) strlen(p) + 1)))
3412       return(-1);
3413     strcpy(v->lv_name, p);              /* Copy name into new node (SAFE) */
3414
3415     if (*s) {
3416         if (!(v->lv_value = (char *) malloc((int) strlen(s) + 1)))
3417           return(-1);
3418         strcpy(v->lv_value, s);         /* Copy value into new node (SAFE) */
3419     } else
3420       v->lv_value = NULL;
3421
3422     tra_asg = 0;
3423     delmac(p,1);                        /* Delete the original macro */
3424     tra_asg = tra_tmp;
3425     return(0);
3426 }
3427
3428 int
3429 dolocal() {                             /* Do the LOCAL command */
3430     int i, x;
3431     char * s;
3432     char * list[MAXLOCALVAR+2];         /* Up to 64 variables per line */
3433
3434     if ((x = cmtxt("Variable name(s)","",&s,NULL)) < 0)
3435       return(x);
3436
3437     xwords(s,MAXLOCALVAR,list,0);       /* Break up line into "words" */
3438
3439     /* Note: Arrays do not use the localhead list, but have their own stack */
3440
3441     for (i = 1; i < MAXLOCALVAR && list[i]; i++) { /* Go through the list */
3442         if (addlocal(list[i]) < 0)
3443           goto localbad;
3444     }
3445     return(success = 1);
3446
3447   localbad:
3448     printf("?Failure to allocate storage for local variables");
3449     freelocal(cmdlvl);
3450     return(-9);
3451 }
3452
3453 /*  D O O U T P U T  --  Returns 0 on failure, 1 on success */
3454
3455 #ifndef NOKVERBS
3456 #define K_BUFLEN 30
3457 #define SEND_BUFLEN 255
3458 #define sendbufd(x) { osendbuf[sendndx++] = x;\
3459  if (sendndx == SEND_BUFLEN) {dooutput(s,cx); sendndx = 0;}}
3460 #endif /* NOKVERBS */
3461
3462 int outesc = 1;                         /* Process special OUTPUT escapes */
3463
3464 int
3465 dooutput(s, cx) char *s; int cx; {
3466 #ifdef SSHBUILTIN
3467     extern int ssh_cas;
3468     extern char * ssh_cmd;
3469 #endif /* SSHBUILTIN */
3470     int x, xx, y, quote;                /* Workers */
3471     int is_tn = 0;
3472
3473     is_tn = (local && network && IS_TELNET()) ||
3474       (!local && sstelnet);
3475
3476     debug(F111,"dooutput s",s,(int)strlen(s));
3477
3478     if (local) {                        /* Condition external line */
3479 #ifdef NOLOCAL
3480         goto outerr;
3481 #else
3482         if (ttchk() < 0) {
3483             printf("?Connection %s %s is not open.\n",
3484                    network ? "to" : "on",
3485                    ttname
3486                    );
3487             return(0);
3488         }
3489         if (ttvt(speed,flow) < 0) {
3490             printf("?OUTPUT initialization error\n");
3491             return(0);
3492         }
3493 #endif /* NOLOCAL */
3494     }
3495 #ifdef SSHBUILTIN
3496     if ( network && nettype == NET_SSH && ssh_cas && ssh_cmd && 
3497          !(strcmp(ssh_cmd,"kermit") && strcmp(ssh_cmd,"sftp"))) {
3498         if (!quiet)
3499             printf("?SSH Subsystem active: %s\n", ssh_cmd);
3500         return(0);
3501     }
3502 #endif /* SSHBUILTIN */
3503
3504     if (!cmdgquo()) {                   /* COMMAND QUOTING OFF */
3505         x = strlen(s);                  /* Just send the string literally */
3506         xx = local ? ttol((CHAR *)s,x) : conxo(x,s);
3507         return(success = (xx == x) ? 1 : 0);
3508     }
3509     quote = 0;                          /* Initialize backslash (\) quote */
3510     obn = 0;                            /* Reset count */
3511     obp = obuf;                         /* and pointers */
3512
3513   outagain:
3514     while ((x = *s++)) {                /* Loop through the string */
3515         y = 0;                          /* Error code, 0 = no error. */
3516         debug(F000,"dooutput","",x);
3517         if (quote) {                    /* This character is quoted */
3518 #ifndef NOKVERBS
3519            if (x == 'k' || x == 'K') {  /* \k or \K */
3520                extern struct keytab kverbs[];
3521                extern int nkverbs;
3522                extern char * keydefptr;
3523                extern int keymac;
3524                extern int keymacx;
3525                int x, y, brace = 0;
3526                int pause;
3527                char * p, * b;
3528                char kbuf[K_BUFLEN + 1]; /* Key verb name buffer */
3529                char osendbuf[SEND_BUFLEN +1];
3530                int  sendndx = 0;
3531
3532                if (xxout(obuf,obn) < 0) /* Flush buffer */
3533                  goto outerr;
3534                debug(F100,"OUTPUT KVERB","",0); /* Send a KVERB */
3535                {                        /* Have K verb? */
3536                    if (!*s) {
3537                        break;
3538                    }
3539 /*
3540   We assume that the verb name is {braced}, or it extends to the end of the
3541   string, s, or it ends with a space, control character, or backslash.
3542 */
3543                    p = kbuf;            /* Copy verb name into local buffer */
3544                    x = 0;
3545                    while ((x++ < K_BUFLEN) && (*s > SP) && (*s != CMDQ)) {
3546                        if (brace && *s == '}') {
3547                            break;
3548                        }
3549                        *p++ = *s++;
3550                    }
3551                    if (*s && !brace)    /* If we broke because of \, etc, */
3552                      s--;               /*  back up so we get another look. */
3553                    brace = 0;
3554                    *p = NUL;            /* Terminate. */
3555                    p = kbuf;            /* Point back to beginning */
3556                    debug(F110,"dooutput kverb",p,0);
3557                    y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
3558                    debug(F101,"dooutput lookup",0,y);
3559                    if (y > -1) {
3560                        if (sendndx) {
3561                            dooutput(osendbuf,cx);
3562                            sendndx = 0;
3563                        }
3564                        dokverb(VCMD,y);
3565 #ifndef NOSPL
3566                    } else {             /* Is it a macro? */
3567                        y = mxlook(mactab,p,nmac);
3568                        if (y > -1) {
3569                            cmpush();
3570                            keymac = 1;  /* Flag for key macro active */
3571                            keymacx = y; /* Key macro index */
3572                            keydefptr = s; /* Where to resume next time */
3573                            debug(F111,"dooutput mxlook",keydefptr,y);
3574                            parser(1);
3575                            cmpop();
3576                        }
3577 #endif /* NOSPL */
3578                    }
3579                }
3580                quote = 0;
3581                continue;
3582            } else
3583 #endif /* NOKVERBS */
3584              if (outesc && (x == 'n' || x == 'N')) { /* \n or \N */
3585                  if (xxout(obuf,obn) < 0) /* Flush buffer */
3586                    goto outerr;
3587                  debug(F100,"OUTPUT NUL","",0); /* Send a NUL */
3588                  if (local)
3589                    ttoc(NUL);
3590                  else
3591                    conoc(NUL);
3592                  quote = 0;
3593                  continue;
3594
3595              } else if (outesc && (x == 'b' || x == 'B')) { /* \b or \B */
3596
3597                 if (xxout(obuf,obn) < 0) /* Flush buffer first */
3598                   goto outerr;
3599                 debug(F100,"OUTPUT BREAK","",0);
3600 #ifndef NOLOCAL
3601                 ttsndb();               /* Send BREAK signal */
3602 #else
3603                  if (local)
3604                    ttoc(NUL);
3605                  else
3606                    conoc(NUL);
3607 #endif /* NOLOCAL */
3608                 quote = 0;              /* Turn off quote flag */
3609                 continue;               /* and not the b or B */
3610 #ifdef CK_LBRK
3611              } else if (outesc && (x == 'l' || x == 'L')) { /* \l or \L */
3612                  if (xxout(obuf,obn) < 0) /* Flush buffer first */
3613                    goto outerr;
3614                  debug(F100,"OUTPUT Long BREAK","",0);
3615 #ifndef NOLOCAL
3616                  ttsndlb();             /* Send Long BREAK signal */
3617 #else
3618                  if (local)
3619                    ttoc(NUL);
3620                  else
3621                    conoc(NUL);
3622 #endif /* NOLOCAL */
3623                  quote = 0;             /* Turn off quote flag */
3624                  continue;              /* and not the l or L */
3625 #endif /* CK_LBRK */
3626
3627              } else if (x == CMDQ) {    /* Backslash itself */
3628                  debug(F100,"OUTPUT CMDQ","",0);
3629                  xx = oboc(dopar(CMDQ)); /* Output the backslash. */
3630                  if (xx < 0)
3631                    goto outerr;
3632                  quote = 0;
3633                  continue;
3634
3635              } else {                   /* if \ not followed by special esc */
3636                 /* Note: Atari ST compiler won't allow macro call in "if ()" */
3637                  xx = oboc(dopar(CMDQ)); /* Output the backslash. */
3638                  if (xx < 0)
3639                    goto outerr;
3640                  quote = 0;             /* Turn off quote flag */
3641              }
3642         } else if (x == CMDQ) {         /* This is the quote character */
3643             quote = 1;                  /* Go back and get next character */
3644             continue;                   /* which is quoted */
3645         }
3646         xx = oboc(dopar((char)x));      /* Output this character */
3647         debug(F111,"dooutput",obuf,obn);
3648         if (xx < 0)
3649           goto outerr;
3650 #ifdef COMMENT
3651         if (seslog && duplex) {         /* Log the character if log is on */
3652             logchar((char)x);
3653         }
3654 #endif /* COMMENT */
3655         if (x == '\015') {              /* String contains carriage return */
3656             int stuff = -1, stuff2 = -1;
3657             if (tnlm) {                 /* TERMINAL NEWLINE ON */
3658                 stuff = LF;             /* Stuff LF */
3659             }
3660 #ifdef TNCODE
3661             /* TELNET NEWLINE ON/OFF/RAW */
3662             if (is_tn) {
3663                 switch (TELOPT_ME(TELOPT_BINARY) ? /* NVT or BINARY */
3664                         tn_b_nlm :
3665                         tn_nlm
3666                         ) {
3667                   case TNL_CR:
3668                     break;
3669                   case TNL_CRNUL:
3670                     stuff2 = stuff;
3671                     stuff  = NUL;
3672                     break;
3673                   case TNL_CRLF:
3674                     stuff2 = stuff;
3675                     stuff = LF;
3676                     break;
3677                 }
3678             }
3679 #endif /* TNCODE */
3680             if (stuff > -1) {           /* Stuffing another character... */
3681                 xx = oboc(dopar((CHAR)stuff));
3682                 if (xx < 0)
3683                   goto outerr;
3684 #ifdef COMMENT
3685                 if (seslog && duplex) { /* Log stuffed char if appropriate */
3686                     logchar((char)stuff);
3687                 }
3688 #endif /* COMMENT */
3689             }
3690             if (stuff2 > -1) {          /* Stuffing another character... */
3691                 xx = oboc(dopar((CHAR)stuff2));
3692                 if (xx < 0)
3693                   goto outerr;
3694 #ifdef COMMENT
3695                 if (seslog && duplex) { /* Log stuffed char if appropriate */
3696                     logchar((char)stuff2);
3697                 }
3698 #endif /* COMMENT */
3699             }
3700             if (xxout(obuf,obn) < 0)    /* Flushing is required here! */
3701               goto outerr;
3702         }
3703     }
3704     if (cx == XXLNOUT) {
3705         s = "\015";
3706         cx = 0;
3707         goto outagain;
3708     }
3709     if (quote == 1)                     /* String ended with backslash */
3710       xx = oboc(dopar(CMDQ));
3711
3712     if (obn > 0)                        /* OUTPUT done */
3713       if (xxout(obuf,obn) < 0)          /* Flush the buffer if necessary. */
3714         goto outerr;
3715     return(1);
3716
3717 outerr:                                 /* OUTPUT command error handler */
3718     if (msgflg) printf("?OUTPUT execution error\n");
3719     return(0);
3720
3721 /* Remove "local" OUTPUT macro defininitions */
3722
3723 #ifdef COMMENT
3724 /* No more macros ... */
3725 #undef oboc
3726 #undef obfls
3727 #endif /* COMMENT */
3728 }
3729 #endif /* NOSPL */
3730
3731 /* Display version herald and initial prompt */
3732
3733 VOID
3734 herald() {
3735     int x = 0, i;
3736     extern int srvcdmsg;
3737     extern char * cdmsgfile[];
3738 #ifndef NOCMDL
3739     extern char * bannerfile;
3740     debug(F110,"herald bannerfile",bannerfile,0);
3741     if (bannerfile) {
3742         concb((char)escape);
3743         if (dotype(bannerfile,1,0,0,NULL,0,NULL,0,0,NULL,0) > 0) {
3744             debug(F111,"herald","srvcdmsg",srvcdmsg);
3745             if (srvcdmsg) {
3746                 for (i = 0; i < 8; i++) {
3747                     debug(F111,"herald cdmsgfile[i]",cdmsgfile[i],i);
3748                     if (zchki(cdmsgfile[i]) > -1) {
3749                         printf("\n");
3750                         dotype(cdmsgfile[i],
3751                                xaskmore,0,0,NULL,0,NULL,0,0,NULL,0);
3752                         break;
3753                     }
3754                 }
3755             }
3756             return;
3757         }
3758     }
3759 #endif /* NOCMDL */
3760
3761 #ifdef COMMENT
3762     /* The following generates bad code in SCO compilers. */
3763     /* Observed in both OSR5 and Unixware 2 -- after executing this */
3764     /* statement when all conditions are false, x has a value of -32. */
3765     if (noherald || bgset > 0 || (bgset != 0 && backgrd != 0)) x = 1;
3766 #else
3767     x = 0;
3768     if (noherald)
3769       x = 1;
3770     else if (bgset > 0)
3771       x = 1;
3772     else if (bgset < 0 && backgrd > 0)
3773       x = 1;
3774 #endif /* COMMENT */
3775
3776     if (x == 0) {
3777 #ifdef datageneral
3778         printf("%s, for%s\n",versio,ckxsys);
3779 #else
3780 #ifdef OSK
3781         printf("%s, for%s\n",versio,ckxsys);
3782 #else
3783         printf("%s, for%s\n\r",versio,ckxsys);
3784 #endif /* OSK */
3785 #endif /* datageneral */
3786         printf(" Copyright (C) 1985, 2004,\n");
3787         printf("  Trustees of Columbia University in the City of New York.\n");
3788 #ifdef OS2
3789        shoreg();
3790 #endif /* OS2 */
3791
3792         if (!quiet && !backgrd) {
3793 #ifdef COMMENT
3794 /* "Default file-transfer mode is AUTOMATIC" is useless information... */
3795             char * s;
3796             extern int xfermode;
3797 #ifdef VMS
3798             s = "AUTOMATIC";
3799 #else
3800             if (xfermode == XMODE_A) {
3801                 s = "AUTOMATIC";
3802             } else {
3803                 s = gfmode(binary,1);
3804             }
3805             if (!s) s = "";
3806 #endif /* VMS */
3807             if (*s)
3808               printf("Default file-transfer mode is %s\n", s);
3809 #endif /* COMMENT */
3810
3811             debug(F111,"herald","srvcdmsg",srvcdmsg);
3812             if (srvcdmsg) {
3813                 for (i = 0; i < 8; i++) {
3814                     debug(F111,"herald cdmsgfile[i]",cdmsgfile[i],i);
3815                     if (zchki(cdmsgfile[i]) > -1) {
3816                         printf("\n");
3817                         dotype(cdmsgfile[i],
3818                                xaskmore,0,0,NULL,0,NULL,0,0,NULL,0);
3819                         break;
3820                     }
3821                 }
3822             }
3823             printf("Type ? or HELP for help.\n");
3824         }
3825     }
3826 }
3827
3828 /*  G F M O D E  --  Get File (transfer) Mode  */
3829
3830 char *
3831 gfmode(binary,upcase) int binary, upcase; {
3832     char * s;
3833     switch (binary) {
3834       case XYFT_T: s = upcase ? "TEXT" : "text"; break;
3835 #ifdef VMS
3836       case XYFT_B: s = upcase ? "BINARY FIXED" : "binary fixed"; break;
3837       case XYFT_I: s = upcase ? "IMAGE" : "image"; break;
3838       case XYFT_L: s = upcase ? "LABELED" : "labeled"; break;
3839       case XYFT_U: s = upcase ? "BINARY UNDEF" : "binary undef"; break;
3840 #else
3841 #ifdef MAC
3842       case XYFT_B: s = upcase ? "BINARY" : "binary"; break;
3843       case XYFT_M: s = upcase ? "MACBINARY" : "macbinary"; break;
3844 #else
3845       case XYFT_B: s = upcase ? "BINARY" : "binary"; break;
3846 #ifdef CK_LABELED
3847       case XYFT_L: s = upcase ? "LABELED" : "labeled"; break;
3848 #endif /* CK_LABELED */
3849 #endif /* MAC */
3850 #endif /* VMS */
3851       case XYFT_X: s = upcase ? "TENEX" : "tenex"; break;
3852       default: s = "";
3853     }
3854     return(s);
3855 }
3856
3857 #ifndef NOSPL
3858 static int
3859 isaa(s) char * s; {                     /* Is associative array */
3860     char c;
3861     int x;
3862     if (!s) s = "";
3863     if (!*s) return(0);
3864     s++;
3865     while ((c = *s++)) {
3866         if (c == '<') {
3867             x = strlen(s);
3868             return ((*(s+x-1) == '>') ? 1 : 0);
3869         }
3870     }
3871     return(0);
3872 }
3873
3874 /*  M L O O K  --  Lookup the macro name in the macro table  */
3875
3876 /*
3877   Call this way:  v = mlook(table,word,n);
3878
3879     table - a 'struct mtab' table.
3880     word  - the target string to look up in the table.
3881     n     - the number of elements in the table.
3882
3883   The keyword table must be arranged in ascending alphabetical order, and
3884   all letters must be lowercase.
3885
3886   Returns the table index, 0 or greater, if the name was found, or:
3887
3888    -3 if nothing to look up (target was null),
3889    -2 if ambiguous,
3890    -1 if not found.
3891
3892   A match is successful if the target matches a keyword exactly, or if
3893   the target is a prefix of exactly one keyword.  It is ambiguous if the
3894   target matches two or more keywords from the table.
3895 */
3896 int
3897 mlook(table,cmd,n) struct mtab table[]; char *cmd; int n; {
3898     register int i;
3899     int v, w, cmdlen = 0;
3900     char c = 0, c1, * s;
3901     if (!cmd) cmd = "";
3902
3903     for (s = cmd; *s; s++) cmdlen++;    /* (instead of strlen) */
3904     debug(F111,"MLOOK",cmd,cmdlen);
3905
3906     c1 = *cmd;
3907     if (isupper(c1))
3908       c1 = tolower(c1);
3909     if (cmdlen < 1)
3910       return(-3);
3911
3912 /* Not null, look it up */
3913
3914     if (n < 12) {                       /* Not worth it for small tables */
3915         i = 0;
3916     } else {                            /* Binary search for where to start */
3917         int lo = 0;
3918         int hi = n;
3919         int count = 0;
3920         while (lo+2 < hi && ++count < 12) {
3921             i = lo + ((hi - lo) / 2);
3922             c = *(table[i].kwd);
3923             if (isupper(c)) c = tolower(c);
3924             if (c < c1) {
3925                 lo = i;
3926             } else {
3927                 hi = i;
3928             }
3929         }
3930         i = (c < c1) ? lo+1 : lo;
3931     }
3932     for ( ; i < n-1; i++) {
3933         s = table[i].kwd;
3934         if (!s) s = "";
3935         if (!*s) continue;              /* Empty table entry */
3936         c = *s;
3937         if (isupper(c)) c = tolower(c);
3938         if (c1 != c) continue;          /* First char doesn't match */
3939         if (!ckstrcmp(s,cmd,-1,0))      /* Have exact match? */
3940           return(i);
3941         v = !ckstrcmp(s,cmd,cmdlen,0);
3942         w = ckstrcmp(table[i+1].kwd,cmd,cmdlen,0);
3943         if (v && w)                     /* Have abbreviated match? */
3944           return(i);
3945         if (v)                          /* Ambiguous? */
3946           return(-2);
3947         if (w > 0)                      /* Past our alphabetic area? */
3948           return(-1);
3949     }
3950
3951 /* Last (or only) element */
3952
3953     if (!ckstrcmp(table[n-1].kwd,cmd,cmdlen,0))
3954       return(n-1);
3955
3956     return(-1);
3957 }
3958
3959 /* mxlook is like mlook, but an exact full-length match is required */
3960
3961 int
3962 mxlook(table,cmd,n) char *cmd; struct mtab table[]; int n; {
3963     register int i;
3964     int w, cmdlen = 0, one = 0;
3965     register char c = 0, c1, * s;
3966
3967     if (!cmd) cmd = "";                 /* Check args */
3968
3969     for (s = cmd; *s; s++) cmdlen++;    /* (instead of strlen) */
3970     debug(F111,"MXLOOK",cmd,cmdlen);
3971
3972     c1 = *cmd;                          /* First char of string to look up */
3973     if (isupper(c1))
3974       c1 = tolower(c1);
3975     if (!*(cmd+1))                      /* Special handling for 1-char names */
3976       one = 1;
3977
3978     if (cmdlen < 1)                     /* Nothing to look up */
3979       return(-3);
3980
3981     if (n < 12) {                       /* Not worth it for small tables */
3982         i = 0;
3983     } else {                            /* Binary search for where to start */
3984         int lo = 0;
3985         int hi = n;
3986         int count = 0;
3987         while (lo+2 < hi && ++count < 12) {
3988             i = lo + ((hi - lo) / 2);
3989             c = *(table[i].kwd);
3990             if (isupper(c)) c = tolower(c);
3991             if (c < c1) {
3992                 lo = i;
3993             } else {
3994                 hi = i;
3995             }
3996         }
3997         i = (c < c1) ? lo+1 : lo;
3998     }
3999     for ( ; i < n; i++) {               /* Look thru table */
4000         s = table[i].kwd;               /* This entry */
4001         if (!s) s = "";
4002         if (!*s) continue;              /* Empty table entry */
4003         c = *s;
4004         if (isupper(c)) c = tolower(c);
4005         if (c1 != c) continue;          /* First char doesn't match */
4006         if (one) {                      /* Name is one char long */
4007             if (!*(s+1))
4008               return(i);                /* So is table entry */
4009         }
4010 #ifdef COMMENT
4011         if (((int)strlen(s) == cmdlen) &&
4012             (!ckstrcmp(s,cmd,cmdlen,0))) return(i);
4013 #else
4014         w = ckstrcmp(s,cmd,-1,0);
4015         if (!w) return(i);
4016         if (w > 0) return(-1);
4017 #endif /* COMMENT */
4018     }
4019     return(-1);
4020 }
4021
4022 /* mxxlook is like mxlook, but case-sensitive */
4023
4024 int
4025 mxxlook(table,cmd,n) char *cmd; struct mtab table[]; int n; {
4026     int i, cmdlen;
4027     if (!cmd) cmd = "";
4028     if (((cmdlen = strlen(cmd)) < 1) || (n < 1)) return(-3);
4029     /* debug(F111,"mxxlook target",cmd,n); */
4030     for (i = 0; i < n; i++) {
4031         if (((int)strlen(table[i].kwd) == cmdlen) &&
4032             (!strncmp(table[i].kwd,cmd,cmdlen)))
4033           return(i);
4034     }
4035     return(-1);
4036 }
4037
4038 static int
4039 traceval(nam, val) char * nam, * val; { /* For TRACE command */
4040     if (val)
4041       printf(">>> %s: \"%s\"\n", nam, val);
4042     else
4043       printf(">>> %s: (undef)\n", nam);
4044     return(0);
4045 }
4046
4047 #ifdef USE_VARLEN                       /* Not used */
4048
4049 /*  V A R L E N  --  Get length of variable's value.
4050
4051   Given a variable name, return the length of its definition or 0 if the
4052   variable is not defined.  If it is defined, set argument s to point to its
4053   definition.  Otherwise set s to NULL.
4054 */
4055 int
4056 varlen(nam,s) char *nam; char **s; {    /* Length of value of variable */
4057     int x, z;
4058     char *p = NULL, c;
4059
4060     *s = NULL;
4061     if (!nam) return(0);                /* Watch out for null pointer */
4062     if (*nam == CMDQ) {
4063         nam++;
4064         if (*nam == '%') {              /* If it's a variable name */
4065             if (!(c = *(nam+1))) return(0); /* Get letter or digit */
4066             p = (char *)0;              /* Initialize value pointer */
4067             if (maclvl > -1 && c >= '0' && c <= '9') { /* Digit? */
4068                 p = m_arg[maclvl][c - '0']; /* Pointer from macro-arg table */
4069             } else {                    /* It's a global variable */
4070                 if (c < 33 || c > GVARS) return(0);
4071                 p = g_var[c];           /* Get pointer from global-var table */
4072             }
4073         } else if (*nam == '&') {               /* An array reference? */
4074             char **q;
4075             if (arraynam(nam,&x,&z) < 0) /* If syntax is bad */
4076               return(-1);               /* return -1. */
4077             x -= ARRAYBASE;             /* Convert name to number. */
4078             if ((q = a_ptr[x]) == NULL) /* If array not declared, */
4079               return(0);                /* return -2. */
4080             if (z > a_dim[x])           /* If subscript out of range, */
4081               return(0);                /* return -3. */
4082             p = q[z];
4083         }
4084     } else {                            /* Macro */
4085         z = isaa(nam);
4086         x = z ? mxxlook(mactab,nam,nmac) : mlook(mactab,nam,nmac);
4087         if (x < 0)
4088           return(0);
4089         p = mactab[x].mval;
4090     }
4091     if (p)
4092       *s = p;
4093     else
4094       p = "";
4095     return((int)strlen(p));
4096 }
4097 #endif /* USE_VARLEN */
4098
4099 /*
4100   This routine is for the benefit of those compilers that can't handle
4101   long string constants or continued lines within them.  Long predefined
4102   macros like FOR, WHILE, and XIF have their contents broken up into
4103   arrays of string pointers.  This routine concatenates them back into a
4104   single string again, and then calls the real addmac() routine to enter
4105   the definition into the macro table.
4106 */
4107 int
4108 addmmac(nam,s) char *nam, *s[]; {       /* Add a multiline macro definition */
4109     int i, x, y; char *p;
4110     x = 0;                              /* Length counter */
4111     for (i = 0; (y = (int)strlen(s[i])) > 0; i++) { /* Add up total length */
4112         debug(F111,"addmmac line",s[i],y);
4113         x += y;
4114     }
4115     debug(F101,"addmmac lines","",i);
4116     debug(F101,"addmmac loop exit","",y);
4117     debug(F111,"addmmac length",nam,x);
4118     if (x < 0) return(-1);
4119
4120     p = malloc(x+1);                    /* Allocate space for all of it. */
4121     if (!p) {
4122         printf("?addmmac malloc error: %s\n",nam);
4123         debug(F110,"addmmac malloc error",nam,0);
4124         return(-1);
4125     }
4126     *p = '\0';                          /* Start off with null string. */
4127     for (i = 0; *s[i]; i++)             /* Concatenate them all together. */
4128       ckstrncat(p,s[i],x+1);
4129     y = (int)strlen(p);                 /* Final precaution. */
4130     debug(F111,"addmmac constructed string",p,y);
4131     if (y == x) {
4132         y = addmac(nam,p);              /* Add result to the macro table. */
4133     } else {
4134         debug(F100,"addmmac length mismatch","",0);
4135         printf("\n!addmmac internal error!\n");
4136         y = -1;
4137     }
4138     free(p);                            /* Free the temporary copy. */
4139     return(y);
4140 }
4141
4142 /* Here is the real addmac routine. */
4143
4144 /* Returns -1 on failure, macro table index >= 0 on success. */
4145
4146 int mtchanged = 0;
4147
4148 int
4149 addmac(nam,def) char *nam, *def; {      /* Add a macro to the macro table */
4150     int i, x, y, z, namlen, deflen, flag = 0;
4151     int replacing = 0, deleting = 0;
4152     char * p = NULL, c, *s;
4153     extern int tra_asg; int tra_tmp;
4154
4155     if (!nam) return(-1);
4156     if (!*nam) return(-1);
4157
4158 #ifdef IKSD
4159     if (inserver &&
4160 #ifdef IKSDCONF
4161         iksdcf
4162 #else /* IKSDCONF */
4163         1
4164 #endif /* IKSDCONF */
4165         ) {
4166         if (!ckstrcmp("on_exit",nam,-1,0) ||
4167             !ckstrcmp("on_logout",nam,-1,0))
4168           return(-1);
4169     }
4170 #endif /* IKSD */
4171
4172     namlen = 0;
4173     p = nam;
4174     while (*p++) namlen++;              /* (instead of strlen) */
4175
4176     tra_tmp = tra_asg;                  /* trace... */
4177     debug(F111,"addmac nam",nam,namlen);
4178     if (!def) {                         /* Watch out for null pointer */
4179         deflen = 0;
4180         debug(F111,"addmac def","(null pointer)",deflen);
4181     } else {
4182         deflen = 0;
4183         p = def;
4184         while (*p++) deflen++;          /* (instead of strlen) */
4185         debug(F010,"addmac def",def,0);
4186     }
4187 #ifdef USE_VARLEN                       /* NOT USED */
4188     /* This does not boost performance much because varlen() does a lot */
4189     x = varlen(nam,&s);
4190     if (x > 0 && x >= deflen) {
4191         strcpy(s,def);                  /* NOT USED */
4192         flag = 1;
4193         p = s;
4194     }
4195 #endif /* USE_VARLEN */
4196
4197     if (*nam == CMDQ) nam++;            /* Backslash quote? */
4198     if (*nam == '%') {                  /* Yes, if it's a variable name, */
4199         if (!(c = *(nam + 1))) return(-1); /* Variable name letter or digit */
4200         if (!flag) {
4201             tra_asg = 0;
4202             delmac(nam,0);              /* Delete any old value. */
4203             tra_asg = tra_tmp;
4204         }
4205         if (deflen < 1) {               /* Null definition */
4206             p = NULL;                   /* Better not malloc or strcpy! */
4207         } else if (!flag) {             /* A substantial definition */
4208             p = malloc(deflen + 1);     /* Allocate space for it */
4209             if (!p) {
4210                 printf("?addmac malloc error 2\n");
4211                 return(-1);
4212             } else strcpy(p,def);       /* Copy def into new space (SAFE) */
4213         }
4214
4215         /* Now p points to the definition, or is a null pointer */
4216
4217         if (c >= '0' && c <= '9') {     /* \%0-9 variable */
4218             if (maclvl < 0) {           /* Are we calling or in a macro? */
4219                 g_var[c] = p;           /* No, it's top level one */
4220                 makestr(&(toparg[c - '0']),p); /* Take care \&_[] too */
4221             } else {                    /* Yes, it's a macro argument */
4222                 m_arg[maclvl][c - '0'] = p; /* Assign the value */
4223                 makestr(&(m_xarg[maclvl][c - '0']),p); /* And a copy here */
4224             }
4225         } else {                        /* It's a \%a-z variable */
4226             if (c < 33 || (unsigned int)c > GVARS) return(-1);
4227             if (isupper(c)) c = (char) tolower(c);
4228             g_var[c] = p;               /* Put pointer in global-var table */
4229         }
4230         if (tra_asg) traceval(nam,p);
4231         return(0);
4232     } else if (*nam == '&') {           /* An array reference? */
4233         char **q = NULL;
4234         int rc = 0;
4235         if ((y = arraynam(nam,&x,&z)) < 0) /* If syntax is bad */
4236           return(-1);                   /* return -1. */
4237         if (chkarray(x,z) < 0)          /* If array not declared or */
4238           rc = -2;                      /* subscript out of range, ret -2 */
4239         if (!flag) {
4240             tra_asg = 0;
4241             delmac(nam,0);              /* Delete any old value. */
4242             tra_asg = tra_tmp;
4243         }
4244         x -= ARRAYBASE;                 /* Convert name letter to index. */
4245         if (x > 'z' - ARRAYBASE + 1)
4246           rc = -1;
4247         if (rc != -1) {
4248             if ((q = a_ptr[x]) == NULL) /* If array not declared, */
4249               return(-3);               /* return -3. */
4250         }
4251         if (rc < 0)
4252           return(rc);
4253         if (!flag) {
4254             if (deflen > 0) {
4255                 if ((p = malloc(deflen+1)) == NULL) { /* Allocate space */
4256                     printf("addmac macro error 7: %s\n",nam);
4257                     return(-4);         /* for new def, return -4 on fail. */
4258                 }
4259                 strcpy(p,def);          /* Copy def into new space (SAFE). */
4260             } else p = NULL;
4261         }
4262         q[z] = p;                       /* Store pointer to it. */
4263         if (x == 0) {                   /* Arg vector array */
4264             if (z >= 0 && z <= 9) {     /* Copy values to corresponding  */
4265                 if (maclvl < 0) {       /* \%1..9 variables. */
4266                     makestr(&(toparg[z]),p);
4267                 } else {
4268                     makestr(&(m_arg[maclvl][z]),p);
4269                 }
4270             }
4271         }
4272         if (tra_asg) traceval(nam,p);
4273         return(0);                      /* Done. */
4274     }
4275
4276 /* Not a macro argument or a variable, so it's a macro definition */
4277
4278 #ifdef USE_VARLEN
4279     if (flag) {
4280         if (tra_asg) traceval(nam,p);
4281         return(0);
4282     }
4283 #endif /* USE_VARLEN */
4284     x = isaa(nam) ?                     /* If it's an associative array */
4285       mxxlook(mactab,nam,nmac) :        /* look it up this way */
4286         mxlook(mactab,nam,nmac);        /* otherwise this way. */
4287     if (x > -1) {                       /* If found... */
4288         if (deflen > 0)                 /* and a new definition was given */
4289           replacing = 1;                /* we're replacing */
4290         else                            /* otherwise */
4291           deleting = 1;                 /* we're deleting */
4292     }
4293     if (deleting) {                     /* Deleting... */
4294         if (delmac(nam,0) < 0)
4295           return(-1);
4296         mtchanged++;
4297         if (tra_asg) traceval(nam,p);
4298         return(0);
4299     } else if (deflen < 1)              /* New macro with no definition */
4300       return(0);                        /* Nothing to do. */
4301
4302     if (replacing) {                    /* Replacing an existing macro */
4303         if (mactab[x].mval) {           /* If it currently has a definition, */
4304             free(mactab[x].mval);       /* free it. */
4305             mactab[x].mval = NULL;
4306         }
4307         mtchanged++;
4308         y = x;                          /* Replacement index. */
4309
4310     } else {                            /* Adding a new macro... */
4311         char c1, c2;                    /* Use fast lookup to find the */
4312         c1 = *nam;                      /* alphabetical slot. */
4313         if (isupper(c1)) c1 = (char) tolower(c1);
4314
4315         if (nmac < 5) {                 /* Not worth it for small tables */
4316             y = 0;
4317         } else {                        /* First binary search to find */
4318             int lo = 0;                 /* where to start */
4319             int hi = nmac;
4320             int count = 0;
4321             char c = 0;
4322             while (lo+2 < hi && ++count < 12) {
4323                 y = lo + ((hi - lo) / 2);
4324                 c = *(mactab[y].kwd);
4325                 if (isupper(c)) c = (char) tolower(c);
4326                 if (c < c1) {
4327                     lo = y;
4328                 } else {
4329                     hi = y;
4330                 }
4331             }
4332             y = (c < c1) ? lo+1 : lo;
4333         }
4334         /* Now search linearly from starting location */
4335         for ( ; y < MAC_MAX && mactab[y].kwd != NULL; y++) {
4336             c2 = *(mactab[y].kwd);
4337             if (isupper(c2)) c2 = (char) tolower(c2);
4338             if (c1 > c2)
4339               continue;
4340             if (c1 < c2)
4341               break;
4342             if (ckstrcmp(nam,mactab[y].kwd,-1,0) <= 0)
4343               break;
4344         }
4345         if (y == MAC_MAX) {             /* Macro table is full. */
4346             debug(F101,"addmac table overflow","",y);
4347             printf("?Macro table overflow\n");
4348             return(-1);
4349         }
4350         if (mactab[y].kwd != NULL) {    /* Must insert */
4351             for (i = nmac; i > y; i--) { /* Move the rest down one slot */
4352                 mactab[i].kwd = mactab[i-1].kwd;
4353                 mactab[i].mval = mactab[i-1].mval;
4354                 mactab[i].flgs = mactab[i-1].flgs;
4355             }
4356         }
4357         mtchanged++;
4358         p = malloc(namlen + 1);         /* Allocate space for name */
4359         if (!p) {
4360             printf("?Addmac: Out of memory - \"%s\"\n",nam);
4361             return(-1);
4362         }
4363         strcpy(p,nam);                  /* Copy name into new space (SAFE) */
4364         mactab[y].kwd = p;              /* Add pointer to table */
4365     }
4366     if (deflen > 0) {                   /* If we have a definition */
4367         p = malloc(deflen + 1);         /* Get space */
4368         if (p == NULL) {
4369             printf("?Space exhausted - \"%s\"\n", nam);
4370             if (mactab[y].kwd) {
4371                 free(mactab[y].kwd);
4372                 mactab[y].kwd = NULL;
4373             }
4374             return(-1);
4375         } else {
4376             strcpy(p,def);              /* Copy the definition (SAFE) */
4377         }
4378     } else {                            /* definition is empty */
4379         p = NULL;
4380     }
4381     mactab[y].mval = p;                 /* Macro points to definition */
4382     mactab[y].flgs = 0;                 /* No flags */
4383     if (!replacing)                     /* If new macro */
4384       nmac++;                           /* count it */
4385     if (tra_asg) traceval(nam,p);
4386     return(y);
4387 }
4388
4389 int
4390 xdelmac(x) int x; {                     /* Delete a macro given its index */
4391     int i;
4392     extern int tra_asg;
4393     if (x < 0) return(x);
4394     if (tra_asg)
4395       traceval(mactab[x].kwd,NULL);
4396
4397     if (mactab[x].kwd) {                /* Free the storage for the name */
4398         free(mactab[x].kwd);
4399         mactab[x].kwd = NULL;
4400     }
4401     if (mactab[x].mval) {               /* and for the definition */
4402         free(mactab[x].mval);
4403         mactab[x].mval = NULL;
4404     }
4405     for (i = x; i < nmac; i++) {        /* Now move up the others. */
4406         mactab[i].kwd = mactab[i+1].kwd;
4407         mactab[i].mval = mactab[i+1].mval;
4408         mactab[i].flgs = mactab[i+1].flgs;
4409     }
4410     nmac--;                             /* One less macro */
4411
4412     mactab[nmac].kwd = NULL;            /* Delete last item from table */
4413     mactab[nmac].mval = NULL;
4414     mactab[nmac].flgs = 0;
4415     mtchanged++;
4416     return(0);
4417 }
4418
4419 int
4420 delmac(nam,exact) char *nam; int exact; { /* Delete the named macro */
4421     int x, z;
4422     char *p, c;
4423     extern int tra_asg;
4424
4425     if (!nam) return(0);                /* Watch out for null pointer */
4426     debug(F110,"delmac nam",nam,0);
4427 #ifdef IKSD
4428     if ( inserver &&
4429 #ifdef IKSDCONF
4430         iksdcf
4431 #else /* IKSDCONF */
4432         1
4433 #endif /* IKSDCONF */
4434         ) {
4435         if (!ckstrcmp("on_exit",nam,-1,0) ||
4436             !ckstrcmp("on_logout",nam,-1,0))
4437           return(-1);
4438     }
4439 #endif /* IKSD */
4440
4441     if (*nam == CMDQ) nam++;
4442     if (*nam == '%') {                  /* If it's a variable name */
4443         if (!(c = *(nam+1))) return(0); /* Get variable name letter or digit */
4444         p = (char *)0;                  /* Initialize value pointer */
4445         if (maclvl < 0 && c >= '0' && c <= '9') { /* Top-level digit? */
4446             p = toparg[c - '0'];
4447             if (p) if (p != g_var[c]) {
4448                 free(p);
4449                 toparg[c - '0'] = NULL;
4450             }
4451             p = g_var[c];
4452             g_var[c] = NULL;            /* Zero the table entry */
4453         } else if (maclvl > -1 && c >= '0' && c <= '9') { /* Digit? */
4454             p = m_xarg[maclvl][c - '0'];
4455             if (p) if (p != g_var[c]) {
4456                 free(p);
4457                 m_xarg[maclvl][c - '0'] = NULL;
4458             }
4459             p = m_arg[maclvl][c - '0']; /* Get pointer from macro-arg table */
4460             m_arg[maclvl][c - '0'] = NULL; /* Zero the table pointer */
4461         } else {                        /* It's a global variable */
4462             if (c < 33 || (unsigned int)c > GVARS) return(0);
4463             p = g_var[c];               /* Get pointer from global-var table */
4464             g_var[c] = NULL;            /* Zero the table entry */
4465         }
4466         if (p) {
4467             debug(F010,"delmac def",p,0);
4468             free(p);                    /* Free the storage */
4469             p = NULL;
4470         } else debug(F110,"delmac def","(null pointer)",0);
4471         if (tra_asg) traceval(nam,NULL);
4472         return(0);
4473     }
4474     if (*nam == '&') {                  /* An array reference? */
4475         char **q;
4476         if (arraynam(nam,&x,&z) < 0)    /* If syntax is bad */
4477           return(-1);                   /* return -1. */
4478         x -= ARRAYBASE;                 /* Convert name to number. */
4479         if ((q = a_ptr[x]) == NULL)     /* If array not declared, */
4480           return(-2);                   /* return -2. */
4481         if (z > a_dim[x])               /* If subscript out of range, */
4482           return(-3);                   /* return -3. */
4483         if (q[z]) {                     /* If there is an old value, */
4484             debug(F010,"delmac def",q[z],0);
4485             if (x != 0)                 /* Macro arg vector is just a copy */
4486               free(q[z]);               /* Others are real so free them */
4487             q[z] = NULL;
4488             if (x == 0) {               /* Arg vector array */
4489                 if (z >= 0 && z <= 9) { /* Copy values to corresponding  */
4490                     if (maclvl < 0) {   /* \%1..9 variables. */
4491                         makestr(&(toparg[z]),NULL);
4492                     } else {
4493                         makestr(&(m_arg[maclvl][z]),NULL);
4494                     }
4495                 }
4496             }
4497             if (tra_asg) traceval(nam,NULL);
4498         } else debug(F010,"delmac def","(null pointer)",0);
4499     }
4500
4501    /* Not a variable or an array, so it must be a macro. */
4502
4503     z = isaa(nam);
4504     debug(F111,"delmac isaa",nam,z);
4505     debug(F111,"delmac exact",nam,exact);
4506     x = z ? mxxlook(mactab,nam,nmac) :
4507       exact ? mxlook(mactab,nam,nmac) :
4508         mlook(mactab,nam,nmac);
4509     if (x < 0) {
4510         debug(F111,"delmac mlook",nam,x);
4511         return(x);
4512     }
4513     return(xdelmac(x));
4514 }
4515
4516 VOID
4517 initmac() {                             /* Init macro & variable tables */
4518     int i, j, x;
4519
4520     nmac = 0;                           /* No macros */
4521     for (i = 0; i < MAC_MAX; i++) {     /* Initialize the macro table */
4522         mactab[i].kwd = NULL;
4523         mactab[i].mval = NULL;
4524         mactab[i].flgs = 0;
4525     }
4526     mtchanged++;
4527     x = (MAXARGLIST + 1) * sizeof(char **);
4528     for (i = 0; i < MACLEVEL; i++) {    /* Init the macro argument tables */
4529         m_xarg[i] = (char **) malloc(x);
4530         mrval[i] = NULL;                /* Macro return value */
4531         /* Pointer to entire argument vector, level i, for \&_[] array */
4532         for (j = 0; j <= MAXARGLIST; j++) { /* Macro argument list */
4533             if (j < 10)                 /* For the \%0..\%9 variables */
4534               m_arg[i][j] = NULL;       /* Pointer to arg j, level i. */
4535             if (m_xarg[i])              /* For \&_[] - all args. */
4536               m_xarg[i][j] = NULL;
4537         }
4538     }
4539     for (i = 0; i < GVARS; i++) {       /* And the global variables table */
4540         g_var[i] = NULL;
4541     }
4542     /* And the table of arrays */
4543     for (i = 0; i < (int) 'z' - ARRAYBASE + 1; i++) {
4544         a_ptr[i] = (char **) NULL;      /* Null pointer for each */
4545         a_dim[i] = 0;                   /* and a dimension of zero */
4546         a_link[i] = -1;
4547         for (j = 0; j < CMDSTKL; j++) {
4548             aa_ptr[j][i] = (char **) NULL;
4549             aa_dim[j][i] = 0;
4550         }
4551     }
4552 }
4553
4554 int
4555 popclvl() {                             /* Pop command level, return cmdlvl */
4556     extern int tra_cmd;
4557     struct localvar * v;
4558     int i, topcmd;
4559     debug(F101,"popclvl cmdlvl","",cmdlvl);
4560     if (cmdlvl > 0) {
4561         if ((v = localhead[cmdlvl])) {  /* Did we save any variables? */
4562             while (v) {                 /* Yes */
4563                 if (v->lv_value)        /* Copy old ones back */
4564                   addmac(v->lv_name,v->lv_value);
4565                 else
4566                   delmac(v->lv_name,1);
4567                 v = v->lv_next;
4568             }
4569             freelocal(cmdlvl);          /* Free local storage */
4570         }
4571         /* Automatic arrays do not use the localhead list */
4572
4573         for (i = 0; i < 28; i++) {      /* Free any local arrays */
4574             if (aa_ptr[cmdlvl][i]) { /* Does this one exist? */
4575                 dclarray((char)(i+ARRAYBASE),0); /* Destroy global one */
4576                 a_ptr[i] = aa_ptr[cmdlvl][i];
4577                 a_dim[i] = aa_dim[cmdlvl][i];
4578                 aa_ptr[cmdlvl][i] = (char **)NULL;
4579                 aa_dim[cmdlvl][i] = 0;
4580             } else if (aa_dim[cmdlvl][i] == -23) { /* Secret code */
4581                 dclarray((char)(i+ARRAYBASE),0); /* (see pusharray()) */
4582                 aa_ptr[cmdlvl][i] = (char **)NULL;
4583                 aa_dim[cmdlvl][i] = 0;
4584             }
4585
4586             /* Otherwise do nothing - it is a local array that was declared */
4587             /* at a level above this one so leave it alone. */
4588         }
4589     }
4590     if (cmdlvl < 1) {                   /* If we're already at top level */
4591         cmdlvl = 0;                     /* just make sure all the */
4592         tlevel = -1;                    /* stack pointers are set right */
4593         maclvl = -1;                    /* and return */
4594     } else if (cmdstk[cmdlvl].src == CMD_TF) { /* Reading from TAKE file? */
4595         debug(F101,"popclvl tlevel","",tlevel);
4596         if (tlevel > -1) {              /* Yes, */
4597             fclose(tfile[tlevel]);      /* close it */
4598
4599             if (tra_cmd)
4600               printf("[%d] -F: \"%s\"\n",cmdlvl,tfnam[tlevel]);
4601             debug(F111,"CMD -F",tfnam[tlevel],cmdlvl);
4602             if (tfnam[tlevel]) {        /* free storage for name */
4603                 free(tfnam[tlevel]);
4604                 tfnam[tlevel] = NULL;
4605             }
4606             tlevel--;                   /* and pop take level */
4607             cmdlvl--;                   /* and command level */
4608             quiet = xquiet[cmdlvl];
4609         } else
4610           tlevel = -1;
4611     } else if (cmdstk[cmdlvl].src == CMD_MD) { /* In a macro? */
4612         topcmd = lastcmd[maclvl];
4613         debug(F101,"popclvl maclvl","",maclvl);
4614         if (maclvl > -1) {              /* Yes, */
4615 #ifdef COMMENT
4616             int i;
4617             char **q;
4618 #endif /* COMMENT */
4619             macp[maclvl] = "";          /* set macro pointer to null string */
4620             *cmdbuf = '\0';             /* clear the command buffer */
4621
4622             if ((maclvl > 0) &&         /* 2 May 1999 */
4623                 (m_arg[maclvl-1][0]) &&
4624                 (!strncmp(m_arg[maclvl-1][0],"_xif",4) ||
4625                  !strncmp(m_arg[maclvl-1][0],"_for",4) ||
4626                  !strncmp(m_arg[maclvl-1][0],"_swi",4) ||
4627                  !strncmp(m_arg[maclvl-1][0],"_whi",4)) &&
4628                 mrval[maclvl+1]) {
4629                 makestr(&(mrval[maclvl-1]),mrval[maclvl+1]);
4630             }
4631             if (maclvl+1 < MACLEVEL) {
4632                 if (mrval[maclvl+1]) {  /* Free any deeper return values. */
4633                     free(mrval[maclvl+1]);
4634                     mrval[maclvl+1] = NULL;
4635                 }
4636             }
4637             if (tra_cmd)
4638               printf("[%d] -M: \"%s\"\n",cmdlvl,m_arg[cmdstk[cmdlvl].lvl][0]);
4639             debug(F111,"CMD -M",m_arg[cmdstk[cmdlvl].lvl][0],cmdlvl);
4640
4641             maclvl--;                   /* Pop macro level */
4642             cmdlvl--;                   /* and command level */
4643             debug(F101,"popclvl mac new maclvl","",maclvl);
4644             debug(F010,"popclvl mac mrval[maclvl+1]",mrval[maclvl+2],0);
4645
4646             quiet = xquiet[cmdlvl];
4647             if (maclvl > -1) {
4648                 a_ptr[0] = m_xarg[maclvl];
4649                 a_dim[0] = n_xarg[maclvl] - 1;
4650                 debug(F111,"a_dim[0]","B",a_dim[0]);
4651             } else {
4652                 a_ptr[0] = topxarg;
4653                 a_dim[0] = topargc - 1;
4654                 debug(F111,"a_dim[0]","C",a_dim[0]);
4655             }
4656         } else {
4657             maclvl = -1;
4658         }
4659 #ifndef NOSEXP
4660         debug(F101,"popclvl topcmd","",topcmd);
4661         if (topcmd == XXSEXP) {
4662             extern char * sexpval;
4663             makestr(&(mrval[maclvl+1]),sexpval);
4664         }
4665 #endif /* NOSEXP */
4666     } else {
4667         cmdlvl--;
4668     }
4669     debug(F101,"popclvl cmdlvl","",cmdlvl);
4670     if (prstring[cmdlvl]) {
4671         cmsetp(prstring[cmdlvl]);
4672         makestr(&(prstring[cmdlvl]),NULL);
4673     }
4674 #ifndef MAC
4675     if (cmdlvl < 1 || xcmdsrc == CMD_KB) { /* If at prompt */
4676         setint();
4677         concb((char)escape);            /* Go into cbreak mode */
4678     }
4679 #endif /* MAC */
4680     xcmdsrc = cmdstk[cmdlvl].src;
4681     debug(F101,"popclvl xcmdsrc","",xcmdsrc);
4682     debug(F101,"popclvl tlevel","",tlevel);
4683     return(cmdlvl < 1 ? 0 : cmdlvl);    /* Return command level */
4684 }
4685 #else /* No script programming language */
4686 int popclvl() {                         /* Just close current take file. */
4687     if (tlevel > -1) {                  /* if any... */
4688         if (tfnam[tlevel]) {
4689             free(tfnam[tlevel]);
4690             tfnam[tlevel] = NULL;
4691         }
4692         fclose(tfile[tlevel--]);
4693     }
4694     if (tlevel == -1) {                 /* And if back at top level */
4695         setint();
4696         concb((char)escape);            /* and go back into cbreak mode. */
4697     }
4698     xcmdsrc = tlevel > -1 ? CMD_TF : 0;
4699     return(tlevel + 1);
4700 }
4701 #endif /* NOSPL */
4702
4703
4704 #ifndef NOSPL
4705 static int
4706 iseom(m) char * m; {                    /* Test if at end of macro def */
4707     if (!m)
4708       m = "";
4709     debug(F111,"iseom",m,maclvl);
4710     while (*m) {
4711         /* Anything but Space and Comma means more macro is left */
4712         if ((*m > SP) && (*m != ',')) {
4713             debug(F111,"iseom return",m,0);
4714             return(0);
4715         }
4716         m++;
4717     }
4718     debug(F111,"iseom return",m,1);
4719     return(1);                          /* Nothing left */
4720 }
4721 #endif /* NOSPL */
4722
4723 /* Pop all command levels that can be popped */
4724
4725 int
4726 prepop() {
4727     if (cmdlvl > 0) {                   /* If command level is > 0 and... */
4728         while (
4729 #ifndef NOSPL
4730                ((cmdstk[cmdlvl].src == CMD_TF) && /* Command source is file */
4731 #endif /* NOSPL */
4732             (tlevel > -1) &&
4733             feof(tfile[tlevel]))        /* And at end of file... */
4734 #ifndef NOSPL
4735                /* Or command source is macro... */
4736                || ((cmdstk[cmdlvl].src == CMD_MD) &&
4737                 (maclvl > -1) &&
4738                 iseom(macp[maclvl])))  /* and at end of macro, then... */
4739 #endif /* NOSPL */
4740         {
4741               popclvl();                /* pop command level. */
4742         }
4743     }
4744     return(cmdlvl < 1 ? 0 : cmdlvl);    /* Return command level */
4745 }
4746
4747 /* STOP - get back to C-Kermit prompt, no matter where from. */
4748
4749 int
4750 dostop() {
4751     extern int cmddep;
4752     while (popclvl()) ;         /* Pop all macros & take files */
4753 #ifndef NOSPL
4754     if (cmddep > -1)            /* And all recursive cmd pkg invocations */
4755       while (cmpop() > -1) ;
4756 #endif /* NOSPL */
4757     cmini(ckxech);              /* Clear the command buffer. */
4758     return(0);
4759 }
4760
4761 /* Close the given log */
4762
4763 int
4764 doclslog(x) int x; {
4765     int y;
4766     switch (x) {
4767 #ifdef DEBUG
4768       case LOGD:
4769         if (deblog <= 0) {
4770             printf("?Debugging log wasn't open\n");
4771             return(0);
4772         }
4773         debug(F100,"Debug Log Closed","",0L);
4774         *debfil = '\0';
4775         deblog = 0;
4776         return(zclose(ZDFILE));
4777 #endif /* DEBUG */
4778
4779 #ifndef NOXFER
4780       case LOGP:
4781         if (pktlog <= 0) {
4782             printf("?Packet log wasn't open\n");
4783             return(0);
4784         }
4785         *pktfil = '\0';
4786         pktlog = 0;
4787         return(zclose(ZPFILE));
4788 #endif /* NOXFER */
4789
4790 #ifndef NOLOCAL
4791       case LOGS:
4792         if (seslog <= 0) {
4793             printf("?Session log wasn't open\n");
4794             return(0);
4795         }
4796         *sesfil = '\0';
4797         setseslog(0);
4798         return(zclose(ZSFILE));
4799 #endif /* NOLOCAL */
4800
4801 #ifdef TLOG
4802       case LOGT: {
4803 #ifdef IKSD
4804           extern int iklogopen, xferlog;
4805 #endif /* IKSD */
4806           if (tralog <= 0
4807 #ifdef IKSD
4808               && !iklogopen
4809 #endif /* IKSD */
4810               ) {
4811               if (msgflg)
4812                 printf("?Transaction log wasn't open\n");
4813               return(0);
4814           }
4815 #ifdef IKSD
4816           if (iklogopen && !inserver) {
4817               close(xferlog);
4818               iklogopen = 0;
4819           }
4820 #endif /* IKSD */
4821           if (tralog) {
4822               tlog(F100,"Transaction Log Closed","",0L);
4823               zclose(ZTFILE);
4824           }
4825           *trafil = '\0';
4826           tralog = 0;
4827           return(1);
4828       }
4829 #endif /* TLOG */
4830
4831 #ifdef CKLOGDIAL
4832       case LOGM:
4833         if (dialog <= 0) {
4834             if (msgflg) printf("?Connection log wasn't open\n");
4835             return(0);
4836         }
4837         *diafil = '\0';
4838         dialog = 0;
4839         return(zclose(ZDIFIL));
4840 #endif /* CKLOGDIAL */
4841
4842 #ifndef NOSPL
4843       case LOGW:                        /* WRITE file */
4844       case LOGR:                        /* READ file */
4845         y = (x == LOGR) ? ZRFILE : ZWFILE;
4846         if (chkfn(y) < 1)               /* If no file to close */
4847           return(1);                    /* succeed silently. */
4848         return(zclose(y));              /* Otherwise, close the file. */
4849 #endif /* NOSPL */
4850
4851       default:
4852         printf("\n?Unexpected log designator - %d\n", x);
4853         return(0);
4854     }
4855 }
4856
4857 static int slc = 0;                     /* Screen line count */
4858
4859 char *
4860 showstring(s) char * s; {
4861     return(s ? s : "(null)");
4862 }
4863
4864 char *
4865 showoff(x) int x; {
4866     return(x ? "on" : "off");
4867 }
4868
4869 char *
4870 showooa(x) int x; {
4871     switch (x) {
4872       case SET_OFF:  return("off");
4873       case SET_ON:   return("on");
4874       case SET_AUTO: return("automatic");
4875       default:       return("(unknown)");
4876     }
4877 }
4878
4879 #ifdef GEMDOS
4880 isxdigit(c) int c; {
4881     return(isdigit(c) ||
4882            (c >= 'a' && c <= 'f') ||
4883            (c >= 'A' && c <= 'F'));
4884 }
4885 #endif /* GEMDOS */
4886
4887 #ifndef NOSETKEY
4888 #ifdef OS2
4889 static struct keytab shokeytab[] = {    /* SHOW KEY modes */
4890     "all",    1, 0,
4891     "one",    0, 0
4892 };
4893 static int nshokey = (sizeof(shokeytab) / sizeof(struct keytab));
4894
4895 #define SHKEYDEF TT_MAX+5
4896 struct keytab shokeymtab[] = {
4897     "aaa",       TT_AAA,     CM_INV,    /* AnnArbor */
4898     "adm3a",     TT_ADM3A,   0,         /* LSI ADM-3A */
4899     "adm5",      TT_ADM5,    0,         /* LSI ADM-5 */
4900     "aixterm",   TT_AIXTERM, 0,         /* IBM AIXterm */
4901     "annarbor",  TT_AAA,     0,         /* AnnArbor */
4902     "ansi-bbs",  TT_ANSI,    0,         /* ANSI.SYS (BBS) */
4903     "at386",     TT_AT386,   0,         /* Unixware ANSI */
4904     "avatar/0+", TT_ANSI,    0,         /* AVATAR/0+ */
4905     "ba80",      TT_BA80,    0,         /* Nixdorf BA80 */
4906     "be",        TT_BEOS,    CM_INV|CM_ABR,
4907     "beos-ansi", TT_BEOS,    CM_INV,    /* BeOS ANSI */
4908     "beterm",    TT_BEOS,    0,         /* BeOS Console */
4909     "d200",      TT_DG200,   CM_INV|CM_ABR, /* Data General DASHER 200 */
4910     "d210",      TT_DG210,   CM_INV|CM_ABR, /* Data General DASHER 210 */
4911     "d217",      TT_DG217,   CM_INV|CM_ABR, /* Data General DASHER 217 */
4912     "default",   SHKEYDEF,   0,
4913     "dg200",     TT_DG200,   0,         /* Data General DASHER 200 */
4914     "dg210",     TT_DG210,   0,         /* Data General DASHER 210 */
4915     "dg217",     TT_DG217,   0,         /* Data General DASHER 217 */
4916     "emacs",     TT_KBM_EMACS,   0,     /* Emacs mode */
4917     "h19",       TT_H19,     CM_INV,    /* Heath-19 */
4918     "heath19",   TT_H19,     0,         /* Heath-19 */
4919     "hebrew",    TT_KBM_HEBREW, 0,      /* Hebrew mode */
4920     "hft",       TT_HFT,     0,         /* IBM HFT */
4921     "hp2621a",   TT_HP2621,  0,         /* HP 2621A */
4922     "hpterm",    TT_HPTERM,  0,         /* HP TERM */
4923     "hz1500",    TT_HZL1500, 0,         /* Hazeltine 1500 */
4924     "ibm3151",   TT_IBM31,   0,         /* IBM 3101-xx,3161 */
4925     "linux",     TT_LINUX,   0,         /* Linux */
4926     "qansi",     TT_QANSI,   0,         /* QNX ANSI */
4927     "qnx",       TT_QNX,     0,         /* QNX */
4928     "russian",   TT_KBM_RUSSIAN, 0,     /* Russian mode */
4929     "scoansi",   TT_SCOANSI, 0,         /* SCO ANSI */
4930     "sni-97801", TT_97801,   0,         /* Sinix 97801 */
4931     "sun",       TT_SUN,     0,         /* Sun Console */
4932 #ifdef OS2PM
4933 #ifdef COMMENT
4934     "tek4014", TT_TEK40, 0,
4935 #endif /* COMMENT */
4936 #endif /* OS2PM */
4937     "tty",     TT_NONE,  0,
4938     "tvi910+", TT_TVI910, 0,
4939     "tvi925",  TT_TVI925, 0,
4940     "tvi950",  TT_TVI950, 0,
4941     "vc404",   TT_VC4404, 0,
4942     "vc4404",  TT_VC4404, CM_INV,
4943     "vip7809", TT_VIP7809, 0,
4944     "vt100",   TT_VT100, 0,
4945     "vt102",   TT_VT102, 0,
4946     "vt220",   TT_VT220, 0,
4947     "vt220pc", TT_VT220PC, 0,
4948     "vt320",   TT_VT320, 0,
4949     "vt320pc", TT_VT320PC, 0,
4950     "vt52",    TT_VT52,  0,
4951     "wp",      TT_KBM_WP, 0,
4952     "wy160",   TT_WY160,  0,
4953     "wy30",    TT_WY30,  0,
4954     "wy370",   TT_WY370, 0,
4955     "wy50",    TT_WY50,  0,
4956     "wy60",    TT_WY60,  0,
4957     "wyse30",  TT_WY30,  CM_INV,
4958     "wyse370", TT_WY370, CM_INV,
4959     "wyse50",  TT_WY50,  CM_INV,
4960     "wyse60",  TT_WY60,  CM_INV
4961 };
4962 int nshokeym = (sizeof(shokeymtab) / sizeof(struct keytab));
4963 #endif /* OS2 */
4964
4965 VOID
4966 #ifdef OS2
4967 shokeycode(c,m) int c, m;
4968 #else
4969 shokeycode(c) int c;
4970 #endif
4971 /* shokeycode */ {
4972     KEY ch;
4973     CHAR *s;
4974 #ifdef OS2
4975     int i;
4976     con_event km;
4977 #else /* OS2 */
4978     int km;
4979 #endif /* OS2 */
4980
4981 #ifdef OS2
4982     extern int mskkeys;
4983     char * mstr = "";
4984
4985     if (c >= KMSIZE) {
4986         bleep(BP_FAIL);
4987         return;
4988     }
4989 #else /* OS2 */
4990     printf(" Key code \\%d => ", c);
4991 #endif /* OS2 */
4992
4993 #ifndef OS2
4994     km = mapkey(c);
4995
4996 #ifndef NOKVERBS
4997     if (IS_KVERB(km)) {                 /* \Kverb? */
4998         int i, kv;
4999         kv = km & ~(F_KVERB);
5000         printf("Verb: ");
5001         for (i = 0; i < nkverbs; i++)
5002           if (kverbs[i].kwval == kv) {
5003               printf("\\K%s",kverbs[i].kwd);
5004               break;
5005           }
5006         printf("\n");
5007     } else
5008 #endif /* NOKVERBS */
5009       if (IS_CSI(km)) {
5010           int xkm = km & 0xFF;
5011           if (xkm <= 32 || xkm >= 127)
5012             printf("String: \\{27}[\\{%d}\n",xkm);
5013           else
5014             printf("String: \\{27}[%c\n",xkm);
5015       } else if (IS_ESC(km)) {
5016           int xkm = km & 0xFF;
5017           if (xkm <= 32 || xkm >= 127)
5018             printf("String: \\{27}\\{%d}\n",xkm);
5019           else
5020             printf("String: \\{27}%c\n",xkm);
5021       } else if (macrotab[c]) {         /* See if there's a macro */
5022           printf("String: ");           /* If so, display its definition */
5023           s = macrotab[c];
5024           shostrdef(s);
5025           printf("\n");
5026 #ifndef NOKVERBS
5027     } else if (km >= 0x100) {           /* This means "undefined" */
5028         printf("Undefined\n");
5029 #endif /* NOKVERBS */
5030     } else {                            /* No macro, show single character */
5031         printf("Character: ");
5032         ch = km;
5033         if (ch < 32 || ch == 127
5034 #ifdef OS2
5035             || ch > 255
5036 #endif /* OS2 */
5037 #ifndef NEXT
5038 #ifndef AUX
5039 #ifndef XENIX
5040 #ifndef OS2
5041             || (ch > 127 && ch < 160)
5042 #endif /* OS2 */
5043 #endif /* XENIX */
5044 #endif /* AUX */
5045 #endif /* NEXT */
5046             )
5047 /*
5048   These used to be %d, but gcc 1.93 & later complain about type mismatches.
5049   %u is supposed to be totally portable.
5050 */
5051           printf("\\%u",(unsigned int) ch);
5052         else printf("%c \\%u",(CHAR) (ch & 0xff),(unsigned int) ch);
5053         if (ch == (KEY) c)
5054           printf(" (self, no translation)\n");
5055         else
5056           printf("\n");
5057     }
5058 #else /* OS2 */
5059     if (m < 0) {
5060         km = mapkey(c);
5061         mstr = "default";
5062     } else {
5063         km = maptermkey(c,m);
5064         for (i = 0; i < nshokeym; i++) {
5065             if (m == shokeymtab[i].kwval) {
5066                 mstr = shokeymtab[i].kwd;
5067                 break;
5068             }
5069         }
5070     }
5071     s = keyname(c);
5072     debug(F111,"shokeycode mstr",mstr,m);
5073     debug(F111,"shokeycode keyname",s,c);
5074     printf(" %sKey code \\%d %s (%s) => ",
5075             mskkeys ? "mskermit " : "",
5076             mskkeys ? cktomsk(c) : c,
5077             s == NULL ? "" : s, mstr);
5078
5079     switch (km.type) {
5080 #ifndef NOKVERBS
5081       case kverb: {
5082           int i, kv;
5083           kv = km.kverb.id & ~(F_KVERB);
5084           printf("Verb: ");
5085           for (i = 0; i < nkverbs; i++) {
5086               if (kverbs[i].kwval == kv) {
5087                   printf("\\K%s",kverbs[i].kwd);
5088                   break;
5089               }
5090           }
5091           printf("\n");
5092           break;
5093       }
5094 #endif /* NOKVERBS */
5095       case csi: {
5096           int xkm = km.csi.key & 0xFF;
5097           if (xkm <= 32 || xkm >= 127)
5098             printf("String: \\{27}[\\{%d}\n",xkm);
5099           else
5100             printf("String: \\{27}[%c\n",xkm);
5101           break;
5102       }
5103       case esc: {
5104           int xkm = km.esc.key & 0xFF;
5105           if (xkm <= 32 || xkm >= 127)
5106             printf("String: \\{%d}\\{%d}\n",ISDG200(tt_type)?30:27,xkm);
5107           else
5108             printf("String: \\{%d}%c\n",ISDG200(tt_type)?30:27,xkm);
5109           break;
5110       }
5111       case macro: {
5112           printf("String: ");           /* Macro, display its definition */
5113           shostrdef(km.macro.string);
5114           printf("\n");
5115           break;
5116       }
5117       case literal: {
5118           printf("Literal string: ");   /* Literal, display its definition */
5119           shostrdef(km.literal.string);
5120           printf("\n");
5121           break;
5122       }
5123       case error: {
5124           if (c >= 0x100) {
5125               printf("Undefined\n");
5126           } else {
5127               printf("Character: ");
5128               ch = c;
5129               if (ch < 32 || ch == 127 || ch > 255
5130 #ifndef NEXT
5131 #ifndef AUX
5132 #ifndef XENIX
5133 #ifndef OS2
5134                    || (ch > 127 && ch < 160)
5135 #endif /* OS2 */
5136 #endif /* XENIX */
5137 #endif /* AUX */
5138 #endif /* NEXT */
5139                    )
5140 /*
5141   These used to be %d, but gcc 1.93 & later complain about type mismatches.
5142   %u is supposed to be totally portable.
5143 */
5144                   printf("\\%u",(unsigned int) ch);
5145               else printf("%c \\%u",(CHAR) (ch & 0xff),(unsigned int) ch);
5146               printf(" (self, no translation)\n");
5147           }
5148           break;
5149       }
5150       case key: {
5151           printf("Character: ");
5152           ch = km.key.scancode;
5153           if (ch < 32 || ch == 127 || ch > 255
5154 #ifndef NEXT
5155 #ifndef AUX
5156 #ifndef XENIX
5157 #ifndef OS2
5158               || (ch > 127 && ch < 160)
5159 #else
5160                || (ch > 127)
5161 #endif /* OS2 */
5162 #endif /* XENIX */
5163 #endif /* AUX */
5164 #endif /* NEXT */
5165               )
5166 /*
5167   These used to be %d, but gcc 1.93 & later complain about type mismatches.
5168   %u is supposed to be totally portable.
5169 */
5170             printf("\\%u",(unsigned int) ch);
5171           else printf("%c \\%u",(CHAR) (ch & 0xff),(unsigned int) ch);
5172           if (ch == (KEY) c)
5173             printf(" (self, no translation)\n");
5174           else
5175             printf("\n");
5176           break;
5177       }
5178     }
5179 #endif /* OS2 */
5180 }
5181 #endif /* NOSETKEY */
5182
5183 VOID
5184 shostrdef(s) CHAR * s; {
5185     CHAR ch;
5186     if (!s) s = (CHAR *)"";
5187     while ((ch = *s++)) {
5188         if (ch < 32 || ch == 127 || ch == 255
5189 /*
5190   Systems whose native character sets have graphic characters in C1...
5191 */
5192 #ifndef NEXT                            /* NeXT */
5193 #ifndef AUX                             /* Macintosh */
5194 #ifndef XENIX                           /* IBM PC */
5195 #ifdef OS2
5196 /*
5197   It doesn't matter whether the local host can display 8-bit characters;
5198   they are not portable among character-sets and fonts.  Who knows what
5199   would be displayed...
5200 */
5201             || (ch > 127)
5202 #else /* OS2 */
5203             || (ch > 127 && ch < 160)
5204 #endif /* OS2 */
5205 #endif /* XENIX */
5206 #endif /* AUX */
5207 #endif /* NEXT */
5208             )
5209           printf("\\{%d}",ch);          /* Display control characters */
5210         else putchar((char) ch);        /* in backslash notation */
5211     }
5212 }
5213
5214 #define xxdiff(v,sys) strncmp(v,sys,strlen(sys))
5215
5216 #ifndef NOSHOW
5217 VOID
5218 shover() {
5219 #ifdef OS2
5220     extern char ckxsystem[];
5221 #endif /* OS2 */
5222     extern char *ck_patch, * cklibv;
5223     printf("\nVersions:\n %s\n",versio);
5224     printf(" Numeric: %ld\n",vernum);
5225 #ifdef OS2
5226     printf(" Operating System: %s\n", ckxsystem);
5227 #else /* OS2 */
5228     printf(" Built for: %s\n", ckxsys);
5229 #ifdef CK_UTSNAME
5230     if (unm_nam[0])
5231       printf(" Running on: %s %s %s %s\n", unm_nam,unm_ver,unm_rel,unm_mch);
5232 #endif /* CK_UTSNAME */
5233     printf(" Patches: %s\n", *ck_patch ? ck_patch : "(none)");
5234 #endif /* OS2 */
5235     if (xxdiff(ckxv,ckxsys))
5236       printf(" %s for%s\n",ckxv,ckxsys);
5237     else
5238       printf(" %s\n",ckxv);
5239     if (xxdiff(ckzv,ckzsys))
5240       printf(" %s for%s\n",ckzv,ckzsys);
5241     else
5242       printf(" %s\n",ckzv);
5243     printf(" %s\n",cklibv);
5244     printf(" %s\n",protv);
5245     printf(" %s\n",fnsv);
5246     printf(" %s\n %s\n",cmdv,userv);
5247 #ifndef NOCSETS
5248     printf(" %s\n",xlav);
5249 #endif /* NOCSETS */
5250 #ifndef MAC
5251 #ifndef NOLOCAL
5252     printf(" %s\n",connv);
5253 #ifdef OS2
5254     printf(" %s\n",ckyv);
5255 #endif /* OS2 */
5256 #endif /* NOLOCAL */
5257 #endif /* MAC */
5258 #ifndef NODIAL
5259     printf(" %s\n",dialv);
5260 #endif /* NODIAL */
5261 #ifndef NOSCRIPT
5262     printf(" %s\n",loginv);
5263 #endif /* NOSCRIPT */
5264 #ifdef NETCONN
5265     printf(" %s\n",cknetv);
5266 #ifdef OS2
5267     printf(" %s\n",ckonetv);
5268 #ifdef CK_NETBIOS
5269     printf(" %s\n",ckonbiv);
5270 #endif /* CK_NETBIOS */
5271 #endif /* OS2 */
5272 #endif /* NETCONN */
5273 #ifdef TNCODE
5274     printf(" %s\n",cktelv);
5275 #endif /* TNCODE */
5276 #ifdef SSHBUILTIN
5277     printf(" %s\n",cksshv);
5278 #ifdef SFTP_BUILTIN
5279     printf(" %s\n",cksftpv);
5280 #endif /* SFTP_BUILTIN */
5281 #endif /* SSHBUILTIN */
5282 #ifdef OS2
5283 #ifdef OS2MOUSE
5284     printf(" %s\n",ckomouv);
5285 #endif /* OS2MOUSE */
5286 #endif /* OS2 */
5287 #ifdef NEWFTP
5288     printf(" %s\n",ckftpv);
5289 #endif /* NEWFTP */
5290 #ifdef CK_AUTHENTICATION
5291     printf(" %s\n",ckathv);
5292 #endif /* CK_AUTHENTICATION */
5293 #ifdef CK_ENCRYPTION
5294 #ifdef CRYPT_DLL
5295     printf(" %s\n",ck_crypt_dll_version());
5296 #else /* CRYPT_DLL */
5297     printf(" %s\n",ckcrpv);
5298 #endif /* CRYPT_DLL */
5299 #endif /* CK_ENCRYPTION */
5300 #ifdef CK_SSL
5301     printf(" %s\n",cksslv);
5302 #endif /* CK_SSL */
5303     printf("\n");
5304 }
5305
5306 #ifdef CK_LABELED
5307 VOID
5308 sholbl() {
5309 #ifdef VMS
5310     printf("VMS Labeled File Features:\n");
5311     printf(" acl %s (ACL info %s)\n",
5312            showoff(lf_opts & LBL_ACL),
5313            lf_opts & LBL_ACL ? "preserved" : "discarded");
5314     printf(" backup-date %s (backup date/time %s)\n",
5315            showoff(lf_opts & LBL_BCK),
5316            lf_opts & LBL_BCK ? "preserved" : "discarded");
5317     printf(" name %s (original filename %s)\n",
5318            showoff(lf_opts & LBL_NAM),
5319            lf_opts & LBL_NAM ? "preserved" : "discarded");
5320     printf(" owner %s (original file owner id %s)\n",
5321            showoff(lf_opts & LBL_OWN),
5322            lf_opts & LBL_OWN ? "preserved" : "discarded");
5323     printf(" path %s (original file's disk:[directory] %s)\n",
5324            showoff(lf_opts & LBL_PTH),
5325            lf_opts & LBL_PTH ? "preserved" : "discarded");
5326 #else
5327 #ifdef OS2
5328     printf("OS/2 Labeled File features (attributes):\n");
5329     printf(" archive:   %s\n", showoff(lf_opts & LBL_ARC));
5330     printf(" extended:  %s\n", showoff(lf_opts & LBL_EXT));
5331     printf(" hidden:    %s\n", showoff(lf_opts & LBL_HID));
5332     printf(" read-only: %s\n", showoff(lf_opts & LBL_RO ));
5333     printf(" system:    %s\n", showoff(lf_opts & LBL_SYS));
5334 #endif /* OS2 */
5335 #endif /* VMS */
5336 }
5337 #endif /* CK_LABELED */
5338
5339 VOID
5340 shotcs(csl,csr) int csl, csr; {         /* Show terminal character set */
5341 #ifndef NOCSETS
5342 #ifdef OS2
5343 #ifndef NOTERM
5344     extern struct _vtG G[4], *GL, *GR;
5345     extern int decnrcm, sni_chcode;
5346     extern int tt_utf8, dec_nrc, dec_kbd, dec_lang;
5347     extern prncs;
5348
5349     printf(" Terminal character-sets:\n");
5350     if (IS97801(tt_type_mode)) {
5351         if (cmask == 0377)
5352           printf("     Mode: 8-bit Mode\n");
5353         else
5354           printf("     Mode: 7-bit Mode\n");
5355         printf("     CH.CODE is %s\n",sni_chcode?"On":"Off");
5356     } else if (ISVT100(tt_type_mode)) {
5357         if (decnrcm)
5358           printf("     Mode: 7-bit National Mode\n");
5359         else
5360           printf("     Mode: 8-bit Multinational Mode\n");
5361     }
5362     if ( isunicode() )
5363         printf("    Local: Unicode display / %s input\n",
5364                 csl == TX_TRANSP ? "transparent" :
5365                 csl == TX_UNDEF ? "undefined" : txrinfo[csl]->keywd);
5366     else
5367         printf("    Local: %s\n",
5368                 csl == TX_TRANSP ? "transparent" :
5369                 csl == TX_UNDEF ? "undefined" : txrinfo[csl]->keywd);
5370
5371     if ( tt_utf8 ) {
5372         printf("   Remote: UTF-8\n");
5373     } else {
5374         printf("   Remote: %sG0: %s (%s)\n",
5375            GL == &G[0] ? "GL->" : GR == &G[0] ? "GR->" : "    ",
5376            txrinfo[G[0].designation]->keywd,
5377            G[0].designation == TX_TRANSP ? "" :
5378            G[0].size == cs94 ? "94 chars" :
5379            G[0].size == cs96 ? "96 chars" : "multi-byte");
5380         printf("           %sG1: %s (%s)\n",
5381            GL == &G[1] ? "GL->" : GR == &G[1] ? "GR->" : "    ",
5382            txrinfo[G[1].designation]->keywd,
5383            G[1].designation == TX_TRANSP ? "" :
5384            G[1].size == cs94 ? "94 chars" :
5385            G[1].size == cs96 ? "96 chars" : "multi-byte");
5386         printf("           %sG2: %s (%s)\n",
5387            GL == &G[2] ? "GL->" : GR == &G[2] ? "GR->" : "    ",
5388            txrinfo[G[2].designation]->keywd,
5389            G[2].designation == TX_TRANSP ? "" :
5390            G[2].size == cs94 ? "94 chars" :
5391            G[2].size == cs96 ? "96 chars" : "multi-byte");
5392         printf("           %sG3: %s (%s)\n",
5393            GL == &G[3] ? "GL->" : GR == &G[3] ? "GR->" : "    ",
5394            txrinfo[G[3].designation]->keywd,
5395            G[3].designation == TX_TRANSP ? "" :
5396            G[3].size == cs94 ? "94 chars" :
5397            G[3].size == cs96 ? "96 chars" : "multi-byte");
5398     }
5399     printf("\n");
5400     printf(" Keyboard character-sets:\n");
5401     printf("   Multinational: %s\n",txrinfo[dec_kbd]->keywd);
5402     printf("        National: %s\n",txrinfo[dec_nrc]->keywd);
5403     printf("\n");
5404     printf(" Printer character-set: %s\n",txrinfo[prncs]->keywd);
5405 #endif /* NOTERM */
5406 #else /* OS2 */
5407 #ifndef MAC
5408     char *s;
5409
5410     debug(F101,"TERM LOCAL CSET","",csl);
5411     debug(F101,"TERM REMOTE CSET","",csr);
5412     printf(" Terminal character-set: ");
5413     if (tcs_transp) {                   /* No translation */
5414         printf("transparent\n");
5415     } else {                            /* Translation */
5416         printf("%s (remote) %s (local)\n",
5417                fcsinfo[csr].keyword,fcsinfo[csl].keyword);
5418         if (csr != csl) {
5419             switch(gettcs(csr,csl)) {
5420               case TC_USASCII:  s = "ascii";        break;
5421               case TC_1LATIN:   s = "latin1-iso";   break;
5422               case TC_2LATIN:   s = "latin2-iso";   break;
5423               case TC_CYRILL:   s = "cyrillic-iso"; break;
5424               case TC_JEUC:     s = "japanese-euc"; break;
5425               case TC_HEBREW:   s = "hebrew-iso";   break;
5426               case TC_GREEK:    s = "greek-iso";    break;
5427               case TC_9LATIN:   s = "latin9-iso";   break;
5428               default:          s = "transparent";  break;
5429             }
5430             if (strcmp(s,fcsinfo[csl].keyword) &&
5431                 strcmp(s,fcsinfo[csr].keyword))
5432               printf("                         (via %s)\n",s);
5433         }
5434     }
5435 #endif /* MAC */
5436 #endif /* OS2 */
5437 #endif /* NOCSETS */
5438 }
5439
5440 #ifndef NOLOCAL
5441 #ifdef OS2
5442 extern char htab[];
5443 VOID
5444 shotabs() {
5445     int i,j,k,n;
5446
5447     printf("Tab Stops:\n\n");
5448     for (i = 0, j = 1, k = VscrnGetWidth(VCMD); i < MAXTERMCOL; ) {
5449         do {
5450             printf("%c",htab[++i]=='T'?'T':'-');
5451         } while (i % k && i < MAXTERMCOL);
5452         printf("\n");
5453         for ( ; j <= i; j++) {
5454             switch ( j%10 ) {
5455               case 1:
5456                 printf("%c",j == 1 ? '1' : '.');
5457                 break;
5458               case 2:
5459               case 3:
5460               case 4:
5461               case 5:
5462               case 6:
5463               case 7:
5464                 printf("%c",'.');
5465                 break;
5466               case 8:
5467                 n = (j+2)/100;
5468                 if (n)
5469                   printf("%d",n);
5470                 else 
5471                   printf("%c",'.');
5472                 break;
5473               case 9:
5474                 n = (j+1)%100/10;
5475                 if (n)
5476                   printf("%d",n);
5477                 else if (j>90)
5478                   printf("0");
5479                 else 
5480                   printf("%c",'.');
5481                 break;
5482               case 0:
5483                 printf("0");
5484                 break;
5485             }
5486         }
5487         printf("\n");
5488     }
5489 #ifdef COMMENT
5490     for (i = 1; i <= 70; i++)
5491       printf("%c",htab[i]=='T'?'T':'-');
5492     printf("\n1.......10........20........30........40........50........60\
5493 ........70\n\n");
5494     for (; i <= 140; i++)
5495       printf("%c",htab[i]=='T'?'T':'-');
5496     printf("\n........80........90.......100.......110.......120.......130\
5497 .......140\n\n");
5498     for (; i <= 210; i++)
5499       printf("%c",htab[i]=='T'?'T':'-');
5500     printf("\n.......150.......160.......170.......180.......190.......200\
5501 .......210\n\n");
5502     for (; i <= 255; i++)
5503       printf("%c",htab[i]=='T'?'T':'-');
5504     printf("\n.......220.......230.......240.......250..255\n");
5505 #endif
5506
5507 }
5508 #endif /* OS2 */
5509 #endif /* NOLOCAL */
5510
5511 #ifdef OS2MOUSE
5512 VOID
5513 shomou() {
5514     int button, event, id, i;
5515     char * name = "";
5516
5517     printf("Mouse settings:\n");
5518     printf("   Button Count:   %d\n",mousebuttoncount());
5519     printf("   Active:         %s\n\n",showoff(tt_mouse));
5520
5521     for (button = 0; button < MMBUTTONMAX; button++)
5522       for (event = 0; event < MMEVENTSIZE; event++)
5523         if (mousemap[button][event].type != error)
5524           switch (mousemap[button][event].type) {
5525             case key:
5526               printf("   %s = Character: %c \\%d\n",
5527                      mousename(button,event),
5528                      mousemap[button][event].key.scancode,
5529                      mousemap[button][event].key.scancode );
5530               break;
5531             case kverb:
5532               id = mousemap[button][event].kverb.id & ~(F_KVERB);
5533               if (id != K_IGNORE) {
5534                   for (i = 0; i< nkverbs; i++)
5535                     if (id == kverbs[i].kwval) {
5536                         name = kverbs[i].kwd;
5537                         break;
5538                     }
5539                   printf("   %s = Kverb: \\K%s\n",
5540                          mousename(button,event),
5541                          name
5542                          );
5543               }
5544               break;
5545             case macro:
5546               printf("   %s = Macro: ",
5547                      mousename(button,event) );
5548               shostrdef(mousemap[button][event].macro.string);
5549               printf("\n");
5550               break;
5551           }
5552 }
5553 #endif /* OS2MOUSE */
5554
5555 #ifndef NOLOCAL
5556 VOID
5557 shotrm() {
5558     char *s;
5559     extern char * getiact();
5560     extern int tt_print, adl_err;
5561 #ifndef NOTRIGGER
5562     extern char * tt_trigger[];
5563 #endif /* NOTRIGGER */
5564 #ifdef CKTIDLE
5565     extern char * tt_idlesnd_str;
5566     extern int tt_idlesnd_tmo;
5567     extern int tt_idlelimit, tt_idleact;
5568 #endif /* CKTIDLE */
5569 #ifdef OS2
5570     extern int wy_autopage, autoscroll, sgrcolors, colorreset, user_erasemode,
5571       decscnm, decscnm_usr, tt_diff_upd, tt_senddata,
5572       wy_blockend, marginbell, marginbellcol, tt_modechg, dgunix;
5573     int lines = 0;
5574 #ifdef KUI
5575     extern CKFLOAT tt_linespacing[];
5576 #endif /* KUI */
5577 #ifdef PCFONTS
5578     int i;
5579     char *font;
5580
5581     if (IsOS2FullScreen()) {            /* Determine the font name */
5582         if (!os2LoadPCFonts()) {
5583             for (i = 0; i < ntermfont; i++) {
5584                 if (tt_font == term_font[i].kwval) {
5585                     font = term_font[i].kwd;
5586                     break;
5587                 }
5588             }
5589         } else {
5590             font = "(DLL not available)";
5591         }
5592     } else {
5593         font =     "(full screen only)";
5594     }
5595 #endif /* PCFONTS */
5596 #ifdef KUI
5597     char font[64] = "(unknown)";
5598     if ( ntermfont > 0 ) {
5599         int i;
5600         for (i = 0; i < ntermfont; i++) {
5601             if (tt_font == term_font[i].kwval) {
5602                 ckstrncpy(font,term_font[i].kwd,59);
5603                 ckstrncat(font," ",64);
5604                 ckstrncat(font,ckitoa(tt_font_size/2),64);
5605                 if ( tt_font_size % 2 )
5606                     ckstrncat(font,".5",64);
5607                 break;
5608             }
5609         }
5610     }
5611 #endif /* KUI */
5612
5613     printf("Terminal parameters:\n");
5614     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5615     printf(" %19s: %1d%-12s  %13s: %1d%-14s\n",
5616            "Bytesize: Command",
5617            (cmdmsk == 0377) ? 8 : 7,
5618            " bits","Terminal",
5619            (cmask == 0377) ? 8 : 7," bits");
5620     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5621     printf(" %19s: %-13s","Type",
5622            (tt_type >= 0 && tt_type <= max_tt) ?
5623            tt_info[tt_type].x_name :
5624            "unknown" );
5625     if (tt_type >= 0 && tt_type <= max_tt)
5626       if (strlen(tt_info[tt_type].x_id))
5627         printf("  %13s: <ESC>%s","ID",tt_info[tt_type].x_id);
5628     printf("\n");
5629     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5630     printf(" %19s: %-13s  %13s: %-15s\n","Echo",
5631            duplex ? "local" : "remote","Locking-shift",showoff(sosi));
5632     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5633     printf(" %19s: %-13s  %13s: %-15s\n","Newline-mode",
5634            showoff(tnlm),"Cr-display",tt_crd ? "crlf" : "normal");
5635     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5636     printf(" %19s: %-13s  %13s: %-15s\n","Cursor",
5637            (tt_cursor == 2) ? "full" :
5638            (tt_cursor == 1) ? "half" : "underline",
5639 #ifdef CK_AUTODL
5640            "autodownload",autodl == TAD_ON ?
5641            (adl_err ? "on, error stop" : "on, error continue") : 
5642            autodl == TAD_ASK ? 
5643            (adl_err ? "ask, error stop" : "ask, error continue") :
5644            "off"
5645 #else /* CK_AUTODL */
5646            "", ""
5647 #endif /* CK_AUTODL */
5648            );
5649     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5650     printf(" %19s: %-13s  %13s: %-15s\n","Arrow-keys",
5651            tt_arrow ? "application" : "cursor",
5652            "Keypad-mode", tt_keypad ? "application" : "numeric"
5653            );
5654
5655     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5656
5657     /* Just to make sure we are using current info */
5658     updanswerbk();
5659
5660     /*
5661        This line doesn't end with '\n' because the answerback string
5662        is terminated with a newline
5663     */
5664     printf(" %19s: %-13s  %13s: %-15s","Answerback",
5665            showoff(tt_answer),"response",answerback);
5666     switch (tt_bell) {
5667       case XYB_NONE:
5668         s = "none";
5669         break;
5670       case XYB_VIS:
5671         s= "visible";
5672         break;
5673       case XYB_AUD | XYB_BEEP:
5674         s="beep";
5675         break;
5676       case XYB_AUD | XYB_SYS:
5677         s="system sounds";
5678         break;
5679       default:
5680         s="(unknown)";
5681     }
5682     printf(" %19s: %-13s  %13s: %-15s\n","Bell",s,
5683            "Wrap",showoff(tt_wrap));
5684     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5685     printf(" %19s: %-13s  %13s: %-15s\n","Autopage",showoff(wy_autopage),
5686            "Autoscroll",showoff(autoscroll));
5687     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5688     printf(" %19s: %-13s  %13s: %-15s\n","SGR Colors",showoff(sgrcolors),
5689            "ESC[0m color",colorreset?"default-color":"current-color");
5690     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5691     printf(" %19s: %-13s  %13s: %-15s\n",
5692             "Erase color",user_erasemode?"default-color":"current-color",
5693            "Screen mode",decscnm?"reverse":"normal");
5694     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5695
5696     printf(" %19s: %-13d  %13s: %-15d\n","Transmit-timeout",tt_ctstmo,
5697            "Output-pacing",tt_pacing);
5698     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5699
5700     printf(" %19s: %-13d  %13s: %s\n","Idle-timeout",tt_idlelimit,
5701            "Idle-action", getiact());
5702
5703     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5704     printf(" %19s: %-13s  %13s: %-15s\n","Send data",
5705           showoff(tt_senddata),"End of Block", wy_blockend?"crlf/etx":"us/cr");
5706     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5707 #ifndef NOTRIGGER
5708     printf(" %19s: %-13s  %13s: %d seconds\n","Auto-exit trigger",
5709            tt_trigger[0],"Output pacing",tt_pacing );
5710     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5711 #endif /* NOTRIGGER */
5712     printf(" %19s: %-13s  %13s: %-15d\n","Margin bell",
5713            showoff(marginbell),"at column", marginbellcol);
5714     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5715     switch (tt_modechg) {
5716       case TVC_DIS: s = "disabled"; break;
5717       case TVC_ENA: s = "enabled";  break;
5718       case TVC_W95: s = "win95-restricted"; break;
5719       default: s = "(unknown)";
5720     }
5721     printf(" %19s: %-13s  %13s: %-15s\n","DG Unix mode",
5722            showoff(dgunix),"Video change", s);
5723     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5724
5725 #ifdef CK_APC
5726     if (apcstatus == APC_ON) s = "on";
5727     else if (apcstatus == APC_OFF) s = "off";
5728     else if (apcstatus == APC_ON|APC_UNCH) s = "unchecked";
5729     else if (apcstatus == APC_ON|APC_NOINP) s = "no-input";
5730     else if (apcstatus == APC_ON|APC_UNCH|APC_NOINP) s = "unchecked-no-input";
5731     printf(" %19s: %-13s  %13s: %-15s\n",
5732            "APC", s,
5733 #ifdef PCFONTS
5734            "Font (VGA)",font
5735 #else /* PCFONTS */
5736 #ifdef KUI
5737            "Font",font
5738 #else
5739            "Font","(not supported)"
5740 #endif /* KUI */
5741 #endif /* PCFONTS */
5742
5743            );
5744 #endif /* CK_APC */
5745     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5746
5747 #ifdef CK_TTGWSIZ                       /* Console terminal screen size */
5748     if (tt_cols[VTERM] < 0 || tt_rows[VTERM] < 0)
5749       ttgwsiz();                        /* Try to get latest size */
5750 #endif /* CK_TTGWSIZ */
5751     printf(" %19s: %-13d  %13s: %-15d\n","Height",tt_rows[VTERM],
5752            "Width",tt_cols[VTERM]);
5753     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5754 #ifdef KUI
5755     printf(" %19s: %-13f  %13s: %-15d\n","Line spacing",tt_linespacing[VTERM],
5756            "Display Height",VscrnGetDisplayHeight(VTERM));
5757     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5758 #endif /* KUI */
5759     printf(" %19s: %-13s  %13s: %d lines\n","Roll-mode",
5760           tt_roll[VTERM]?"insert":"overwrite","Scrollback", tt_scrsize[VTERM]);
5761     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5762
5763     if (updmode == tt_updmode)
5764       if (updmode == TTU_FAST)
5765         s = "fast (fast)";
5766       else
5767         s = "smooth (smooth)";
5768     else
5769       if (updmode == TTU_FAST)
5770         s = "fast (smooth)";
5771       else
5772         s = "smooth (fast)";
5773
5774     printf(" %19s: %-13s  %13s: %d ms\n","Screen-update: mode",s,
5775            "interval",tt_update);
5776     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5777     printf(" %19s: %-13s  %13s: %-15s\n",
5778            "Screen-optimization",showoff(tt_diff_upd),
5779            "Status line",showoff(tt_status[VTERM]));
5780     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5781     printf(" %19s: %-13s  %13s: %-15s\n","Debug",
5782            showoff(debses),"Session log", seslog? sesfil : "(none)" );
5783     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5784
5785     /* Display colors (should become SHOW COLORS) */
5786     {
5787         USHORT row, col;
5788         char * colors[16] = {
5789             "black","blue","green","cyan","red","magenta","brown","lgray",
5790             "dgray","lblue","lgreen","lcyan","lred","lmagent","yellow","white"
5791         };
5792         printf("\n");
5793         if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5794
5795         printf(" Color:");
5796 #ifndef ONETERMUPD
5797         GetCurPos(&row, &col);
5798         WrtCharStrAtt("border",    6, row, 9, &colorborder );
5799         WrtCharStrAtt("debug",     5, row, 17, &colordebug );
5800         WrtCharStrAtt("helptext",  8, row, 25, &colorhelp );
5801         WrtCharStrAtt("reverse",   7, row, 34, &colorreverse );
5802         WrtCharStrAtt("select",    6, row, 42, &colorselect );
5803         WrtCharStrAtt("status",    6, row, 50, &colorstatus );
5804         WrtCharStrAtt("terminal",  8, row, 58, &colornormal );
5805         WrtCharStrAtt("underline", 9, row, 67, &colorunderline );
5806 #endif /* ONETERMUPD */
5807         row = VscrnGetCurPos(VCMD)->y+1;
5808         VscrnWrtCharStrAtt(VCMD, "border",    6, row, 9, &colorborder );
5809         VscrnWrtCharStrAtt(VCMD, "debug",     5, row, 17, &colordebug );
5810         VscrnWrtCharStrAtt(VCMD, "helptext",  8, row, 25, &colorhelp );
5811         VscrnWrtCharStrAtt(VCMD, "reverse",   7, row, 34, &colorreverse );
5812         VscrnWrtCharStrAtt(VCMD, "select",    6, row, 42, &colorselect );
5813         VscrnWrtCharStrAtt(VCMD, "status",    6, row, 50, &colorstatus );
5814         VscrnWrtCharStrAtt(VCMD, "terminal",  8, row, 58, &colornormal );
5815         VscrnWrtCharStrAtt(VCMD, "underline",  9, row, 67, &colorunderline );
5816         printf("\n");
5817         if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5818
5819         /* Foreground color names */
5820         printf("%6s: %-8s%-8s%-9s%-8s%-8s%-8s%-9s%-9s\n","fore",
5821                 "",
5822                 colors[colordebug&0x0F],
5823                 colors[colorhelp&0x0F],
5824                 colors[colorreverse&0x0F],
5825                 colors[colorselect&0x0F],
5826                 colors[colorstatus&0x0F],
5827                 colors[colornormal&0x0F],
5828                 colors[colorunderline&0x0F]);
5829         if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5830
5831         /* Background color names */
5832         printf("%6s: %-8s%-8s%-9s%-8s%-8s%-8s%-9s%-9s\n","back",
5833                 colors[colorborder],
5834                 colors[colordebug>>4],
5835                 colors[colorhelp>>4],
5836                 colors[colorreverse>>4],
5837                 colors[colorselect>>4],
5838                 colors[colorstatus>>4],
5839                 colors[colornormal>>4],
5840                 colors[colorunderline>>4] );
5841         if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5842         printf("\n");
5843         if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5844         printf(" Color:");
5845 #ifndef ONETERMUPD
5846         GetCurPos(&row, &col);
5847         WrtCharStrAtt("graphic",   7, row, 9, &colorgraphic );
5848         WrtCharStrAtt("command",   7, row, 17, &colorcmd );
5849         WrtCharStrAtt("italic",    6, row, 26, &coloritalic );
5850 #endif /* ONETERMUPD */
5851         row = VscrnGetCurPos(VCMD)->y+1;
5852         VscrnWrtCharStrAtt(VCMD, "graphic",   7, row, 9,  &colorgraphic );
5853         VscrnWrtCharStrAtt(VCMD, "command",   7, row, 17, &colorcmd );
5854         VscrnWrtCharStrAtt(VCMD, "italic",    6, row, 26, &coloritalic );
5855         printf("\n");
5856         if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5857
5858         /* Foreground color names */
5859         printf("%6s: %-8s%-8s%-8s\n","fore",
5860                 colors[colorgraphic&0x0F],
5861                 colors[colorcmd&0x0F],
5862                 colors[coloritalic&0x0F]);
5863         if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5864
5865         /* Background color names */
5866         printf("%6s: %-8s%-8s%-8s\n","back",
5867                 colors[colorgraphic>>4],
5868                 colors[colorcmd>>4],
5869                 colors[coloritalic>>4]);
5870         if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5871     }
5872     printf("\n");
5873     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5874     {
5875         extern int trueblink, truereverse, trueunderline, trueitalic;
5876         printf(
5877     " Attribute:  blink: %-3s  reverse: %-3s  underline: %-3s italic: %-3s\n",
5878                 trueblink?"on":"off", truereverse?"on":"off",
5879                 trueunderline?"on":"off", trueitalic?"on":"off");
5880         if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5881     }
5882     {
5883         extern vtattrib WPattrib;
5884         printf(" ASCII Protected chars: %s%s%s%s%s%s%s\n",
5885                 WPattrib.blinking?"blink ":"",
5886                 WPattrib.italic?"italic ":"",
5887                 WPattrib.reversed?"reverse ":"",
5888                 WPattrib.underlined?"underline ":"",
5889                 WPattrib.bold?"bold ":"",
5890                 WPattrib.dim?"dim ":"",
5891                 WPattrib.invisible?"invisible ":"");
5892         if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5893     }
5894
5895     printf("\n");
5896     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5897     (VOID) shoesc(escape);
5898     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5899     printf(" See SHOW CHARACTER-SETS for character-set info\n");
5900     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5901
5902 #else /* OS2 */   /* Beginning of new non-OS2 version */
5903
5904     printf("\n");
5905     printf("Terminal parameters:\n");
5906     printf(" %19s: %1d%-12s  %13s: %1d%-14s\n",
5907            "Bytesize: Command",
5908            (cmdmsk == 0377) ? 8 : 7,
5909            " bits","Terminal",
5910            (cmask == 0377) ? 8 : 7," bits");
5911     s = getenv("TERM");
5912 #ifdef XPRINT
5913     printf(" %19s: %-13s  %13s: %-15s\n",
5914            "Type",
5915            s ? s : "(unknown)",
5916            "Print",
5917            showoff(tt_print)
5918            );
5919 #else
5920     printf(" %19s: %-13s\n","Type", s ? s : "(unknown)");
5921 #endif /* XPRINT */
5922     printf(" %19s: %-13s  %13s: %-15s\n","Echo",
5923            duplex ? "local" : "remote","Locking-shift",showoff(sosi));
5924     printf(" %19s: %-13s  %13s: %-15s\n","Newline-mode",
5925            showoff(tnlm),"Cr-display",tt_crd ? "crlf" : "normal");
5926
5927 #ifdef CK_APC
5928     if (apcstatus == APC_ON) s = "on";
5929     else if (apcstatus == APC_OFF) s = "off";
5930     else if (apcstatus == APC_ON|APC_UNCH) s = "unchecked";
5931     else if (apcstatus == APC_ON|APC_NOINP) s = "no-input";
5932     else if (apcstatus == APC_ON|APC_UNCH|APC_NOINP) s = "unchecked-no-input";
5933     printf(" %19s: %-13s  %13s: %-15s\n",
5934            "APC", s,
5935 #ifdef CK_AUTODL
5936            "Autodownload", autodl ?
5937            (adl_err ? "on, error stop" : "on, error continue") : "off"
5938 #else
5939            "",""
5940 #endif /* CK_AUTODL */
5941            );
5942 #endif /* CK_APC */
5943
5944 #ifdef CK_TTGWSIZ                       /* Console terminal screen size */
5945     ttgwsiz();                          /* Try to get latest size */
5946     printf(" %19s: %-13d  %13s: %-15d\n","Height",tt_rows, "Width", tt_cols);
5947 #endif /* CK_TTGWSIZ */
5948
5949     printf(" %19s: %-13s  %13s: %-15s\n","Debug",
5950            showoff(debses),"Session log", seslog? sesfil : "(none)" );
5951
5952 #ifdef CKTIDLE
5953     printf(" %19s: %-13d  %13s: %s\n","Idle-timeout",tt_idlelimit,
5954            "Idle-action", getiact());
5955 #endif /* CKTIDLE */
5956
5957 #ifndef NOTRIGGER
5958     printf(" %19s: %-13s\n","Trigger",
5959            tt_trigger[0] ? tt_trigger[0] : "(none)");
5960 #endif /* NOTRIGGER */
5961 #ifdef UNIX
5962 #ifndef NOJC
5963     printf(" %19s: %-13s\n\n","Suspend", showoff(xsuspend));
5964 #endif /* NOJC */
5965 #endif /* UNIX */
5966
5967     printf("\n");
5968     (VOID) shoesc(escape);
5969 #ifndef NOCSETS
5970     shotcs(tcsl,tcsr);          /* Show terminal character sets */
5971 #endif /* NOCSETS */
5972
5973 #endif /* OS2 */
5974 }
5975
5976 VOID
5977 shmdmlin() {                            /* Briefly show modem & line */
5978 #ifndef NODIAL
5979 #ifndef MINIDIAL
5980 #ifdef OLDTBCODE
5981     extern int tbmodel;
5982     _PROTOTYP( char * gtbmodel, (void) );
5983 #endif /* OLDTBCODE */
5984 #endif /* MINIDIAL */
5985 #endif /* NODIAL */
5986     if (local)
5987 #ifdef OS2
5988       printf(" Port: %s, Modem type: ",ttname);
5989 #else
5990       printf(" Line: %s, Modem type: ",ttname);
5991 #endif /* OS2 */
5992     else
5993       printf(
5994 #ifdef OS2
5995 " Communication device not yet selected with SET PORT\n Modem type: "
5996 #else
5997 " Communication device not yet selected with SET LINE\n Modem type: "
5998 #endif /* OS2 */
5999              );
6000 #ifndef NODIAL
6001     printf("%s",gmdmtyp());
6002 #ifndef MINIDIAL
6003 #ifdef OLDTBCODE
6004     if (tbmodel) printf(" (%s)",gtbmodel()); /* Telebit model info */
6005 #endif /* OLDTBCODE */
6006 #endif /* MINIDIAL */
6007 #else
6008     printf("(disabled)");
6009 #endif /* NODIAL */
6010 }
6011
6012 #ifdef CK_TAPI
6013 void
6014 shotapi(int option) {
6015     int rc=0,k ;
6016     char *s=NULL;
6017     LPDEVCFG        lpDevCfg = NULL;
6018     LPCOMMCONFIG    lpCommConfig = NULL;
6019     LPMODEMSETTINGS lpModemSettings = NULL;
6020     DCB *           lpDCB = NULL;
6021     extern struct keytab * tapiloctab;  /* Microsoft TAPI Locations */
6022     extern int ntapiloc;
6023     extern struct keytab * tapilinetab; /* Microsoft TAPI Line Devices */
6024     extern int ntapiline;
6025     extern int tttapi;                  /* TAPI in use */
6026     extern int tapipass;                /* TAPI Passthrough mode */
6027     extern int tapiconv;                /* TAPI Conversion mode */
6028     extern int tapilights;
6029     extern int tapipreterm;
6030     extern int tapipostterm;
6031     extern int tapimanual;
6032     extern int tapiinactivity;
6033     extern int tapibong;
6034     extern int tapiusecfg;
6035     extern char tapiloc[];
6036     extern int tapilocid;
6037     extern int TAPIAvail;
6038
6039     if (!TAPIAvail) {
6040         printf("TAPI Support not enabled\r\n");
6041         return;
6042     }
6043     switch (option) {
6044       case 0:
6045         printf("TAPI Settings:\n");
6046         printf("  Line:                      %s\n",
6047                tttapi ? ttname : "(none in use)");
6048
6049         cktapiBuildLocationTable(&tapiloctab, &ntapiloc);
6050         if (tapilocid == -1)
6051           tapilocid = cktapiGetCurrentLocationID();
6052
6053         /* Find the current tapiloc entry */
6054         /* and use it as the default. */
6055         for (k = 0; k < ntapiloc; k++) {
6056             if (tapiloctab[k].kwval == tapilocid)
6057               break;
6058         }
6059         if (k >= 0 && k < ntapiloc)
6060           s = tapiloctab[k].kwd;
6061         else
6062           s = "(unknown)";
6063         printf("  Location:                  %s\n",s);
6064         printf("  Modem-dialing:             %s\n",tapipass?"off":"on");
6065         printf("  Phone-number-conversions:  %s\n",
6066                 tapiconv==CK_ON?"on":tapiconv==CK_AUTO?"auto":"off");
6067         printf("  Modem-lights:              %s %s\n",tapilights?"on ":"off",
6068                 tapipass?"(n/a)":"");
6069         printf("  Predial-terminal:          %s %s\n",tapipreterm?"on ":"off",
6070                 tapipass?"(n/a)":"");
6071         printf("  Postdial-terminal:         %s %s\n",tapipostterm?"on ":"off",
6072                 tapipass?"(n/a)":"");
6073         printf("  Manual-dial:               %s %s\n",tapimanual?"on ":"off",
6074                 tapipass?"(n/a)":"");
6075         printf("  Inactivity-timeout:        %d seconds %s\n",tapiinactivity,
6076                 tapipass?"(n/a)":"");
6077         printf("  Wait-for-bong:             %d seconds %s\n",tapibong,
6078                 tapipass?"(n/a)":"");
6079         printf("  Use-windows-configuration: %s %s\n",
6080                 tapiusecfg?"on ":"off", tapipass?"(n/a)":"");
6081         printf("\n");
6082
6083 #ifdef BETATEST
6084         if (tapipass) {
6085 printf("K-95 uses the TAPI Line in an exclusive mode.  Other applications\n");
6086 printf("may open the device but may not place calls nor answer calls.\n");
6087 printf("Dialing is performed using the K-95 dialing procedures.  SET MODEM\n");
6088 printf("TYPE TAPI after the SET TAPI LINE command to activate the modem\n");
6089 printf("definition associated with the active TAPI LINE device.\n\n");
6090
6091         } else {
6092
6093 printf("K-95 uses the TAPI Line in a cooperative mode.  Other applications\n");
6094 printf("may open the device, place and answer calls.  Dialing is performed\n");
6095 printf("by TAPI.  K-95 SET MODEM commands are not used.\n\n");
6096         }
6097
6098         if (tapiconv == CK_ON ||
6099             tapiconv == CK_AUTO && !tapipass) {
6100 printf(
6101 "Phone numbers are converted from canonical to dialable form by TAPI\n");
6102 printf("using the dialing rules specified in the TAPI Dialing Properties\n");
6103 printf("dialog.\n\n");
6104
6105         } else {
6106
6107 printf(
6108 "Phone numbers are converted from canonical to dialable form by K-95\n");
6109 printf(
6110 "using the dialing rules specified with the SET DIAL commands.  TAPI\n");
6111 printf(
6112 "Dialing Properties are imported automaticly upon startup and whenever\n");
6113 printf("the TAPI Dialing Properties are altered or when the TAPI Location\n");
6114 printf("is changed.\n\n");
6115         }
6116 #endif /* BETATEST */
6117
6118         if (tapipass) {
6119             printf("Type SHOW MODEM to see MODEM configuration.\n");
6120             if (tapiconv == CK_ON)
6121               printf("Type SHOW DIAL to see DIAL-related items.\n");
6122         } else {
6123             if (tapiconv == CK_ON || tapiconv == CK_AUTO)
6124               printf("Type SHOW DIAL to see DIAL-related items.\n");
6125         }
6126         break;
6127       case 1:
6128         cktapiDisplayTapiLocationInfo();
6129         break;
6130       case 2:
6131         rc = cktapiGetModemSettings(&lpDevCfg,&lpModemSettings,
6132                                      &lpCommConfig,&lpDCB);
6133         if (rc) {
6134             cktapiDisplayModemSettings(lpDevCfg,lpModemSettings,
6135                                          lpCommConfig,lpDCB);
6136         } else {
6137             printf("?Unable to retrieve Modem Settings\n");
6138         }
6139         break;
6140       case 3: {
6141           HANDLE hModem = GetModemHandleFromLine((HLINE)0);
6142           if (hModem)
6143             DisplayCommProperties(hModem);
6144           else
6145             printf("?Unable to retrieve a valid Modem Handle\n");
6146           CloseHandle(hModem);
6147           break;
6148       }
6149     }
6150     printf("\n");
6151 }
6152 #endif /* CK_TAPI */
6153 #endif /* NOLOCAL */
6154
6155 #ifdef PATTERNS
6156 static VOID
6157 shopat() {
6158     extern char * binpatterns[], * txtpatterns[];
6159     extern int patterns, filepeek;
6160     char **p, *s;
6161     int i, j, k, n, flag, width;
6162 #ifdef CK_TTGWSIZ
6163     ttgwsiz();                          /* Try to get latest size */
6164 #ifdef OS2
6165     width = tt_cols[VCMD];
6166 #else /* OS2 */
6167     width = tt_cols;
6168 #endif /* OS2 */
6169     if (width < 1)
6170 #endif /* CK_TTGWSIZ */
6171       width = 80;
6172     printf("\n");
6173     printf(" Set file type:            %s\n",gfmode(binary,1));
6174     printf(" Set file patterns:        %s", showooa(patterns));
6175 #ifdef CK_LABELED
6176     if (binary == XYFT_L)
6177       printf(" (but SET FILE TYPE LABELED overrides)\n");
6178     else
6179 #endif /* CK_LABELED */
6180 #ifdef VMS
6181     if (binary == XYFT_I)
6182       printf(" (but SET FILE TYPE IMAGE overrides)\n");
6183     else
6184 #endif /* VMS */
6185     if (filepeek)
6186       printf(" (but SET FILE SCAN ON overrides)\n");
6187     else
6188       printf("\n");
6189     printf(" Maximum patterns allowed: %d\n", FTPATTERNS);
6190     for (k = 0; k < 2; k++) {           /* For each kind of patter */
6191         printf("\n");
6192         if (k == 0) {                   /* binary... */
6193             printf(" File binary-patterns: ");
6194             p = binpatterns;
6195         } else {                        /* text... */
6196             printf(" File text-patterns:   ");
6197             p = txtpatterns;
6198         }
6199         if (!p[0]) {
6200             printf("(none)\n");
6201         } else {
6202             printf("\n ");
6203             n = 2;
6204             for (i = 0; i < FTPATTERNS; i++) { /* For each pattern */
6205                 if (!p[i])              /* Done */
6206                   break;
6207                 s = p[i];               /* Look for embedded space */
6208                 for (j = 0, flag = 1; *s; s++, j++) /* and also get length */
6209                   if (*s == SP)
6210                     flag = 3;
6211                 n += j + flag;          /* Length of this line */
6212                 if (n >= width - 1) {
6213                     printf("\n ");
6214                     n = j+2;
6215                 }
6216                 printf(flag == 3 ? " {%s}" : " %s", p[i]);
6217             }
6218             if (n > 2)
6219               printf("\n");
6220         }
6221     }
6222     printf("\n");
6223 }
6224 #endif /* PATTERNS */
6225
6226 #ifndef NOSPL
6227 static VOID
6228 shooutput() {
6229     printf(" Output pacing:          %d (milliseconds)\n",pacing);
6230     printf(" Output special-escapes: %s\n", showoff(outesc));
6231 }
6232
6233 static VOID
6234 shoinput() {
6235 #ifdef CKFLOAT
6236     extern char * inpscale;
6237 #endif  /* CKFLOAT */
6238
6239 #ifdef CK_AUTODL
6240     printf(" Input autodownload:     %s\n", showoff(inautodl));
6241 #endif /* CK_AUTODL */
6242     printf(" Input cancellation:     %s\n", showoff(inintr));
6243     printf(" Input case:             %s\n", inpcas[cmdlvl] ?
6244            "observe" : "ignore");
6245     printf(" Input buffer-length:    %d\n", inbufsize);
6246     printf(" Input echo:             %s\n", showoff(inecho));
6247     printf(" Input silence:          %d (seconds)\n", insilence);
6248 #ifdef OS2
6249     printf(" Input terminal:         %s\n", showoff(interm));
6250 #endif /* OS2 */
6251     printf(" Input timeout:          %s\n", intime[cmdlvl] ?
6252            "quit" : "proceed");
6253 #ifdef CKFLOAT
6254     printf(" Input scale-factor:     %s\n", inpscale ? inpscale : "1.0");
6255 #endif  /* CKFLOAT */
6256
6257     if (instatus < 0)
6258       printf(" Last INPUT:             -1 (INPUT command not yet given)\n");
6259     else
6260       printf(" Last INPUT:             %d (%s)\n", instatus,i_text[instatus]);
6261 }
6262 #endif /* NOSPL */
6263
6264 #ifndef NOSPL
6265 int
6266 showarray() {
6267 #ifdef COMMENT
6268     char * p, * q, ** ap;
6269     int i;
6270 #endif /* COMMENT */
6271     char *s; int x = 0, y;
6272     int range[2];
6273
6274     if ((y = cmfld("Array name","",&s,NULL)) < 0)
6275       if (y != -3)
6276         return(y);
6277     ckstrncpy(line,s,LINBUFSIZ);
6278     s = line;
6279     if ((y = cmcfm()) < 0)
6280       return(y);
6281     if (*s) {
6282         char ** ap;
6283         if ((x = arraybounds(s,&(range[0]),&(range[1]))) < 0) {
6284             printf("?Bad array: %s\n",s);
6285             return(-9);
6286         }
6287         ap = a_ptr[x];
6288         if (!ap) {
6289             printf("Array not declared: %s\n", s);
6290             return(success = 1);
6291         } else {
6292             int i, n, max;
6293             max = (range[1] > 0) ?
6294               range[1] :
6295                 ((range[0] > 0) ? range[0] : a_dim[x]);
6296             if (range[0] < 0)
6297               range[0] = 0;
6298             if (max > a_dim[x])
6299               max = a_dim[x];
6300             n = 1;
6301             printf("\\&%c[]: Dimension = %d",arrayitoa(x),a_dim[x]);
6302             if (a_link[x] > -1)
6303               printf(" (Link to \\&%c[])",arrayitoa(a_link[x]));
6304             printf("\n");
6305             for (i = range[0]; i <= max; i++) {
6306                 if (ap[i]) {
6307                     printf("%3d. %s\n",i,ap[i]);
6308                     if (xaskmore) {
6309                         if (cmd_cols > 0) {
6310                             x = strlen(ap[i]) + 5;
6311                             y = (x % cmd_cols) ? 1 : 0;
6312                             n += (x / cmd_cols) + y;
6313                         } else {
6314                             n++;
6315                         }
6316                         if (n > (cmd_rows - 3)) {
6317                             if (!askmore())
6318                               break;
6319                             else
6320                               n = 0;
6321                         }
6322                     }
6323                 }
6324             }
6325         }
6326         return(1);
6327     }
6328
6329     /* All arrays - just show name and dimension */
6330
6331     for (y = 0; y < (int) 'z' - ARRAYBASE + 1; y++) {
6332         if (a_ptr[y]) {
6333             if (x == 0) printf("Declared arrays:\n");
6334             x = 1;
6335             printf(" \\&%c[%d]",
6336                    (y == 1) ? 64 : y + ARRAYBASE, a_dim[y]);
6337             if (a_link[y] > -1)
6338               printf(" => \\&%c[]",arrayitoa(a_link[y]));
6339             printf("\n");
6340         }
6341         if (!x) printf(" No arrays declared\n");
6342     }
6343     return(1);
6344 }
6345 #endif /* NOSPL */
6346
6347 int
6348 doshow(x) int x; {
6349     int y, z, i; long zz;
6350     extern int optlines;
6351     char *s;
6352 #ifdef OS2
6353     extern int os2gks;
6354     extern int tt_kb_mode;
6355 #endif /* OS2 */
6356     extern int srvcdmsg;
6357     extern char * cdmsgstr, * ckcdpath;
6358
6359 #ifndef NOSETKEY
6360     if (x == SHKEY) {                   /* SHOW KEY */
6361         int c;
6362 #ifdef OS2
6363         if ((x = cmkey(shokeytab,nshokey,"How many keys should be shown?",
6364                         "one",xxstring)) < 0) return(x);
6365         switch (tt_kb_mode) {
6366           case KBM_EM:
6367             s = "emacs";
6368             break;
6369           case KBM_HE:
6370             s = "hebrew";
6371             break;
6372           case KBM_RU:
6373             s = "russian";
6374             break;
6375           case KBM_EN:
6376           default:
6377             s = "default";
6378             break;
6379         }
6380         if ((z = cmkey(shokeymtab,nshokeym,"Which definition should be shown?",
6381                         s,xxstring)) < 0) return(z);
6382         if (z == SHKEYDEF)
6383           z = -1;
6384 #endif /* OS2 */
6385         if ((y = cmcfm()) < 0) return(y);
6386 #ifdef IKSD
6387         if (inserver) {
6388             printf("Sorry, command disabled.\r\n");
6389             return(success = 0);
6390         }
6391 #endif /* IKSD */
6392
6393 #ifdef MAC
6394         printf("Not implemented\n");
6395         return(0);
6396 #else /* Not MAC */
6397 #ifdef OS2
6398         if (x) {
6399             con_event evt;
6400             for (c = 0; c < KMSIZE; c++) {
6401                 evt = (z < 0) ? mapkey(c) : maptermkey(c,z);
6402                 if (evt.type != error) {
6403                     shokeycode(c,z);
6404                 }
6405             }
6406         } else {
6407 #endif /* OS2 */
6408             printf(" Press key: ");
6409 #ifdef UNIX
6410 #ifdef NOSETBUF
6411             fflush(stdout);
6412 #endif /* NOSETBUF */
6413 #endif /* UNIX */
6414             conbin((char)escape);       /* Put terminal in binary mode */
6415 #ifdef OS2
6416             os2gks = 0;                 /* Raw scancode processing */
6417 #endif /* OS2 */
6418             c = congks(0);              /* Get character or scan code */
6419 #ifdef OS2
6420             os2gks = 1;                 /* Cooked scancode processing */
6421 #endif /* OS2 */
6422             concb((char)escape);        /* Restore terminal to cbreak mode */
6423             if (c < 0) {                /* Check for error */
6424                 printf("?Error reading key\n");
6425                 return(0);
6426             }
6427 #ifndef OS2
6428 /*
6429   Do NOT mask when it can be a raw scan code, perhaps > 255
6430 */
6431             c &= cmdmsk;                /* Apply command mask */
6432 #endif /* OS2 */
6433             printf("\n");
6434 #ifdef OS2
6435             shokeycode(c,z);
6436 #else /* OS2 */
6437             shokeycode(c);
6438 #endif /* OS2 */
6439 #ifdef OS2
6440         }
6441 #endif /* OS2 */
6442         return(1);
6443 #endif /* MAC */
6444     }
6445 #ifndef NOKVERBS
6446     if (x == SHKVB) {                   /* SHOW KVERBS */
6447         if ((y = cmcfm()) < 0) return(y);
6448 #ifdef IKSD
6449         if (inserver) {
6450             printf("Sorry, command disabled.\r\n");
6451             return(success = 0);
6452         }
6453 #endif /* IKSD */
6454         printf("\nThe following %d keyboard verbs are available:\n\n",nkverbs);
6455         kwdhelp(kverbs,nkverbs,"","\\K","",3,0);
6456         printf("\n");
6457         return(1);
6458     }
6459 #ifdef OS2
6460     if (x == SHUDK) {                   /* SHOW UDKs */
6461         extern void showudk(void);
6462         if ((y = cmcfm()) < 0) return(y);
6463 #ifdef IKSD
6464         if (inserver) {
6465             printf("Sorry, command disabled.\r\n");
6466             return(success = 0);
6467         }
6468 #endif /* IKSD */
6469         showudk();
6470         return(1);
6471     }
6472 #endif /* OS2 */
6473 #endif /* NOKVERBS */
6474 #endif /* NOSETKEY */
6475
6476 #ifndef NOSPL
6477     if (x == SHMAC) {                   /* SHOW MACRO */
6478         struct FDB kw, fl, cm;
6479         int i, k, n = 0, left, flag, confirmed = 0;
6480         char * p, *q[64];
6481         for (i = 0; i < nmac; i++) {    /* copy the macro table */
6482             mackey[i].kwd = mactab[i].kwd; /* into a regular keyword table */
6483             mackey[i].kwval = i;        /* with value = pointer to macro tbl */
6484             mackey[i].flgs = mactab[i].flgs;
6485         }
6486         p = line;
6487         left = LINBUFSIZ;
6488         while (!confirmed && n < 64) {
6489             cmfdbi(&kw,                 /* First FDB - macro table */
6490                    _CMKEY,              /* fcode */
6491                    "Macro name",        /* hlpmsg */
6492                    "",                  /* default */
6493                    "",                  /* addtl string data */
6494                    nmac,                /* addtl numeric data 1: tbl size */
6495                    0,                   /* addtl numeric data 2: 4 = cmswi */
6496                    xxstring,            /* Processing function */
6497                    mackey,              /* Keyword table */
6498                    &fl                  /* Pointer to next FDB */
6499                    );
6500             cmfdbi(&fl,                 /* 2nd FDB - something not in mactab */
6501                    _CMFLD,              /* fcode */
6502                    "",                  /* hlpmsg */
6503                    "",                  /* default */
6504                    "",                  /* addtl string data */
6505                    0,                   /* addtl numeric data 1 */
6506                    0,                   /* addtl numeric data 2 */
6507                    xxstring,
6508                    NULL,
6509                    &cm
6510                    );
6511             cmfdbi(&cm,                 /* 3rd FDB - Confirmation */
6512                    _CMCFM,              /* fcode */
6513                    "",                  /* hlpmsg */
6514                    "",                  /* default */
6515                    "",                  /* addtl string data */
6516                    0,                   /* addtl numeric data 1 */
6517                    0,                   /* addtl numeric data 2 */
6518                    NULL,
6519                    NULL,
6520                    NULL
6521                    );
6522             x = cmfdb(&kw);             /* Parse something */
6523             if (x < 0)
6524               return(x);
6525             s = atmbuf;                 /* What the user typed */
6526             switch (cmresult.fcode) {
6527               case _CMKEY:              /* If it was a keyword */
6528                 y = mlook(mactab,atmbuf,nmac); /* get full name */
6529                 if (y > -1)
6530                   s = mactab[y].kwd;    /* (fall thru on purpose...) */
6531               case _CMFLD:
6532                 k = ckstrncpy(p,s,left) + 1; /* Copy result to list */
6533                 left -= k;
6534                 if (left <= 0) {
6535                     *p = NUL;
6536                     break;
6537                 }
6538                 q[n++] = p;             /* Point to this item */
6539                 p += k;                 /* Move buffer pointer past it */
6540                 break;
6541               case _CMCFM:              /* End of command */
6542                 confirmed++;
6543               default:
6544                 break;
6545             }
6546         }
6547         if (n == 0) {
6548             printf("Macros:\n");
6549             slc = 1;
6550             for (y = 0; y < nmac; y++)
6551               if (shomac(mactab[y].kwd,mactab[y].mval) < 0) break;
6552             return(1);
6553         }
6554         slc = 0;
6555         for (i = 0; i < n; i++) {
6556             flag = 0;
6557             s = q[i];
6558             if (!s) s = "";
6559             if (!*s) continue;
6560             if (iswild(s)) {            /* Pattern match */
6561                 for (k = 0, x = 0; x < nmac; x++) {
6562                     if (ckmatch(s,mactab[x].kwd,0,1)) {
6563                         shomac(mactab[x].kwd,mactab[x].mval);
6564                         k++;
6565                     }
6566                 }
6567                 if (!k)
6568                   x = -1;
6569                 else
6570                   continue;
6571             } else {                    /* Exact match */
6572                 x = mxlook(mactab,s,nmac);
6573                 flag = 1;
6574             }
6575             if (flag && x == -1)
6576               x = mlook(mactab,s,nmac);
6577             switch (x) {
6578               case -3:                  /* Nothing to look up */
6579               case -1:                  /* Not found */
6580                 printf("%s - (not defined)\n",s);
6581                 break;
6582               case -2:                  /* Ambiguous, matches more than one */
6583                 printf("%s - ambiguous\n",s);
6584                 break;
6585               default:                  /* Matches one exactly */
6586                 shomac(mactab[x].kwd,mactab[x].mval);
6587                 break;
6588             }
6589         }
6590         return(1);
6591     }
6592 #endif /* NOSPL */
6593
6594 /*
6595   Other SHOW commands only have two fields.  Get command confirmation here,
6596   then handle with big switch() statement.
6597 */
6598 #ifndef NOSPL
6599     if (x != SHBUI && x != SHARR)
6600 #endif /* NOSPL */
6601       if ((y = cmcfm()) < 0)
6602         return(y);
6603
6604 #ifdef COMMENT
6605     /* This restriction is too general. */
6606 #ifdef IKSD
6607     if (inserver &&
6608 #ifdef CK_LOGIN
6609         isguest
6610 #else
6611         0
6612 #endif /* CK_LOGIN */
6613         ) {
6614         printf("Sorry, command disabled.\r\n");
6615         return(success = 0);
6616     }
6617 #endif /* IKSD */
6618 #endif /* COMMENT */
6619
6620     switch (x) {
6621
6622 #ifdef ANYX25
6623 #ifndef IBMX25
6624       case SHPAD:
6625         shopad(0);
6626         break;
6627 #endif /* IBMX25 */
6628 #endif /* ANYX25 */
6629
6630       case SHNET:
6631 #ifdef NOLOCAL
6632         printf(" No network support in this version of C-Kermit.\n");
6633 #else
6634 #ifndef NETCONN
6635         printf(" No network support in this version of C-Kermit.\n");
6636 #else
6637         shonet();
6638 #endif /* NETCONN */
6639 #endif /* NOLOCAL */
6640         break;
6641
6642       case SHPAR:
6643         shopar();
6644         break;
6645
6646 #ifndef NOXFER
6647       case SHATT:
6648         shoatt();
6649         break;
6650 #endif /* NOXFER */
6651
6652 #ifndef NOSPL
6653       case SHCOU:
6654         printf(" %d\n",count[cmdlvl]);
6655         break;
6656 #endif /* NOSPL */
6657
6658 #ifndef NOSERVER
6659       case SHSER:                       /* Show Server */
6660         i = 0;
6661 #ifndef NOFRILLS
6662         printf("Function:          Status:\n");
6663         i++;
6664         printf(" GET                %s\n",nm[en_get]);
6665         i++;
6666         printf(" SEND               %s\n",nm[en_sen]);
6667         i++;
6668         printf(" MAIL               %s\n",nm[inserver ? 0 : en_mai]);
6669         i++;
6670         printf(" PRINT              %s\n",nm[inserver ? 0 : en_pri]);
6671         i++;
6672 #ifndef NOSPL
6673         printf(" REMOTE ASSIGN      %s\n",nm[en_asg]);
6674         i++;
6675 #endif /* NOSPL */
6676         printf(" REMOTE CD/CWD      %s\n",nm[en_cwd]);
6677         i++;
6678 #ifdef ZCOPY
6679         printf(" REMOTE COPY        %s\n",nm[en_cpy]);
6680         i++;
6681 #endif /* ZCOPY */
6682         printf(" REMOTE DELETE      %s\n",nm[en_del]);
6683         printf(" REMOTE DIRECTORY   %s\n",nm[en_dir]);
6684         printf(" REMOTE HOST        %s\n",nm[inserver ? 0 : en_hos]);
6685         i += 3;
6686 #ifndef NOSPL
6687         printf(" REMOTE QUERY       %s\n",nm[en_que]);
6688         i++;
6689 #endif /* NOSPL */
6690         printf(" REMOTE MKDIR       %s\n",nm[en_mkd]);
6691         printf(" REMOTE RMDIR       %s\n",nm[en_rmd]);
6692         printf(" REMOTE RENAME      %s\n",nm[en_ren]);
6693         printf(" REMOTE SET         %s\n",nm[en_set]);
6694         printf(" REMOTE SPACE       %s\n",nm[en_spa]);
6695         printf(" REMOTE TYPE        %s\n",nm[en_typ]);
6696         printf(" REMOTE WHO         %s\n",nm[inserver ? 0 : en_who]);
6697         printf(" BYE                %s\n",nm[en_bye]);
6698         printf(" FINISH             %s\n",nm[en_fin]);
6699         printf(" EXIT               %s\n",nm[en_xit]);
6700         printf(" ENABLE             %s\n",nm[en_ena]);
6701         i += 11;
6702 #endif /* NOFRILLS */
6703         if (i > cmd_rows - 3) { if (!askmore()) return(1); else i = 0; }
6704         printf("Server timeout:      %d\n",srvtim);
6705         if (++i > cmd_rows - 3) { if (!askmore()) return(1); else i = 0; }
6706         printf("Server idle-timeout: %d\n",srvidl);
6707         if (++i > cmd_rows - 3) { if (!askmore()) return(1); else i = 0; }
6708         printf("Server keepalive     %s\n", showoff(srvping));
6709         if (++i > cmd_rows - 3) { if (!askmore()) return(1); else i = 0; }
6710         printf("Server cd-message    %s\n", showoff(srvcdmsg));
6711         if (srvcdmsg && cdmsgstr)
6712           printf("Server cd-message    %s\n", cdmsgstr);
6713         if (++i > cmd_rows - 3) { if (!askmore()) return(1); else i = 0; }
6714         printf("Server display:      %s\n", showoff(srvdis));
6715         if (++i > cmd_rows - 3) { if (!askmore()) return(1); else i = 0; }
6716         printf("Server login:        ");
6717         if (!x_user) {
6718             printf("(none)\n");
6719         } else {
6720             printf("\"%s\", \"%s\", \"%s\"\n",
6721                    x_user,
6722                    x_passwd ? x_passwd : "",
6723                    x_acct ? x_acct : ""
6724                    );
6725         }
6726         if (++i > cmd_rows - 3) { if (!askmore()) return(1); else i = 0; }
6727         printf("Server get-path: ");
6728         if (ngetpath == 0) {
6729             printf("    (none)\n");
6730         } else {
6731             printf("\n");
6732             i += 3;
6733             for (x = 0; x < ngetpath; x++) {
6734                 if (getpath[x]) printf(" %d. %s\n", x, getpath[x]);
6735                 if (++i > (cmd_rows - 3)) { /* More than a screenful... */
6736                     if (!askmore())
6737                       break;
6738                     else
6739                       i = 0;
6740                 }
6741             }
6742         }
6743         break;
6744 #endif /* NOSERVER */
6745
6746       case SHSTA:                       /* Status of last command */
6747         printf(" %s\n", success ? "SUCCESS" : "FAILURE");
6748         return(0);                      /* Don't change it */
6749
6750       case SHSTK: {                     /* Stack for MAC debugging */
6751 #ifdef MAC
6752           long sp;
6753           sp = -1;
6754           loadA0 ((char *)&sp);         /* set destination address */
6755           SPtoaA0();                    /* move SP to destination */
6756           printf("Stack at 0x%x\n", sp);
6757           show_queue();                 /* more debugging */
6758           break;
6759 #else
6760           shostack();
6761 #endif /* MAC */
6762           break;
6763       }
6764
6765
6766 #ifndef NOLOCAL
6767 #ifdef OS2
6768       case SHTAB:                       /* SHOW TABS */
6769 #ifdef IKSD
6770         if (inserver) {
6771             printf("Sorry, command disabled.\r\n");
6772             return(success = 0);
6773         }
6774 #endif /* IKSD */
6775         shotabs();
6776         break;
6777 #endif /* OS2 */
6778
6779       case SHTER:                       /* SHOW TERMINAL */
6780 #ifdef IKSD
6781         if (inserver) {
6782             printf("Sorry, command disabled.\r\n");
6783             return(success = 0);
6784         }
6785 #endif /* IKSD */
6786         shotrm();
6787         break;
6788
6789 #ifdef OS2
6790       case SHVSCRN:                     /* SHOW Virtual Screen - for debug */
6791         shovscrn();
6792         break;
6793 #endif /* OS2 */
6794 #endif /* NOLOCAL */
6795
6796 #ifdef OS2MOUSE
6797       case SHMOU:                       /* SHOW MOUSE */
6798 #ifdef IKSD
6799         if (inserver) {
6800             printf("Sorry, command disabled.\r\n");
6801             return(success = 0);
6802         }
6803 #endif /* IKSD */
6804         shomou();
6805         break;
6806 #endif /* OS2MOUSE */
6807
6808 #ifndef NOFRILLS
6809       case SHVER:
6810         shover();
6811         break;
6812 #endif /* NOFRILLS */
6813
6814 #ifndef NOSPL
6815       case SHBUI:                       /* Built-in variables */
6816         if ((y = cmtxt("Variable name or pattern","",&s,xxstring)) < 0)
6817           return(y);
6818         ckstrncpy(line,s,LINBUFSIZ);
6819         /* if (line[0]) ckstrncat(line,"*",LINBUFSIZ); */
6820
6821       case SHFUN:                       /* or built-in functions */
6822 #ifdef CK_TTGWSIZ
6823 #ifdef OS2
6824         if (tt_cols[VTERM] < 0 || tt_rows[VTERM] < 0)
6825           ttgwsiz();
6826 #else /* OS2 */
6827         if (ttgwsiz() > 0) {            /* Get current screen size */
6828             if (tt_rows > 0 && tt_cols > 0) {
6829                 cmd_rows = tt_rows;
6830                 cmd_cols = tt_cols;
6831             }
6832         }
6833 #endif /* OS2 */
6834 #endif /* CK_TTGWSIZ */
6835
6836         if (x == SHFUN) {               /* Functions */
6837             printf("\nThe following functions are available:\n\n");
6838             kwdhelp(fnctab,nfuncs,"","\\F","()",3,0);
6839             printf("\n");
6840 #ifndef NOHELP
6841             printf(
6842 "HELP FUNCTION <name> gives the calling conventions of the given function.\n\n"
6843                    );
6844 #endif /* NOHELP */
6845             break;
6846         } else {                        /* Variables */
6847             int j, flag = 0, havearg = 0;
6848             struct stringarray * q = NULL;
6849             char ** pp;
6850             if (line[0]) {              /* Have something to search for */
6851                 havearg = 1;            /* Maybe a list of things */
6852                 q = cksplit(1,0,line,NULL,"_-^$*?[]{}",0,0,0);
6853                 if (!q) break;
6854                 pp = q->a_head;
6855             }
6856             i = 0;
6857             for (y = 0; y < nvars; y++) {
6858                 if ((vartab[y].flgs & CM_INV))
6859                   continue;
6860                 if (havearg) {          /* If I have something to match */
6861                     char * s2;
6862                     for (flag = 0, j = 1; j <= q->a_size && !flag; j++) {
6863                         s2 = pp[j] ? pp[j] : "";
6864 #ifdef COMMENT
6865 /* This is not needed because it's what the 4 arg does in ckmatch() */
6866                         len = strlen(s2);
6867                         if (len > 0) {
6868                             if (s2[len-1] != '$') {/* To allow anchors */
6869                                 ckmakmsg(line,LINBUFSIZ,pp[j],"*",NULL,NULL);
6870                                 s2 = line;
6871                             }
6872                         }
6873 #endif /* COMMENT */
6874                         if (ckmatch(s2,vartab[y].kwd,0,4) > 0) {
6875                             flag = 1;   /* Matches */
6876                             break;
6877                         }
6878                     }
6879                     if (!flag)          /* Doesn't match */
6880                       continue;
6881                 }
6882                 s = nvlook(vartab[y].kwd);
6883                 printf(" \\v(%s) = ",vartab[y].kwd);
6884                 if (vartab[y].kwval == VN_NEWL) { /* \v(newline) */
6885                     while (*s)          /* Show control chars symbolically */
6886                       printf("\\{%d}",*s++);
6887                     printf("\n");
6888                 } else if (vartab[y].kwval == VN_IBUF  || /* \v(input) */
6889                            vartab[y].kwval == VN_QUE   || /* \v(query) */
6890 #ifdef OS2
6891                            vartab[y].kwval == VN_SELCT || /* \v(select) */
6892 #endif /* OS2 */
6893                            (vartab[y].kwval >= VN_M_AAA && /* modem ones */
6894                             vartab[y].kwval <= VN_M_ZZZ)
6895                            ) {
6896                     int r = 12;         /* This one can wrap around */
6897                     char buf[10];
6898                     while (*s) {
6899                         if (isprint(*s)) {
6900                             buf[0] = *s;
6901                             buf[1] = NUL;
6902                             r++;
6903                         } else {
6904                             sprintf(buf,"\\{%d}",*s); /* SAFE */
6905                             r += (int) strlen(buf);
6906                         }
6907                         if (r >= cmd_cols - 1) {
6908                             printf("\n");
6909                             r = 0;
6910                             i++;
6911                         }
6912                         printf("%s",buf);
6913                         s++;
6914                     }
6915                     printf("\n");
6916                 } else
6917                   printf("%s\n",s);
6918                 if (++i > (cmd_rows - 3)) { /* More than a screenful... */
6919                     if ((y >= nvars - 1) || !askmore())
6920                       break;
6921                     else
6922                       i = 0;
6923                 }
6924             }
6925         }
6926         break;
6927
6928       case SHVAR:                       /* Global variables */
6929         x = 0;                          /* Variable count */
6930         slc = 1;                        /* Screen line count for "more?" */
6931         for (y = 33; y < GVARS; y++)
6932           if (g_var[y]) {
6933               if (x++ == 0) printf("Global variables:\n");
6934               sprintf(line," \\%%%c",y); /* SAFE */
6935               if (shomac(line,g_var[y]) < 0) break;
6936           }
6937         if (!x) printf(" No variables defined\n");
6938         break;
6939
6940       case SHARG: {                     /* Args */
6941           char * s1, * s2;
6942           if (maclvl > -1) {
6943               printf("Macro arguments at level %d (\\v(argc) = %d):\n",
6944                      maclvl,
6945                      macargc[maclvl]
6946                      );
6947               for (y = 0; y < macargc[maclvl]; y++) {
6948                   s1 = m_arg[maclvl][y];
6949                   if (!s1) s1 = "(NULL)";
6950                   s2 = m_xarg[maclvl][y];
6951                   if (!s2) s2 = "(NULL)";
6952                   if (y < 10)
6953                     printf(" \\%%%d = %s\n",y,s1);
6954                   else
6955                     printf(" \\&_[%d] = %s\n",y,s2);
6956               }
6957           } else {
6958               printf("Top-level arguments (\\v(argc) = %d):\n", topargc);
6959               for (y = 0; y < topargc; y++) {
6960                   s1 = g_var[y + '0'];
6961                   if (!s1) s1 = "(NULL)";
6962                   s2 = toparg[y];
6963                   if (!s2) s2 = "(NULL)";
6964                   if (y < 10 && g_var[y])
6965                     printf(" \\%%%d = %s\n",y,s1);
6966                   if (toparg[y])
6967                     printf(" \\&_[%d] = %s\n",y,s2);
6968               }
6969           }
6970         }
6971         break;
6972
6973       case SHARR:                       /* Arrays */
6974         return(showarray());
6975 #endif /* NOSPL */
6976
6977 #ifndef NOXFER
6978       case SHPRO:                       /* Protocol parameters */
6979         shoparp();
6980         printf("\n");
6981         break;
6982 #endif /* NOXFER */
6983
6984 #ifndef NOLOCAL
6985       case SHCOM:                       /* Communication parameters */
6986         printf("\n");
6987         shoparc();
6988 #ifdef OS2
6989         {
6990             int i;
6991             char *s = "(unknown)";
6992             for (i = 0; i < nprty; i++)
6993               if (prtytab[i].kwval == priority) {
6994                   s = prtytab[i].kwd;
6995                   break;
6996               }
6997             printf(" Priority: %s\n", s );
6998         }
6999 #endif /* OS2 */
7000
7001         printf("\n");
7002 #ifdef NETCONN
7003         if (!network
7004 #ifdef IKSD
7005              && !inserver
7006 #endif /* IKSD */
7007              ) {
7008 #endif /* NETCONN */
7009             shomdm();
7010             printf("\n");
7011 #ifdef NETCONN
7012         }
7013 #endif /* NETCONN */
7014
7015 #ifndef NODIAL
7016 #ifdef IKSD
7017         if ( !inserver )
7018 #endif /* IKSD */
7019         {
7020             printf("Type SHOW DIAL to see DIAL-related items.\n");
7021             printf("Type SHOW MODEM to see modem-related items.\n");
7022 #ifdef CK_TAPI
7023             printf("Type SHOW TAPI to see TAPI-related items.\n");
7024 #endif /* CK_TAPI */
7025             printf("\n");
7026         }
7027 #endif /* NODIAL */
7028         break;
7029 #endif /* NOLOCAL */
7030
7031       case SHFIL:                       /* File parameters */
7032         shofil();
7033         /* printf("\n"); */             /* (out o' space) */
7034         break;
7035
7036 #ifndef NOCSETS
7037       case SHLNG:                       /* Languages */
7038         shoparl();
7039         break;
7040 #endif /* NOCSETS */
7041
7042 #ifndef NOSPL
7043       case SHSCR:                       /* Scripts */
7044         printf(" Command quoting:        %s\n", showoff(cmdgquo()));
7045         printf(" Take  echo:             %s\n", showoff(techo));
7046         printf(" Take  error:            %s\n", showoff(takerr[cmdlvl]));
7047         printf(" Macro echo:             %s\n", showoff(mecho));
7048         printf(" Macro error:            %s\n", showoff(merror[cmdlvl]));
7049         printf(" Quiet:                  %s\n", showoff(quiet));
7050         printf(" Function diagnostics:   %s\n", showoff(fndiags));
7051         printf(" Function error:         %s\n", showoff(fnerror));
7052 #ifdef CKLEARN
7053         {
7054             extern char * learnfile;
7055             extern int learning;
7056             if (learnfile) {
7057                 printf(" LEARN file:             %s (%s)\n",
7058                        learnfile,
7059                        learning ? "ON" : "OFF"
7060                        );
7061             } else
7062               printf(" LEARN file:             (none)\n");
7063         }
7064 #endif /* CKLEARN */
7065         shoinput();
7066         shooutput();
7067 #ifndef NOSCRIPT
7068         printf(" Script echo:            %s\n", showoff(secho));
7069 #endif /* NOSCRIPT */
7070         printf(" Command buffer length:  %d\n", CMDBL);
7071         printf(" Atom buffer length:     %d\n", ATMBL);
7072         break;
7073 #endif /* NOSPL */
7074
7075 #ifndef NOXMIT
7076       case SHXMI:
7077         printf("\n");
7078         printf(" File type:                       %s\n",
7079                binary ? "binary" : "text");
7080 #ifndef NOCSETS
7081         printf(" File character-set:              %s\n",
7082                fcsinfo[fcharset].keyword);
7083 #ifdef OS2
7084         if ( isunicode() ) {
7085         printf(" Terminal Character (remote):     %s\n",
7086               tt_utf8 ? "utf-8" : tcsr == TX_TRANSP ? "transparent" :
7087               tcsr == TX_UNDEF ? "undefined" : txrinfo[tcsr]->keywd);
7088         printf(" Terminal Character (local):      %s\n",
7089               tcsl == TX_TRANSP ? "transparent" :
7090               tcsl == TX_UNDEF ? "undefined" : txrinfo[tcsl]->keywd);
7091         } else {
7092         printf(" Terminal Character (remote):     %s\n",
7093               tt_utf8 ? "utf-8" : tcsr == TX_TRANSP ? "transparent" :
7094               tcsr == TX_UNDEF ? "undefined" : txrinfo[tcsr]->keywd);
7095         printf(" Terminal Character (local):      %s\n",
7096               tcsl == TX_TRANSP ? "transparent" :
7097               tcsl == TX_UNDEF ? "undefined" : txrinfo[tcsl]->keywd);
7098         }
7099 #else /* OS2 */
7100         printf(" Terminal character-set (remote): %s\n",
7101                fcsinfo[tcsr].keyword);
7102         printf(" Terminal character-set (local):  %s\n",
7103                fcsinfo[tcsl].keyword);
7104 #endif /* OS2 */
7105 #endif /* NOCSETS */
7106         printf(" Terminal bytesize:               %d\n",
7107                (cmask == 0xff) ? 8 : 7);
7108         printf(" Terminal echo:                   %s\n",
7109                duplex ? "local" : "remote");
7110         printf(" Transmit EOF:                    ");
7111         if (*xmitbuf == NUL) {
7112             printf("(none)\n");
7113         } else {
7114             char *p;
7115             p = xmitbuf;
7116             while (*p) {
7117                 if (*p < SP)
7118                   printf("^%c",ctl(*p));
7119                 else
7120                   printf("%c",*p);
7121                 p++;
7122             }
7123             printf("\n");
7124         }
7125         if (xmitf)
7126           printf(" Transmit Fill:                   %d\n", xmitf);
7127         else
7128           printf(" Transmit Fill:                   (none)\n");
7129         printf(" Transmit Linefeed:               %s\n",showoff(xmitl));
7130         if (xmitp)
7131           printf(" Transmit Prompt:                 %d (%s)\n",
7132                  xmitp,
7133                  chartostr(xmitp)
7134                  );
7135         else
7136           printf(" Transmit Prompt:                 (none)\n");
7137         printf(" Transmit Echo:                   %s\n", showoff(xmitx));
7138         printf(" Transmit Locking-Shift:          %s\n", showoff(xmits));
7139         printf(" Transmit Pause:                  %d (millisecond%s)\n",
7140                xmitw,
7141                (xmitw == 1) ? "" : "s"
7142                );
7143         printf(" Transmit Timeout:                %d (second%s)\n",
7144                xmitt,
7145                (xmitt == 1) ? "" : "s"
7146                );
7147         printf("\n");
7148         break;
7149 #endif /* NOXMIT */
7150
7151 #ifndef NODIAL
7152       case SHMOD:                       /* SHOW MODEM */
7153 #ifdef IKSD
7154         if (inserver) {
7155             printf("Sorry, command disabled.\r\n");
7156             return(success = 0);
7157         }
7158 #endif /* IKSD */
7159         shomodem();                     /* Show SET MODEM items */
7160         break;
7161 #endif /* NODIAL */
7162
7163 #ifndef MAC
7164       case SHDFLT:
7165         printf("%s\n",zgtdir());
7166         break;
7167 #endif /* MAC */
7168
7169 #ifndef NOLOCAL
7170       case SHESC:
7171 #ifdef IKSD
7172         if (inserver) {
7173             printf("Sorry, command disabled.\r\n");
7174             return(success = 0);
7175         }
7176 #endif /* IKSD */
7177         return(shoesc(escape));
7178
7179 #ifndef NODIAL
7180       case SHDIA:                       /* SHOW DIAL */
7181 #ifdef IKSD
7182         if (inserver) {
7183             printf("Sorry, command disabled.\r\n");
7184             return(success = 0);
7185         }
7186 #endif /* IKSD */
7187         shmdmlin();
7188         printf(", speed: ");
7189         if ((zz = ttgspd()) < 0) {
7190             printf("unknown");
7191         } else {
7192             if (zz == 8880) printf("75/1200"); else printf("%ld",zz);
7193         }
7194         if (carrier == CAR_OFF) s = "off";
7195         else if (carrier == CAR_ON) s = "on";
7196         else if (carrier == CAR_AUT) s = "auto";
7197         else s = "unknown";
7198         printf(", carrier: %s", s);
7199         if (carrier == CAR_ON) {
7200             if (cdtimo) printf(", timeout: %d sec", cdtimo);
7201             else printf(", timeout: none");
7202         }
7203         printf("\n");
7204         doshodial();
7205         if (local
7206 #ifdef NETCONN
7207             && !network
7208 #endif /* NETCONN */
7209             ) {
7210             printf("Type SHOW MODEM to see modem settings.\n");
7211 #ifdef CK_TAPI
7212             printf("Type SHOW TAPI to see TAPI-related items\n");
7213 #endif /* CK_TAPI */
7214             printf("Type SHOW COMMUNICATIONS to see modem signals.\n");
7215         }
7216         break;
7217 #endif /* NODIAL */
7218 #endif /* NOLOCAL */
7219
7220 #ifndef NOXFER
7221 #ifdef CK_LABELED
7222       case SHLBL:                       /* Labeled file info */
7223         sholbl();
7224         break;
7225 #endif /* CK_LABELED */
7226 #endif /* NOXFER */
7227
7228       case SHCSE:                       /* Character sets */
7229 #ifdef NOCSETS
7230         printf(
7231 " Character set translation is not supported in this version of C-Kermit\n");
7232 #else
7233         shocharset();
7234 #ifndef NOXFER
7235         printf("\n Unknown-Char-Set: %s\n",
7236                unkcs ? "Keep" : "Discard");
7237 #endif /* NOXFER */
7238 #ifdef OS2
7239         printf("\n");
7240 #endif /* OS2 */
7241         shotcs(tcsl,tcsr);
7242         printf("\n");
7243 #ifdef OS2
7244         /* PC Code Page information */
7245         {
7246             char cpbuf[128];
7247             int cplist[16], cps;
7248             int activecp;
7249             cps = os2getcplist(cplist, sizeof(cplist));
7250
7251             sprintf(cpbuf,              /* SAFE */
7252                     "%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d",
7253                      cps > 1 ? cplist[1] : 0,
7254                      cps > 2 ? cplist[2] : 0, cps > 3 ? cplist[3] : 0,
7255                      cps > 4 ? cplist[4] : 0, cps > 5 ? cplist[5] : 0,
7256                      cps > 6 ? cplist[6] : 0, cps > 7 ? cplist[7] : 0,
7257                      cps > 8 ? cplist[8] : 0, cps > 9 ? cplist[9] : 0,
7258                      cps > 10 ? cplist[10] : 0, cps > 11 ? cplist[11] : 0,
7259                      cps > 12 ? cplist[12] : 0
7260                      );
7261             printf(" Code Pages:\n");
7262             activecp = os2getcp();
7263             if ( activecp ) {
7264               printf("     Active: %d\n",activecp);
7265               if (!isWin95())
7266                 printf("  Available: %s\n",cpbuf);
7267             } else
7268               printf("     Active: n/a\n");
7269             printf("\n");
7270         }
7271 #endif /* OS2 */
7272 #endif /* NOCSETS */
7273         break;
7274
7275       case SHFEA:                       /* Features */
7276         shofea();
7277         break;
7278
7279 #ifdef CK_SPEED
7280       case SHCTL:                       /* Control-Prefix table */
7281         shoctl();
7282         break;
7283 #endif /* CK_SPEED */
7284
7285       case SHEXI: {
7286           extern int exithangup;
7287           printf("\n Exit warning %s\n", xitwarn ?
7288                  (xitwarn == 1 ? "on" : "always") : "off");
7289           printf(" Exit on-disconnect: %s\n", showoff(exitonclose));
7290           printf(" Exit hangup: %s\n", showoff(exithangup));
7291           printf(" Current exit status: %d\n\n", xitsta);
7292           break;
7293       }
7294       case SHPRT: {
7295 #ifdef PRINTSWI
7296           extern int printtimo, printertype, noprinter;
7297           extern char * printterm, * printsep;
7298 #ifdef BPRINT
7299           extern int printbidi;
7300 #endif /* BPRINT */
7301 #endif /* PRINTSWI */
7302
7303 #ifdef IKSD
7304         if (inserver &&
7305 #ifdef CK_LOGIN
7306             isguest
7307 #else /* CK_LOGIN */
7308             0
7309 #endif /* CK_LOGIN */
7310              ) {
7311             printf("Sorry, command disabled.\r\n");
7312             return(success = 0);
7313         }
7314 #endif /* IKSD */
7315 #ifdef PRINTSWI
7316           if (noprinter) {
7317               printf("Printer: (none)\n\n");
7318               break;
7319           }
7320 #endif /* PRINTSWI */
7321
7322           printf("Printer: %s%s\n",
7323
7324                  printpipe ? "| " : "",
7325                  printername ? printername :
7326 #ifdef OS2
7327                  "PRN"
7328 #else
7329                  "(default)"
7330 #endif /* OS2 */
7331                  );
7332 #ifdef PRINTSWI
7333 #ifdef BPRINT
7334           if (printbidi) {
7335               printf(" /BIDIRECTIONAL\n");
7336               if (pportspeed > 0)
7337                 printf(" /SPEED:%ld\n",pportspeed);
7338               printf(" /PARITY:%s\n",parnam((char)pportparity));
7339               printf(" /FLOW:%s\n",
7340                      pportflow == FLO_NONE ? "NONE" :
7341                      (pportflow == FLO_RTSC ? "RTS/CTS" : "XON/XOFF")
7342                      );
7343           } else
7344             printf(" /OUTPUT-ONLY\n");
7345 #endif /* BPRINT */
7346           switch (printertype) {
7347             case PRT_NON: printf(" /NONE\n"); break;
7348             case PRT_FIL: printf(" /FILE\n"); break;
7349             case PRT_PIP: printf(" /PIPE\n"); break;
7350             case PRT_DOS: printf(" /DOS-DEVICE\n"); break;
7351             case PRT_WIN: printf(" /WINDOWS-QUEUE\n"); break;
7352           }
7353           printf(" /TIMEOUT:%d\n",printtimo);
7354           if (printterm) {
7355               printf(" /END-OF-JOB-STRING:");
7356               shostrdef(printterm);
7357               printf("\n");
7358           } else
7359             printf(" /END-OF-JOB-STRING:(none)\n");
7360           printf(" /JOB-HEADER-FILE:%s\n",printsep ? printsep : "(none)");
7361 #endif /* PRINTSWI */
7362           printf("\n");
7363           break;
7364       }
7365
7366       case SHCMD: {
7367 #ifdef DOUBLEQUOTING
7368           extern int dblquo;
7369 #endif /* DOUBLEQUOTING */
7370 #ifdef CK_AUTODL
7371           printf(" Command autodownload: %s\n",showoff(cmdadl));
7372 #else
7373           printf(" Command autodownload: (not available)\n");
7374 #endif /* CK_AUTODL */
7375           printf(" Command bytesize: %d bits\n", (cmdmsk == 0377) ? 8 : 7);
7376 #ifdef CK_RECALL
7377           printf(" Command recall-buffer-size: %d\n",cm_recall);
7378 #else
7379           printf(" Command recall-buffer not available in this version\n");
7380 #endif /* CK_RECALL */
7381 #ifdef CK_RECALL
7382           printf(" Command retry: %s\n",showoff(cm_retry));
7383 #else
7384           printf(" Command retry not available in this version\n");
7385 #endif /* CK_RECALL */
7386           printf(" Command interruption: %s\n", showoff(cmdint));
7387           printf(" Command quoting: %s\n", showoff(cmdgquo()));
7388 #ifdef DOUBLEQUOTING
7389           printf(" Command doublequoting: %s\n", showoff(dblquo));
7390 #endif /* DOUBLEQUOTING */
7391           printf(" Command more-prompting: %s\n", showoff(xaskmore));
7392           printf(" Command height: %d\n", cmd_rows);
7393           printf(" Command width:  %d\n", cmd_cols);
7394 #ifndef IKSDONLY
7395 #ifdef OS2
7396           printf(" Command statusline: %s\n",showoff(tt_status[VCMD]));
7397 #endif /* OS2 */
7398 #endif /* IKSDONLY */
7399 #ifdef LOCUS
7400           printf(" Locus:          %s",
7401                  autolocus ? (autolocus == 2 ? "ask" : "auto") :
7402                  (locus ? "local" : "remote"));
7403           if (autolocus)
7404             printf(" (%s)", locus ? "local" : "remote");
7405           printf("\n");
7406 #endif /* LOCUS */
7407           printf(" Hints:          %s\n", showoff(hints));
7408           printf(" Quiet:          %s\n", showoff(quiet));
7409           printf(" Maximum command length: %d\n", CMDBL);
7410 #ifndef NOSPL
7411           {
7412               char * s;
7413               int k;
7414               printf(" Maximum number of macros: %d\n", MAC_MAX);
7415               printf(" Macros defined: %d\n", nmac);
7416               printf(" Maximum macro depth: %d\n", MACLEVEL);
7417               printf(" Maximum TAKE depth: %d\n", MAXTAKE);
7418               s = "(not defined)";
7419               k = mlook(mactab,"on_unknown_command",nmac);
7420               if (k > -1) if (mactab[k].mval) s = mactab[k].mval;
7421               printf(" ON_UNKNOWN_COMMAND: %s\n",s);
7422           }
7423 #endif /* NOSPL */
7424 #ifdef UNIX
7425 #ifndef NOJC
7426           printf(" Suspend: %s\n", showoff(xsuspend));
7427 #endif /* NOJC */
7428 #endif /* UNIX */
7429           printf(" Access to external commands and programs%s allowed\n",
7430 #ifndef NOPUSH
7431                  !nopush ? "" :
7432 #endif /* NOPUSH */
7433                   " not");
7434           break;
7435       }
7436
7437 #ifndef NOSPL
7438       case SHALRM:
7439         if (ck_alarm)
7440           printf("Alarm at %s %s\n",alrm_date,alrm_time);
7441         else
7442           printf("(no alarm set)\n");
7443         break;
7444 #endif /* NOSPL */
7445
7446 #ifndef NOMSEND
7447       case SHSFL: {
7448           extern struct filelist * filehead;
7449           if (!filehead) {
7450               printf("send-list is empty\n");
7451           } else {
7452               struct filelist * flp;
7453               char * s;
7454               flp = filehead;
7455               while (flp) {
7456                   s = flp->fl_alias;
7457                   if (!s) s = "(none)";
7458                   printf("%s, mode: %s, alias: %s\n",
7459                          flp->fl_name,
7460                          gfmode(flp->fl_mode,0),
7461                          s
7462                          );
7463                   flp = flp->fl_next;
7464               }
7465           }
7466       }
7467       break;
7468 #endif /* NOMSEND */
7469
7470 #ifdef CKXXCHAR
7471       case SHDBL:
7472         shodbl();
7473         break;
7474 #endif /* CKXXCHAR */
7475
7476 #ifndef NOPUSH
7477 #ifndef NOFRILLS
7478       case SHEDIT:
7479         if (!editor[0]) {
7480             s = getenv("EDITOR");
7481             if (s) ckstrncpy(editor,s,CKMAXPATH);
7482         }
7483         printf("\n editor:  %s\n", editor[0] ? editor : "(none)");
7484         if (editor[0]) {
7485             printf(" options: %s\n", editopts[0] ? editopts : "(none)");
7486             printf(" file:    %s\n", editfile[0] ? editfile : "(none)");
7487         }
7488         printf("\n");
7489         break;
7490
7491 #ifdef BROWSER
7492       case SHBROWSE:
7493         if (!browser[0]) {
7494             s = getenv("BROWSER");
7495             if (s) ckstrncpy(browser,s,CKMAXPATH);
7496         }
7497         printf("\n browser: %s\n", browser[0] ? browser : "(none)");
7498         if (browser[0]) {
7499             printf(" options: %s\n", browsopts[0] ? browsopts : "(none)");
7500             printf(" url:     %s\n", browsurl[0] ? browsurl : "(none)");
7501         }
7502         printf("\n");
7503         break;
7504 #endif /* BROWSER */
7505 #endif /*  NOFRILLS */
7506 #endif /* NOPUSH */
7507
7508 #ifndef NOLOCAL
7509 #ifdef CK_TAPI
7510       case SHTAPI:                      /* TAPI options */
7511 #ifdef IKSD
7512         if (inserver) {
7513             printf("Sorry, command disabled.\r\n");
7514             return(success = 0);
7515         }
7516 #endif /* IKSD */
7517         shotapi(0);
7518         break;
7519       case SHTAPI_L:                    /* TAPI Locations */
7520 #ifdef IKSD
7521         if (inserver) {
7522             printf("Sorry, command disabled.\r\n");
7523             return(success = 0);
7524         }
7525 #endif /* IKSD */
7526         shotapi(1);
7527         break;
7528       case SHTAPI_M:                    /* TAPI Modem */
7529 #ifdef IKSD
7530         if (inserver) {
7531             printf("Sorry, command disabled.\r\n");
7532             return(success = 0);
7533         }
7534 #endif /* IKSD */
7535         shotapi(2);
7536         break;
7537       case SHTAPI_C:                    /* TAPI Comm */
7538 #ifdef IKSD
7539         if (inserver) {
7540             printf("Sorry, command disabled.\r\n");
7541             return(success = 0);
7542         }
7543 #endif /* IKSD */
7544         shotapi(3);
7545         break;
7546 #endif /* CK_TAPI */
7547
7548       case SHTCP:                       /* SHOTCP */
7549         printf("\n");
7550         shotcp(0);
7551         printf("\n");
7552         break;
7553
7554 #ifdef TNCODE
7555       case SHTEL:                       /* TELNET */
7556         printf("\n");
7557         shotel(0);
7558         printf("\n");
7559         break;
7560
7561       case SHTOPT:                      /* TELNET OPTIONS */
7562         printf("\n");
7563         shotopt(0);
7564         printf("\n");
7565         break;
7566 #endif /* TNCODE */
7567
7568 #ifdef CK_TRIGGER
7569       case SHTRIG: {
7570           extern char * tt_trigger[], * triggerval;
7571           int i;
7572           if (!tt_trigger[0]) {
7573               printf(" Triggers: (none)\n");
7574           } else {
7575               printf(" Triggers:\n");
7576               for (i = 0; i < TRIGGERS; i++) {
7577                   if (!tt_trigger[i])
7578                     break;
7579                   printf("  \"%s\"\n",tt_trigger[i]);
7580               }
7581               printf(" Most recent trigger encountered: ");
7582               if (triggerval)
7583                 printf("\"%s\"\n",triggerval);
7584               else
7585                 printf("(none)\n");
7586           }
7587           break;
7588       }
7589 #endif /* CK_TRIGGER */
7590 #endif /* NOLOCAL */
7591
7592 #ifndef NOSPL
7593       case SHINP:
7594         shoinput();
7595         break;
7596 #endif /* NOSPL */
7597
7598       case SHLOG: {
7599 #ifndef MAC
7600 #ifdef IKSD
7601           if (inserver &&
7602 #ifdef CK_LOGIN
7603               isguest
7604 #else /* CK_LOGIN */
7605               0
7606 #endif /* CK_LOGIN */
7607              ) {
7608             printf("Sorry, command disabled.\r\n");
7609             return(success = 0);
7610         }
7611 #endif /* IKSD */
7612 #ifdef DEBUG
7613           printf("\n Debug log:       %s\n", deblog ? debfil : "(none)");
7614 #endif /* DEBUG */
7615 #ifndef NOXFER
7616           printf(" Packet log:      %s\n",   pktlog ? pktfil : "(none)");
7617 #endif /* NOXFER */
7618 #ifndef NOLOCAL
7619           printf(" Session log:     %s\n",   seslog ? sesfil : "(none)");
7620 #endif /* NOLOCAL */
7621 #ifdef TLOG
7622           printf(" Transaction log: %s (%s)\n",
7623                  (tralog ? (*trafil ? trafil : "(none)") : "(none)"),
7624                  (tlogfmt ? ((tlogfmt == 2) ? "ftp" : "verbose") : "brief")
7625                  );
7626 #endif /* TLOG */
7627 #ifdef CKLOGDIAL
7628             printf(" Connection log:  %s\n", dialog ? diafil : "(none)");
7629 #endif /* CKLOGDIAL */
7630           printf("\n");
7631 #endif /* MAC */
7632           break;
7633       }
7634
7635 #ifndef NOSPL
7636       case SHOUTP:                      /* OUTPUT */
7637         shooutput();
7638         break;
7639 #endif /* NOSPL */
7640
7641 #ifdef PATTERNS
7642       case SHOPAT:                      /* PATTERNS */
7643         shopat();
7644         break;
7645 #endif /* PATTERNS */
7646
7647 #ifdef STREAMING
7648       case SHOSTR: {                    /* STREAMING */
7649           extern int streamrq, clearrq, cleared;
7650           extern long tfcps;
7651           debug(F101,"SHOW RELIABLE reliable","",reliable);
7652           printf("\n Reliable:     %s\n",showooa(reliable));
7653           printf(" Clearchannel: %s\n",showooa(clearrq));
7654           printf(" Streaming:    %s\n\n",showooa(streamrq));
7655           if ((!local && (streamrq == SET_ON)) ||
7656               (streamrq == SET_AUTO && reliable))
7657             printf(" Streaming will be done if requested.\n");
7658           else if ((streamrq == SET_OFF) ||
7659                    ((streamrq == SET_AUTO) && !reliable))
7660             printf(" Streaming will not be requested and will not be done.\n");
7661           else if ((streamrq == SET_ON) ||
7662                    ((streamrq == SET_AUTO) && reliable))
7663             printf(
7664 " Streaming will be requested and will be done if the other Kermit agrees.\n");
7665           printf(" Last transfer: %sstreaming%s, %ld cps.\n",
7666                  streamed > 0 ? "" : "no ",
7667                  cleared ? ", clearchannel" : "",
7668                  tfcps
7669                  );
7670           printf("\n");
7671           break;
7672       }
7673 #endif /* STREAMING */
7674
7675       case SHOIKS:
7676         return(sho_iks());
7677         break;
7678
7679 #ifdef CK_AUTHENTICATION
7680       case SHOAUTH:
7681         return(sho_auth(0));
7682 #endif /* CK_AUTHENTICATION */
7683
7684 #ifndef NOFTP
7685       case SHOFTP: {
7686 #ifdef IKSD
7687         if (inserver) {
7688             printf("Sorry, command disabled.\r\n");
7689             return(success = 0);
7690         }
7691 #endif /* IKSD */
7692 #ifdef SYSFTP
7693         {
7694             extern char ftpapp[], ftpopts[];
7695             printf(" ftp-client:  %s\n", ftpapp[0] ? ftpapp : "(none)");
7696             if (ftpapp[0])
7697               printf(" ftp options: %s\n", ftpopts[0] ? ftpopts : "(none)");
7698         }
7699 #else
7700 #ifdef NEWFTP
7701         shoftp(0);
7702 #else
7703         printf("(No FTP client included in this version of Kermit.)\n");
7704 #endif /* NEWFTP */
7705 #endif /* SYSFTP */
7706         break;
7707       }
7708 #endif /* NOFTP */
7709
7710 #ifndef NOCMDL
7711       case SHXOPT: {
7712 #ifdef IKSDB
7713           extern int dbenabled;
7714           extern char * dbfile, * dbdir;
7715 #endif /* IKSDB */
7716 #ifdef CKWTMP
7717           extern int ckxwtmp;
7718           extern char * wtmpfile;
7719 #endif /* CKWTMP */
7720 #ifdef CK_LOGIN
7721           extern int ckxanon, xferlog, logintimo;
7722           extern char * xferfile;
7723 #ifdef UNIX
7724           extern int ckxpriv;
7725 #endif /* UNIX */
7726 #ifdef CK_PERMS
7727           extern int ckxperms;
7728 #endif /* CK_PERMS */
7729 #endif /* CK_LOGIN */
7730           extern char * bannerfile, * helpfile;
7731
7732 #ifdef IKSD
7733           if (inserver &&
7734 #ifdef CK_LOGIN
7735               isguest
7736 #else /* CK_LOGIN */
7737               0
7738 #endif /* CK_LOGIN */
7739               ) {
7740               printf("Sorry, command disabled.\r\n");
7741               return(success = 0);
7742           }
7743 #endif /* IKSD */
7744           printf("\n");
7745           if (!cmdint)
7746             printf(" --nointerrupts\n");
7747           printf(" --bannerfile=%s\n",bannerfile ? bannerfile : "(null)");
7748           printf(" --cdfile:%s\n",cdmsgstr ? cdmsgstr : "(null)");
7749           printf(" --cdmessage:%d\n",srvcdmsg);
7750           printf(" --helpfile:%d\n",helpfile);
7751           if (inserver) {
7752               printf("\n");
7753               break;
7754           }
7755 #ifdef CKSYSLOG
7756 #ifdef SYSLOGLEVEL
7757           printf(" --syslog:%d (forced)\n",ckxsyslog);
7758 #else
7759           printf(" --syslog:%d\n",ckxsyslog);
7760 #endif /* SYSLOGLEVEL */
7761 #endif /* CKSYSLOG */
7762 #ifdef CKWTMP
7763           printf(" --wtmplog:%d\n",ckxwtmp);
7764           printf(" --wtmpfile=%s\n",wtmpfile ? wtmpfile : "(null)");
7765 #endif /* CKWTMP */
7766 #ifdef IKSD
7767 #ifdef CK_LOGIN
7768           printf(" --anonymous:%d\n",ckxanon);
7769 #ifdef UNIX
7770           printf(" --privid:%d\n",ckxpriv);
7771 #endif /* UNIX */
7772 #ifdef CK_PERMS
7773           printf(" --permission:%04o\n",ckxperms);
7774 #endif /* CK_PERMS */
7775           printf(" --initfile:%s\n",anonfile ? anonfile : "(null)");
7776           printf(" --userfile:%s\n",userfile ? userfile : "(null)");
7777           printf(" --root:%s\n",anonroot ? anonroot : "(null)");
7778           printf(" --xferlog=%d\n",xferlog);
7779           printf(" --xferfile=%s\n",xferfile ? xferfile : "(null)");
7780           printf(" --timeout=%d\n",logintimo);
7781 #endif /* CK_LOGIN */
7782 #ifdef IKSDB
7783           printf(" --database=%d\n",dbenabled);
7784           printf(" --dbfile=%s\n",dbfile ? dbfile : "(null)");
7785           if (dbdir)
7786             printf("   (db directory=[%s])\n",dbdir);
7787 #endif /* IKSDB */
7788 #ifdef IKSDCONF
7789           printf(" IKSD conf=%s\n",iksdconf);
7790 #endif /* IKSDCONF */
7791 #endif /* IKSD */
7792           printf("\n");
7793           break;
7794       }
7795 #endif /* NOCMDL */
7796
7797       case SHCD: {
7798           extern char * myhome;
7799           s = getenv("CDPATH");
7800           if (!s) s = "(none)";
7801           printf("\n current directory:  %s\n", zgtdir());
7802           printf(" previous directory: %s\n", prevdir ? prevdir : "(none)");
7803           printf(" cd home:            %s\n", homepath());
7804           printf(" cd path:            %s\n", ckcdpath ? ckcdpath : s);
7805           printf(" cd message:         %s\n", showoff(srvcdmsg & 2));
7806           printf(" server cd-message:  %s\n", showoff(srvcdmsg & 1));
7807           printf(" cd message file:    %s\n\n",cdmsgstr ? cdmsgstr : "(none)");
7808           break;
7809       }
7810 #ifndef NOCSETS
7811       case SHASSOC:
7812         (VOID) showassoc();
7813         break;
7814 #endif /* NOCSETS */
7815
7816 #ifdef CKLOGDIAL
7817       case SHCONNX:
7818 #ifdef NEWFTP
7819         if (ftpisconnected()) {
7820             extern char cxlogbuf[];
7821             dologshow(W_FTP | 1);
7822             if (cxlogbuf[0])
7823               dologshow(1);
7824         } else {
7825 #endif /* NEWFTP */
7826             dologshow(1);
7827 #ifdef NEWFTP
7828         }
7829 #endif /* NEWFTP */
7830         break;
7831 #endif /* CKLOGDIAL */
7832
7833       case SHOPTS:
7834         optlines = 0;
7835 #ifndef NOFRILLS
7836         (VOID) showdelopts();
7837 #endif /* NOFRILLS */
7838 #ifdef DOMYDIR
7839         (VOID) showdiropts();
7840 #endif /* DOMYDIR */
7841 #ifdef CKPURGE
7842         (VOID) showpurgopts();
7843 #endif /* CKPURGE */
7844         (VOID) showtypopts();
7845         break;
7846
7847 #ifndef NOLOCAL
7848       case SHOFLO:
7849         (VOID) shoflow();
7850         break;
7851 #endif /* NOLOCAL */
7852
7853 #ifndef NOXFER
7854       case SHOXFER:
7855         (VOID) shoxfer();
7856         break;
7857 #endif /* NOXFER */
7858
7859 #ifdef CK_RECALL
7860       case SHHISTORY:
7861         (VOID) cmhistory();
7862         break;
7863 #endif /* CK_RECALL */
7864
7865 #ifndef NOSEXP
7866 #ifndef NOSPL
7867       case SHSEXP:
7868         (VOID) shosexp();
7869         break;
7870 #endif /* NOSPL */
7871 #endif /* NOSEXP */
7872
7873 #ifdef ANYSSH
7874       case SHOSSH:
7875         (VOID) shossh();
7876         break;
7877 #endif /* ANYSSH */
7878
7879 #ifdef KUI
7880       case SHOGUI:
7881         (VOID) shogui();
7882         break;
7883 #endif /* KUI */
7884
7885       default:
7886         printf("\nNothing to show...\n");
7887         return(-2);
7888     }
7889     return(success = 1);
7890 }
7891
7892 #ifndef NOXFER
7893 int
7894 shoatt() {
7895     printf("Attributes: %s\n", showoff(atcapr));
7896     if (!atcapr) return(0);
7897     printf(" Blocksize: %s\n", showoff(atblki));
7898     printf(" Date: %s\n", showoff(atdati));
7899     printf(" Disposition: %s\n", showoff(atdisi));
7900     printf(" Encoding (Character Set): %s\n", showoff(atenci));
7901     printf(" Length: %s\n", showoff(atleni));
7902     printf(" Type (text/binary): %s\n", showoff(attypi));
7903     printf(" System ID: %s\n", showoff(atsidi));
7904     printf(" System Info: %s\n", showoff(atsysi));
7905 #ifdef CK_PERMS
7906     printf(" Permissions In:  %s\n", showoff(atlpri));
7907     printf(" Permissions Out: %s\n", showoff(atlpro));
7908 #endif /* CK_PERMS */
7909 #ifdef STRATUS
7910     printf(" Format: %s\n", showoff(atfrmi));
7911     printf(" Creator: %s\n", showoff(atcrei));
7912     printf(" Account: %s\n", showoff(atacti));
7913 #endif /* STRATUS */
7914     return(0);
7915 }
7916 #endif /* NOXFER */
7917
7918 #ifndef NOSPL
7919 int                                     /* SHOW MACROS */
7920 shomac(s1, s2) char *s1, *s2; {
7921     int x, n, pp;
7922     pp = 0;                             /* Parenthesis counter */
7923
7924     debug(F110,"shomac s1",s1,0);
7925     debug(F110,"shomac s2",s2,0);
7926
7927 #ifdef IKSD
7928     if ( inserver &&
7929 #ifdef IKSDCONF
7930         iksdcf
7931 #else /* IKSDCONF */
7932         1
7933 #endif /* IKSDCONF */
7934         ) {
7935         if (!ckstrcmp("on_exit",s1,-1,0) ||
7936             !ckstrcmp("on_logout",s1,-1,0))
7937           return(0);
7938     }
7939 #endif /* IKSD */
7940
7941     if (!s1)
7942       return(0);
7943     else
7944       printf("%s = ",s1);               /* Print blank line and macro name */
7945     n = (int)strlen(s1) + 4;            /* Width of current line */
7946     if (!s2) s2 = "(not defined)";
7947
7948     while ((x = *s2++)) {               /* Loop thru definition */
7949         if (x == '(') pp++;             /* Treat commas within parens */
7950         if (x == ')') pp--;             /* as ordinary text */
7951         if (pp < 0) pp = 0;             /* Outside parens, */
7952         if (x == ',' && pp == 0) {      /* comma becomes comma-dash-NL. */
7953             putchar(',');
7954             putchar('-');
7955             x = '\n';
7956         }
7957         if (inserver && (x == '\n'))    /* Send CR before LF */
7958           putchar(CR);
7959         putchar((CHAR)x);               /* Output the character */
7960         if (x == '\n') {                /* If it was a newline */
7961 #ifdef UNIX
7962 #ifdef NOSETBUF
7963             fflush(stdout);
7964 #endif /* NOSETBUF */
7965 #endif /* UNIX */
7966             putchar(' ');               /* Indent the next line 1 space */
7967             while(*s2 == ' ') s2++;     /* skip past leading blanks */
7968             n = 2;                      /* restart the character counter */
7969             slc++;                      /* and increment the line counter. */
7970         } else if (++n > (cmd_cols - 1)) { /* If line is too wide */
7971             putchar('-');               /* output a dash */
7972             if (inserver)
7973               putchar(CR);              /* and a carriage return */
7974             putchar(NL);                /* and a newline */
7975 #ifdef UNIX
7976 #ifdef NOSETBUF
7977             fflush(stdout);
7978 #endif /* NOSETBUF */
7979 #endif /* UNIX */
7980             n = 1;                      /* and restart the char counter */
7981             slc++;                      /* and increment the line counter */
7982         }
7983         if (n < 3 && slc > (cmd_rows - 3)) { /* If new line and screen full */
7984             if (!askmore()) return(-1); /* ask if they want more. */
7985             n = 1;                      /* They do, start a new line */
7986             slc = 0;                    /* and restart line counter */
7987         }
7988     }
7989     if (inserver)
7990       putchar(CR);
7991     putchar(NL);                        /* End of definition */
7992     if (++slc > (cmd_rows - 3)) {
7993         if (!askmore()) return(-1);
7994         slc = 0;
7995     }
7996     return(0);
7997 }
7998 #endif /* NOSPL */
7999 #endif /* NOSHOW */
8000
8001 int x_ifnum = 0;                        /* Flag for IF NUMERIC active */
8002
8003 #ifndef NOSPL
8004 /* Evaluate an arithmetic expression. */
8005 /* Code adapted from ev, by Howie Kaye of Columbia U & others. */
8006
8007 static int xerror = 0;
8008 int divbyzero = 0;
8009 static char *cp;
8010 static long tokval;
8011 static char curtok;
8012 static long expval;
8013
8014 #define LONGBITS (8*sizeof (long))
8015 #define NUMBER 'N'
8016 #define N_EOT 'E'
8017
8018 /*
8019  Replacement for strchr() and index(), neither of which seem to be universal.
8020 */
8021
8022 static char *
8023 #ifdef CK_ANSIC
8024 windex(char * s, char c)
8025 #else
8026 windex(s,c) char *s, c;
8027 #endif /* CK_ANSIC */
8028 /* windex */ {
8029     while (*s != NUL && *s != c) s++;
8030     if (*s == c) return(s); else return(NULL);
8031 }
8032
8033
8034 /*
8035  g e t t o k
8036
8037  Returns the next token.  If token is a NUMBER, sets tokval appropriately.
8038 */
8039 static char
8040 gettok() {
8041     char tbuf[80] /* ,*tp */ ;          /* Buffer to accumulate number */
8042
8043     while (isspace(*cp))                /* Skip past leading spaces */
8044       cp++;
8045
8046     debug(F110,"GETTOK",cp,0);
8047
8048     switch (*cp) {
8049       case '$':                         /* ??? */
8050       case '+':                         /* Add */
8051       case '-':                         /* Subtract or Negate */
8052       case '@':                         /* Greatest Common Divisor */
8053       case '*':                         /* Multiply */
8054       case '/':                         /* Divide */
8055       case '%':                         /* Modulus */
8056       case '<':                         /* Left shift */
8057       case '>':                         /* Right shift */
8058       case '&':                         /* And */
8059       case '|':                         /* Or */
8060       case '#':                         /* Exclusive Or */
8061       case '~':                         /* Not */
8062       case '^':                         /* Exponent */
8063       case '!':                         /* Factorial */
8064       case '(':                         /* Parens for grouping */
8065       case ')': return(*cp++);          /* operator, just return it */
8066       case '\n':
8067       case '\0': return(N_EOT);         /* End of line, return that */
8068     }
8069 #ifdef COMMENT
8070 /* This is the original code, which allows only integer numbers. */
8071
8072     if (isxdigit(*cp)) {                /* Digit, must be a number */
8073         int radix = 10;                 /* Default radix */
8074         for (tp = tbuf; isxdigit(*cp); cp++)
8075           *tp++ = (char) (isupper(*cp) ? tolower(*cp) : *cp);
8076         *tp = '\0';                     /* End number */
8077         switch(isupper(*cp) ? tolower(*cp) : *cp) { /* Examine break char */
8078           case 'h':
8079           case 'x': radix = 16; cp++; break; /* if radix signifier... */
8080           case 'o':
8081           case 'q': radix = 8; cp++; break;
8082           case 't': radix = 2; cp++; break;
8083         }
8084         for (tp = tbuf, tokval = 0; *tp != '\0'; tp++)  {
8085             int dig;
8086             dig = *tp - '0';            /* Convert number */
8087             if (dig > 10) dig -= 'a'-'0'-10;
8088             if (dig >= radix) {
8089                 if (cmdlvl == 0 && !x_ifnum && !xerror)
8090                   printf("?Invalid digit '%c' in number\n",*tp);
8091                 xerror = 1;
8092                 return(NUMBER);
8093             }
8094             tokval = radix*tokval + dig;
8095         }
8096         return(NUMBER);
8097     }
8098     if (cmdlvl == 0 && !x_ifnum && !xerror)
8099       printf("Invalid character '%c' in input\n",*cp);
8100     xerror = 1;
8101     cp++;
8102     return(gettok());
8103 #else
8104 /* This code allows non-numbers to be treated as macro names */
8105     {
8106         int i, x;
8107         char * s, * cp1;
8108         cp1 = cp;
8109         tp = tbuf;
8110         for (i = 0; i < 80; i++) {
8111             /* Look ahead to next break character */
8112             /* pretty much anything that is not in the switch() above. */
8113             if (isalpha(*cp) || isdigit(*cp) ||
8114                 *cp == '_' || *cp == ':' || *cp == '.' ||
8115                 *cp == '[' || *cp == ']' ||
8116                 *cp == '{' || *cp == '}'
8117                 )
8118               tbuf[i] = *cp++;
8119             else
8120               break;
8121         }
8122         if (i >= 80) {
8123             printf("Too long - \"%s\"\n", cp1);
8124             xerror = 1;
8125             cp++;
8126             return(gettok());
8127         }
8128         if (xerror) return(NUMBER);
8129
8130         tbuf[i] = NUL;
8131         s = tbuf;
8132         if (!isdigit(tbuf[0])) {
8133             char * s2 = NULL;
8134             x = mxlook(mactab,tbuf,nmac);
8135             debug(F111,"gettok mxlook",tbuf,x);
8136             if (x < 0) {
8137                 if (cmdlvl == 0 && !x_ifnum && !xerror)
8138                   printf("Bad number - \"%s\"\n",tbuf);
8139                 xerror = 1;
8140                 cp++;
8141                 return(gettok());
8142             }
8143             s2 = mactab[x].mval;
8144             if (!s2) s2 = "";
8145             if (*s2) s = s2;
8146         }
8147 #ifdef CKFLOAT
8148         x = isfloat(s,0);
8149 #else
8150         x = chknum(s);
8151 #endif /* CKFLOAT */
8152         if (x > 0) {
8153             tokval = atoi(s);
8154         } else {
8155             if (cmdlvl == 0 && !x_ifnum && !xerror)
8156               printf("Bad number - \"%s\"\n",tbuf);
8157             xerror = 1;
8158             cp++;
8159             return(gettok());
8160         }
8161         return(NUMBER);
8162     }
8163 #endif /* COMMENT */
8164 }
8165
8166 static long
8167 #ifdef CK_ANSIC
8168 expon(long x, long y)
8169 #else
8170 expon(x,y) long x,y;
8171 #endif /* CK_ANSIC */
8172 /* expon */ {
8173     long result = 1;
8174     int sign = 1;
8175     if (y < 0) return(0);
8176     if (x < 0) {
8177         x = -x;
8178         if (y & 1) sign = -1;
8179     }
8180     while (y != 0) {
8181         if (y & 1) result *= x;
8182         y >>= 1;
8183         if (y != 0) x *= x;
8184   }
8185   return(result * sign);
8186 }
8187
8188 /*
8189  * factor ::= simple | simple ^ factor
8190  *
8191  */
8192 static VOID
8193 factor() {
8194     long oldval;
8195     simple();
8196     if (curtok == '^') {
8197         oldval = expval;
8198         curtok = gettok();
8199         factor();
8200         expval = expon(oldval,expval);
8201     }
8202 }
8203
8204 /*
8205  * termp ::= NULL | {*,/,%,&} factor termp
8206  *
8207  */
8208 static VOID
8209 termp() {
8210     while (curtok == '*' || curtok == '/' || curtok == '%' || curtok == '&') {
8211         long oldval;
8212         char op;
8213         op = curtok;
8214         curtok = gettok();              /* skip past operator */
8215         oldval = expval;
8216         factor();
8217         switch(op) {
8218           case '*': expval = oldval * expval; break;
8219           case '/':
8220           case '%':
8221             if (expval == 0) {
8222                 if (!x_ifnum)
8223                   printf("?Divide by zero\n");
8224                 xerror = 1;
8225                 divbyzero = 1;
8226                 expval = -1;
8227             } else
8228               expval = (op == '/') ? (oldval / expval) : (oldval % expval);
8229             break;
8230           case '&':
8231             expval = oldval & expval; break;
8232         }
8233     }
8234 }
8235
8236 static long
8237 #ifdef CK_ANSIC
8238 fact(long x)
8239 #else
8240 fact(x) long x;
8241 #endif /* CK_ANSIC */
8242 /* fact */ {                            /* factorial */
8243     long result = 1;
8244     while (x > 1)
8245       result *= x--;
8246     return(result);
8247 }
8248
8249 /*
8250  * term ::= factor termp
8251  *
8252  */
8253 static VOID
8254 term() {
8255     factor();
8256     termp();
8257 }
8258
8259 static long
8260 #ifdef CK_ANSIC
8261 gcd(long x, long y)
8262 #else
8263 gcd(x,y) long x,y;
8264 #endif /* CK_ANSIC */
8265 /* gcd */ {                             /* Greatest Common Divisor */
8266     int nshift = 0;
8267     if (x < 0) x = -x;
8268     if (y < 0) y = -y;                  /* validate arguments */
8269     if (x == 0 || y == 0) return(x + y);    /* this is bogus */
8270
8271     while (!((x & 1) | (y & 1))) {      /* get rid of powers of 2 */
8272         nshift++;
8273         x >>= 1;
8274         y >>= 1;
8275     }
8276     while (x != 1 && y != 1 && x != 0 && y != 0) {
8277         while (!(x & 1)) x >>= 1;       /* eliminate unnecessary */
8278         while (!(y & 1)) y >>= 1;       /* powers of 2 */
8279         if (x < y) {                    /* force x to be larger */
8280             long t;
8281             t = x;
8282             x = y;
8283             y = t;
8284         }
8285         x -= y;
8286     }
8287     if (x == 0 || y == 0) return((x + y) << nshift); /* gcd is non-zero one */
8288     else return((long) 1 << nshift);    /* else gcd is 1 */
8289 }
8290
8291 /*
8292  * exprp ::= NULL | {+,-,|,...} term exprp
8293  *
8294  */
8295 static VOID
8296 exprp() {
8297     while (windex("+-|<>#@",curtok) != NULL) {
8298         long oldval;
8299         char op;
8300         op = curtok;
8301         curtok = gettok();              /* skip past operator */
8302         oldval = expval;
8303         term();
8304         switch(op) {
8305           case '+' : expval = oldval + expval; break;
8306           case '-' : expval = oldval - expval; break;
8307           case '|' : expval = oldval | expval; break;
8308           case '#' : expval = oldval ^ expval; break;
8309           case '@' : expval = gcd(oldval,expval); break;
8310           case '<' : expval = oldval << expval; break;
8311           case '>' : expval = oldval >> expval; break;
8312         }
8313     }
8314 }
8315
8316 /*
8317  * expr ::= term exprp
8318  *
8319  */
8320 static VOID
8321 expr() {
8322     term();
8323     exprp();
8324 }
8325
8326 static long
8327 xparse() {
8328     curtok = gettok();
8329     expr();
8330 #ifdef COMMENT
8331     if (curtok == '$') {
8332         curtok = gettok();
8333         if (curtok != NUMBER) {
8334             if (cmdlvl == 0 && !x_ifnum)
8335               printf("?Illegal radix\n");
8336             xerror = 1;
8337             return(0);
8338         }
8339         curtok = gettok();
8340     }
8341 #endif /* COMMENT */
8342     if (curtok != N_EOT) {
8343         if (cmdlvl == 0 && !x_ifnum && !xerror)
8344           printf("?Extra characters after expression\n");
8345         xerror = 1;
8346     }
8347     return(expval);
8348 }
8349
8350 char *                                  /* Silent front end for evala() */
8351 evalx(s) char *s; {
8352     char * p;
8353     int t;
8354     t = x_ifnum;
8355     x_ifnum = 1;
8356     p = evala(s);
8357     x_ifnum = t;
8358     return(p);
8359 }
8360
8361 char *
8362 evala(s) char *s; {
8363     long v;                             /* Numeric value */
8364     if (!s) return("");
8365     xerror = 0;                         /* Start out with no error */
8366     divbyzero = 0;
8367     cp = s;                             /* Make the argument global */
8368     v = xparse();                       /* Parse the string */
8369     return(xerror ? "" : ckltoa(v));    /* Return empty string on error */
8370 }
8371
8372 /*
8373  * simplest ::= NUMBER | ( expr )
8374  *
8375  */
8376 static VOID
8377 simplest() {
8378     char * p;
8379     p = cp;
8380     if (curtok == NUMBER)
8381       expval = tokval;
8382     else if (curtok == '(') {
8383         curtok = gettok();              /* skip over paren */
8384         expr();
8385         if (curtok != ')') {
8386             if (cmdlvl == 0 && !x_ifnum && !xerror)
8387               printf("?Missing right parenthesis\n");
8388             xerror = 1;
8389         }
8390         debug(F110,"GETTOK SIMPLEST ()",p,0);
8391
8392     } else {
8393         if (cmdlvl == 0 && !x_ifnum && !xerror)
8394           printf("?Operator unexpected\n");
8395         xerror = 1;
8396     }
8397     curtok = gettok();
8398 }
8399
8400 /*
8401  * simpler ::= simplest | simplest !
8402  *
8403  */
8404 static VOID
8405 simpler() {
8406     simplest();
8407     if (curtok == '!') {
8408         curtok = gettok();
8409         expval = fact(expval);
8410     }
8411 }
8412
8413 /*
8414  * simple ::= {-,~,!} simpler | simpler
8415  *
8416  */
8417
8418 static VOID
8419 simple() {
8420     if (curtok == '-' || curtok == '~' || curtok == '!' || curtok == '+') {
8421         int op = curtok;
8422         curtok = gettok();              /* skip over - sign */
8423         simpler();                      /* parse the factor again */
8424         if (op != '+')
8425           expval = (op == '-') ? -expval : ((op == '!') ? !expval : ~expval);
8426     } else simpler();
8427 }
8428
8429 /*  D C L A R R A Y  --  Declare an array  */
8430 /*
8431   Call with:
8432    char a = single character designator for the array, e.g. "a".
8433    int  n = size of array.
8434   Returns:
8435    0 or greater on success, having created the requested array with
8436      with n+1 elements, 0..n.  If an array of the same name existed
8437      previously, it is destroyed.  The new array has all its elements
8438      initialized to NULL pointers.
8439   -1 on failure (because 'a' out of range or malloc failure).
8440 */
8441 int
8442 #ifdef CK_ANSIC
8443 dclarray(char a, int n)
8444 #else
8445 dclarray(a,n) char a; int n;
8446 #endif /* CK_ANSIC */
8447 /* dclarray */ {
8448     char c, **p; int i, n2, rc;
8449
8450     if (a > 63 && a < 91) a += 32;      /* Convert letters to lowercase */
8451     if (a < ARRAYBASE || a > 122)       /* Verify name */
8452       return(-1);
8453
8454     if (n < 0)                          /* Check arg */
8455       return(-1);
8456     if (n+1 < 0)                        /* MAXINT+1 wraps around */
8457       return(-1);
8458
8459     c = a;
8460     a -= ARRAYBASE;                     /* Convert name to number */
8461     rc = a;
8462     if ((p = a_ptr[a]) != NULL) {       /* Delete old array of same name */
8463         if (a_link[a] > -1) {           /* Is it a link? */
8464             if (n == 0) {               /* If we're just deleting it */
8465                 a_ptr[a] = (char **) NULL; /* clear all the info. */
8466                 a_dim[a] = 0;
8467                 a_link[a] = -1;
8468                 return(0);
8469             }                           /* Not deleting */
8470             a = a_link[a];              /* Switch to linked-to array */
8471         }
8472         n2 = a_dim[a];                  /* Real array */
8473         for (i = 0; i <= n2; i++) {     /* First delete its elements */
8474             if (p[i]) {
8475                 free(p[i]);
8476                 p[i] = NULL;
8477             }
8478         }
8479         free((char *)a_ptr[a]);         /* Then the element list */
8480         if (n == 0) {                   /* If undeclaring this array... */
8481             for (i = 0; i < 122 - ARRAYBASE; i++) { /* Any linked arrays? */
8482                 if (i != a && a_link[i] == a) {     /* Find them */
8483                     a_ptr[i] = (char **) NULL;      /* and remove them */
8484                     a_dim[i] = 0;
8485                     a_link[i] = -1;
8486                 }
8487             }
8488         }
8489         a_ptr[a] = (char **) NULL;      /* Remove pointer to element list */
8490         a_dim[a] = 0;                   /* Set dimension at zero. */
8491         a_link[a] = -1;                 /* Unset link word */
8492         if (n == 0)
8493           return(0);                    /* If dimension 0, just deallocate. */
8494     }
8495     p = (char **) malloc((n+1) * sizeof(char **)); /* Allocate for new array */
8496     if (p == NULL) return(-1);          /* Check */
8497     a_ptr[a] = p;                       /* Save pointer to member list */
8498     a_dim[a] = n;                       /* Save dimension */
8499     for (i = 0; i <= n; i++)            /* Initialize members to null */
8500       p[i] = NULL;
8501     for (i = 0; i < (int) 'z' - ARRAYBASE; i++) { /* Any linked arrays? */
8502         if (i != a && a_link[i] == a) { /* Find and update them */
8503             a_ptr[i] = p;
8504             a_dim[i] = n;
8505         }
8506     }
8507     return(rc);
8508 }
8509
8510 /*  X A R R A Y  -- Convert array name to array index  */
8511
8512 int
8513 xarray(s) char * s; {
8514     char buf[8];
8515     int x;
8516     char c;
8517
8518     if (!s) s = "";
8519     debug(F110,"xarray",s,0);
8520     if (!*s)
8521       return(-1);
8522     x = strlen(s);
8523
8524     buf[0] = NUL;
8525     buf[1] = NUL;
8526     buf[2] = s[0];
8527     buf[3] = (x > 0) ? s[1] : NUL;
8528     buf[4] = (x > 1) ? s[2] : NUL;
8529     buf[5] = (x > 2) ? s[3] : NUL;
8530     buf[6] = NUL;
8531     s = buf+2;
8532     if (*s == '&') {
8533         buf[1] = CMDQ;
8534         s--;
8535     } else if (*s != CMDQ) {
8536         buf[0] = CMDQ;
8537         buf[1] = '&';
8538         s = buf;
8539     }
8540     c = *(s+2);
8541     if (isupper(c))
8542       c = tolower(c);
8543     if (c == '@')
8544       c = 96;
8545     x = (int)c - ARRAYBASE;
8546     if (*(s+3) == '[')
8547       *(s+3) = NUL;
8548     return((x < 0 || x > 'z' - ARRAYBASE || *(s+3)) ? -1 : x);
8549 }
8550
8551 /*  A R R A Y B O U N D S  --  Parse array segment notation \&a[n:m]  */
8552
8553 /*
8554   Call with s = array reference, plus two pointers to ints.
8555   Returns -1 on error, or array index, with the two ints set as follows:
8556    \&a[]     -1, -1
8557    \&a[3]     3, -1
8558    \&a[3:17]  3, 17
8559   The array need not be declared -- this routine is just for parsing.
8560 */
8561 int
8562 arraybounds(s,lo,hi) char * s; int * lo, * hi; {
8563     int i, x, y, range[2];
8564     char buf[256], * p, * q;
8565     char * tmp = NULL;
8566
8567     *lo = -1;                           /* Default bounds */
8568     *hi = -1;
8569
8570     if (!s) s = "";                     /* Defense de null args */
8571     if (!*s)
8572       return(-1);
8573
8574     x = xarray(s);                      /* Check basic structure */
8575     debug(F111,"arraybounds xarray",s,x);
8576
8577     if (x < 0)                          /* Not OK, fail. */
8578       return(-1);
8579     range[0] = -1;                      /* It's OK -- get contents */
8580     range[1] = -1;                      /* of subscript brackets */
8581     makestr(&tmp,s);                    /* Make a pokeable copy */
8582     s = tmp;
8583     p = s;
8584     for (p = s, q = NULL; *p; p++) {    /* First find the brackets */
8585         if (*p == '[') {
8586             q = p+1;
8587         } else if (*p == ']')
8588           break;
8589     }
8590     if (q && *p == ']') {               /* If we have brackets... */
8591         int quitnow = 0;
8592         for (i = 0; i < 2 && !quitnow; i++) { /* Loop thru their contents */
8593             for (p = q; *p; p++) {
8594                 if ((i == 0 && *p == ':') || *p == ']') {
8595                     if (*p == ']')
8596                       quitnow = 1;
8597                     *p = NUL;
8598                     if (*q) {           /* We have something */
8599                         y = 255;        /* Expand variables, etc. */
8600                         s = buf;
8601                         zzstring(q,&s,&y);
8602                         s = evalx(buf); /* Evaluate it arithmetically */
8603                         if (s) if (*s)
8604                           ckstrncpy(buf,s,256);
8605                         if (!chknum(buf)) { /* Did we get a number? */
8606                             makestr(&tmp,NULL); /* No, fail. */
8607                             return(-1);
8608                         }
8609                         q = (i == 0) ? p+1 : NULL; /* Point to next if any */
8610                         range[i] = atoi(buf); /* Set this one */
8611                     }
8612                     break;
8613                 }
8614             }
8615         }
8616     }
8617     makestr(&tmp,NULL);                 /* Free temporary poked string */
8618     *lo = range[0];                     /* Return what we got */
8619     *hi = range[1];
8620     debug(F101,"arraybounds lo","",*lo);
8621     debug(F101,"arraybounds hi","",*hi);
8622     return(x);
8623 }
8624
8625 /*  A R R A Y N A M  --  Parse an array name  */
8626
8627 /*
8628   Call with pointer to string that starts with the array reference.
8629   String may begin with either \& or just &.
8630   On success,
8631     Returns letter ID (always lowercase) in argument c,
8632       which can also be accent grave (` = 96; '@' is converted to grave);
8633     Dimension or subscript in argument n;
8634     IMPORTANT: These arguments must be provided by the caller as addresses
8635     of ints (not chars), for example:
8636       char *s; int x, y;
8637       arraynam(s,&x,&y);
8638   On failure, returns a negative number, with args n and c set to zero.
8639 */
8640 int
8641 arraynam(ss,c,n) char *ss; int *c; int *n; {
8642     int i, y, pp, len;
8643     char x;
8644     char *s, *p, *sx, *vnp;
8645     /* On stack to allow for recursive calls... */
8646     char vnbuf[ARRAYREFLEN+1];          /* Entire array reference */
8647     char ssbuf[ARRAYREFLEN+1];          /* Subscript in "plain text" */
8648     char sxbuf[16];                     /* Evaluated subscript */
8649
8650     *c = *n = 0;                        /* Initialize return values */
8651     len = strlen(ss);
8652     for (pp = 0,i = 0; i < len; i++) {          /* Check length */
8653         if (ss[i] == '[') {
8654             pp++;
8655         } else if (ss[i] == ']') {
8656             if (--pp == 0)
8657               break;
8658         }
8659     }
8660     if (i > ARRAYREFLEN) {
8661         printf("?Array reference too long - %s\n",ss);
8662         return(-9);
8663     }
8664     ckstrncpy(vnbuf,ss,ARRAYREFLEN);
8665     vnp = vnbuf;
8666     if (vnbuf[0] == CMDQ && vnbuf[1] == '&') vnp++;
8667     if (*vnp != '&') {
8668         printf("?Not an array - %s\n",vnbuf);
8669         return(-9);
8670     }
8671     x = *(vnp + 1);                     /* Fold case of array name */
8672
8673     /* We don't use isupper & tolower here on purpose because these */
8674     /* would produce undesired effects with accented letters. */
8675     if (x > 63 && x < 91) x  = *(vnp + 1) = (char) (x + 32);
8676     if ((x < ARRAYBASE) || (x > 122) || (*(vnp+2) != '[')) {
8677         if (msgflg) {
8678             printf("?Invalid format for array name - %s\n",vnbuf);
8679             return(-9);
8680         } else
8681           return(-2);
8682     }
8683     *c = x;                             /* Return the array name */
8684     s = vnp+3;                          /* Get dimension */
8685     p = ssbuf;
8686     pp = 1;                             /* Bracket counter */
8687     for (i = 0; i < ARRAYREFLEN && *s != NUL; i++) { /* Copy up to ] */
8688         if (*s == '[') pp++;
8689         if (*s == ']' && --pp == 0) break;
8690         *p++ = *s++;
8691     }
8692     if (*s != ']') {
8693         printf("?No closing bracket on array dimension - %s\n",vnbuf);
8694         return(-9);
8695     }
8696     p--;                                /* Trim whitespace from end */
8697     while (*p == SP || *p == HT)
8698       p--;
8699     p++;
8700     *p = NUL;                           /* Terminate subscript with null */
8701     p = ssbuf;                          /* Point to beginning of subscript */
8702     while (*p == SP || *p == HT)        /* Trim whitespace from beginning */
8703       p++;
8704     sx = sxbuf;                         /* Where to put expanded subscript */
8705     y = 16;
8706     zzstring(p,&sx,&y);                 /* Convert variables, etc. */
8707     sx = sxbuf;
8708     while (*sx == SP) sx++;
8709     debug(F110,"arraynam sx","",sx);
8710     if (!*sx) {                         /* Empty brackets... */
8711         *n = -17;                       /* (Secret code :-) */
8712         return(-2);
8713     }
8714     p = evala(sx);                      /* Run it thru \fneval()... */
8715     if (p) if (*p) ckstrncpy(sxbuf,p,16); /* We know it has to be a number. */
8716
8717     if (!chknum(sxbuf)) {               /* Make sure it's all digits */
8718         if (msgflg) {
8719             printf("?Array dimension or subscript missing or not numeric\n");
8720             return(-9);
8721         } else
8722           return(-2);
8723     }
8724     if ((y = atoi(sxbuf)) < 0) {
8725         if (cmflgs == 0) printf("\n");
8726         if (msgflg) {
8727             printf("?Array dimension or subscript not positive or zero\n");
8728             return(-9);
8729         } else
8730           return(-2);
8731     }
8732     *n = y;                             /* Return the subscript or dimension */
8733     return(0);
8734 }
8735
8736 int
8737 chkarray(a,i) int a, i; {               /* Check if array is declared */
8738     int x;                              /* and if subscript is in range */
8739     if (a == 64) a = 96;                /* Convert atsign to grave accent */
8740     x = a - ARRAYBASE;                  /* Values must be in range 95-122 */
8741 #ifdef COMMENT
8742     if (x == 0 && maclvl < 0)           /* Macro arg vector but no macro */
8743       return(0);
8744 #endif /* COMMENT */
8745     if (x < 0 || x > 'z' - ARRAYBASE)   /* Not in range */
8746       return(-2);
8747     if (a_ptr[x] == NULL) return(-1);   /* Not declared */
8748     if (i > a_dim[x]) return(-2);       /* Declared but out of range. */
8749     return(a_dim[x]);                   /* All ok, return dimension */
8750 }
8751
8752 #ifdef COMMENT                          /* This isn't used. */
8753 char *
8754 arrayval(a,i) int a, i; {               /* Return value of \&a[i] */
8755     int x; char **p;                    /* (possibly NULL) */
8756     if (a == 64) a = 96;                /* Convert atsign to grave accent */
8757     x = a - ARRAYBASE;                  /* Values must be in range 95-122 */
8758     if (x < 0 || x > 27) return(NULL);  /* Not in range */
8759     if ((x > 0) && (p = a_ptr[x]) == NULL) /* Array not declared */
8760       return(NULL);
8761     if (i > a_dim[x])                   /* Subscript out of range. */
8762       return(NULL);
8763     return(p[i]);                       /* All ok, return pointer to value. */
8764 }
8765 #endif /* COMMENT */
8766
8767 /*
8768   pusharray() is called when an array name is included in a LOCAL statement.
8769   It moves the pointers from the global definition to the stack, and removes
8770   the global definition.  Later, if the same array is declared in the local
8771   context, it occupies the global definition in the normal way.  But when
8772   popclvl() is called, it replaces the global definition with the one saved
8773   here.  The "secret code" is used to indicate to popclv() that it should
8774   remove the global array when popping through this level -- otherwise if a
8775   local array were declared that had no counterpart at any higher level, it
8776   would never be deleted.  This allows Algol-like inheritance to work both
8777   on the way down and on the way back up.
8778 */
8779 int
8780 pusharray(x,z) int x, z; {
8781     int y;
8782     debug(F000,"pusharray x","",x);
8783     debug(F101,"pusharray z","",z);
8784     y = chkarray(x,z);
8785     debug(F101,"pusharray y","",y);
8786     x -= ARRAYBASE;                     /* Convert name letter to index. */
8787     if (x < 0 || x > 27)
8788       return(-1);
8789     if (y < 0) {
8790         aa_ptr[cmdlvl][x] = (char **) NULL;
8791         aa_dim[cmdlvl][x] = -23;        /* Secret code (see popclvl()) */
8792     } else {
8793         aa_ptr[cmdlvl][x] = a_ptr[x];
8794         aa_dim[cmdlvl][x] = y;
8795     }
8796     a_ptr[x] = (char **) NULL;
8797     a_dim[x] = 0;
8798     return(0);
8799 }
8800
8801 /*  P A R S E V A R  --  Parse a variable name or array reference.  */
8802 /*
8803  Call with:
8804    s  = pointer to candidate variable name or array reference.
8805    *c = address of integer in which to return variable ID.
8806    *i = address of integer in which to return array subscript.
8807  Returns:
8808    -2:  syntax error in variable name or array reference.
8809     1:  successful parse of a simple variable, with ID in c.
8810     2:  successful parse of an array reference, w/ID in c and subscript in i.
8811 */
8812 int
8813 parsevar(s,c,i) char *s; int *c, *i; {
8814     char *p;
8815     int x,y,z;
8816
8817     p = s;
8818     if (*s == CMDQ) s++;                /* Point after backslash */
8819
8820     if (*s != '%' && *s != '&') {       /* Make sure it's % or & */
8821         printf("?Not a variable name - %s\n",p);
8822         return(-9);
8823     }
8824     if ((int)strlen(s) < 2) {
8825         printf("?Incomplete variable name - %s\n",p);
8826         return(-9);
8827     }
8828     if (*s == '%' && *(s+2) != '\0') {
8829         printf("?Only one character after '%%' in variable name, please\n");
8830         return(-9);
8831     }
8832     if (*s == '&' && *(s+2) != '[') {
8833         printf("?Array subscript expected - %s\n",p);
8834         return(-9);
8835     }
8836     if (*s == '%') {                    /* Simple variable. */
8837         y = *(s+1);                     /* Get variable ID letter/char */
8838         if (isupper(y)) y -= ('a'-'A'); /* Convert upper to lower case */
8839         *c = y;                         /* Set the return values. */
8840         *i = -1;                        /* No array subscript. */
8841         return(1);                      /* Return 1 = simple variable */
8842     }
8843     if (*s == '&') {                    /* Array reference. */
8844         y = arraynam(s,&x,&z);          /* Go parse it. */
8845         debug(F101,"parsevar arraynam","",y);
8846         if ((y) < 0) {
8847             if (y == -2)
8848               return(pusharray(x,z));
8849             if (y != -9)
8850               printf("?Invalid array reference - %s\n",p);
8851             return(-9);
8852         }
8853         if (chkarray(x,z) < 0) {        /* Check if declared, etc. */
8854             printf("?Array not declared or subscript out of range\n");
8855             return(-9);
8856         }
8857         *c = x;                         /* Return array letter */
8858         *i = z;                         /* and subscript. */
8859         return(2);
8860     }
8861     return(-2);                         /* None of the above. */
8862 }
8863
8864
8865 #define VALN 32
8866
8867 /* Get the numeric value of a variable */
8868 /*
8869   Call with pointer to variable name, pointer to int for return value.
8870   Returns:
8871     0 on success with second arg containing the value.
8872    -1 on failure (bad variable syntax, variable not defined or not numeric).
8873 */
8874 int
8875 varval(s,v) char *s; int *v; {
8876     char valbuf[VALN+1];                /* s is pointer to variable name */
8877     char name[256];
8878     char *p;
8879     int y;
8880
8881     if (*s != CMDQ) {                   /* Handle macro names too */
8882         ckmakmsg(name,256,"\\m(",s,")",NULL);
8883         s = name;
8884     }
8885     p = valbuf;                         /* Expand variable into valbuf. */
8886     y = VALN;
8887     if (zzstring(s,&p,&y) < 0) return(-1);
8888     p = valbuf;                         /* Make sure value is numeric  */
8889     if (!*p) {                          /* Be nice -- let an undefined */
8890         valbuf[0] = '0';                /* variable be treated as 0.   */
8891         valbuf[1] = NUL;
8892     }
8893     if (chknum(p)) {                    /* Convert numeric string to int */
8894         *v = atoi(p);                   /* OK */
8895     } else {                            /* Not OK */
8896         p = evala(p);                   /* Maybe it's an expression */
8897         if (!chknum(p))                 /* Did it evaluate? */
8898           return(-1);                   /* No, failure. */
8899         else                            /* Yes, */
8900           *v = atoi(p);                 /* success */
8901     }
8902     return(0);
8903 }
8904
8905 /* Increment or decrement a variable */
8906 /* Returns -1 on failure, 0 on success */
8907
8908 int
8909 incvar(s,x,z) char *s; int x; int z; {  /* Increment a numeric variable */
8910     int n;                              /* s is pointer to variable name */
8911                                         /* x is amount to increment by */
8912                                         /* z != 0 means add */
8913                                         /* z = 0 means subtract */
8914     if (varval(s,&n) < 0)               /* Convert numeric string to int */
8915       return(-1);
8916     if (z)                              /* Increment it by the given amount */
8917       n += x;
8918     else                                /* or decrement as requested. */
8919       n -= x;
8920     addmac(s,ckitoa(n));                /* Replace old variable */
8921     return(0);
8922 }
8923
8924 /* D O D O  --  Do a macro */
8925
8926 /*
8927   Call with x = macro table index, s = pointer to arguments.
8928   Returns 0 on failure, 1 on success.
8929 */
8930
8931 int
8932 dodo(x,s,flags) int x; char *s; int flags; {
8933     int y;
8934     extern int tra_asg, tra_cmd; int tra_tmp;
8935 #ifndef NOLOCAL
8936 #ifdef OS2
8937     extern int term_io;
8938     int term_io_sav = term_io;
8939 #endif /* OS2 */
8940 #endif /* NOLOCAL */
8941
8942     if (x < 0)                          /* It can happen! */
8943       return(-1);
8944
8945     tra_tmp = tra_asg;
8946
8947     if (++maclvl >= MACLEVEL) {         /* Make sure we have storage */
8948         debug(F101,"dodo maclvl too deep","",maclvl);
8949         --maclvl;
8950         printf("Macros nested too deeply\n");
8951         return(0);
8952     }
8953     macp[maclvl] = mactab[x].mval;      /* Point to the macro body */
8954     macx[maclvl] = mactab[x].mval;      /* Remember where the beginning is */
8955
8956 #ifdef COMMENT
8957     makestr(&(m_line[maclvl]),s);       /* Entire arg string for "\%*" */
8958 #endif /* COMMENT */
8959
8960     cmdlvl++;                           /* Entering a new command level */
8961     if (cmdlvl >= CMDSTKL) {            /* Too many macros + TAKE files? */
8962         debug(F101,"dodo cmdlvl too deep","",cmdlvl);
8963         cmdlvl--;
8964         printf("?TAKE files and DO commands nested too deeply\n");
8965         return(0);
8966     }
8967 #ifdef DEBUG
8968     if (deblog) {
8969         debug(F111,"CMD +M",mactab[x].kwd,cmdlvl);
8970         debug(F010,"CMD ->",s,0);
8971     }
8972 #endif /* DEBUG */
8973
8974 #ifdef VMS
8975     conres();                           /* So Ctrl-C, etc, will work. */
8976 #endif /* VMS */
8977 #ifndef NOLOCAL
8978 #ifdef OS2
8979     term_io = 0;                        /* Disable terminal emulator I/O */
8980 #endif /* OS2 */
8981 #endif /* NOLOCAL */
8982     ifcmd[cmdlvl] = 0;
8983     iftest[cmdlvl] = 0;
8984     count[cmdlvl] = count[cmdlvl-1];    /* Inherit COUNT from previous level */
8985     intime[cmdlvl] = intime[cmdlvl-1];  /* Inherit previous INPUT TIMEOUT */
8986     inpcas[cmdlvl] = inpcas[cmdlvl-1];  /*   and INPUT CASE */
8987     takerr[cmdlvl] = takerr[cmdlvl-1];  /*   and TAKE ERROR */
8988     merror[cmdlvl] = merror[cmdlvl-1];  /*   and MACRO ERROR */
8989     xquiet[cmdlvl] = quiet;
8990     xcmdsrc = CMD_MD;
8991     cmdstk[cmdlvl].src = CMD_MD;        /* Say we're in a macro */
8992     cmdstk[cmdlvl].lvl = maclvl;        /* and remember the macro level */
8993     cmdstk[cmdlvl].ccflgs = flags & ~CF_IMAC; /* Set flags */
8994
8995     /* Initialize return value except in FOR, WHILE, IF, and SWITCH macros */
8996
8997     if (!(flags & CF_IMAC) && mrval[maclvl]) {
8998         free(mrval[maclvl]);
8999         mrval[maclvl] = NULL;
9000     }
9001
9002     /* Clear old %0..%9 arguments */
9003
9004     addmac("%0",mactab[x].kwd);         /* Define %0 = name of macro */
9005     makestr(&(m_xarg[maclvl][0]),mactab[x].kwd);
9006     varnam[0] = '%';
9007     varnam[2] = '\0';
9008     tra_asg = 0;
9009     for (y = 1; y < 10; y++) {          /* Clear args %1..%9 */
9010         if (m_arg[maclvl][y]) {         /* Don't call delmac() unless */
9011             varnam[1] = (char) (y + '0'); /* we have to... */
9012             delmac(varnam,0);
9013         }
9014     }
9015     tra_asg = tra_tmp;
9016
9017 /* Assign the new args one word per arg, allowing braces to group words */
9018
9019     xwords(s,MAXARGLIST,NULL,0);
9020
9021 #ifndef NOLOCAL
9022 #ifdef OS2
9023     term_io = term_io_sav;
9024 #endif /* OS2 */
9025 #endif /* NOLOCAL */
9026     if (tra_cmd)
9027       printf("[%d] +M: \"%s\"\n",cmdlvl,mactab[x].kwd);
9028     return(1);
9029 }
9030
9031 /* Insert "literal" quote around each comma-separated command to prevent */
9032 /* its premature expansion.  Only do this if object command is surrounded */
9033 /* by braces. */
9034
9035 static char* flit = "\\flit(";
9036
9037 int
9038 litcmd(src,dest,n) char **src, **dest; int n; {
9039     int bc = 0, pp = 0;
9040     char c, *s, *lp, *ss;
9041
9042     s = *src;
9043     lp = *dest;
9044
9045     debug(F010,"litcmd",s,0);
9046
9047     while (*s == SP) s++;               /* Strip extra leading spaces */
9048
9049     if (*s == '{') {                    /* Starts with brace */
9050         pp = 0;                         /* Paren counter */
9051         bc = 1;                         /* Count leading brace */
9052         *lp++ = *s++;                   /* Copy it */
9053         if (--n < 1) return(-1);        /* Check space */
9054         while (*s == SP) s++;           /* Strip interior leading spaces */
9055         ss = flit;                      /* Point to "\flit(" */
9056         while ((*lp++ = *ss++))         /* Copy it */
9057           if (--n < 1)                  /* and check space */
9058             return(-1);
9059         lp--;                           /* Back up over null */
9060
9061         while (*s) {                    /* Go thru rest of text */
9062             c = *s;
9063             if (c == '{') bc++;         /* Count brackets */
9064             if (c == '(') pp++;         /* and parens */
9065             if (c == ')') {             /* Right parenthesis. */
9066                 pp--;                   /* Count it. */
9067                 if (pp < 0) {           /* An unbalanced right paren... */
9068 #ifdef COMMENT
9069 /*
9070   The problem here is that "\{" appears to be a quoted brace and therefore
9071   isn't counted; then the "}" matches an earlier opening brace, causing
9072   (e.g.) truncation of macros by getncm().
9073 */
9074                     if (n < 5)          /* Out of space in dest buffer? */
9075                       return(-1);       /* If so, give up. */
9076                     *lp++ = CMDQ;       /* Must be quoted to prevent */
9077                     *lp++ = '}';        /* premature termination of */
9078                     *lp++ = '4';        /* \flit(...) */
9079                     *lp++ = '1';
9080                     *lp++ = '}';
9081                     n -= 5;
9082 #else
9083 /* Here we rely on the fact the \nnn never takes more than 3 digits */
9084                     if (n < 4)          /* Out of space in dest buffer? */
9085                       return(-1);       /* If so, give up. */
9086                     *lp++ = CMDQ;       /* Must be quoted to prevent */
9087                     *lp++ = '0';        /* premature termination of */
9088                     *lp++ = '4';        /* \flit(...) */
9089                     *lp++ = '1';
9090                     n -= 4;
9091 #endif /* COMMENT */
9092                     pp++;               /* Uncount it. */
9093                     s++;
9094                     continue;
9095                 }
9096             }
9097             if (c == '}') {             /* Closing brace. */
9098                 if (--bc == 0) {        /* Final one? */
9099                     *lp++ = ')';        /* Add closing paren for "\flit()" */
9100                     if (--n < 1) return(-1);
9101                     *lp++ = c;
9102                     if (--n < 1) return(-1);
9103                     s++;
9104                     break;
9105                 }
9106             }
9107             *lp++ = c;                  /* General case */
9108             if (--n < 1) return(-1);
9109             s++;
9110         }
9111         *lp = NUL;
9112     } else {                            /* No brackets around, */
9113         while ((*lp++ = *s++))          /* just copy. */
9114           if (--n < 1)
9115             return(-1);
9116         lp--;
9117     }
9118     *src = s;                           /* Return updated source */
9119     *dest = lp;                         /* and destination pointers */
9120     if (bc)                             /* Fail if braces unbalanced */
9121       return(-1);
9122     else                                /* Otherwise succeed. */
9123       return(0);
9124 }
9125 #endif /* NOSPL */
9126
9127 /* Functions moved here from ckuusr.c to even out the module sizes... */
9128
9129 /*
9130   Breaks up string s -- IN PLACE! -- into a list of up to max words.
9131   Pointers to each word go into the array list[].
9132   max is the maximum number of words (pointers).
9133   If list is NULL, then they are added to the macro table.
9134   flag = 0 means the last field is to be one word, like all the other fields,
9135          so anything after it is discarded.
9136   flag = 1 means the last field extends to the end of the string, even if
9137          there are lots of words left, so the last field contains the
9138          remainder of the string.
9139 */
9140 VOID
9141 xwords(s,max,list,flag) char *s; int max; char *list[]; int flag; {
9142     char *p;
9143     int b, i, k, q, y, z;
9144 #ifndef NOSPL
9145     int macro;
9146     macro = (list == NULL);
9147     debug(F010,"xwords",s,0);
9148 #endif /* NOSPL */
9149
9150 #ifdef XWORDSDEBUG
9151     printf("XWORDS string=%s\n",s);
9152     printf("XWORDS max=%d\n",max);
9153 #endif /* XWORDSDEBUG */
9154     p = s;                              /* Pointer to beginning of string */
9155     q = 0;                              /* Flag for doublequote removal */
9156     b = 0;                              /* Flag for outer brace removal */
9157     k = 0;                              /* Flag for in-word */
9158     y = 0;                              /* Brace nesting level */
9159     z = 0;                              /* "Word" counter, 0 thru max */
9160
9161     if (list)
9162       for (i = 0; i <= max; i++)        /* Initialize pointers */
9163         list[i] = NULL;
9164
9165     if (flag) max--;
9166
9167     while (1) {                         /* Go thru word list */
9168         if (!s || (*s == '\0')) {       /* No more characters? */
9169             if (k != 0) {               /* Was I in a word? */
9170                 if (z == max) break;    /* Yes, only go up to max. */
9171                 z++;                    /* Count this word. */
9172 #ifdef XWORDSDEBUG
9173                 printf("1 z++ = %d\n", z);
9174 #endif /* XWORDSDEBUG */
9175 #ifndef NOSPL
9176                 if (macro) {            /* Doing macro args */
9177                     if (z < 10) {
9178                         varnam[1] = (char) (z + '0'); /* Assign last arg */
9179                         addmac(varnam,p);
9180                     }
9181                     if (z <= max) {
9182 #ifdef COMMENT
9183                         if (maclvl < 0)
9184                           addmac(varnam,p);
9185                         else
9186 #endif /* COMMENT */
9187                           makestr(&(m_xarg[maclvl][z]),p);
9188                     }
9189                 } else {                /* Not doing macro args */
9190 #endif /* NOSPL */
9191                     list[z] = p;        /* Assign pointer. */
9192 #ifdef XWORDSDEBUG
9193                     printf("[1]LIST[%d]=\"%s\"\n",z,list[z]);
9194 #endif /* XWORDSDEBUG */
9195 #ifndef NOSPL
9196                 }
9197 #endif /* NOSPL */
9198                 break;                  /* And get out. */
9199             } else break;               /* Was not in a word */
9200         }
9201         if (k == 0 && (*s == SP || *s == HT)) { /* Eat leading blanks */
9202             s++;
9203             continue;
9204         } else if (q == 0 && *s == '{') { /* An opening brace */
9205             if (k == 0 && y == 0) {     /* If leading brace */
9206                 p = s+1;                /* point past it */
9207                 b = 1;                  /* and flag that we did this */
9208             }
9209             k = 1;                      /* Flag that we're in a word */
9210             y++;                        /* Count the brace. */
9211         } else if (q == 0 && *s == '}') { /* A closing brace. */
9212             y--;                        /* Count it. */
9213             if (y <= 0 && b != 0) {     /* If it matches the leading brace */
9214                 char c;
9215                 c = *(s+1);
9216                 if (!c || c == SP || c == HT) { /* at EOL or followed by SP */
9217                     *s = SP;            /* change it to a space */
9218                     b = 0;              /* and we're not in braces any more */
9219                 }
9220             }
9221 #ifdef DOUBLEQUOTING
9222         /* Opening doublequote */
9223         } else if (k == 0 && b == 0 && *s == '"' && dblquo) {
9224             y++;
9225             p = s+1;                    /* point past it */
9226             q = 1;                      /* and flag that we did this */
9227             k = 1;                      /* Flag that we're in a word */
9228         /* Closing double quote */
9229         } else if (q > 0 && k > 0 && b == 0 && *s == '"' && dblquo) {
9230             char c;
9231             c = *(s+1);
9232             if (!c || c == SP || c == HT) { /* at EOL or followed by SP */
9233                 y--;
9234                 *s = SP;                /* change it to a space */
9235                 q = 0;                  /* and we're not in quotes any more */
9236             }
9237 #endif /* DOUBLEQUOTING */
9238
9239         } else if (*s != SP && *s != HT) { /* Nonspace means we're in a word */
9240             if (k == 0) {               /* If we weren't in a word before, */
9241                 p = s;                  /* Mark the beginning */
9242                 if (flag && z == max) { /* Want last word to be remainder? */
9243                     z++;
9244 #ifdef XWORDSDEBUG
9245                     printf("1 z++ = %d\n", z);
9246 #endif /* XWORDSDEBUG */
9247                     list[z] = p;        /* Yes, point to it */
9248 #ifdef XWORDSDEBUG
9249                     printf("[4]LIST[%d]=\"%s\"\n",z,list[z]);
9250 #endif /* XWORDSDEBUG */
9251                     break;              /* and quit */
9252                 }
9253                 k = 1;                  /* Set in-word flag */
9254             }
9255         }
9256         /* If we're not inside a braced quantity, and we are in a word, and */
9257         /* we have hit whitespace, then we have a word. */
9258         if ((y < 1) && (k != 0) && (*s == SP || *s == HT) && !b) {
9259             if (!flag || z < max)       /* if we don't want to keep rest */
9260               *s = '\0';                /* terminate the arg with null */
9261             k = 0;                      /* say we're not in a word any more */
9262             y = 0;                      /* start braces off clean again */
9263             if (z == max) break;        /* Only go up to max. */
9264             z++;                        /* count this arg */
9265 #ifdef XWORDSDEBUG
9266             printf("1 z++ = %d\n", z);
9267 #endif /* XWORDSDEBUG */
9268
9269 #ifndef NOSPL
9270             if (macro) {
9271                 if (z < 10) {
9272                     varnam[1] = (char) (z + '0'); /* compute its name */
9273                     addmac(varnam,p);   /* add it to the macro table */
9274                 }
9275                 if (z <= max) {
9276 #ifdef COMMENT
9277                     if (maclvl < 0)
9278                       addmac(varnam,p);
9279                     else
9280 #endif /* COMMENT */
9281                       makestr(&(m_xarg[maclvl][z]),p);
9282                 }
9283             } else {
9284 #endif /* NOSPL */
9285                 list[z] = p;
9286 #ifdef XWORDSDEBUG
9287                 printf("[2]LIST[%d]=\"%s\"\n",z,list[z]);
9288 #endif /* XWORDSDEBUG */
9289 #ifndef NOSPL
9290             }
9291 #endif /* NOSPL */
9292             p = s+1;
9293         }
9294         s++;                            /* Point past this character */
9295     }
9296     if ((z == 0) && (y > 1)) {          /* Extra closing brace(s) at end */
9297         z++;
9298 #ifndef NOSPL
9299         if (macro) {
9300             if (z < 10) {
9301                 varnam[1] = z + '0';    /* compute its name */
9302                 addmac(varnam,p);       /* Add rest of line to last arg */
9303             }
9304             if (z <= max) {
9305 #ifdef COMMENT
9306                 if (maclvl < 0)
9307                   addmac(varnam,p);
9308                 else
9309 #endif /* COMMENT */
9310                   makestr(&(m_xarg[maclvl][z]),p);
9311             }
9312         } else {
9313 #endif /* NOSPL */
9314             list[z] = p;
9315 #ifdef XWORDSDEBUG
9316             printf("[3]LIST[%d]=\"%s\"\n",z,list[z]);
9317 #endif /* XWORDSDEBUG */
9318 #ifndef NOSPL
9319         }
9320 #endif /* NOSPL */
9321     }
9322 #ifndef NOSPL
9323     if (macro) {                        /* Macro */
9324         if (maclvl < 0) {
9325             a_dim[0] = z;               /* Array dimension is one less */
9326             topargc = z + 1;            /* than \v(argc) */
9327             debug(F111,"a_dim[0]","D",a_dim[0]);
9328         } else {
9329             macargc[maclvl] = z + 1;    /* Set \v(argc) variable */
9330             n_xarg[maclvl] = z + 1;     /* This is the actual number */
9331             a_ptr[0] = m_xarg[maclvl];  /* Point \&_[] at the args */
9332             a_dim[0] = z;               /* And give it this dimension */
9333             debug(F111,"a_dim[0]","E",a_dim[0]);
9334         }
9335     }
9336 #endif /* NOSPL */
9337     return;
9338 }
9339
9340 #ifndef NOSPL
9341
9342 /*  D O S H I F T  --  Do the SHIFT Command; shift macro args left by n */
9343
9344 /*  Note: at some point let's consolidate m_arg[][] and m_xarg[][]. */
9345
9346 int
9347 doshift(n) int n; {                     /* n = shift count */
9348     int i, top, level;
9349     char /* *s, *m, */ buf[6];          /* Buffer to build scalar names */
9350     char * sx = tmpbuf;
9351     int nx = TMPBUFSIZ;
9352
9353     debug(F101,"SHIFT count","",n);
9354     debug(F101,"SHIFT topargc","",topargc);
9355
9356     if (n < 1)                          /* Stay in range */
9357       return(n == 0 ? 1 : 0);
9358
9359     level = maclvl;
9360     top = (level < 0) ? topargc : macargc[level];
9361
9362     if (n >= top)
9363       n = top - 1;
9364
9365 #ifdef DEBUG
9366     if (deblog) {
9367         debug(F101,"SHIFT count 2","",n);
9368         debug(F101,"SHIFT level","",level);
9369         if (level > -1)
9370           debug(F101,"SHIFT macargc[level]","",macargc[level]);
9371     }
9372 #endif /* DEBUG */
9373
9374     buf[0] = '\\';                      /* Initialize name template */
9375     buf[1] = '%';
9376     buf[2] = NUL;
9377     buf[3] = NUL;
9378
9379     for (i = 1; i <= n; i++) {          /* Free shifted-over args */
9380         if (level < 0) {
9381             makestr(&(toparg[i]),NULL);
9382         } else {
9383             makestr(&(m_xarg[level][i]),NULL);
9384         }
9385         if (i < 10) {                   /* Is this necessary? */
9386             buf[2] = (char)(i+'0');
9387             delmac(buf,0);
9388         }
9389     }
9390     for (i = 1; i <= top-n; i++) {      /* Shift remaining args */
9391         if (level < 0) {
9392 #ifdef COMMENT
9393             toparg[i] = toparg[i+n];    /* Full vector */
9394 #else
9395             makestr(&(toparg[i]),toparg[i+n]); /* Full vector */
9396 #endif /* COMMENT */
9397             if (i < 10)                 /* Scalars... */
9398               makestr(&(g_var[i+'0']),toparg[i+n]);
9399         } else {
9400 #ifdef COMMENT
9401             m_xarg[level][i] = m_xarg[level][i+n];
9402 #else
9403             makestr(&(m_xarg[level][i]),m_xarg[level][i+n]);
9404 #endif /* COMMENT */
9405             if (i < 10) {
9406                 buf[2] = (char)(i+'0');
9407                 debug(F010,"SHIFT buf",buf,0);
9408                 addmac(buf,m_xarg[level][i+n]);
9409             }
9410         }
9411     }
9412     for (i = top-n; i <= top; i++) {    /* Clear n args from the end */
9413         if (level < 0) {
9414 #ifdef COMMENT
9415             toparg[i] = NULL;
9416 #else
9417             makestr(&(toparg[i]),NULL);
9418 #endif /* COMMENt */
9419             if (i < 10)
9420               makestr(&(g_var[i+'0']),NULL);
9421         } else {
9422 #ifdef COMMENT
9423             m_xarg[level][i] = NULL;
9424 #else
9425             makestr(&(m_xarg[level][i]),NULL);
9426 #endif /* COMMENt */
9427             if (i < 10) {
9428                 buf[2] = (char)(i+'0');
9429                 delmac(buf,0);
9430             }
9431         }
9432     }
9433     if (level > -1) {                   /* Macro args */
9434         macargc[level] -= n;            /* Adjust count */
9435         n_xarg[maclvl] = macargc[level]; /* Here too */
9436         a_dim[0] = macargc[level] - 1;  /* Adjust array dimension */
9437         debug(F111,"a_dim[0]","F",a_dim[0]);
9438         zzstring("\\fjoin(&_[],{ },1)",&sx,&nx); /* Handle \%* */
9439 #ifdef COMMENT
9440         makestr(&(m_line[level]),tmpbuf);
9441 #endif /* COMMENT */
9442     } else {                            /* Ditto for top level */
9443         topargc -= n;
9444         a_dim[0] = topargc - 1;
9445         debug(F111,"a_dim[0]","G",a_dim[0]);
9446         zzstring("\\fjoin(&_[],{ },1)",&sx,&nx);
9447 #ifdef COMMENT
9448         makestr(&topline,tmpbuf);
9449 #endif /* COMMENT */
9450     }
9451     return(1);
9452 }
9453 #endif /* NOSPL */
9454
9455 int
9456 docd(cx) int cx; {                      /* Do the CD command */
9457     int x;
9458     extern int server, srvcdmsg, cdactive;
9459     extern char * cdmsgfile[], * ckcdpath;
9460     char *s, *p;
9461 #ifdef MAC
9462     char temp[34];
9463 #endif /* MAC */
9464 #ifdef IKSDCONF
9465 extern int iksdcf;
9466 #endif /* IKSDCONF */
9467
9468 #ifndef NOFRILLS
9469     if (cx == XXBACK) {
9470         if ((x = cmcfm()) < 0)
9471         cwdf = 1;
9472         if (prevdir) {
9473             s = zgtdir();
9474             if (!zchdir(prevdir)) {
9475                 cwdf = 0;
9476                 perror(s);
9477             } else {
9478                 makestr(&prevdir,s);
9479             }
9480         }
9481         return(cwdf);
9482     }
9483 #endif /* NOFRILLS */
9484
9485     if (cx == XXCDUP) {
9486 #ifdef VMS
9487         s = "[-]";
9488 #else
9489 #ifdef datageneral
9490         s = "^";
9491 #else
9492         s = "..";
9493 #endif /* datageneral */
9494 #endif /* VMS */
9495         ckstrncpy(line,s,LINBUFSIZ);
9496         goto gocd;
9497     }
9498 #ifndef NOSPL
9499     if (cx == XXKCD) {                  /* Symbolic (Kermit) CD */
9500         char * p;
9501         int n, k;
9502         x = cmkey(kcdtab,nkcdtab,"Symbolic directory name","home",xxstring);
9503         if (x < 0)
9504           return(x);
9505         x = lookup(kcdtab,atmbuf,nkcdtab,&k); /* Get complete keyword */
9506         if (x < 0) {
9507             printf("?Lookup error\n");  /* shouldn't happen */
9508             return(-9);
9509         }
9510         if ((x = cmcfm()) < 0)
9511           return(x);
9512         if (k == VN_HOME) {             /* HOME: allow SET HOME to override */
9513             ckstrncpy(line,homepath(),LINBUFSIZ);
9514         } else {                        /* Other symbolic name */
9515             /* Convert to variable syntax */
9516             ckmakmsg(tmpbuf,TMPBUFSIZ,"\\v(",kcdtab[k].kwd,")",NULL);
9517             p = line;                   /* Expand the variable */
9518             n = LINBUFSIZ;
9519             zzstring(tmpbuf,&p,&n);
9520             if (!line[0]) {             /* Fail if variable not defined */
9521                 printf("?%s - not defined\n",tmpbuf);
9522                 return(success = 0);
9523             }
9524         }
9525         s = line;                       /* All OK, go try to CD... */
9526         goto gocd;
9527     }
9528 #endif /* NOSPL */
9529
9530     cdactive = 1;
9531 #ifdef GEMDOS
9532     if ((x = cmdir("Name of local directory, or carriage return",
9533                    homepath(),
9534                    &s,
9535                    NULL
9536                    )
9537          ) < 0 )
9538       return(x);
9539 #else
9540 #ifdef OS2
9541     if ((x = cmdirp("Name of PC disk and/or directory,\n\
9542        or press the Enter key for the default",
9543                     homepath(),
9544                     &s,
9545                     ckcdpath ? ckcdpath : getenv("CDPATH"),
9546                     xxstring
9547                     )
9548          ) < 0 )
9549       return(x);
9550 #else
9551 #ifdef MAC
9552     x = ckstrncpy(temp,homepath(),32);
9553     if (x > 0) if (temp[x-1] != ':') { temp[x] = ':'; temp[x+1] = NUL; }
9554     if ((x = cmtxt("Name of Macintosh volume and/or folder,\n\
9555  or press the Return key for the desktop on the boot disk",
9556                    temp,&s, xxstring)) < 0 )
9557       return(x);
9558 #else
9559     if ((x = cmdirp("Carriage return for home directory,\n\
9560 or name of directory on this computer",
9561 #ifdef VMS
9562                     "SYS$LOGIN",        /* With no colon */
9563 #else
9564                     homepath(),         /* In VMS this is "SYS$LOGIN:" */
9565 #endif /* VMS */
9566                     &s,
9567                     ckcdpath ? ckcdpath : getenv("CDPATH"),
9568                     xxstring
9569                     )) < 0)
9570       return(x);
9571 #endif /* MAC */
9572 #endif /* OS2 */
9573 #endif /* GEMDOS */
9574     ckstrncpy(line,s,LINBUFSIZ);        /* Make a safe copy */
9575     s = line;
9576 #ifdef VMS
9577     if (ckmatch("*.DIR;1$",s,0,0))
9578       if (cvtdir(s,tmpbuf,TMPBUFSIZ) > 0)
9579         s = tmpbuf;
9580 #endif /* VMS */
9581     debug(F110,"docd",s,0);
9582 #ifndef MAC
9583     if ((x = cmcfm()) < 0)              /* Get confirmation */
9584       return(x);
9585 #endif /* MAC */
9586
9587   gocd:
9588
9589 #ifdef datageneral
9590     x = strlen(line);                   /* homdir ends in colon, */
9591     if (x > 1 && line[x-1] == ':')      /* and "dir" doesn't like that... */
9592       line[x-1] = NUL;
9593 #endif /* datageneral */
9594
9595 #ifdef MAC
9596     cwdf = 1;
9597     if (!zchdir(s)) {
9598         cwdf = 0;
9599         if (*s != ':') {                /* If it failed, */
9600             char *p;                    /* supply leading colon */
9601             int len = (int)strlen(s) + 2;
9602             p = malloc(len);            /* and try again... */
9603             if (p) {
9604                 strcpy(p,":");          /* safe */
9605                 strcat(p,s);            /* safe */
9606                 if (zchdir(p))
9607                   cwdf = 1;
9608                 free(p);
9609                 p = NULL;
9610             }
9611         }
9612     }
9613     if (!cwdf)
9614       perror(s);
9615 #else
9616     p = zgtdir();
9617     if (!zchdir(s)) {
9618         cwdf = 0;
9619 #ifdef CKROOT
9620         if (ckrooterr)
9621           printf("?Off limits: \"%s\"\n",s);
9622         else
9623 #endif /* CKROOT */
9624           perror(s);
9625     } else cwdf = 1;
9626 #endif /* MAC */
9627
9628     x = 0;
9629     if (cwdf) {
9630         makestr(&prevdir,p);
9631         debug(F111,"docd","srvcdmsg",srvcdmsg);
9632         if (srvcdmsg
9633 #ifdef IKSDCONF
9634             && !(inserver && !iksdcf)
9635 #endif /* IKSDCONF */
9636             ) {
9637             int i;
9638             for (i = 0; i < 8; i++) {
9639                 debug(F111,"docd cdmsgfile[i]",cdmsgfile[i],i);
9640                 if (zchki(cdmsgfile[i]) > -1) {
9641                     x = 1;
9642                     dotype(cdmsgfile[i],xaskmore,0,0,NULL,0,NULL,0,0,NULL,0);
9643                     break;
9644                 }
9645             }
9646         }
9647     }
9648 /* xdocd: */
9649     if (!x && srvcdmsg && !server
9650 #ifdef IKSDCONF
9651         && !(inserver && !iksdcf)
9652 #endif /* IKSDCONF */
9653         && !quiet && !xcmdsrc)
9654       printf("%s\n", zgtdir());
9655
9656     return(cwdf);
9657 }
9658
9659 static int on_ctrlc = 0;
9660
9661 VOID
9662 fixcmd() {                      /* Fix command parser after interruption */
9663 #ifndef NOSPL
9664 #ifndef NOONCTRLC
9665     if (nmac) {                         /* Any macros defined? */
9666         int k;                          /* Yes */
9667         char * s = "on_ctrlc";          /* Name of Ctrl-C handling macro */
9668         k = mlook(mactab,s,nmac);       /* Look it up. */
9669         if (k >= 0) {                   /* If found, */
9670             if (on_ctrlc++ == 0) {      /* if not already executing, */
9671                 if (dodo(k,"",0) > -1)  /* set it up, */
9672                   parser(1);            /* execute it, */
9673             }
9674             delmac(s,1);                /* and undefine it. */
9675         }
9676     }
9677     on_ctrlc = 0;
9678 #endif /* NOONCTRLC */
9679 #endif /* NOSPL */
9680     dostop();                   /* Back to top level (also calls conint()). */
9681     bgchk();                    /* Check background status */
9682     if (*psave) {               /* If old prompt saved, */
9683         cmsetp(psave);          /* restore it. */
9684         *psave = NUL;
9685     }
9686     success = 0;                /* Tell parser last command failed */
9687 }
9688
9689 #ifndef NOSHOW                          /* SHOW FEATURES */
9690 /*
9691   Note, presently optlist[] index overflow is not checked.
9692   There is plenty of room (less than 360 entries for 1000 slots).
9693   When space starts to get tight, check for noptlist >= NOPTLIST
9694   every time noptlist is incremented.
9695 */
9696 #define NOPTLIST 1024
9697 static int noptlist = 0;
9698 static char * optlist[NOPTLIST+1];
9699 static int hpos = 0;
9700
9701 int
9702 prtopt(lines,s) int * lines; char *s; { /* Print an option */
9703     int y, i;                           /* Does word wrap. */
9704     if (!s) s = "";
9705     i = *lines;
9706     if (!*s) {                          /* Empty argument */
9707         if (hpos > 0) {                 /* means to end this line. */
9708             printf("\n");               /* Not needed if already at */
9709             if (++i > (cmd_rows - 3)) { /* beginning of new line. */
9710                 if (!askmore())
9711                   return(0);
9712                 else
9713                   i = 0;
9714             }
9715         }
9716         printf("\n");                   /* And then make a blank line */
9717         if (++i > (cmd_rows - 3)) {
9718             if (!askmore())
9719               return(0);
9720             else
9721               i = 0;
9722         }
9723         hpos = 0;
9724         *lines = i;
9725         return(1);
9726     }
9727     y = (int)strlen(s) + 1;
9728     hpos += y;
9729     debug(F101,"prtopt hpos","",hpos);
9730     debug(F101,"prtopt cmd_cols","",cmd_cols);
9731
9732     if (
9733 #ifdef OS2
9734         hpos > ((cmd_cols > 40) ? (cmd_cols - 1) : 79)
9735 #else /* OS2 */
9736         hpos > ((tt_cols > 40) ? (tt_cols - 1) : 79)
9737 #endif /* OS2 */
9738         ) {
9739         printf("\n");
9740         if (++i > (cmd_rows - 3)) {
9741             if (!askmore())
9742               return(0);
9743             else
9744               i = 0;
9745         }
9746         printf(" %s",s);
9747         hpos = y;
9748     } else
9749       printf(" %s",s);
9750     *lines = i;
9751     return(1);
9752 }
9753
9754 static VOID
9755 initoptlist() {
9756     int i;
9757     if (noptlist > 0)
9758       return;
9759     for (i = 0; i < NOPTLIST; i++)
9760       optlist[i] = NULL;
9761
9762 #ifdef MAC
9763 #ifdef MPW
9764     makestr(&(optlist[noptlist++]),"MPW");
9765 #endif /* MPW */
9766 #endif /* MAC */
9767
9768 #ifdef MAC
9769 #ifdef THINK_C
9770     makestr(&(optlist[noptlist++]),"THINK_C");
9771 #endif /* THINK_C */
9772 #endif /* MAC */
9773
9774 #ifdef __386__
9775     makestr(&(optlist[noptlist++]),"__386__");
9776 #endif /* __386__ */
9777
9778 /* Memory models... */
9779
9780 #ifdef __FLAT__
9781     makestr(&(optlist[noptlist++]),"__FLAT__");
9782 #endif /* __FLAT__ */
9783 #ifdef __SMALL__
9784     makestr(&(optlist[noptlist++]),"__SMALL__");
9785 #endif /* __SMALL__ */
9786 #ifdef __MEDIUM__
9787     makestr(&(optlist[noptlist++]),"__MEDIUM__");
9788 #endif /* __MEDIUM__ */
9789 #ifdef __COMPACT__
9790     makestr(&(optlist[noptlist++]),"__COMPACT__");
9791 #endif /* __COMPACT__ */
9792 #ifdef __LARGE__
9793     makestr(&(optlist[noptlist++]),"__LARGE__");
9794 #endif /* __LARGE__ */
9795
9796 #ifdef DEBUG
9797 #ifdef IFDEBUG
9798     makestr(&(optlist[noptlist++]),"IFDEBUG");
9799 #else
9800     makestr(&(optlist[noptlist++]),"DEBUG");
9801 #endif /* IFDEBUG */
9802 #endif /* DEBUG */
9803 #ifdef TLOG
9804     makestr(&(optlist[noptlist++]),"TLOG");
9805 #endif /* TLOG */
9806 #ifdef BIGBUFOK
9807     makestr(&(optlist[noptlist++]),"BIGBUFOK");
9808 #endif /* BIGBUFOK */
9809 #ifdef INPBUFSIZ
9810     sprintf(line,"INPBUFSIZ=%d",INPBUFSIZ); /* SAFE */
9811     makestr(&(optlist[noptlist++]),line);
9812 #endif /* INPBUFSIZE */
9813 #ifdef INBUFSIZE
9814     sprintf(line,"INBUFSIZE=%d",INBUFSIZE); /* SAFE */
9815     makestr(&(optlist[noptlist++]),line);
9816 #endif /* INBUFSIZE */
9817 #ifdef OBUFSIZE
9818     sprintf(line,"OBUFSIZE=%d",OBUFSIZE); /* SAFE */
9819     makestr(&(optlist[noptlist++]),line);
9820 #endif /* OBUFSIZE */
9821 #ifdef FD_SETSIZE
9822     sprintf(line,"FD_SETSIZE=%d",FD_SETSIZE); /* SAFE */
9823     makestr(&(optlist[noptlist++]),line);
9824 #endif /* FD_SETSIZE */
9825 #ifdef XFRCAN
9826     makestr(&(optlist[noptlist++]),"XFRCAN");
9827 #endif /* XFRCAN */
9828 #ifdef XPRINT
9829     makestr(&(optlist[noptlist++]),"XPRINT");
9830 #endif /* XPRINT */
9831 #ifdef PIPESEND
9832     makestr(&(optlist[noptlist++]),"PIPESEND");
9833 #endif /* PIPESEND */
9834 #ifdef CK_SPEED
9835     makestr(&(optlist[noptlist++]),"CK_SPEED");
9836 #endif /* CK_SPEED */
9837 #ifdef CK_FAST
9838     makestr(&(optlist[noptlist++]),"CK_FAST");
9839 #endif /* CK_FAST */
9840 #ifdef CK_APC
9841     makestr(&(optlist[noptlist++]),"CK_APC");
9842 #endif /* CK_APC */
9843 #ifdef CK_AUTODL
9844     makestr(&(optlist[noptlist++]),"CK_AUTODL");
9845 #endif /* CK_AUTODL */
9846 #ifdef CK_MKDIR
9847     makestr(&(optlist[noptlist++]),"CK_MKDIR");
9848 #endif /* CK_MKDIR */
9849 #ifdef NOMKDIR
9850     makestr(&(optlist[noptlist++]),"NOMKDIR");
9851 #endif /* NOMKDIR */
9852 #ifdef CK_LABELED
9853     makestr(&(optlist[noptlist++]),"CK_LABELED");
9854 #endif /* CK_LABELED */
9855 #ifdef NODIAL
9856     makestr(&(optlist[noptlist++]),"NODIAL");
9857 #endif /* NODIAL */
9858 #ifdef MINIDIAL
9859     makestr(&(optlist[noptlist++]),"MINIDIAL");
9860 #endif /* MINIDIAL */
9861 #ifdef WHATAMI
9862     makestr(&(optlist[noptlist++]),"WHATAMI");
9863 #endif /* WHATAMI */
9864 #ifdef DYNAMIC
9865     makestr(&(optlist[noptlist++]),"DYNAMIC");
9866 #endif /* IFDEBUG */
9867 #ifndef NOSPL
9868     sprintf(line,"CMDDEP=%d",CMDDEP);   /* SAFE */
9869     makestr(&(optlist[noptlist++]),line);
9870 #endif /* NOSPL */
9871
9872 #ifdef MAXPATHLEN
9873     sprintf(line,"MAXPATHLEN=%d",MAXPATHLEN); /* SAFE */
9874     makestr(&(optlist[noptlist++]),line);
9875 #endif /* MAXPATHLEN */
9876
9877 #ifdef DEVNAMLEN
9878     sprintf(line,"DEVNAMLEN=%d",DEVNAMLEN); /* SAFE */
9879     makestr(&(optlist[noptlist++]),line);
9880 #endif /* DEVNAMLEN */
9881
9882 #ifdef NO_PARAM_H
9883     makestr(&(optlist[noptlist++]),"NO_PARAM_H");
9884 #endif /* NO_PARAM_H */
9885
9886 #ifdef INCL_PARAM_H
9887     makestr(&(optlist[noptlist++]),"INCL_PARAM_H");
9888 #endif /* INCL_PARAM_H */
9889
9890     sprintf(line,"CKMAXPATH=%d",CKMAXPATH); /* SAFE */
9891     makestr(&(optlist[noptlist++]),line);
9892
9893     sprintf(line,"CKMAXOPEN=%d",CKMAXOPEN); /* SAFE */
9894     makestr(&(optlist[noptlist++]),line);
9895
9896     sprintf(line,"Z_MAXCHAN=%d",Z_MAXCHAN); /* SAFE */
9897     makestr(&(optlist[noptlist++]),line);
9898
9899 #ifdef OPEN_MAX
9900     sprintf(line,"OPEN_MAX=%d",OPEN_MAX); /* SAFE */
9901     makestr(&(optlist[noptlist++]),line);
9902 #endif /* OPEN_MAX */
9903
9904 #ifdef _POSIX_OPEN_MAX
9905     sprintf(line,"_POSIX_OPEN_MAX=%d",_POSIX_OPEN_MAX); /* SAFE */
9906     makestr(&(optlist[noptlist++]),line);
9907 #endif /* _POSIX_OPEN_MAX */
9908
9909 #ifdef CKCHANNELIO
9910     {
9911         extern int z_maxchan;
9912 #ifdef UNIX
9913         extern int ckmaxfiles;
9914         sprintf(line,"ckmaxfiles=%d",ckmaxfiles); /* SAFE */
9915         makestr(&(optlist[noptlist++]),line);
9916 #endif /* UNIX */
9917         sprintf(line,"z_maxchan=%d",z_maxchan); /* SAFE */
9918         makestr(&(optlist[noptlist++]),line);
9919     }
9920 #endif /* CKCHANNELIO */
9921
9922 #ifdef FOPEN_MAX
9923     sprintf(line,"FOPEN_MAX=%d",FOPEN_MAX); /* SAFE */
9924     makestr(&(optlist[noptlist++]),line);
9925 #endif /* FOPEN_MAX */
9926
9927 #ifdef MAXGETPATH
9928     sprintf(line,"MAXGETPATH=%d",MAXGETPATH); /* SAFE */
9929     makestr(&(optlist[noptlist++]),line);
9930 #endif /* MAXGETPATH */
9931
9932 #ifdef CMDBL
9933     sprintf(line,"CMDBL=%d",CMDBL);     /* SAFE */
9934     makestr(&(optlist[noptlist++]),line);
9935 #endif /* CMDBL */
9936
9937 #ifdef VNAML
9938     sprintf(line,"VNAML=%d",VNAML);     /* SAFE */
9939     makestr(&(optlist[noptlist++]),line);
9940 #endif /* VNAML */
9941
9942 #ifdef ARRAYREFLEN
9943     sprintf(line,"ARRAYREFLEN=%d",ARRAYREFLEN); /* SAFE */
9944     makestr(&(optlist[noptlist++]),line);
9945 #endif /* ARRAYREFLEN */
9946
9947 #ifdef UIDBUFLEN
9948     sprintf(line,"UIDBUFLEN=%d",UIDBUFLEN); /* SAFE */
9949     makestr(&(optlist[noptlist++]),line);
9950 #endif /* UIDBUFLEN */
9951
9952 #ifdef FORDEPTH
9953     sprintf(line,"FORDEPTH=%d",FORDEPTH); /* SAFE */
9954     makestr(&(optlist[noptlist++]),line);
9955 #endif /* FORDEPTH */
9956
9957 #ifdef MAXTAKE
9958     sprintf(line,"MAXTAKE=%d",MAXTAKE); /* SAFE */
9959     makestr(&(optlist[noptlist++]),line);
9960 #endif /* MAXTAKE */
9961
9962 #ifdef MACLEVEL
9963     sprintf(line,"MACLEVEL=%d",MACLEVEL); /* SAFE */
9964     makestr(&(optlist[noptlist++]),line);
9965 #endif /* MACLEVEL */
9966
9967 #ifdef MAC_MAX
9968     sprintf(line,"MAC_MAX=%d",MAC_MAX); /* SAFE */
9969     makestr(&(optlist[noptlist++]),line);
9970 #endif /* MAC_MAX */
9971
9972 #ifdef MINPUTMAX
9973     sprintf(line,"MINPUTMAX=%d",MINPUTMAX); /* SAFE */
9974     makestr(&(optlist[noptlist++]),line);
9975 #endif /* MINPUTMAX */
9976
9977 #ifdef MAXWLD
9978     sprintf(line,"MAXWLD=%d",MAXWLD); /* SAFE */
9979     makestr(&(optlist[noptlist++]),line);
9980 #else
9981 #ifdef OS2
9982     makestr(&(optlist[noptlist++]),"MAXWLD=unlimited");
9983 #endif /* OS2 */
9984 #endif /* MAXWLD */
9985
9986 #ifdef MSENDMAX
9987     sprintf(line,"MSENDMAX=%d",MSENDMAX); /* SAFE */
9988     makestr(&(optlist[noptlist++]),line);
9989 #endif /* MSENDMAX */
9990
9991 #ifdef MAXDDIR
9992     sprintf(line,"MAXDDIR=%d",MAXDDIR); /* SAFE */
9993     makestr(&(optlist[noptlist++]),line);
9994 #endif /* MAXDDIR */
9995
9996 #ifdef MAXDNUMS
9997     sprintf(line,"MAXDNUMS=%d",MAXDNUMS); /* SAFE */
9998     makestr(&(optlist[noptlist++]),line);
9999 #endif /* MAXDNUMS */
10000
10001 #ifdef UNIX
10002     makestr(&(optlist[noptlist++]),"UNIX");
10003 #endif /* UNIX */
10004 #ifdef VMS
10005     makestr(&(optlist[noptlist++]),"VMS");
10006 #ifdef __VMS_VER
10007     sprintf(line,"__VMS_VER=%d",__VMS_VER); /* SAFE */
10008     makestr(&(optlist[noptlist++]),line);
10009 #endif /* __VMS_VER */
10010 #ifdef VMSV70
10011     makestr(&(optlist[noptlist++]),"VMSV70");
10012 #endif /* VMSV70 */
10013 #endif /* VMS */
10014 #ifdef OLD_VMS
10015     makestr(&(optlist[noptlist++]),"OLD_VMS");
10016 #endif /* OLD_VMS */
10017 #ifdef vms
10018     makestr(&(optlist[noptlist++]),"vms");
10019 #endif /* vms */
10020 #ifdef VMSV60
10021     makestr(&(optlist[noptlist++]),"VMSV60");
10022 #endif /* VMSV60 */
10023 #ifdef VMSV80
10024     makestr(&(optlist[noptlist++]),"VMSV80");
10025 #endif /* VMSV80 */
10026 #ifdef VMSSHARE
10027     makestr(&(optlist[noptlist++]),"VMSSHARE");
10028 #endif /* VMSSHARE */
10029 #ifdef NOVMSSHARE
10030     makestr(&(optlist[noptlist++]),"NOVMSSHARE");
10031 #endif /* NOVMSSHARE */
10032 #ifdef datageneral
10033     makestr(&(optlist[noptlist++]),"datageneral");
10034 #endif /* datageneral */
10035 #ifdef apollo
10036     makestr(&(optlist[noptlist++]),"apollo");
10037 #endif /* apollo */
10038 #ifdef aegis
10039     makestr(&(optlist[noptlist++]),"aegis");
10040 #endif /* aegis */
10041 #ifdef A986
10042     makestr(&(optlist[noptlist++]),"A986");
10043 #endif /* A986 */
10044 #ifdef AMIGA
10045     makestr(&(optlist[noptlist++]),"AMIGA");
10046 #endif /* AMIGA */
10047 #ifdef CONVEX9
10048     makestr(&(optlist[noptlist++]),"CONVEX9");
10049 #endif /* CONVEX9 */
10050 #ifdef CONVEX10
10051     makestr(&(optlist[noptlist++]),"CONVEX10");
10052 #endif /* CONVEX9 */
10053 #ifdef MAC
10054     makestr(&(optlist[noptlist++]),"MAC");
10055 #endif /* MAC */
10056 #ifdef AUX
10057     makestr(&(optlist[noptlist++]),"AUX");
10058 #endif /* AUX */
10059 #ifdef OS2
10060     makestr(&(optlist[noptlist++]),"OS2");
10061 #ifdef NT
10062     makestr(&(optlist[noptlist++]),"NT");
10063 #endif /* NT */
10064 #endif /* OS2 */
10065 #ifdef OSK
10066     makestr(&(optlist[noptlist++]),"OS9");
10067 #endif /* OSK */
10068 #ifdef MSDOS
10069     makestr(&(optlist[noptlist++]),"MSDOS");
10070 #endif /* MSDOS */
10071 #ifdef DIRENT
10072     makestr(&(optlist[noptlist++]),"DIRENT");
10073 #endif /* DIRENT */
10074 #ifdef SDIRENT
10075     makestr(&(optlist[noptlist++]),"SDIRENT");
10076 #endif /* SDIRENT */
10077 #ifdef NDIR
10078     makestr(&(optlist[noptlist++]),"NDIR");
10079 #endif /* NDIR */
10080 #ifdef XNDIR
10081     makestr(&(optlist[noptlist++]),"XNDIR");
10082 #endif /* XNDIR */
10083 #ifdef SAVEDUID
10084     makestr(&(optlist[noptlist++]),"SAVEDUID");
10085 #endif /* SAVEDUID */
10086 #ifdef RENAME
10087     makestr(&(optlist[noptlist++]),"RENAME");
10088 #endif /* RENAME */
10089 #ifdef CK_TMPDIR
10090     makestr(&(optlist[noptlist++]),"CK_TMPDIR");
10091 #endif /* CK_TMPDIR */
10092 #ifdef NOCCTRAP
10093     makestr(&(optlist[noptlist++]),"NOCCTRAP");
10094 #endif /* NOCCTRAP */
10095 #ifdef NOCOTFMC
10096     makestr(&(optlist[noptlist++]),"NOCOTFMC");
10097 #endif /* NOCOTFMC */
10098 #ifdef NOFRILLS
10099     makestr(&(optlist[noptlist++]),"NOFRILLS");
10100 #endif /* NOFRILLS */
10101 #ifdef PARSENSE
10102     makestr(&(optlist[noptlist++]),"PARSENSE");
10103 #endif /* PARSENSE */
10104 #ifdef TIMEH
10105     makestr(&(optlist[noptlist++]),"TIMEH");
10106 #endif /* TIMEH */
10107 #ifdef NOTIMEH
10108     makestr(&(optlist[noptlist++]),"TIMEH");
10109 #endif /* NOTIMEH */
10110
10111 #ifdef SYSTIMEH
10112     makestr(&(optlist[noptlist++]),"SYSTIMEH");
10113 #endif /* SYSTIMEH */
10114 #ifdef NOSYSTIMEH
10115     makestr(&(optlist[noptlist++]),"SYSTIMEH");
10116 #endif /* NOSYSTIMEH */
10117
10118 #ifdef SYSTIMEBH
10119     makestr(&(optlist[noptlist++]),"SYSTIMEBH");
10120 #endif /* SYSTIMEBH */
10121 #ifdef NOSYSTIMEBH
10122     makestr(&(optlist[noptlist++]),"SYSTIMEBH");
10123 #endif /* NOSYSTIMEBH */
10124 #ifdef UTIMEH
10125     makestr(&(optlist[noptlist++]),"UTIMEH");
10126 #endif /* UTIMEH */
10127 #ifdef SYSUTIMEH
10128     makestr(&(optlist[noptlist++]),"SYSUTIMEH");
10129 #endif /* SYSUTIMEH */
10130
10131 #ifdef CK_NEED_SIG
10132     makestr(&(optlist[noptlist++]),"CK_NEED_SIG");
10133 #endif /* CK_NEED_SIG */
10134 #ifdef CK_TTYFD
10135     makestr(&(optlist[noptlist++]),"CK_TTYFD");
10136 #endif /* CK_TTYFD */
10137 #ifdef NETCONN
10138     makestr(&(optlist[noptlist++]),"NETCONN");
10139 #endif /* NETCONN */
10140 #ifdef TCPSOCKET
10141     makestr(&(optlist[noptlist++]),"TCPSOCKET");
10142 #ifdef NOTCPOPTS
10143     makestr(&(optlist[noptlist++]),"NOTCPOPTS");
10144 #endif /* NOTCPOPTS */
10145 #ifdef CK_DNS_SRV
10146     makestr(&(optlist[noptlist++]),"CK_DNS_SRV");
10147 #endif /* CK_DNS_SRV */
10148 #ifdef NO_DNS_SRV
10149     makestr(&(optlist[noptlist++]),"NO_DNS_SRV");
10150 #endif /* NO_DNS_SRV */
10151 #ifdef CKGHNLHOST
10152     makestr(&(optlist[noptlist++]),"CKGHNLHOST");
10153 #endif /* CKGHNLHOST */
10154 #ifdef NOLISTEN
10155     makestr(&(optlist[noptlist++]),"NOLISTEN");
10156 #endif /* NOLISTEN */
10157 #ifdef SOL_SOCKET
10158     makestr(&(optlist[noptlist++]),"SOL_SOCKET");
10159 #endif /* SOL_SOCKET */
10160 #ifdef SO_OOBINLINE
10161     makestr(&(optlist[noptlist++]),"SO_OOBINLINE");
10162 #endif /* SO_OOBINLNE */
10163 #ifdef SO_DONTROUTE
10164     makestr(&(optlist[noptlist++]),"SO_DONTROUTE");
10165 #endif /* SO_DONTROUTE */
10166 #ifdef SO_KEEPALIVE
10167     makestr(&(optlist[noptlist++]),"SO_KEEPALIVE");
10168 #endif /* SO_KEEPALIVE */
10169 #ifdef SO_LINGER
10170     makestr(&(optlist[noptlist++]),"SO_LINGER");
10171 #endif /* SO_LINGER */
10172 #ifdef TCP_NODELAY
10173     makestr(&(optlist[noptlist++]),"TCP_NODELAY");
10174 #endif /* TCP_NODELAY */
10175 #ifdef SO_SNDBUF
10176     makestr(&(optlist[noptlist++]),"SO_SNDBUF");
10177 #endif /* SO_SNDBUF */
10178 #ifdef SO_RCVBUF
10179     makestr(&(optlist[noptlist++]),"SO_RCVBUF");
10180 #endif /* SO_RCVBUF */
10181 #ifdef h_addr
10182     makestr(&(optlist[noptlist++]),"h_addr");
10183 #endif /* h_addr */
10184 #ifdef HADDRLIST
10185     makestr(&(optlist[noptlist++]),"HADDRLIST");
10186 #endif /* HADDRLIST */
10187 #ifdef CK_SOCKS
10188     makestr(&(optlist[noptlist++]),"CK_SOCKS");
10189 #ifdef CK_SOCKS5
10190     makestr(&(optlist[noptlist++]),"CK_SOCKS5");
10191 #endif /* CK_SOCKS5 */
10192 #ifdef CK_SOCKS_NS
10193     makestr(&(optlist[noptlist++]),"CK_SOCKS_NS");
10194 #endif /* CK_SOCKS_NS */
10195 #endif /* CK_SOCKS */
10196 #ifdef RLOGCODE
10197     makestr(&(optlist[noptlist++]),"RLOGCODE");
10198 #endif /* RLOGCODE */
10199 #ifdef NETCMD
10200     makestr(&(optlist[noptlist++]),"NETCMD");
10201 #endif /* NETCMD */
10202 #ifdef NONETCMD
10203     makestr(&(optlist[noptlist++]),"NONETCMD");
10204 #endif /* NONETCMD */
10205 #ifdef NETPTY
10206     makestr(&(optlist[noptlist++]),"NETPTY");
10207 #endif /* NETPTY */
10208 #ifdef CK_ENVIRONMENT
10209     makestr(&(optlist[noptlist++]),"CK_ENVIRONMENT");
10210 #endif /* CK_ENVIRONMENT */
10211 #endif /* TCPSOCKET */
10212 #ifdef TNCODE
10213     makestr(&(optlist[noptlist++]),"TNCODE");
10214 #endif /* TNCODE */
10215 #ifdef CK_FORWARD_X
10216     makestr(&(optlist[noptlist++]),"CK_FORWARD_X");
10217 #endif /* CK_FORWARD_X */
10218 #ifdef TN_COMPORT
10219     makestr(&(optlist[noptlist++]),"TN_COMPORT");
10220 #endif /* TN_COMPORT */
10221 #ifdef MULTINET
10222     makestr(&(optlist[noptlist++]),"MULTINET");
10223 #endif /* MULTINET */
10224 #ifdef DEC_TCPIP
10225     makestr(&(optlist[noptlist++]),"DEC_TCPIP");
10226 #endif /* DEC_TCPIP */
10227 #ifdef TCPWARE
10228     makestr(&(optlist[noptlist++]),"TCPWARE");
10229 #endif /* TCPWARE */
10230 #ifdef UCX50
10231     makestr(&(optlist[noptlist++]),"UCX50");
10232 #endif /* UCX50 */
10233 #ifdef CMU_TCPIP
10234     makestr(&(optlist[noptlist++]),"CMU_TCPIP");
10235 #endif /* CMU_TCPIP */
10236 #ifdef TTLEBUF
10237     makestr(&(optlist[noptlist++]),"TTLEBUF");
10238 #endif /* TTLEBUF */
10239 #ifdef NETLEBUF
10240     makestr(&(optlist[noptlist++]),"NETLEBUF");
10241 #endif /* NETLEBUF */
10242 #ifdef IKS_OPTION
10243     makestr(&(optlist[noptlist++]),"IKS_OPTION");
10244 #endif /* IKS_OPTION */
10245 #ifdef IKSDB
10246     makestr(&(optlist[noptlist++]),"IKSDB");
10247 #endif /* IKSDB */
10248 #ifdef IKSDCONF
10249     makestr(&(optlist[noptlist++]),"IKSDCONF");
10250 #endif /* IKSDCONF */
10251 #ifdef CK_LOGIN
10252     makestr(&(optlist[noptlist++]),"CK_LOGIN");
10253 #endif /* CK_LOGIN */
10254 #ifdef CK_PAM
10255     makestr(&(optlist[noptlist++]),"CK_PAM");
10256 #endif /* CK_PAM */
10257 #ifdef CK_SHADOW
10258     makestr(&(optlist[noptlist++]),"CK_SHADOW");
10259 #endif /* CK_SHADOW */
10260 #ifdef CONGSPD
10261     makestr(&(optlist[noptlist++]),"CONGSPD");
10262 #endif /* CONGSPD */
10263 #ifdef SUNX25
10264     makestr(&(optlist[noptlist++]),"SUNX25");
10265 #endif /* SUNX25 */
10266 #ifdef IBMX25
10267     makestr(&(optlist[noptlist++]),"IBMX25");
10268 #endif /* IBMX25 */
10269 #ifdef HPX25
10270     makestr(&(optlist[noptlist++]),"HPX25");
10271 #endif /* HPX25 */
10272 #ifdef DECNET
10273     makestr(&(optlist[noptlist++]),"DECNET");
10274 #endif /* DECNET */
10275 #ifdef SUPERLAT
10276     makestr(&(optlist[noptlist++]),"SUPERLAT");
10277 #endif /* SUPERLAT */
10278 #ifdef NPIPE
10279     makestr(&(optlist[noptlist++]),"NPIPE");
10280 #endif /* NPIPE */
10281 #ifdef CK_NETBIOS
10282     makestr(&(optlist[noptlist++]),"CK_NETBIOS");
10283 #endif /* CK_NETBIOS */
10284 #ifdef ATT7300
10285     makestr(&(optlist[noptlist++]),"ATT7300");
10286 #endif /* ATT7300 */
10287 #ifdef ATT6300
10288     makestr(&(optlist[noptlist++]),"ATT6300");
10289 #endif /* ATT6300 */
10290 #ifdef HDBUUCP
10291     makestr(&(optlist[noptlist++]),"HDBUUCP");
10292 #endif /* HDBUUCP */
10293 #ifdef USETTYLOCK
10294     makestr(&(optlist[noptlist++]),"USETTYLOCK");
10295 #endif /* USETTYLOCK */
10296 #ifdef USE_UU_LOCK
10297     makestr(&(optlist[noptlist++]),"USE_UU_LOCK");
10298 #endif /* USE_UU_LOCK */
10299 #ifdef HAVE_BAUDBOY
10300     makestr(&(optlist[noptlist++]),"HAVE_BAUDBOY");
10301 #endif /* HAVE_BAUDBOY */
10302 #ifdef NOUUCP
10303     makestr(&(optlist[noptlist++]),"NOUUCP");
10304 #endif /* NOUUCP */
10305 #ifdef LONGFN
10306     makestr(&(optlist[noptlist++]),"LONGFN");
10307 #endif /* LONGFN */
10308 #ifdef RDCHK
10309     makestr(&(optlist[noptlist++]),"RDCHK");
10310 #endif /* RDCHK */
10311 #ifdef SELECT
10312     makestr(&(optlist[noptlist++]),"SELECT");
10313 #endif /* SELECT */
10314 #ifdef USLEEP
10315     makestr(&(optlist[noptlist++]),"USLEEP");
10316 #endif /* USLEEP */
10317 #ifdef NAP
10318     makestr(&(optlist[noptlist++]),"NAP");
10319 #endif /* NAP */
10320 #ifdef NAPHACK
10321     makestr(&(optlist[noptlist++]),"NAPHACK");
10322 #endif /* NAPHACK */
10323 #ifdef CK_POLL
10324     makestr(&(optlist[noptlist++]),"CK_POLL");
10325 #endif /* CK_POLL */
10326 #ifdef NOIEXTEN
10327     makestr(&(optlist[noptlist++]),"NOIEXTEN");
10328 #endif /* NOIEXTEN */
10329 #ifdef EXCELAN
10330     makestr(&(optlist[noptlist++]),"EXCELAN");
10331 #endif /* EXCELAN */
10332 #ifdef INTERLAN
10333     makestr(&(optlist[noptlist++]),"INTERLAN");
10334 #endif /* INTERLAN */
10335 #ifdef NOFILEH
10336     makestr(&(optlist[noptlist++]),"NOFILEH");
10337 #endif /* NOFILEH */
10338 #ifdef NOSYSIOCTLH
10339     makestr(&(optlist[noptlist++]),"NOSYSIOCTLH");
10340 #endif /* NOSYSIOCTLH */
10341 #ifdef DCLPOPEN
10342     makestr(&(optlist[noptlist++]),"DCLPOPEN");
10343 #endif /* DCLPOPEN */
10344 #ifdef NOSETBUF
10345     makestr(&(optlist[noptlist++]),"NOSETBUF");
10346 #endif /* NOSETBUF */
10347 #ifdef NOXFER
10348     makestr(&(optlist[noptlist++]),"NOXFER");
10349 #endif /* NOXFER */
10350 #ifdef NOCURSES
10351     makestr(&(optlist[noptlist++]),"NOCURSES");
10352 #endif /* NOCURSES */
10353 #ifdef NOSERVER
10354     makestr(&(optlist[noptlist++]),"NOSERVER");
10355 #endif /* NOSERVER */
10356 #ifdef NOPATTERNS
10357     makestr(&(optlist[noptlist++]),"NOPATTERNS");
10358 #else
10359 #ifdef PATTERNS
10360     makestr(&(optlist[noptlist++]),"PATTERNS");
10361 #endif /* PATTERNS */
10362 #endif /* NOPATTERNS */
10363 #ifdef NOCKEXEC
10364     makestr(&(optlist[noptlist++]),"NOCKEXEC");
10365 #else
10366 #ifdef CKEXEC
10367     makestr(&(optlist[noptlist++]),"CKEXEC");
10368 #endif /* CKEXEC */
10369 #endif /* NOCKEXEC */
10370 #ifdef NOAUTODL
10371     makestr(&(optlist[noptlist++]),"NOAUTODL");
10372 #endif /* NOAUTODL */
10373 #ifdef NOMSEND
10374     makestr(&(optlist[noptlist++]),"NOMSEND");
10375 #endif /* NOMSEND */
10376 #ifdef NOFDZERO
10377     makestr(&(optlist[noptlist++]),"NOFDZERO");
10378 #endif /* NOFDZERO */
10379 #ifdef NOPOPEN
10380     makestr(&(optlist[noptlist++]),"NOPOPEN");
10381 #endif /* NOPOPEN */
10382 #ifdef NOPARTIAL
10383     makestr(&(optlist[noptlist++]),"NOPARTIAL");
10384 #endif /* NOPARTIAL */
10385 #ifdef NOKVERBS
10386     makestr(&(optlist[noptlist++]),"NOKVERBS");
10387 #endif /* NOKVERBS */
10388 #ifdef NOSETREU
10389     makestr(&(optlist[noptlist++]),"NOSETREU");
10390 #endif /* NOSETREU */
10391 #ifdef LCKDIR
10392     makestr(&(optlist[noptlist++]),"LCKDIR");
10393 #endif /* LCKDIR */
10394 #ifdef ACUCNTRL
10395     makestr(&(optlist[noptlist++]),"ACUCNTRL");
10396 #endif /* ACUCNTRL */
10397 #ifdef BSD4
10398     makestr(&(optlist[noptlist++]),"BSD4");
10399 #endif /* BSD4 */
10400 #ifdef BSD44
10401     makestr(&(optlist[noptlist++]),"BSD44");
10402 #endif /* BSD44 */
10403 #ifdef BSD41
10404     makestr(&(optlist[noptlist++]),"BSD41");
10405 #endif /* BSD41 */
10406 #ifdef BSD43
10407     makestr(&(optlist[noptlist++]),"BSD43");
10408 #endif /* BSD43 */
10409 #ifdef BSD29
10410     makestr(&(optlist[noptlist++]),"BSD29");
10411 #endif /* BSD29 */
10412 #ifdef BSDI
10413     makestr(&(optlist[noptlist++]),"BSDI");
10414 #endif /* BSDI */
10415 #ifdef __bsdi__
10416     makestr(&(optlist[noptlist++]),"__bsdi__");
10417 #endif /* __bsdi__ */
10418 #ifdef __NetBSD__
10419     makestr(&(optlist[noptlist++]),"__NetBSD__");
10420 #endif /* __NetBSD__ */
10421 #ifdef __OpenBSD__
10422     makestr(&(optlist[noptlist++]),"__OpenBSD__");
10423 #endif /* __OpenBSD__ */
10424 #ifdef __FreeBSD__
10425     makestr(&(optlist[noptlist++]),"__FreeBSD__");
10426 #endif /* __FreeBSD__ */
10427 #ifdef __linux__
10428     makestr(&(optlist[noptlist++]),"__linux__");
10429 #endif /* __linux__ */
10430 #ifdef LINUX_HI_SPD
10431     makestr(&(optlist[noptlist++]),"LINUX_HI_SPD");
10432 #endif /* LINUX_HI_SPD */
10433 #ifdef LYNXOS
10434     makestr(&(optlist[noptlist++]),"LYNXOS");
10435 #endif /* LYNXOS */
10436 #ifdef V7
10437     makestr(&(optlist[noptlist++]),"V7");
10438 #endif /* V7 */
10439 #ifdef AIX370
10440     makestr(&(optlist[noptlist++]),"AIX370");
10441 #endif /* AIX370 */
10442 #ifdef RTAIX
10443     makestr(&(optlist[noptlist++]),"RTAIX");
10444 #endif /* RTAIX */
10445 #ifdef HPUX
10446     makestr(&(optlist[noptlist++]),"HPUX");
10447 #endif /* HPUX */
10448 #ifdef HPUXPRE65
10449     makestr(&(optlist[noptlist++]),"HPUXPRE65");
10450 #endif /* HPUXPRE65 */
10451 #ifdef DGUX
10452     makestr(&(optlist[noptlist++]),"DGUX");
10453 #endif /* DGUX */
10454 #ifdef DGUX430
10455     makestr(&(optlist[noptlist++]),"DGUX430");
10456 #endif /* DGUX430 */
10457 #ifdef DGUX540
10458     makestr(&(optlist[noptlist++]),"DGUX540");
10459 #endif /* DGUX540 */
10460 #ifdef DGUX543
10461     makestr(&(optlist[noptlist++]),"DGUX543");
10462 #endif /* DGUX543 */
10463 #ifdef DGUX54410
10464     makestr(&(optlist[noptlist++]),"DGUX54410");
10465 #endif /* DGUX54410 */
10466 #ifdef DGUX54411
10467     makestr(&(optlist[noptlist++]),"DGUX54411");
10468 #endif /* DGUX54411 */
10469 #ifdef sony_news
10470     makestr(&(optlist[noptlist++]),"sony_news");
10471 #endif /* sony_news */
10472 #ifdef CIE
10473     makestr(&(optlist[noptlist++]),"CIE");
10474 #endif /* CIE */
10475 #ifdef XENIX
10476     makestr(&(optlist[noptlist++]),"XENIX");
10477 #endif /* XENIX */
10478 #ifdef SCO_XENIX
10479     makestr(&(optlist[noptlist++]),"SCO_XENIX");
10480 #endif /* SCO_XENIX */
10481 #ifdef ISIII
10482     makestr(&(optlist[noptlist++]),"ISIII");
10483 #endif /* ISIII */
10484 #ifdef I386IX
10485     makestr(&(optlist[noptlist++]),"I386IX");
10486 #endif /* I386IX */
10487 #ifdef RTU
10488     makestr(&(optlist[noptlist++]),"RTU");
10489 #endif /* RTU */
10490 #ifdef PROVX1
10491     makestr(&(optlist[noptlist++]),"PROVX1");
10492 #endif /* PROVX1 */
10493 #ifdef PYRAMID
10494     makestr(&(optlist[noptlist++]),"PYRAMID");
10495 #endif /* PYRAMID */
10496 #ifdef TOWER1
10497     makestr(&(optlist[noptlist++]),"TOWER1");
10498 #endif /* TOWER1 */
10499 #ifdef UTEK
10500     makestr(&(optlist[noptlist++]),"UTEK");
10501 #endif /* UTEK */
10502 #ifdef ZILOG
10503     makestr(&(optlist[noptlist++]),"ZILOG");
10504 #endif /* ZILOG */
10505 #ifdef TRS16
10506     makestr(&(optlist[noptlist++]),"TRS16");
10507 #endif /* TRS16 */
10508 #ifdef MINIX
10509     makestr(&(optlist[noptlist++]),"MINIX");
10510 #endif /* MINIX */
10511 #ifdef C70
10512     makestr(&(optlist[noptlist++]),"C70");
10513 #endif /* C70 */
10514 #ifdef AIXPS2
10515     makestr(&(optlist[noptlist++]),"AIXPS2");
10516 #endif /* AIXPS2 */
10517 #ifdef AIXRS
10518     makestr(&(optlist[noptlist++]),"AIXRS");
10519 #endif /* AIXRS */
10520 #ifdef UTSV
10521     makestr(&(optlist[noptlist++]),"UTSV");
10522 #endif /* UTSV */
10523 #ifdef ATTSV
10524     makestr(&(optlist[noptlist++]),"ATTSV");
10525 #endif /* ATTSV */
10526 #ifdef SVR3
10527     makestr(&(optlist[noptlist++]),"SVR3");
10528 #endif /* SVR3 */
10529 #ifdef SVR4
10530     makestr(&(optlist[noptlist++]),"SVR4");
10531 #endif /* SVR4 */
10532 #ifdef DELL_SVR4
10533     makestr(&(optlist[noptlist++]),"DELL_SVR4");
10534 #endif /* DELL_SVR4 */
10535 #ifdef ICL_SVR4
10536     makestr(&(optlist[noptlist++]),"ICL_SVR4");
10537 #endif /* ICL_SVR4 */
10538 #ifdef OSF
10539     makestr(&(optlist[noptlist++]),"OSF");
10540 #endif /* OSF */
10541 #ifdef OSF1
10542     makestr(&(optlist[noptlist++]),"OSF1");
10543 #endif /* OSF1 */
10544 #ifdef __OSF
10545     makestr(&(optlist[noptlist++]),"__OSF");
10546 #endif /* __OSF */
10547 #ifdef __OSF__
10548     makestr(&(optlist[noptlist++]),"__OSF__");
10549 #endif /* __OSF__ */
10550 #ifdef __osf__
10551     makestr(&(optlist[noptlist++]),"__osf__");
10552 #endif /* __osf__ */
10553 #ifdef __OSF1
10554     makestr(&(optlist[noptlist++]),"__OSF1");
10555 #endif /* __OSF1 */
10556 #ifdef __OSF1__
10557     makestr(&(optlist[noptlist++]),"__OSF1__");
10558 #endif /* __OSF1__ */
10559 #ifdef PTX
10560     makestr(&(optlist[noptlist++]),"PTX");
10561 #endif /* PTX */
10562 #ifdef POSIX
10563     makestr(&(optlist[noptlist++]),"POSIX");
10564 #endif /* POSIX */
10565 #ifdef BSD44ORPOSIX
10566     makestr(&(optlist[noptlist++]),"BSD44ORPOSIX");
10567 #endif /* BSD44ORPOSIX */
10568 #ifdef SVORPOSIX
10569     makestr(&(optlist[noptlist++]),"SVORPOSIX");
10570 #endif /* SVORPOSIX */
10571 #ifdef SVR4ORPOSIX
10572     makestr(&(optlist[noptlist++]),"SVR4ORPOSIX");
10573 #endif /* SVR4ORPOSIX */
10574 #ifdef OS2ORVMS
10575     makestr(&(optlist[noptlist++]),"OS2ORVMS");
10576 #endif /* OS2ORVMS */
10577 #ifdef OS2ORUNIX
10578     makestr(&(optlist[noptlist++]),"OS2ORUNIX");
10579 #endif /* OS2ORUNIX */
10580 #ifdef VMSORUNIX
10581     makestr(&(optlist[noptlist++]),"VMSORUNIX");
10582 #endif /* VMSORUNIX */
10583 #ifdef VMS64BIT
10584     makestr(&(optlist[noptlist++]),"VMS64BIT"); /* VMS on Alpha or IA64 */
10585 #endif /* VMS64BIT */
10586 #ifdef VMSI64
10587     makestr(&(optlist[noptlist++]),"VMSI64"); /* VMS on IA64 */
10588 #endif /* VMSI64 */
10589 #ifdef _POSIX_SOURCE
10590     makestr(&(optlist[noptlist++]),"_POSIX_SOURCE");
10591 #endif /* _POSIX_SOURCE */
10592 #ifdef _XOPEN_SOURCE
10593     makestr(&(optlist[noptlist++]),"_XOPEN_SOURCE");
10594 #endif
10595 #ifdef _ALL_SOURCE
10596     makestr(&(optlist[noptlist++]),"_ALL_SOURCE");
10597 #endif
10598 #ifdef _SVID3
10599     makestr(&(optlist[noptlist++]),"_SVID3");
10600 #endif /* _SVID3 */
10601 #ifdef Plan9
10602     makestr(&(optlist[noptlist++]),"Plan9");
10603 #endif /* Plan9 */
10604 #ifdef SOLARIS
10605     makestr(&(optlist[noptlist++]),"SOLARIS");
10606 #ifdef SOLARIS24
10607     makestr(&(optlist[noptlist++]),"SOLARIS24");
10608 #endif /* SOLARIS24 */
10609 #ifdef SOLARIS25
10610     makestr(&(optlist[noptlist++]),"SOLARIS25");
10611 #endif /* SOLARIS25 */
10612 #ifdef SOLARIS26
10613     makestr(&(optlist[noptlist++]),"SOLARIS26");
10614 #endif /* SOLARIS26 */
10615 #ifdef SOLARIS7
10616     makestr(&(optlist[noptlist++]),"SOLARIS7");
10617 #endif /* SOLARIS7 */
10618 #ifdef SOLARIS8
10619     makestr(&(optlist[noptlist++]),"SOLARIS8");
10620 #endif /* SOLARIS8 */
10621 #endif /* SOLARIS */
10622
10623 #ifdef SUNOS4
10624     makestr(&(optlist[noptlist++]),"SUNOS4");
10625 #endif /* SUNOS4 */
10626 #ifdef SUN4S5
10627     makestr(&(optlist[noptlist++]),"SUN4S5");
10628 #endif /* SUN4S5 */
10629 #ifdef IRIX
10630     makestr(&(optlist[noptlist++]),"IRIX");
10631 #endif /* IRIX */
10632 #ifdef ENCORE
10633     makestr(&(optlist[noptlist++]),"ENCORE");
10634 #endif /* ENCORE */
10635 #ifdef ultrix
10636     makestr(&(optlist[noptlist++]),"ultrix");
10637 #endif
10638 #ifdef sxaE50
10639     makestr(&(optlist[noptlist++]),"sxaE50");
10640 #endif
10641 #ifdef mips
10642     makestr(&(optlist[noptlist++]),"mips");
10643 #endif
10644 #ifdef MIPS
10645     makestr(&(optlist[noptlist++]),"MIPS");
10646 #endif
10647 #ifdef vax
10648     makestr(&(optlist[noptlist++]),"vax");
10649 #endif
10650 #ifdef VAX
10651     makestr(&(optlist[noptlist++]),"VAX");
10652 #endif
10653 #ifdef alpha
10654     makestr(&(optlist[noptlist++]),"alpha");
10655 #endif
10656 #ifdef ALPHA
10657     makestr(&(optlist[noptlist++]),"ALPHA");
10658 #endif
10659 #ifdef __ALPHA
10660     makestr(&(optlist[noptlist++]),"__ALPHA");
10661 #endif
10662 #ifdef __alpha
10663     makestr(&(optlist[noptlist++]),"__alpha");
10664 #endif
10665 #ifdef __AXP
10666     makestr(&(optlist[noptlist++]),"__AXP");
10667 #endif
10668 #ifdef AXP
10669     makestr(&(optlist[noptlist++]),"AXP");
10670 #endif
10671 #ifdef axp
10672     makestr(&(optlist[noptlist++]),"axp");
10673 #endif
10674 #ifdef __ALPHA__
10675     makestr(&(optlist[noptlist++]),"__ALPHA__");
10676 #endif
10677 #ifdef __alpha__
10678     makestr(&(optlist[noptlist++]),"__alpha__");
10679 #endif
10680 #ifdef sun
10681     makestr(&(optlist[noptlist++]),"sun");
10682 #endif
10683 #ifdef sun3
10684     makestr(&(optlist[noptlist++]),"sun3");
10685 #endif
10686 #ifdef sun386
10687     makestr(&(optlist[noptlist++]),"sun386");
10688 #endif
10689 #ifdef _SUN
10690     makestr(&(optlist[noptlist++]),"_SUN");
10691 #endif
10692 #ifdef sun4
10693     makestr(&(optlist[noptlist++]),"sun4");
10694 #endif
10695 #ifdef sparc
10696     makestr(&(optlist[noptlist++]),"sparc");
10697 #endif
10698 #ifdef _CRAY
10699     makestr(&(optlist[noptlist++]),"_CRAY");
10700 #endif /* _CRAY */
10701 #ifdef NEXT33
10702     makestr(&(optlist[noptlist++]),"NEXT33");
10703 #endif
10704 #ifdef NEXT
10705     makestr(&(optlist[noptlist++]),"NEXT");
10706 #endif
10707 #ifdef NeXT
10708     makestr(&(optlist[noptlist++]),"NeXT");
10709 #endif
10710 #ifdef MACH
10711     makestr(&(optlist[noptlist++]),"MACH");
10712 #endif
10713
10714 #ifdef MACOSX
10715     makestr(&(optlist[noptlist++]),"MACOSX");
10716 #endif
10717 #ifdef MACOSX10
10718     makestr(&(optlist[noptlist++]),"MACOSX10");
10719 #endif
10720 #ifdef MACOSX103
10721     makestr(&(optlist[noptlist++]),"MACOSX103");
10722 #endif
10723
10724 #ifdef sgi
10725     makestr(&(optlist[noptlist++]),"sgi");
10726 #endif
10727 #ifdef M_SYS5
10728     makestr(&(optlist[noptlist++]),"M_SYS5");
10729 #endif
10730 #ifdef __SYSTEM_FIVE
10731     makestr(&(optlist[noptlist++]),"__SYSTEM_FIVE");
10732 #endif
10733 #ifdef sysV
10734     makestr(&(optlist[noptlist++]),"sysV");
10735 #endif
10736 #ifdef M_XENIX                          /* SCO Xenix V and UNIX/386 */
10737     makestr(&(optlist[noptlist++]),"M_XENIX");
10738 #endif
10739 #ifdef M_UNIX                           /* SCO UNIX */
10740     makestr(&(optlist[noptlist++]),"M_UNIX");
10741 #endif
10742 #ifdef _M_UNIX                          /* SCO UNIX 3.2v4 = ODT 2.0 */
10743     makestr(&(optlist[noptlist++]),"_M_UNIX");
10744 #endif
10745 #ifdef CK_SCOV5
10746     makestr(&(optlist[noptlist++]),"CK_SCOV5");
10747 #endif
10748 #ifdef SCO_OSR504
10749     makestr(&(optlist[noptlist++]),"SCO_OSR504");
10750 #endif
10751 #ifdef M_IA64
10752     makestr(&(optlist[noptlist++]),"M_IA64");
10753 #endif
10754 #ifdef _M_IA64
10755     makestr(&(optlist[noptlist++]),"_M_IA64");
10756 #endif
10757 #ifdef ia64
10758     makestr(&(optlist[noptlist++]),"ia64");
10759 #endif
10760 #ifdef _ia64
10761     makestr(&(optlist[noptlist++]),"_ia64");
10762 #endif
10763 #ifdef _ia64_
10764     makestr(&(optlist[noptlist++]),"_ia64_");
10765 #endif
10766 #ifdef __ia64
10767     makestr(&(optlist[noptlist++]),"__ia64");
10768 #endif
10769 #ifdef M_I686
10770     makestr(&(optlist[noptlist++]),"M_I686");
10771 #endif
10772 #ifdef _M_I686
10773     makestr(&(optlist[noptlist++]),"_M_I686");
10774 #endif
10775 #ifdef i686
10776     makestr(&(optlist[noptlist++]),"i686");
10777 #endif
10778 #ifdef M_I586
10779     makestr(&(optlist[noptlist++]),"M_I586");
10780 #endif
10781 #ifdef _M_I586
10782     makestr(&(optlist[noptlist++]),"_M_I586");
10783 #endif
10784 #ifdef i586
10785     makestr(&(optlist[noptlist++]),"i586");
10786 #endif
10787 #ifdef M_I486
10788     makestr(&(optlist[noptlist++]),"M_I486");
10789 #endif
10790 #ifdef _M_I486
10791     makestr(&(optlist[noptlist++]),"_M_I486");
10792 #endif
10793 #ifdef i486
10794     makestr(&(optlist[noptlist++]),"i486");
10795 #endif
10796 #ifdef M_I386
10797     makestr(&(optlist[noptlist++]),"M_I386");
10798 #endif
10799 #ifdef _M_I386
10800     makestr(&(optlist[noptlist++]),"_M_I386");
10801 #endif
10802 #ifdef i386
10803     makestr(&(optlist[noptlist++]),"i386");
10804 #endif
10805 #ifdef i286
10806     makestr(&(optlist[noptlist++]),"i286");
10807 #endif
10808 #ifdef M_I286
10809     makestr(&(optlist[noptlist++]),"M_I286");
10810 #endif
10811 #ifdef mc68000
10812     makestr(&(optlist[noptlist++]),"mc68000");
10813 #endif
10814 #ifdef mc68010
10815     makestr(&(optlist[noptlist++]),"mc68010");
10816 #endif
10817 #ifdef mc68020
10818     makestr(&(optlist[noptlist++]),"mc68020");
10819 #endif
10820 #ifdef mc68030
10821     makestr(&(optlist[noptlist++]),"mc68030");
10822 #endif
10823 #ifdef mc68040
10824     makestr(&(optlist[noptlist++]),"mc68040");
10825 #endif
10826 #ifdef M_68000
10827     makestr(&(optlist[noptlist++]),"M_68000");
10828 #endif
10829 #ifdef M_68010
10830     makestr(&(optlist[noptlist++]),"M_68010");
10831 #endif
10832 #ifdef M_68020
10833     makestr(&(optlist[noptlist++]),"M_68020");
10834 #endif
10835 #ifdef M_68030
10836     makestr(&(optlist[noptlist++]),"M_68030");
10837 #endif
10838 #ifdef M_68040
10839     makestr(&(optlist[noptlist++]),"M_68040");
10840 #endif
10841 #ifdef m68k
10842     makestr(&(optlist[noptlist++]),"m68k");
10843 #endif
10844 #ifdef m88k
10845     makestr(&(optlist[noptlist++]),"m88k");
10846 #endif
10847 #ifdef pdp11
10848     makestr(&(optlist[noptlist++]),"pdp11");
10849 #endif
10850 #ifdef iAPX
10851     makestr(&(optlist[noptlist++]),"iAPX");
10852 #endif
10853 #ifdef hpux
10854     makestr(&(optlist[noptlist++]),"hpux");
10855 #endif
10856 #ifdef __hpux
10857     makestr(&(optlist[noptlist++]),"__hpux");
10858 #endif
10859 #ifdef __hp9000s800
10860     makestr(&(optlist[noptlist++]),"__hp9000s800");
10861 #endif
10862 #ifdef __hp9000s700
10863     makestr(&(optlist[noptlist++]),"__hp9000s700");
10864 #endif
10865 #ifdef __hp9000s500
10866     makestr(&(optlist[noptlist++]),"__hp9000s500");
10867 #endif
10868 #ifdef __hp9000s300
10869     makestr(&(optlist[noptlist++]),"__hp9000s300");
10870 #endif
10871 #ifdef __hp9000s200
10872     makestr(&(optlist[noptlist++]),"__hp9000s200");
10873 #endif
10874 #ifdef AIX
10875     makestr(&(optlist[noptlist++]),"AIX");
10876 #endif
10877 #ifdef _AIXFS
10878     makestr(&(optlist[noptlist++]),"_AIXFS");
10879 #endif
10880 #ifdef u370
10881     makestr(&(optlist[noptlist++]),"u370");
10882 #endif
10883 #ifdef u3b
10884     makestr(&(optlist[noptlist++]),"u3b");
10885 #endif
10886 #ifdef u3b2
10887     makestr(&(optlist[noptlist++]),"u3b2");
10888 #endif
10889 #ifdef multimax
10890     makestr(&(optlist[noptlist++]),"multimax");
10891 #endif
10892 #ifdef balance
10893     makestr(&(optlist[noptlist++]),"balance");
10894 #endif
10895 #ifdef ibmrt
10896     makestr(&(optlist[noptlist++]),"ibmrt");
10897 #endif
10898 #ifdef _IBMRT
10899     makestr(&(optlist[noptlist++]),"_IBMRT");
10900 #endif
10901 #ifdef ibmrs6000
10902     makestr(&(optlist[noptlist++]),"ibmrs6000");
10903 #endif
10904 #ifdef _AIX
10905     makestr(&(optlist[noptlist++]),"_AIX");
10906 #endif /* _AIX */
10907 #ifdef _IBMR2
10908     makestr(&(optlist[noptlist++]),"_IBMR2");
10909 #endif
10910 #ifdef UNIXWARE
10911     makestr(&(optlist[noptlist++]),"UNIXWARE");
10912 #endif
10913 #ifdef QNX
10914     makestr(&(optlist[noptlist++]),"QNX");
10915 #ifdef __QNX__
10916     makestr(&(optlist[noptlist++]),"__QNX__");
10917 #ifdef __16BIT__
10918     makestr(&(optlist[noptlist++]),"__16BIT__");
10919 #endif
10920 #ifdef CK_QNX16
10921     makestr(&(optlist[noptlist++]),"CK_QNX16");
10922 #endif
10923 #ifdef __32BIT__
10924     makestr(&(optlist[noptlist++]),"__32BIT__");
10925 #endif
10926 #ifdef CK_QNX32
10927     makestr(&(optlist[noptlist++]),"CK_QNX32");
10928 #endif
10929 #endif /* __QNX__ */
10930 #endif /* QNX */
10931
10932 #ifdef QNX6
10933     makestr(&(optlist[noptlist++]),"QNX6");
10934 #endif /* QNX6 */
10935
10936 #ifdef NEUTRINO
10937     makestr(&(optlist[noptlist++]),"NEUTRINO");
10938 #endif /* NEUTRINO */
10939
10940 #ifdef __STRICT_BSD__
10941     makestr(&(optlist[noptlist++]),"__STRICT_BSD__");
10942 #endif
10943 #ifdef __STRICT_ANSI__
10944     makestr(&(optlist[noptlist++]),"__STRICT_ANSI__");
10945 #endif
10946 #ifdef _ANSI_C_SOURCE
10947     makestr(&(optlist[noptlist++]),"_ANSI_C_SOURCE");
10948 #endif
10949 #ifdef __STDC__
10950     makestr(&(optlist[noptlist++]),"__STDC__");
10951 #endif
10952 #ifdef __DECC
10953     makestr(&(optlist[noptlist++]),"__DECC");
10954 #ifdef __DECC_VER
10955     sprintf(line,"__DECC_VER=%d",__DECC_VER); /* SAFE */
10956     makestr(&(optlist[noptlist++]),line);
10957 #endif /* __DECC_VER */
10958 #endif /* __DECC */
10959 #ifdef __CRTL_VER
10960     sprintf(line,"__CRTL_VER=%d",__CRTL_VER); /* SAFE */
10961     makestr(&(optlist[noptlist++]),line);
10962 #endif /* __CRTL_VER */
10963 #ifdef __GNUC__                         /* gcc in ansi mode */
10964     makestr(&(optlist[noptlist++]),"__GNUC__");
10965 #endif
10966 #ifdef GNUC                             /* gcc in traditional mode */
10967     makestr(&(optlist[noptlist++]),"GNUC");
10968 #endif
10969 #ifdef __EGCS__                         /* egcs in ansi mode */
10970     makestr(&(optlist[noptlist++]),"__EGCS__");
10971 #endif
10972 #ifdef __egcs__                         /* egcs in ansi mode */
10973     makestr(&(optlist[noptlist++]),"__egcs__");
10974 #endif
10975 #ifdef __WATCOMC__
10976     makestr(&(optlist[noptlist++]),"__WATCOMC__");
10977 #endif
10978 #ifdef CK_ANSIC
10979     makestr(&(optlist[noptlist++]),"CK_ANSIC");
10980 #endif
10981 #ifdef CK_ANSILIBS
10982     makestr(&(optlist[noptlist++]),"CK_ANSILIBS");
10983 #endif
10984 #ifdef CKCONINTB4CB
10985     makestr(&(optlist[noptlist++]),"CKCONINTB4CB");
10986 #endif /* CKCONINTB4CB */
10987 #ifdef NOTERMCAP
10988     makestr(&(optlist[noptlist++]),"NOTERMCAP");
10989 #endif /* NOTERMCAP */
10990 #ifdef __GLIBC__
10991     makestr(&(optlist[noptlist++]),"__GLIBC__");
10992 #endif
10993 #ifdef _SC_JOB_CONTROL
10994     makestr(&(optlist[noptlist++]),"_SC_JOB_CONTROL");
10995 #endif
10996 #ifdef _POSIX_JOB_CONTROL
10997     makestr(&(optlist[noptlist++]),"_POSIX_JOB_CONTROL");
10998 #endif
10999 #ifdef SIG_I
11000     makestr(&(optlist[noptlist++]),"SIG_I");
11001 #endif /* SIG_I */
11002 #ifdef SIG_V
11003     makestr(&(optlist[noptlist++]),"SIG_V");
11004 #endif /* SIG_V */
11005 #ifdef CK_POSIX_SIG
11006     makestr(&(optlist[noptlist++]),"CK_POSIX_SIG");
11007 #endif
11008 #ifdef SVR3JC
11009     makestr(&(optlist[noptlist++]),"SVR3JC");
11010 #endif
11011 #ifdef _386BSD
11012     makestr(&(optlist[noptlist++]),"_386BSD");
11013 #endif
11014 #ifdef _BSD
11015     makestr(&(optlist[noptlist++]),"_BSD");
11016 #endif
11017 #ifdef USE_MEMCPY
11018     makestr(&(optlist[noptlist++]),"USE_MEMCPY");
11019 #endif /* USE_MEMCPY */
11020 #ifdef USE_LSTAT
11021     makestr(&(optlist[noptlist++]),"USE_LSTAT");
11022 #endif /* USE_LSTAT */
11023 #ifdef TERMIOX
11024     makestr(&(optlist[noptlist++]),"TERMIOX");
11025 #endif /* TERMIOX */
11026 #ifdef STERMIOX
11027     makestr(&(optlist[noptlist++]),"STERMIOX");
11028 #endif /* STERMIOX */
11029 #ifdef CK_CURSES
11030     makestr(&(optlist[noptlist++]),"CK_CURSES");
11031 #endif /* CK_CURSES */
11032 #ifdef CK_NEWTERM
11033     makestr(&(optlist[noptlist++]),"CK_NEWTERM");
11034 #endif /* CK_NEWTERM */
11035 #ifdef CK_WREFRESH
11036     makestr(&(optlist[noptlist++]),"CK_WREFRESH");
11037 #endif /* CK_WREFRESH */
11038 #ifdef CK_PCT_BAR
11039     makestr(&(optlist[noptlist++]),"CK_PCT_BAR");
11040 #endif /* CK_PCT_BAR */
11041 #ifdef CK_DTRCD
11042     makestr(&(optlist[noptlist++]),"CK_DTRCD");
11043 #endif /* CK_DTRCD */
11044 #ifdef CK_DTRCTS
11045     makestr(&(optlist[noptlist++]),"CK_DTRCTS");
11046 #endif /* CK_DTRCTS */
11047 #ifdef CK_RTSCTS
11048     makestr(&(optlist[noptlist++]),"CK_RTSCTS");
11049 #endif /* CK_RTSCTS */
11050 #ifdef POSIX_CRTSCTS
11051     makestr(&(optlist[noptlist++]),"POSIX_CRTSCTS");
11052 #endif /* POSIX_CRTSCTS */
11053 #ifdef FIXCRTSCTS
11054     makestr(&(optlist[noptlist++]),"FIXCRTSCTS");
11055 #endif /* FIXCRTSCTS */
11056 #ifdef HWPARITY
11057     makestr(&(optlist[noptlist++]),"HWPARITY");
11058 #endif /* HWPARITY */
11059 #ifdef CK_SYSINI
11060 #ifdef CK_INI_A
11061     makestr(&(optlist[noptlist++]),"CK_INI_A");
11062     ckmakmsg(line,LINBUFSIZ,"CK_SYSINI=\"",CK_SYSINI,"\"",NULL);
11063     makestr(&(optlist[noptlist++]),line);
11064 #else
11065 #ifdef CK_INI_B
11066     makestr(&(optlist[noptlist++]),"CK_INI_B");
11067     ckmakmsg(line,LINBUFSIZ,"CK_SYSINI=\"",CK_SYSINI,"\"",NULL);
11068     makestr(&(optlist[noptlist++]),line);
11069 #else
11070     makestr(&(optlist[noptlist++]),"CK_SYSINI");
11071 #endif /* CK_INI_B */
11072 #endif /* CK_INI_A */
11073 #endif /* CK_DSYSINI */
11074 #ifdef CK_DSYSINI
11075     makestr(&(optlist[noptlist++]),"CK_DSYSINI");
11076 #endif /* CK_DSYSINI */
11077 #ifdef CK_TTGWSIZ
11078     makestr(&(optlist[noptlist++]),"CK_TTGWSIZ");
11079 #endif /* CK_TTGWSIZ */
11080 #ifdef CK_NAWS
11081     makestr(&(optlist[noptlist++]),"CK_NAWS");
11082 #endif /* CK_NAWS */
11083 #ifdef MDMHUP
11084     makestr(&(optlist[noptlist++]),"MDMHUP");
11085 #endif /* MDMHUP */
11086 #ifdef HUP_CLOSE_POSIX
11087     makestr(&(optlist[noptlist++]),"HUP_CLOSE_POSIX");
11088 #endif /* HUP_CLOSE_POSIX */
11089 #ifdef NO_HUP_CLOSE_POSIX
11090     makestr(&(optlist[noptlist++]),"NO_HUP_CLOSE_POSIX");
11091 #endif /* NO_HUP_CLOSE_POSIX */
11092 #ifdef DCMDBUF
11093     makestr(&(optlist[noptlist++]),"DCMDBUF");
11094 #endif /* DCMDBUF */
11095 #ifdef CK_RECALL
11096     makestr(&(optlist[noptlist++]),"CK_RECALL");
11097 #endif /* CK_RECALL */
11098 #ifdef BROWSER
11099     makestr(&(optlist[noptlist++]),"BROWSER");
11100 #endif /* BROWSER */
11101 #ifdef CLSOPN
11102     makestr(&(optlist[noptlist++]),"CLSOPN");
11103 #endif /* CLSOPN */
11104 #ifdef STRATUS
11105     makestr(&(optlist[noptlist++]),"STRATUS");
11106 #endif /* STRATUS */
11107 #ifdef __VOS__
11108     makestr(&(optlist[noptlist++]),"__VOS__");
11109 #endif /* __VOS__ */
11110 #ifdef STRATUSX25
11111     makestr(&(optlist[noptlist++]),"STRATUSX25");
11112 #endif /* STRATUSX25 */
11113 #ifdef OS2MOUSE
11114     makestr(&(optlist[noptlist++]),"OS2MOUSE");
11115 #endif /* OS2MOUSE */
11116 #ifdef CK_REXX
11117     makestr(&(optlist[noptlist++]),"CK_REXX");
11118 #endif /* CK_REXX */
11119 #ifdef CK_TIMERS
11120     makestr(&(optlist[noptlist++]),"CK_TIMERS");
11121 #endif /* CK_TIMERS */
11122 #ifdef TTSPDLIST
11123     makestr(&(optlist[noptlist++]),"TTSPDLIST");
11124 #endif /* TTSPDLIST */
11125 #ifdef CK_PERMS
11126     makestr(&(optlist[noptlist++]),"CK_PERMS");
11127 #endif /* CK_PERMS */
11128 #ifdef CKTUNING
11129     makestr(&(optlist[noptlist++]),"CKTUNING");
11130 #endif /* CKTUNING */
11131 #ifdef NEWFTP
11132     makestr(&(optlist[noptlist++]),"NEWFTP");
11133 #endif /* NEWFTP */
11134 #ifdef SYSFTP
11135     makestr(&(optlist[noptlist++]),"SYSFTP");
11136 #endif /* SYSFTP */
11137 #ifdef NOFTP
11138     makestr(&(optlist[noptlist++]),"NOFTP");
11139 #endif /* NOFTP */
11140 #ifdef CKHTTP
11141     makestr(&(optlist[noptlist++]),"CKHTTP");
11142 #endif /* CKHTTP */
11143 #ifdef NOHTTP
11144     makestr(&(optlist[noptlist++]),"NOHTTP");
11145 #endif /* NOHTTP */
11146 #ifdef CKROOT
11147     makestr(&(optlist[noptlist++]),"CKROOT");
11148 #endif /* CKROOT */
11149 #ifdef CKREALPATH
11150     makestr(&(optlist[noptlist++]),"CKREALPATH");
11151 #endif /* CKREALPATH */
11152 #ifdef STREAMING
11153     makestr(&(optlist[noptlist++]),"STREAMING");
11154 #endif /* STREAMING */
11155 #ifdef UNPREFIXZERO
11156     makestr(&(optlist[noptlist++]),"UNPREFIXZERO");
11157 #endif /* UNPREFIXZERO */
11158 #ifdef CKREGEX
11159     makestr(&(optlist[noptlist++]),"CKREGEX");
11160 #endif /* CKREGEX */
11161 #ifdef ZXREWIND
11162     makestr(&(optlist[noptlist++]),"ZXREWIND");
11163 #endif /* ZXREWIND */
11164 #ifdef CKSYSLOG
11165     makestr(&(optlist[noptlist++]),"CKSYSLOG");
11166 #endif /* CKSYSLOG */
11167 #ifdef SYSLOGLEVEL
11168     sprintf(line,"SYSLOGLEVEL=%d",SYSLOGLEVEL); /* SAFE */
11169     makestr(&(optlist[noptlist++]),line);
11170 #endif /* SYSLOGLEVEL */
11171 #ifdef NOSEXP
11172     makestr(&(optlist[noptlist++]),"NOSEXP");
11173 #endif /* NOSEXP */
11174 #ifdef CKLEARN
11175     makestr(&(optlist[noptlist++]),"CKLEARN");
11176 #else
11177 #ifdef NOLOEARN
11178     makestr(&(optlist[noptlist++]),"NOLOEARN");
11179 #endif /* NOLOEARN */
11180 #endif /* CKLEARN */
11181 #ifdef NOFLOAT
11182     makestr(&(optlist[noptlist++]),"NOFLOAT");
11183 #else
11184 #ifdef FNFLOAT
11185     makestr(&(optlist[noptlist++]),"FNFLOAT");
11186 #endif /* FNFLOAT */
11187 #ifdef CKFLOAT
11188 #ifdef GFTIMER
11189     makestr(&(optlist[noptlist++]),"GFTIMER");
11190 #endif /* GFTIMER */
11191 #ifdef CKFLOAT_S
11192     ckmakmsg(line,LINBUFSIZ,"CKFLOAT=",CKFLOAT_S,NULL,NULL);
11193     makestr(&(optlist[noptlist++]),line);
11194 #else
11195     makestr(&(optlist[noptlist++]),"CKFLOAT");
11196 #endif /* CKFLOAT_S */
11197 #endif /* CKFLOAT */
11198 #endif /* NOFLOAT */
11199
11200 #ifdef SSH
11201     makestr(&(optlist[noptlist++]),"SSH");
11202 #endif /* SSH */
11203 #ifdef NETDLL
11204     makestr(&(optlist[noptlist++]),"NETDLL");
11205 #endif /* NETDLL */
11206 #ifdef NETFILE
11207     makestr(&(optlist[noptlist++]),"NETFILE");
11208 #endif /* NETFILE */
11209 #ifdef CK_TAPI
11210     makestr(&(optlist[noptlist++]),"CK_TAPI");
11211 #endif /* CK_TAPI */
11212 #ifdef CK_SSL
11213     makestr(&(optlist[noptlist++]),"CK_SSL");
11214 #endif /* CK_SSL */
11215
11216     debug(F101,"initoptlist noptlist","",noptlist);
11217     sh_sort(optlist,NULL,noptlist,0,0,0);
11218 }
11219
11220 int
11221 shofea() {
11222     int i;
11223     int flag = 0;
11224     int lines = 1;
11225 #ifdef FNFLOAT
11226     extern int fp_digits, fp_rounding;
11227 #endif /* FNFLOAT */
11228     extern int byteorder;
11229     printf("%s\n",versio);
11230     if (inserver)
11231       return(1);
11232     debug(F101,"shofea NOPTLIST","",NOPTLIST);
11233     initoptlist();
11234     debug(F101,"shofea noptlist","",noptlist);
11235 #ifdef OS2
11236 #ifdef NT
11237 #ifdef _M_ALPHA
11238     printf("Microsoft Windows Operating Systems for Alpha CPUs.\n");
11239 #else /* _M_ALPHA */
11240 #ifdef _M_PPC
11241     printf("Microsoft Windows Operating Systems for PowerPC CPUs.\n");
11242 #else /* _M_PPC */
11243 #ifdef _M_MRX000
11244     printf("Microsoft Windows Operating Systems for MIPS CPUs.\n");
11245 #else /* _M_MRX000 */
11246 #ifdef _M_IX86
11247     printf("Microsoft Windows Operating Systems for 32-bit Intel CPUs.\n");
11248 #else /* _M_IX86 */
11249     UNKNOWN WINDOWS PLATFORM
11250 #endif /* _M_IX86 */
11251 #endif /* _M_MRX000 */
11252 #endif /* _M_PPC */
11253 #endif /* _M_ALPHA */
11254 #else /* NT */
11255 #ifdef M_I286
11256     printf("IBM OS/2 16-bit.\n");
11257 #else
11258     printf("IBM OS/2 32-bit.\n");
11259 #endif /* M_I286 */
11260 #endif /* NT */
11261     lines++;
11262 #endif /* OS2 */
11263     printf("\n");
11264     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11265     printf("Major optional features included:\n");
11266     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11267
11268 #ifdef NETCONN
11269     printf(" Network support (type SHOW NET for further info)\n");
11270     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11271 #ifdef IKS_OPTION
11272     printf(" Telnet Kermit Option\n");
11273     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11274 #endif /* IKS_OPTION */
11275 #ifdef CK_AUTHENTICATION
11276     printf(" Telnet Authentication Option\n");
11277     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11278 #ifdef CK_KERBEROS
11279 #ifdef KRB4
11280 #ifdef KRB5
11281     printf(" Kerberos(TM) IV and Kerberos V authentication\n");
11282     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11283 #else /* KRB5 */
11284     printf(" Kerberos(TM) IV authentication\n");
11285     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11286 #endif /* KRB5 */
11287 #else /* KRB4 */
11288 #ifdef KRB5
11289     printf(" Kerberos(TM) V authentication\n");
11290     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11291 #endif /* KRB5 */
11292 #endif /* KRB4 */
11293 #endif /* CK_KERBEROS */
11294 #ifdef CK_SRP
11295     printf(" SRP(TM) (Secure Remote Password) authentication\n");
11296     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11297 #endif /* CK_SRP */
11298 #ifdef CK_SSL
11299     printf(" Secure Sockets Layer (SSL)\n");
11300     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11301     printf(" Transport Layer Security (TLS)\n");
11302     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11303 #endif /* CK_SSL */
11304 #ifdef SSHBUILTIN
11305     printf(" Secure Shell (SSH) [internal]\n");
11306     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11307 #endif /* SSHBUILTIN */
11308 #ifdef SSHCMD
11309     printf(" Secure Shell (SSH) [external]\n");
11310     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11311 #endif /* SSHCMD */
11312 #ifdef CK_ENCRYPTION
11313     printf(" Telnet Encryption Option\n");
11314     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11315 #ifdef CK_DES
11316     printf(" Telnet DES Encryption\n");
11317     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11318 #endif /* CK_DES */
11319 #ifdef CK_CAST
11320     printf(" Telnet CAST Encryption\n");
11321     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11322 #endif /* CK_CAST */
11323 #ifdef CK_KERBEROS
11324 #ifdef KRB5
11325 #ifdef ALLOW_KRB_3DES_ENCRYPT
11326     printf(" Kerberos 3DES/AES Telnet Encryption\n");
11327     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11328 #endif /* ALLOW_KRB_3DES_ENCRYPT */
11329 #endif /* KRB5 */
11330 #endif /* CK_KERBEROS */
11331 #endif /* CK_ENCRYPTION */
11332 #endif /* CK_AUTHENTICATION */
11333 #ifdef CK_FORWARD_X
11334     printf(" X Windows forwarding\n");
11335     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11336 #endif /* CK_FORWARD_X */
11337 #ifdef TN_COMPORT
11338     printf(" Telnet Remote Com Port Control Option\n");
11339     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11340 #endif /* TN_COMPORT */
11341 #ifdef CK_SOCKS
11342 #ifdef CK_SOCKS5
11343     printf(" SOCKS 5\n");
11344     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11345 #else /* CK_SOCKS5 */
11346     printf(" SOCKS 4\n");
11347     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11348 #endif /* CK_SOCKS5 */
11349 #endif /* CK_SOCKS */
11350 #ifdef NEWFTP
11351     printf(" Built-in FTP client\n");
11352     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11353 #endif /* NEWFTP */
11354 #ifdef CKHTTP
11355     printf(" Built-in HTTP client\n");
11356     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11357 #endif /* CKHTTP */
11358 #endif /* NETCONN */
11359
11360 #ifdef CK_RTSCTS
11361     printf(" Hardware flow control\n");
11362     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11363 #endif /* CK_RTSCTS */
11364
11365 #ifdef CK_XYZ
11366 #ifdef XYZ_INTERNAL
11367     printf(" Built-in XYZMODEM protocols\n");
11368 #else
11369     printf(" External XYZMODEM protocol support\n");
11370 #endif /* XYZ_INTERNAL */
11371     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11372 #endif /* CK_XYZ */
11373
11374 #ifndef NOCSETS
11375     printf(" Latin-1 (West European) character-set translation\n");
11376     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11377 #ifdef LATIN2
11378     printf(" Latin-2 (East European) character-set translation\n");
11379     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11380 #endif /* LATIN2 */
11381 #ifdef CYRILLIC
11382     printf(" Cyrillic (Russian, Ukrainian, etc) character-set translation\n");
11383     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11384 #endif /* CYRILLIC */
11385 #ifdef GREEK
11386     printf(" Greek character-set translation\n");
11387     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11388 #endif /* GREEK */
11389 #ifdef HEBREW
11390     printf(" Hebrew character-set translation\n");
11391     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11392 #endif /* HEBREW */
11393 #ifdef KANJI
11394     printf(" Japanese character-set translation\n");
11395     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11396 #endif /* KANJI */
11397 #ifdef UNICODE
11398     printf(" Unicode character-set translation\n");
11399     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11400 #endif /* UNICODE */
11401 #ifdef CKOUNI
11402     if (isunicode())
11403       printf(" Unicode support for ISO-2022 Terminal Emulation\n");
11404     else
11405       printf(" Unicode translation for Terminal Character-Sets\n");
11406     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11407 #endif /* CKOUNI */
11408 #endif /* NOCSETS */
11409
11410 #ifdef NETPTY
11411     printf(" Pseudoterminal control\n");
11412     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11413 #endif /* NETPTY */
11414
11415 #ifdef CK_REDIR
11416     printf(" REDIRECT command\n");
11417     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11418 #endif /* CK_REDIR */
11419
11420 #ifdef CK_RESEND
11421     printf(" RESEND command\n");
11422     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11423 #endif /* CK_RESEND */
11424
11425 #ifndef NOXFER
11426 #ifdef CK_CURSES
11427     printf(" Fullscreen file transfer display\n");
11428     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11429 #endif /* CK_CURSES */
11430 #endif /* NOXFER */
11431
11432 #ifdef CK_SPEED
11433     printf(" Control-character unprefixing\n");
11434     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11435 #endif /* CK_SPEED */
11436
11437 #ifdef STREAMING
11438     printf(" Streaming\n");
11439     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11440 #endif /* STREAMING */
11441
11442 #ifdef CK_AUTODL
11443     printf(" Autodownload\n");
11444     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11445 #endif /* CK_AUTODL */
11446
11447 #ifdef OS2MOUSE
11448     printf(" Mouse support\n");
11449     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11450 #endif /* OS2MOUSE */
11451
11452 #ifdef CK_REXX
11453     printf(" REXX script language interface\n");
11454     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11455 #endif /* CK_REXX */
11456
11457 #ifdef IKSD
11458 #ifdef CK_LOGIN
11459     printf(" Internet Kermit Service with user login support\n");
11460 #else /* CK_LOGIN */
11461     printf(" Internet Kermit Service without user login support\n");
11462 #endif /* CK_LOGIN */
11463     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11464 #endif /* IKSD */
11465
11466     printf("\n");
11467     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11468     printf("Major optional features not included:\n");
11469     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11470
11471 #ifdef NOXFER
11472     printf(" No file-transfer protocols\n");
11473     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11474     flag = 1;
11475 #else
11476 #ifndef CK_CURSES
11477 #ifndef MAC
11478     printf(" No fullscreen file transfer display\n");
11479     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11480     flag = 1;
11481 #endif /* MAC */
11482 #endif /* CK_CURSES */
11483
11484 #ifdef NOSERVER
11485     printf(" No server mode\n");
11486     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11487     flag = 1;
11488 #endif /* NOSERVER */
11489
11490 #ifndef CK_SPEED
11491     printf(" No control-character unprefixing\n");
11492     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11493     flag = 1;
11494 #endif /* CK_SPEED */
11495
11496 #ifndef STREAMING
11497     printf(" No streaming\n");
11498     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11499     flag = 1;
11500 #endif /* STREAMING */
11501
11502 #ifndef CK_AUTODL
11503     printf(" No autodownload\n");
11504     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11505     flag = 1;
11506 #endif /* CK_AUTODL */
11507
11508 #ifndef CK_XYZ
11509     printf(" No built-in XYZMODEM protocols\n");
11510     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11511     flag = 1;
11512 #endif /* CK_XYZ */
11513
11514 #ifdef NOTLOG
11515     printf(" No transaction log\n");
11516     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11517     flag = 1;
11518 #endif /* NOTLOG */
11519 #endif /* NOXFER */
11520
11521 #ifdef NODEBUG
11522     printf(" No debugging\n");
11523     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11524     flag = 1;
11525 #endif /* NODEBUG */
11526
11527 #ifdef NOHELP
11528     printf(" No built-in help\n");
11529     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11530     flag = 1;
11531 #endif /* NOHELP */
11532
11533 #ifdef NOLOCAL
11534     printf(" No making connections\n");
11535     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11536     flag = 1;
11537 #else
11538 #ifndef NETCONN
11539     printf(" No network support\n");
11540     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11541     flag = 1;
11542 #else /* NETCONN */
11543 #ifndef IKS_OPTION
11544     printf(" No Telnet Kermit Option\n");
11545     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11546     flag = 1;
11547 #endif /* IKS_OPTION */
11548 #endif /* NETCONN */
11549
11550 #ifdef NOSSH
11551     printf(" No Secure Shell (SSH)\n");
11552     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11553 #endif /* NOSSH */
11554 #ifndef CK_AUTHENTICATION
11555     printf(" No Kerberos(TM) authentication\n");
11556     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11557     printf(" No SRP(TM) (Secure Remote Password) protocol\n");
11558     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11559     printf(" No Secure Sockets Layer (SSL) protocol\n");
11560     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11561     printf(" No Transport Layer Security (TLS) protocol\n");
11562     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11563     printf(" No encryption\n");
11564     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11565     flag = 1;
11566 #else /* CK_AUTHENTICATION */
11567 #ifndef CK_KERBEROS
11568     printf(" No Kerberos(TM) authentication\n");
11569     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11570     flag = 1;
11571 #else /* CK_KERBEROS */
11572 #ifndef KRB4
11573     printf(" No Kerberos(TM) IV authentication\n");
11574     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11575     flag = 1;
11576 #endif /* KRB4 */
11577 #ifndef KRB5
11578     printf(" No Kerberos(TM) V authentication\n");
11579     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11580     flag = 1;
11581 #endif /* KRB5 */
11582 #endif /* CK_KERBEROS */
11583 #ifndef CK_SRP
11584     printf(" No SRP(TM) (Secure Remote Password) authentication\n");
11585     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11586     flag = 1;
11587 #endif /* CK_SRP */
11588 #ifndef CK_SSL
11589     printf(" No Secure Sockets Layer (SSL) protocol\n");
11590     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11591     printf(" No Transport Layer Security (TLS) protocol\n");
11592     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11593     flag = 1;
11594 #endif /* CK_SSL */
11595 #ifndef CK_ENCRYPTION
11596     printf(" No Telnet Encryption Option\n");
11597     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11598     flag = 1;
11599 #else /* CK_ENCRYPTION */
11600 #ifndef OS2
11601 #ifndef CK_DES
11602     printf(" No Telnet DES encryption\n");
11603     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11604     flag = 1;
11605 #endif /* CK_DES */
11606 #ifndef CK_CAST
11607     printf(" No Telnet CAST encryption\n");
11608     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11609     flag = 1;
11610 #endif /* CK_CAST */
11611 #ifdef CK_KERBEROS
11612 #ifdef KRB5
11613 #ifndef ALLOW_KRB_3DES_ENCRYPT
11614     printf(" No Kerberos 3DES/AES Telnet Encryption\n");
11615     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11616 #endif /* ALLOW_KRB_3DES_ENCRYPT */
11617 #endif /* KRB5 */
11618 #endif /* CK_KERBEROS */
11619 #endif /* OS2 */
11620 #endif /* CK_ENCRYPTION */
11621 #endif /* CK_AUTHENTICATION */
11622 #ifndef CK_FORWARD_X
11623     printf(" No X Windows forwarding\n");
11624     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11625 #endif /* CK_FORWARD_X */
11626 #ifndef TN_COMPORT
11627     printf(" No Telnet Remote Com Port Control Option\n");
11628     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11629 #endif /* TN_COMPORT */
11630 #ifndef CK_SOCKS
11631     printf(" No SOCKS\n");
11632     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11633 #endif /* CK_SOCKS */
11634 #ifndef NEWFTP
11635     printf(" No built-in FTP client\n");
11636     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11637 #endif /* NEWFTP */
11638 #ifdef NOHTTP
11639     printf(" No built-in HTTP client\n");
11640     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11641 #endif /* NOHTTP */
11642
11643 #ifdef NODIAL
11644     printf(" No DIAL command\n");
11645     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11646     flag = 1;
11647 #else
11648 #ifdef MINIDIAL
11649     printf(" Support for most modem types excluded\n");
11650     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11651     flag = 1;
11652 #endif /* MINIDIAL */
11653 #endif /* NODIAL */
11654 #endif /* NOLOCAL */
11655
11656 #ifndef CK_RTSCTS
11657 #ifndef MAC
11658     printf(" No hardware flow control\n");
11659     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11660     flag = 1;
11661 #endif /* MAC */
11662 #endif /* CK_RTSCTS */
11663
11664 #ifdef NOXMIT
11665     printf(" No TRANSMIT command\n");
11666     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11667     flag = 1;
11668 #endif /* NOXMIT */
11669
11670 #ifdef NOSCRIPT
11671     printf(" No SCRIPT command\n");
11672     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11673     flag = 1;
11674 #endif /* NOSCRIPT */
11675
11676 #ifdef NOSPL
11677     printf(" No script programming features\n");
11678     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11679     flag = 1;
11680 #endif /* NOSPL */
11681
11682 #ifdef NOCSETS
11683     printf(" No character-set translation\n");
11684     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11685     flag = 1;
11686 #else
11687
11688 #ifndef LATIN2
11689     printf(" No Latin-2 character-set translation\n");
11690     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11691     flag = 1;
11692 #endif /* LATIN2 */
11693
11694 #ifdef NOGREEK
11695     printf(" No Greek character-set translation\n");
11696     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11697     flag = 1;
11698 #endif /* NOGREEK */
11699
11700 #ifdef NOHEBREW
11701     printf(" No Hebrew character-set translation\n");
11702     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11703     flag = 1;
11704 #endif /* NOHEBREW */
11705
11706 #ifdef NOUNICODE
11707     printf(" No Unicode character-set translation\n");
11708     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11709     flag = 1;
11710 #endif /* NOUNICODE */
11711
11712 #ifdef NOCYRIL
11713     printf(" No Cyrillic character-set translation\n");
11714     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11715     flag = 1;
11716 #endif /* NOCYRIL */
11717
11718 #ifndef KANJI
11719     printf(" No Kanji character-set translation\n");
11720     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11721     flag = 1;
11722 #endif /* KANJI */
11723 #endif /* NOCSETS */
11724
11725 #ifdef NOCMDL
11726     printf(" No command-line arguments\n");
11727     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11728     flag = 1;
11729 #endif /* NOCMDL */
11730
11731 #ifdef NOPUSH
11732     printf(" No escape to system\n");
11733     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11734     flag = 1;
11735 #endif /* NOPUSH */
11736
11737 #ifdef NOJC
11738 #ifdef UNIX
11739     printf(" No UNIX job control\n");
11740     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11741     flag = 1;
11742 #endif /* UNIX */
11743 #endif /* NOJC */
11744
11745 #ifdef NOSETKEY
11746     printf(" No SET KEY command\n");
11747     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11748     flag = 1;
11749 #endif /* NOSETKEY */
11750
11751 #ifndef CK_REDIR
11752     printf(" No REDIRECT or PIPE command\n");
11753     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11754     flag = 1;
11755 #endif /* CK_REDIR */
11756
11757 #ifdef UNIX
11758 #ifndef NETPTY
11759     printf(" No pseudoterminal control\n");
11760     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11761     flag = 1;
11762 #endif /* NETPTY */
11763 #endif /* UNIX */
11764
11765 #ifndef CK_RESEND
11766     printf(" No RESEND command\n");
11767     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11768     flag = 1;
11769 #endif /* CK_RESEND */
11770
11771 #ifdef OS2
11772 #ifdef __32BIT__
11773 #ifndef OS2MOUSE
11774     printf(" No Mouse support\n");
11775     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11776     flag = 1;
11777 #endif /* __32BIT__ */
11778 #endif /* OS2 */
11779 #endif /* OS2MOUSE */
11780
11781 #ifdef OS2
11782 #ifndef NT
11783 #ifndef CK_REXX
11784     printf(" No REXX script language interface\n");
11785     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11786     flag = 1;
11787 #endif /* CK_REXX */
11788 #endif /* NT */
11789 #endif /* OS2 */
11790
11791 #ifndef IKSD
11792     printf(" No Internet Kermit Service\n");
11793     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11794     flag = 1;
11795 #endif /* IKSD */
11796
11797     if (flag == 0) {
11798         printf(" None\n");
11799         if (++lines > cmd_rows - 3)
11800           { if (!askmore()) return(1); else lines = 0; }
11801     }
11802     printf("\n");
11803     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11804
11805 #ifdef CK_UTSNAME
11806     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11807     printf("Host info:\n");
11808     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11809     printf(" Machine:    %s\n",unm_mch[0] ? unm_mch : "(unknown)");
11810     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11811     printf(" Model:      %s\n",unm_mod[0] ? unm_mod : "(unknown)");
11812     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11813     printf(" OS:         %s\n",unm_nam[0] ? unm_nam : "(unknown)");
11814     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11815     printf(" OS Release: %s\n",unm_rel[0] ? unm_rel : "(unknown)");
11816     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11817     printf(" OS Version: %s\n",unm_ver[0] ? unm_ver : "(unknown)");
11818     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11819     printf("\n");
11820     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11821 #endif /* CK_UTSNAME */
11822
11823 /*
11824   Print compile-time (-D) options, as well as C preprocessor
11825   predefined symbols that might affect us...
11826 */
11827 #ifdef KTARGET
11828     {
11829         char * s;                       /* Makefile target */
11830         s = KTARGET;
11831         if (!s) s = "";
11832         if (!*s) s = "(unknown)";
11833         printf("\n");
11834         if (++lines > cmd_rows - 3) {
11835             if (!askmore()) return(1); else lines = 0;
11836         }
11837         printf("Target: %s\n", s);
11838         if (++lines > cmd_rows - 3) {
11839             if (!askmore()) return(1); else lines = 0;
11840         }
11841     }
11842 #endif /* KTARGET */
11843
11844 #ifdef __VERSION__
11845 #ifdef __GNUC__
11846     printf("GCC version: %s\n", __VERSION__);
11847 #else
11848     printf("Compiler version: %s\n", __VERSION__);
11849 #endif /* __GNUC__ */
11850     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11851 #endif /* __VERSION__ */
11852
11853 #ifdef __DATE__                         /* GNU and other ANSI */
11854 #ifdef __TIME__
11855     printf("Compiled %s %s, options:\n", __DATE__, __TIME__);
11856 #else
11857     printf("Compiled %s, options:\n", __DATE__);
11858 #endif /* __TIME__ */
11859 #else /* !__DATE__ */
11860     printf("Compiler options:\n");
11861 #endif /* __DATE__ */
11862     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11863
11864     for (i = 0; i < noptlist; i++)      /* Print sorted option list */
11865       if (!prtopt(&lines,optlist[i]))
11866         return(0);
11867
11868     if (!prtopt(&lines,"")) return(0);  /* Start a new section */
11869
11870 /* Sizes of data types */
11871
11872     ckmakmsg(line,
11873              LINBUFSIZ,
11874              "byte order: ",
11875              byteorder ? "little" : "big",
11876              " endian",
11877              NULL
11878              );
11879     if (!prtopt(&lines,line)) return(0);
11880     if (!prtopt(&lines,"")) return(0);  /* Start a new section */
11881     sprintf(line,"sizeofs: int=%ld",sizeof(int)); /* SAFE */
11882     if (!prtopt(&lines,line)) return(0);
11883     sprintf(line,"long=%ld",sizeof(long)); /* SAFE */
11884     if (!prtopt(&lines,line)) return(0);
11885     sprintf(line,"short=%ld",sizeof(short)); /* SAFE */
11886     if (!prtopt(&lines,line)) return(0);
11887     sprintf(line,"char=%ld",sizeof(char)); /* SAFE */
11888     if (!prtopt(&lines,line)) return(0);
11889     sprintf(line,"char*=%ld",sizeof(char *)); /* SAFE */
11890     if (!prtopt(&lines,line)) return(0);
11891 #ifdef LONG_MAX
11892     sprintf(line,"LONG_MAX=%d",LONG_MAX); /* SAFE */
11893 #endif /* LONG_MAX */
11894 #ifdef CKFLOAT
11895     sprintf(line,"float=%ld",sizeof(float)); /* SAFE */
11896     if (!prtopt(&lines,line)) return(0);
11897     sprintf(line,"double=%ld",sizeof(double)); /* SAFE */
11898     if (!prtopt(&lines,line)) return(0);
11899 #ifdef FNFLOAT
11900     if (!prtopt(&lines,"")) return(0);  /* Start a new section */
11901     if (!prtopt(&lines,"floating-point:")) return(0);
11902     sprintf(line,"precision=%d",fp_digits); /* SAFE */
11903     if (!prtopt(&lines,line)) return(0);
11904     sprintf(line,"rounding=%d",fp_rounding); /* SAFE */
11905     if (!prtopt(&lines,line)) return(0);
11906 #endif /* FNFLOAT */
11907 #endif /* CKFLOAT */
11908
11909     prtopt(&lines,"");
11910     return(0);
11911 }
11912 #endif /* NOSHOW */
11913 #endif /* NOICP */