1 #include "ckcsym.h"
2 
3 int xcmdsrc = 0;
4 
5 #ifdef NOICP
cmdsrc()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, New York City
15     Jeffrey E Altman <jaltman@secure-endpoints.com>
16       Secure Endpoints Inc., New York City
17 
18   Copyright (C) 1985, 2021,
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 char lasttakeline[TMPBUFSIZ+1];        /* Last TAKE-file line */
39 
40 #ifndef NOICP
41 
42 #include "ckcnet.h"
43 #ifndef NOCSETS
44 #include "ckcxla.h"
45 #endif /* NOCSETS */
46 #ifdef MAC
47 #include "ckmasm.h"
48 #endif /* MAC */
49 #ifdef CK_SSL
50 #include "ck_ssl.h"
51 #endif /* CK_SSL */
52 
53 extern char * ck_cryear;       /* (ckcmai.c) Latest C-Kermit copyright year */
54 
55 #ifdef OS2
56 #include "ckoetc.h"
57 #ifndef NT
58 #define INCL_NOPM
59 #define INCL_VIO /* Needed for ckocon.h */
60 #include <os2.h>
61 #undef COMMENT
62 #else /* NT */
63 #include <windows.h>
64 #define TAPI_CURRENT_VERSION 0x00010004
65 #include <tapi.h>
66 #include <mcx.h>
67 #include "ckntap.h"
68 #define APIRET ULONG
69 extern int DialerHandle;
70 extern int StartedFromDialer;
71 #endif /* NT */
72 #include "ckocon.h"
73 #include "ckokey.h"
74 #ifdef KUI
75 #include "ikui.h"
76 #endif /* KUI */
77 #ifdef putchar
78 #undef putchar
79 #endif /* putchar */
80 #define putchar(x) conoc(x)
81 extern int cursor_save ;
82 extern bool cursorena[] ;
83 #endif /* OS2 */
84 
85 /* 2010-03-09 SMS.  VAX C V3.1-051 needs <stat.h> for off_t. */
86 #ifdef VMS
87 #include <stat.h>
88 #endif /* def VMS */
89 
90 /* For formatted screens, "more?" prompting, etc. */
91 
92 #ifdef FT18
93 #define isxdigit(c) isdigit(c)
94 #endif /* FT18 */
95 
96 #ifdef STRATUS                          /* Stratus Computer, Inc.  VOS */
97 #ifdef putchar
98 #undef putchar
99 #endif /* putchar */
100 #define putchar(x) conoc(x)
101 #ifdef getchar
102 #undef getchar
103 #endif /* getchar */
104 #define getchar(x) coninc(0)
105 #endif /* STRATUS */
106 
107 /* External variables */
108 
109 extern int carrier, cdtimo, local, quiet, backgrd, bgset, sosi, xsuspend,
110   binary, escape, xargs, flow, cmdmsk, duplex, ckxech, seslog, what,
111   inserver, diractive, tlevel, cwdf, nfuncs, msgflg, remappd, hints, mdmtyp,
112   zincnt, cmask, rcflag, success, xitsta, pflag, tnlm, tn_nlm, xitwarn,
113   debses, xaskmore, parity, saveask, wasclosed, whyclosed, cdactive,
114   rcdactive, keepallchars, cmd_err;
115 
116 #ifdef LOCUS
117 extern int locus, autolocus;
118 #endif /* LOCUS */
119 
120 #ifndef NOMSEND
121 extern int addlist;
122 #endif /* NOMSEND */
123 
124 #ifdef CK_SPEED
125 extern int prefixing;
126 #endif /* CK_SPEED */
127 
128 extern int g_matchdot;
129 
130 #ifdef RECURSIVE
131 extern int recursive;
132 #endif /* RECURSIVE */
133 extern int xfiletype;
134 
135 #ifdef IKSDCONF
136 extern char * iksdconf;
137 extern int iksdcf;
138 #endif /* IKSDCONF */
139 
140 #ifdef CK_RECALL
141 extern int on_recall;
142 #endif /* CK_RECALL */
143 
144 extern int ngetpath, exitonclose;
145 extern char * getpath[];
146 extern CHAR * epktmsg;
147 
148 extern char * snd_move;
149 extern char * snd_rename;
150 extern char * rcv_move;
151 extern char * rcv_rename;
152 extern char * g_snd_move;
153 extern char * g_snd_rename;
154 extern char * g_rcv_move;
155 extern char * g_rcv_rename;
156 
157 extern char * nm[];
158 
159 #ifdef CK_UTSNAME
160 extern char unm_mch[];
161 extern char unm_mod[];
162 extern char unm_nam[];
163 extern char unm_rel[];
164 extern char unm_ver[];
165 #endif /* CK_UTSNAME */
166 
167 #ifndef NOPUSH
168 #ifndef NOFRILLS
169 extern char editor[];
170 extern char editfile[];
171 extern char editopts[];
172 #ifdef BROWSER
173 extern char browser[];
174 extern char browsopts[];
175 extern char browsurl[];
176 #endif /* BROWSER */
177 #endif /*  NOFRILLS */
178 #endif /* NOPUSH */
179 
180 #ifndef NOFRILLS
181 #ifndef NORENAME
182 _PROTOTYP(VOID shorename, (void));
183 #endif	/* NORENAME */
184 #endif	/* NOFRILLS */
185 
186 #ifndef NOSERVER
187 extern char * x_user, * x_passwd, * x_acct;
188 #endif /* NOSERVER */
189 
190 #ifdef CKLOGDIAL
191 extern int dialog;
192 extern char diafil[];
193 #endif /* CKLOGDIAL */
194 
195 #ifdef CKROOT
196 extern int ckrooterr;
197 #endif /* CKROOT */
198 
199 #ifndef NOSPL
200 extern int cfilef, xxdot, vareval;
201 extern char cmdfil[];
202 
203 struct localvar * localhead[CMDSTKL];
204 struct localvar * localtail = NULL;
205 struct localvar * localnext = NULL;
206 
207 _PROTOTYP( VOID shosexp, (void) );
208 _PROTOTYP( static VOID shoinput, (void) );
209 _PROTOTYP( static char gettok,   (void) );
210 _PROTOTYP( static VOID factor,   (void) );
211 _PROTOTYP( static VOID term,     (void) );
212 _PROTOTYP( static VOID termp,    (void) );
213 _PROTOTYP( static VOID exprp,    (void) );
214 _PROTOTYP( static VOID expr,     (void) );
215 _PROTOTYP( static VOID simple,   (void) );
216 _PROTOTYP( static VOID simpler,  (void) );
217 _PROTOTYP( static VOID simplest, (void) );
218 _PROTOTYP( static CK_OFF_T xparse,   (void) );
219 #endif /* NOSPL */
220 #ifndef NOSHOW
221 _PROTOTYP( int sho_iks, (void) );
222 #endif /* NOSHOW */
223 
224 #ifdef MAC
225 char * ckprompt = "Mac-Kermit>";        /* Default prompt for Macintosh */
226 char * ikprompt = "IKSD>";
227 #else  /* Not MAC */
228 #ifdef NOSPL
229 #ifdef OS2
230 char * ckprompt = "K-95> ";             /* Default prompt for Win32 */
231 char * ikprompt = "IKSD> ";
232 #else
233 char * ckprompt = "C-Kermit>";
234 char * ikprompt = "IKSD>";
235 #endif /* NT */
236 #else  /* NOSPL */
237 #ifdef OS2
238 /* Default prompt for OS/2 and Win32 */
239 /* fdc 2013-12-06 - C-Kermit 9.0 and later is just "C-Kermit" */
240 #ifdef NT
241 #ifdef COMMENT
242 char * ckprompt = "[\\freplace(\\flongpath(\\v(dir)),/,\\\\)] K-95> ";
243 #else
244 char * ckprompt = "[\\freplace(\\flongpath(\\v(dir)),/,\\\\)] C-Kermit> ";
245 #endif /* COMMENT */
246 char * ikprompt = "[\\freplace(\\flongpath(\\v(dir)),/,\\\\)] IKSD> ";
247 #else  /* NT */
248 #ifdef COMMENT
249 char * ckprompt = "[\\freplace(\\v(dir),/,\\\\)] K-95> ";
250 #else
251 char * ckprompt = "[\\freplace(\\v(dir),/,\\\\)] C-Kermit> ";
252 #endif /* COMMENT */
253 char * ikprompt = "[\\freplace(\\v(dir),/,\\\\)] IKSD> ";
254 #endif /* NT */
255 #else  /* OS2 */
256 #ifdef VMS
257 char * ckprompt = "\\v(dir) C-Kermit>"; /* Default prompt VMS */
258 char * ikprompt = "\\v(dir) IKSD>";
259 #else
260 #ifdef UNIX
261 /* Note: parens, not brackets, because of ISO646 */
262 /* Collapse long paths using ~ notation if in home directory tree */
263 char * ckprompt = "(\\freplace(\\v(dir),\\fpathname(\\v(home)),~/)) C-Kermit>";
264 char * ikprompt = "(\\freplace(\\v(dir),\\fpathname(\\v(home)),~/)) IKSD>";
265 #else
266 /* Default prompt for other platforms */
267 char * ckprompt = "(\\v(dir)) C-Kermit>"; /* Default prompt for others */
268 char * ikprompt = "(\\v(dir)) IKSD>";
269 #endif /* UNIX */
270 #endif /* VMS */
271 #endif /* NT */
272 #endif /* NOSPL */
273 #endif /* MAC */
274 
275 #ifndef CCHMAXPATH
276 #define CCHMAXPATH 257
277 #endif /* CCHMAXPATH */
278 char inidir[CCHMAXPATH] = { NUL, NUL }; /* Directory INI file executed from */
279 
280 #ifdef TNCODE
281 extern int tn_b_nlm;                    /* TELNET BINARY newline mode */
282 #endif /* TNCODE */
283 
284 #ifndef NOKVERBS
285 extern struct keytab kverbs[];          /* Table of \Kverbs */
286 extern int nkverbs;                     /* Number of \Kverbs */
287 #endif /* NOKVERBS */
288 
289 #ifndef NOPUSH
290 extern int nopush;
291 #endif /* NOPUSH */
292 
293 #ifdef CK_RECALL
294 extern int cm_recall;
295 #endif /* CK_RECALL */
296 
297 extern char *ccntab[];
298 
299 /* Printer stuff */
300 
301 extern char *printername;
302 extern int printpipe;
303 #ifdef BPRINT
304 extern int printbidi, pportparity, pportflow;
305 extern long pportspeed;
306 #endif /* BPRINT */
307 
308 #ifdef OS2
309 _PROTOTYP (int os2getcp, (void) );
310 _PROTOTYP (int os2getcplist, (int *, int) );
311 #ifdef OS2MOUSE
312 extern int tt_mouse;
313 #endif /* OS2MOUSE */
314 extern int tt_update, tt_updmode, updmode, tt_utf8;
315 #ifndef IKSDONLY
316 extern int tt_status[];
317 #endif /* IKSDONLY */
318 #ifdef PCFONTS
319 extern struct keytab term_font[];
320 #else
321 #ifdef KUI
322 extern struct keytab * term_font;
323 #endif /* KUI */
324 #endif /* PCFONTS */
325 extern int ntermfont, tt_font, tt_font_size;
326 extern unsigned char colornormal, colorunderline, colorstatus,
327     colorhelp, colorselect, colorborder, colorgraphic, colordebug,
328     colorreverse, colorcmd, coloritalic;
329 extern int priority;
330 extern struct keytab prtytab[];
331 extern int nprty;
332 char * cmdmac = NULL;
333 #endif /* OS2 */
334 
335 #ifdef VMS
336 _PROTOTYP (int zkermini, (char *, int, char *) );
337 #endif /* VMS */
338 
339 extern long vernum;
340 extern int inecho, insilence, inbufsize, nvars, inintr;
341 extern char *protv, *fnsv, *cmdv, *userv, *ckxv, *ckzv, *ckzsys, *xlav,
342  *cknetv, *clcmds;
343 #ifdef OS2
344 extern char *ckyv;
345 #endif /* OS2 */
346 #ifdef CK_AUTHENTICATION
347 extern char * ckathv;
348 #endif /* CK_AUTHENTICATION */
349 #ifdef CK_SSL
350 extern char * cksslv;
351 #endif /* CK_SSL */
352 #ifdef CK_ENCRYPTION
353 #ifndef CRYPT_DLL
354 extern char * ckcrpv;
355 #endif /* CRYPT_DLL */
356 #endif /* CK_ENCRYPTION */
357 
358 #ifdef SSHBUILTIN
359 extern char *cksshv;
360 #ifdef SFTP_BUILTIN
361 extern char *cksftpv;
362 #endif /* SFTP_BUILTIN */
363 #endif /* SSHBUILTIN */
364 
365 #ifdef TNCODE
366 extern char *cktelv;
367 #endif /* TNCODE */
368 #ifndef NOFTP
369 #ifndef SYSFTP
370 extern char * ckftpv;
371 #endif /* SYSFTP */
372 #endif /* NOFTP */
373 
374 extern int srvidl;
375 
376 #ifdef OS2
377 extern char *ckonetv;
378 extern int interm;
379 #ifdef CK_NETBIOS
380 extern char *ckonbiv;
381 #endif /* CK_NETBIOS */
382 #ifdef OS2MOUSE
383 extern char *ckomouv;
384 #endif /* OS2MOUSE */
385 #endif /* OS2 */
386 
387 #ifndef NOLOCAL
388 extern char *connv;
389 #endif /* NOLOCAL */
390 #ifndef NODIAL
391 extern char *dialv;
392 #endif /* NODIAL */
393 #ifndef NOSCRIPT
394 extern char *loginv;
395 extern int secho;
396 #endif /* NOSCRIPT */
397 
398 #ifndef NODIAL
399 extern int nmdm, dirline;
400 extern struct keytab mdmtab[];
401 #endif /* NODIAL */
402 
403 extern int network, nettype, ttnproto;
404 
405 #ifdef OS2
406 #ifndef NOTERM
407 /* SET TERMINAL items... */
408 extern int tt_type, tt_arrow, tt_keypad, tt_wrap, tt_answer, tt_scrsize[];
409 extern int tt_bell, tt_roll[], tt_ctstmo, tt_cursor, tt_pacing, tt_type_mode;
410 extern char answerback[];
411 extern struct tt_info_rec tt_info[];    /* Indexed by terminal type */
412 extern int max_tt;
413 #endif /* NOTERM */
414 #endif /* OS2 */
415 
416 _PROTOTYP( VOID shotrm, (void) );
417 _PROTOTYP( int shofea, (void) );
418 
419 #ifdef OS2
420 extern int tt_rows[], tt_cols[];
421 #else /* OS2 */
422 extern int tt_rows, tt_cols;
423 #endif /* OS2 */
424 extern int cmd_rows, cmd_cols;
425 
426 #ifdef CK_TMPDIR
427 extern int f_tmpdir;                    /* Directory changed temporarily */
428 extern char savdir[];                   /* Temporary directory */
429 #endif /* CK_TMPDIR */
430 
431 #ifndef NOLOCAL
432 extern int tt_crd, tt_lfd, tt_escape;
433 #endif /* NOLOCAL */
434 
435 #ifndef NOCSETS
436 extern int language, nfilc, tcsr, tcsl, tcs_transp, fcharset;
437 extern struct keytab fcstab[];
438 extern struct csinfo fcsinfo[];
439 #ifndef MAC
440 extern struct keytab ttcstab[];
441 #endif /* MAC */
442 #endif /* NOCSETS */
443 
444 extern long speed;
445 
446 #ifndef NOXMIT
447 extern int xmitf, xmitl, xmitp, xmitx, xmits, xmitw, xmitt;
448 extern char xmitbuf[];
449 #endif /* NOXMIT */
450 
451 extern char **xargv, *versio, *ckxsys, *dftty, *lp;
452 
453 #ifdef DCMDBUF
454 extern char *cmdbuf, *atmbuf;           /* Command buffers */
455 #ifndef NOSPL
456 extern char *savbuf;                    /* Command buffers */
457 #endif /* NOSPL */
458 #else
459 extern char cmdbuf[], atmbuf[];         /* Command buffers */
460 #ifndef NOSPL
461 extern char savbuf[];                   /* Command buffers */
462 #endif /* NOSPL */
463 #endif /* DCMDBUF */
464 
465 extern char toktab[], ttname[], psave[];
466 extern CHAR sstate, feol;
467 extern int cmflgs, techo, repars, ncmd;
468 extern struct keytab cmdtab[];
469 
470 #ifndef NOSETKEY
471 KEY *keymap;
472 #ifndef OS2
473 #define mapkey(x) keymap[x]
474 #endif /* OS2 */
475 MACRO *macrotab;
476 _PROTOTYP( VOID shostrdef, (CHAR *) );
477 #endif /* NOSETKEY */
478 
479 extern int cmdlvl;
480 
481 #ifndef NOSPL
482 extern struct mtab *mactab;
483 extern struct keytab mackey[];
484 extern struct keytab vartab[], fnctab[], iftab[];
485 extern int maclvl, nmac, mecho, fndiags, fnerror, fnsuccess, nif;
486 #endif /* NOSPL */
487 
488 FILE *tfile[MAXTAKE];                   /* TAKE file stack */
489 char *tfnam[MAXTAKE];                   /* Name of TAKE file */
490 int tfline[MAXTAKE];                    /* Current line number */
491 int tfblockstart[MAXTAKE];              /* Current block-start line */
492 
493 int topcmd = -1;                        /* cmdtab index of current command */
494 int havetoken = 0;
495 extern int dblquo;                      /* Doublequoting enabled */
496 
497 #ifdef DCMDBUF                          /* Initialization filespec */
498 char *kermrc = NULL;
499 #else
500 char kermrcb[KERMRCL];
501 char *kermrc = kermrcb;
502 #endif /* DCMDBUF */
503 
504 int noherald = 0;
505 int cm_retry = 1;                       /* Command retry enabled */
506 xx_strp xxstring = zzstring;
507 
508 #ifndef NOXFER
509 extern int displa, bye_active, protocol, pktlog, remfile, rempipe, unkcs,
510   keep, lf_opts, fncnv, pktpaus, autodl, xfrcan, xfrchr, xfrnum, srvtim,
511   srvdis, query, retrans, streamed, reliable, crunched, timeouts,
512   fnrpath, autopath, rpackets, spackets, epktrcvd, srvping;
513 
514 #ifdef CK_AUTODL
515 extern int inautodl, cmdadl;
516 #endif /* CK_AUTODL */
517 
518 #ifndef NOSERVER
519 extern int en_asg, en_cwd, en_cpy, en_del, en_dir, en_fin, en_bye, en_ret,
520   en_get, en_hos, en_que, en_ren, en_sen, en_set, en_spa, en_typ, en_who,
521   en_mai, en_pri, en_mkd, en_rmd, en_xit, en_ena;
522 #endif /* NOSERVER */
523 
524 extern int atcapr,
525   atenci, atenco, atdati, atdato, atleni, atleno, atblki, atblko,
526   attypi, attypo, atsidi, atsido, atsysi, atsyso, atdisi, atdiso;
527 
528 #ifdef STRATUS
529 extern int atfrmi, atfrmo, atcrei, atcreo, atacti, atacto;
530 #endif /* STRATUS */
531 
532 #ifdef CK_PERMS
533 extern int atlpri, atlpro, atgpri, atgpro;
534 #endif /* CK_PERMS */
535 
536 #ifdef CK_LOGIN
537 extern char * anonfile;                 /* Anonymous login init file */
538 extern char * anonroot;                 /* Anonymous file-system root */
539 extern char * userfile;                 /* Forbidden user file */
540 extern int isguest;                     /* Flag for anonymous user */
541 #endif /* CK_LOGIN */
542 #endif /* NOXFER */
543 
544 #ifdef DCMDBUF
545 int *xquiet = NULL;
546 int *xvarev = NULL;
547 #else
548 int xquiet[CMDSTKL];
549 int xvarev[CMDSTKL];
550 #endif /* DCMDBUF */
551 
552 char * prstring[CMDSTKL];
553 
554 #ifndef NOSPL
555 
556 extern long ck_alarm;
557 extern char alrm_date[], alrm_time[];
558 
559 /* Local declarations */
560 
561 static int nulcmd = 0;                  /* Flag for next cmd to be ignored */
562 
563 /* Definitions for predefined macros */
564 
565 /* First, the single-line macros, installed with addmac()... */
566 
567 /* IBM-LINEMODE macro */
568 char *m_ibm = "set parity mark, set dupl half, set handsh xon, set flow none";
569 
570 /* FATAL macro */
571 char *m_fat = "if def \\%1 echo \\%1, if not = \\v(local) 0 hangup, stop 1";
572 
573 #ifdef CK_SPEED
574 #ifdef IRIX65
575 char *m_fast = "set win 30, set rec pack 4000, set prefix cautious";
576 #else
577 #ifdef IRIX
578 /* Because of bug in telnet server */
579 char *m_fast = "set window 30, set rec pack 4000, set send pack 4000,\
580  set pref cautious";
581 #else
582 #ifdef pdp11
583 char *m_fast = "set win 3, set rec pack 1024, set prefix cautious";
584 #else
585 #ifdef BIGBUFOK
586 char *m_fast = "set win 30, set rec pack 4000, set prefix cautious";
587 #else
588 char *m_fast = "set win 4, set rec pack 2200, set prefix cautious";
589 #endif /* BIGBUFOK */
590 #endif /* IRIX */
591 #endif /* IRIX65 */
592 #endif /* pdp11 */
593 #ifdef pdp11
594 char *m_cautious = "set win 2, set rec pack 512, set prefixing cautious";
595 #else
596 char *m_cautious = "set win 4, set rec pack 1000, set prefixing cautious";
597 #endif /* pdp11 */
598 char *m_robust = "set win 1, set rec pack 90, set prefixing all, \
599 set reliable off, set clearchannel off, set send timeout 20 fixed";
600 #else
601 #ifdef BIGBUFOK
602 #ifdef IRIX65
603 char *m_fast = "set win 30, set rec pack 4000";
604 #else
605 #ifdef IRIX
606 char *m_fast = "set win 30, set rec pack 4000, set send pack 4000";
607 #else
608 char *m_fast = "set win 30, set rec pack 4000";
609 #endif /* IRIX */
610 #endif /* IRIX65 */
611 #else /* Not BIGBUFOK */
612 char *m_fast = "set win 4, set rec pack 2200";
613 #endif /* BIGBUFOK */
614 char *m_cautious = "set win 4, set rec pack 1000";
615 char *m_robust = "set win 1, set rec pack 90, set reliable off,\
616  set send timeout 20 fixed";
617 #endif /* CK_SPEED */
618 
619 #ifdef VMS
620 char *m_purge = "run purge \\%*";
621 #endif /* VMS */
622 
623 #ifdef OS2
624 char *m_manual = "browse \\v(exedir)docs/manual/kermit95.htm";
625 #endif /* OS2 */
626 
627 /* Now the multiline macros, defined with addmmac()... */
628 
629 /*
630   Kermit's scripting language is so much more powerful than C that it was
631   about a thousand time easier to implement FOR, WHILE, IF, and SWITCH
632   commands as internal Kermit macros.  This was done in 1996 for C-Kermit 6.0.
633 
634   The following definitions, down to #ifdef COMMENT, are from C-Kermit
635   9.0.304 Dev.22, April 2017, where the command parser was changed to not
636   evaluate macro arguments on the DO command line, but to defer evaluation
637   until after the arguments had been separated and counted.  This change
638   required subtle modifications to the internal macro templates.
639 
640   IMPORTANT: Internal macros must have names that start with '_', followed
641   by three letters, e.g. _whi for WHILE.  The definitions below are just
642   templates for some other code that constructs the actual menu to be
643   executed by filling in the \%x variables.  The generated macros have names
644   like _whil2, _whil3, etc, where the trailing number is the execution stack
645   level.  The reason for the strict naming convention is so internal macros
646   can be parsed differently than regular ones.  See
647   ckuusr.c:isinternalmacro(), which determines the type of macro.
648 */
649 
650 /*
651  The WHILE macro:
652  \%1 = Loop condition
653  \%2 = Loop body
654 */
655 char *whil_def[] = { "_assign _whi\\v(cmdlevel) {_getargs,",
656 ":_..inc,\\fcontents(\\%1),\\fcontents(\\%2),goto _..inc,:_..bot,_putargs},",
657 "_define break goto _..bot, _define continue goto _..inc,",
658 "do _whi\\v(cmdlevel),_assign _whi\\v(cmdlevel)",
659 ""};
660 
661 /*
662  FOR macro for \%i-style loop variables (see dofor()...)
663  \%1 = Loop variable
664  \%2 = Initial value (can be an expression)
665  \%3 = Loop exit value
666  \%4 = Loop increment
667  \%5 = > or <
668  \%6 = Loop body
669 */
670 char *for_def[] = { "_assign _for\\v(cmdlevel) { _getargs,",
671 "define \\\\\\%1 \\feval(\\%2),:_..top,if \\%5 \\\\\\%1 \\%3 goto _..bot,",
672 "\\fcontents(\\%6),:_..inc,incr \\\\\\%1 \\%4,goto _..top,:_..bot,_putargs},",
673 "define break goto _..bot, define continue goto _..inc,",
674 "do _for\\v(cmdlevel) \\\\%1 \\%2 \\%3 \\%4 { \\%5 },_assign _for\\v(cmdlevel)",
675 ""};
676 
677 /*
678   FOR macro when the loop variable is itself a macro, with same arguments
679   but slightly different quoting.
680 */
681 char *foz_def[] = { "_assign _for\\v(cmdlevel) { _getargs,",
682 "def \\%1 \\feval(\\%2),:_..top,if \\%5 \\%1 \\%3 goto _..bot,",
683 "\\fcontents(\\%6),:_..inc,incr \\%1 \\%4,goto _..top,:_..bot,_putargs},",
684 "def break goto _..bot, def continue goto _..inc,",
685 "do _for\\v(cmdlevel) \\%1 \\%2 \\%3 \\%4 { \\%5 },_assign _for\\v(cmdlevel)",
686 ""};
687 
688 /*
689  SWITCH macro
690  \%1 = Switch variable
691  \%2 = Switch body
692 */
693 char *sw_def[] = { "_assign _sw_\\v(cmdlevel) {_getargs,",
694 "_forward {\\fcontents(\\%1)},\\fcontents(\\%2),:default,:_..bot,_putargs},_def break goto _..bot,",
695 "do _sw_\\v(cmdlevel),_assign _sw_\\v(cmdlevel)",
696 ""};
697 
698 /*
699   IF macro
700   /%1 = Commands to execute (IF part and ELSE part if any)
701 */
702 char *xif_def[] = {
703 "_assign _if_\\v(cmdlevel) {_getargs,\\fcontents(\\%1),_putargs},",
704 "do _if_\\v(cmdlevel),_assign _if\\v(cmdlevel)",
705 ""};
706 
707 #ifdef COMMENT
708 /* Internal macro definitions for C-Kermit 6.0 through 9.0.302 */
709 
710 char *for_def[] = { "_assign _for\\v(cmdlevel) { _getargs,",
711 "def \\\\\\%1 \\feval(\\%2),:_..top,if \\%5 \\\\\\%1 \\%3 goto _..bot,",
712 "\\%6,:_..inc,incr \\\\\\%1 \\%4,goto _..top,:_..bot,_putargs},",
713 "def break goto _..bot, def continue goto _..inc,",
714 "do _for\\v(cmdlevel) \\%1 \\%2 \\%3 \\%4 { \\%5 },_assign _for\\v(cmdlevel)",
715 ""};
716 
717 char *foz_def[] = { "_assign _for\\v(cmdlevel) { _getargs,",
718 "def \\%1 \\feval(\\%2),:_..top,if \\%5 \\%1 \\%3 goto _..bot,",
719 "\\%6,:_..inc,incr \\%1 \\%4,goto _..top,:_..bot,_putargs},",
720 "def break goto _..bot, def continue goto _..inc,",
721 "do _for\\v(cmdlevel) \\%1 \\%2 \\%3 \\%4 { \\%5 },_assign _for\\v(cmdlevel)",
722 ""};
723 
724 /* SWITCH macro */
725 char *sw_def[] = { "_assign _sw_\\v(cmdlevel) {_getargs,",
726 "_forward {\\%1},\\%2,:default,:_..bot,_putargs},_def break goto _..bot,",
727 "do _sw_\\v(cmdlevel),_assign _sw_\\v(cmdlevel)",
728 ""};
729 
730 /* XIF macro */
731 char *xif_def[] = {
732 "_assign _if\\v(cmdlevel) {_getargs,\\%1,_putargs},",
733 "do _if\\v(cmdlevel),_assign _if\\v(cmdlevel)",
734 ""};
735 
736 #endif  /* COMMENT */
737 
738 /*
739   Variables declared here for use by other ckuus*.c modules.
740   Space is allocated here to save room in ckuusr.c.
741 */
742 #ifdef DCMDBUF
743 struct cmdptr *cmdstk;
744 int
745   *ifcmd  = NULL,
746   *count  = NULL,
747   *iftest = NULL,
748   *intime = NULL,
749   *inpcas = NULL,
750   *takerr = NULL,
751   *merror = NULL;
752 #else
753 struct cmdptr cmdstk[CMDSTKL];
754 int ifcmd[CMDSTKL], count[CMDSTKL], iftest[CMDSTKL], intime[CMDSTKL],
755   inpcas[CMDSTKL], takerr[CMDSTKL], merror[CMDSTKL];
756 #endif /* DCMDBUF */
757 
758 /* Macro stack */
759 
760 #ifdef COMMENT
761 char *topline = NULL;                   /* Program invocation arg line */
762 char *m_line[MACLEVEL] = { NULL, NULL }; /* Stack of macro invocation lines */
763 #endif /* COMMENT */
764 
765 char **m_xarg[MACLEVEL];                /* Pointers to arg vector arrays */
766 int n_xarg[MACLEVEL];                   /* Sizes of arg vector arrays */
767 char *m_arg[MACLEVEL][NARGS];           /* Args of each level */
768 int macargc[MACLEVEL];                  /* Argc of each level */
769 char *macp[MACLEVEL];                   /* Current position in each macro */
770 char *macx[MACLEVEL];                   /* Beginning of each macro def */
771 char *mrval[MACLEVEL];                  /* RETURN value at each level */
772 int lastcmd[MACLEVEL];                  /* Last command at each level */
773 int topargc = 0;                        /* Argc at top level */
774 char **topxarg = NULL;                  /* Argv at top level */
775 char *toparg[MAXARGLIST+2];
776 
777 /* Global Variables */
778 
779 char *g_var[GVARS+1];                   /* Global \%a..z pointers */
780 extern char varnam[];                   /* \%x variable name buffer */
781 
782 /* Arrays -- Dimension must be 'z' - ARRAYBASE + 1 */
783 /* Note: a_link[x] < 0 means no link; >= 0 is a link */
784 
785 char **a_ptr[32];                       /* Array pointers, for arrays a-z */
786 int a_dim[32];                          /* Dimensions for each array */
787 int a_link[32];                         /* Link (index of linked-to-array) */
788 
789 char **aa_ptr[CMDSTKL][32];             /* Array stack for automatic arrays */
790 int aa_dim[CMDSTKL][32];                /* Dimensions for each array */
791 
792 /* INPUT command buffers and variables */
793 
794 char * inpbuf = NULL;                   /* Buffer for INPUT and REINPUT */
795 extern char * inpbp;                    /* Global/static pointer to it  */
796 char inchar[2] = { NUL, NUL };          /* Last character that was INPUT */
797 int  incount = 0;                       /* INPUT character count */
798 extern int instatus;                    /* INPUT status */
799 static char * i_text[] = {              /* INPUT status text */
800     "success", "timeout", "interrupted", "internal error", "i/o error"
801 };
802 
803 char lblbuf[LBLSIZ];                    /* Buffer for labels */
804 
805 #else  /* NOSPL */
806 
807 int takerr[MAXTAKE];
808 #endif /* NOSPL */
809 
810 static char *prevdir = NULL;
811 
812 int pacing = 0;                         /* OUTPUT pacing */
813 
814 char *tp;                               /* Temporary buffer pointer */
815 
816 int timelimit = 0, asktimer = 0;        /* Timers for time-limited commands */
817 
818 #ifdef CK_APC                           /* Application Program Command (APC) */
819 int apcactive = APC_INACTIVE;
820 int apcstatus = APC_OFF;                /* OFF by default everywhere */
821 #ifdef DCMDBUF
822 char *apcbuf;
823 #else
824 char apcbuf[APCBUFLEN];
825 #endif /* DCMDBUF */
826 #endif /* CK_APC */
827 
828 extern char pktfil[],
829 #ifdef DEBUG
830   debfil[],
831 #endif /* DEBUG */
832 #ifdef TLOG
833   trafil[],
834 #endif /* TLOG */
835   sesfil[];
836 
837 #ifndef NOFRILLS
838 extern int rmailf, rprintf;             /* REMOTE MAIL & PRINT items */
839 extern char optbuf[];
840 #endif /* NOFRILLS */
841 
842 extern int noinit;			/* Flat to skip init file */
843 
844 #ifndef NOSPL
845 static struct keytab kcdtab[] = {	/* Symbolic directory names */
846 #ifdef NT
847     { "appdata",  VN_APPDATA,   0 },
848     { "common",   VN_COMMON,    0 },
849     { "desktop",  VN_DESKTOP,   0 },
850 #endif /* NT */
851     { "download", VN_DLDIR,     0 },
852 #ifdef OS2ORUNIX
853     { "exedir",   VN_EXEDIR,    0 },
854 #endif /* OS2ORUNIX */
855     { "home",     VN_HOME,      0 },
856     { "inidir",   VN_INI,       0 },
857 #ifdef UNIX
858     { "lockdir",  VN_LCKDIR,    0 },
859 #endif /* UNIX */
860 #ifdef NT
861     { "my_documents",VN_PERSONAL,  0 },
862     { "personal", VN_PERSONAL,  CM_INV },
863 #endif /* NT */
864     { "startup",  VN_STAR,      0 },
865     { "textdir",  VN_TXTDIR,    0 },
866     { "tmpdir",   VN_TEMP,      0 }
867 };
868 static int nkcdtab = (sizeof(kcdtab) / sizeof(struct keytab));
869 #endif /* NOSPL */
870 
871 #ifndef NOSPL
872 _PROTOTYP( VOID freelocal, (int) );
873 _PROTOTYP( static CK_OFF_T expon, (CK_OFF_T, CK_OFF_T) );
874 _PROTOTYP( static CK_OFF_T gcd, (CK_OFF_T, CK_OFF_T) );
875 _PROTOTYP( static CK_OFF_T fact, (CK_OFF_T) );
876 
877 int                     /* Initialize macro data structures. */
macini()878 macini() {              /* Allocate mactab and preset the first element. */
879     int i;
880     if (!(mactab = (struct mtab *) malloc(sizeof(struct mtab) * MAC_MAX)))
881       return(-1);
882     mactab[0].kwd = NULL;
883     mactab[0].mval = NULL;
884     mactab[0].flgs = 0;
885     for (i = 0; i < MACLEVEL; i++)
886       localhead[i] = NULL;
887     return(0);
888 }
889 #endif /* NOSPL */
890 
891 /*  C M D S R C  --  Returns current command source  */
892 
893 /*  0 = top level, 1 = file, 2 = macro, -1 = error (shouldn't happen) */
894 
895 /*
896   As of 19 Aug 2000 this routine is obsolete.  The scalar global variable
897   xcmdsrc can be checked instead to save the overhead of a function call.
898 */
899 int
cmdsrc()900 cmdsrc() {
901 #ifdef COMMENT
902     return(xcmdsrc);
903 #else
904 #ifndef NOSPL
905     if (cmdlvl == 0)
906       return(0);
907     else if (cmdstk[cmdlvl].src == CMD_MD)
908       return(2);
909     else if (cmdstk[cmdlvl].src == CMD_TF)
910       return(1);
911     else
912       return(-1);
913 #else
914     if (tlevel < 0)
915       return(0);
916     else
917       return(1);
918 #endif /* NOSPL */
919 #endif /* COMMENT */
920 }
921 
922 /*  C M D I N I  --  Initialize the interactive command parser  */
923 
924 static int cmdinited = 0;               /* Command parser initialized */
925 extern int cmdint;                      /* Interrupts are allowed */
926 #ifdef CK_AUTODL
927 int cmdadl = 1;                         /* Autodownload */
928 #else
929 int cmdadl = 0;
930 #endif /* CK_AUTODL */
931 
932 char * k_info_dir = NULL;               /* Where to find text files */
933 #ifdef UNIX
934 static char * txtdir[] = {
935     "/usr/local/doc/",                  /* Linux, SunOS, ... */
936     "/usr/share/lib/",                  /* HP-UX 10.xx... */
937     "/usr/share/doc/",                  /* Other possibilities... */
938     "/usr/local/lib/",                  /* NOTE: Each of these is tried */
939     "/usr/local/share/",                /* as is, and also with a kermit */
940     "/usr/local/share/doc/",            /* subdirectory. */
941     "/usr/local/share/lib/",
942     "/opt/kermit/",                     /* Solaris */
943     "/opt/kermit/doc/",
944     "/opt/",
945     "/usr/doc/",
946     "/doc/",
947     ""
948 };
949 #endif /* UNIX */
950 
951 /*
952   lookup() cache to speed up script execution.
953 
954   This is a static cache.  Items are stored in decreasing frequency of
955   reference based on statistics from a range of scripts.  This gives
956   better performance than a dynamic cache, which would require a lot more
957   code and also would require system-dependent elements including system
958   calls (e.g. to get subsecond times for entry aging).
959 */
960 #ifdef USE_LUCACHE                      /* Set in ckuusr.h */
961 #define LUCACHE 32                      /* Change this to reduce cache size */
962 int lusize = 0;
963 char * lucmd[LUCACHE];
964 int luval[LUCACHE];
965 int luidx[LUCACHE];
966 struct keytab * lutab[LUCACHE];
967 #endif /* USE_LUCACHE */
968 
969 static VOID
luinit()970 luinit() {                              /* Initialize lookup() cache */
971     int x, y;
972 
973 #ifdef USE_LUCACHE
974     x = lookup(cmdtab,"if",ncmd,&y);
975     lucmd[lusize] = "if";
976     luval[lusize] = x;
977     luidx[lusize] = y;
978     lutab[lusize] = cmdtab;
979     if (++lusize > LUCACHE) return;
980 
981     x = lookup(iftab,"not",nif,&y);
982     lucmd[lusize] = "not";
983     luval[lusize] = x;
984     luidx[lusize] = y;
985     lutab[lusize] = iftab;
986     if (++lusize > LUCACHE) return;
987 
988     x = lookup(vartab,"cmdlevel",nvars,&y);
989     lucmd[lusize] = "cmdlevel";
990     luval[lusize] = x;
991     luidx[lusize] = y;
992     lutab[lusize] = vartab;
993     if (++lusize > LUCACHE) return;
994 
995     x = lookup(cmdtab,"goto",ncmd,&y);
996     lucmd[lusize] = "goto";
997     luval[lusize] = x;
998     luidx[lusize] = y;
999     lutab[lusize] = cmdtab;
1000     if (++lusize > LUCACHE) return;
1001 
1002     x = lookup(iftab,">",nif,&y);
1003     lucmd[lusize] = ">";
1004     luval[lusize] = x;
1005     luidx[lusize] = y;
1006     lutab[lusize] = iftab;
1007     if (++lusize > LUCACHE) return;
1008 
1009     x = lookup(cmdtab,"incr",ncmd,&y);
1010     lucmd[lusize] = "incr";
1011     luval[lusize] = x;
1012     luidx[lusize] = y;
1013     lutab[lusize] = cmdtab;
1014     if (++lusize > LUCACHE) return;
1015 
1016     x = lookup(cmdtab,"def",ncmd,&y);
1017     lucmd[lusize] = "def";
1018     luval[lusize] = x;
1019     luidx[lusize] = y;
1020     lutab[lusize] = cmdtab;
1021     if (++lusize > LUCACHE) return;
1022 
1023     x = lookup(cmdtab,"_assign",ncmd,&y);
1024     lucmd[lusize] = "_assign";
1025     luval[lusize] = x;
1026     luidx[lusize] = y;
1027     lutab[lusize] = cmdtab;
1028     if (++lusize > LUCACHE) return;
1029 
1030     x = lookup(cmdtab,"echo",ncmd,&y);
1031     lucmd[lusize] = "echo";
1032     luval[lusize] = x;
1033     luidx[lusize] = y;
1034     lutab[lusize] = cmdtab;
1035     if (++lusize > LUCACHE) return;
1036 
1037     x = lookup(fnctab,"eval",nfuncs,&y);
1038     lucmd[lusize] = "eval";
1039     luval[lusize] = x;
1040     luidx[lusize] = y;
1041     lutab[lusize] = fnctab;
1042     if (++lusize > LUCACHE) return;
1043 
1044     x = lookup(fnctab,"lit",nfuncs,&y);
1045     lucmd[lusize] = "lit";
1046     luval[lusize] = x;
1047     luidx[lusize] = y;
1048     lutab[lusize] = fnctab;
1049     if (++lusize > LUCACHE) return;
1050 
1051     x = lookup(cmdtab,"do",ncmd,&y);
1052     lucmd[lusize] = "do";
1053     luval[lusize] = x;
1054     luidx[lusize] = y;
1055     lutab[lusize] = cmdtab;
1056     if (++lusize > LUCACHE) return;
1057 
1058     x = lookup(cmdtab,"_getargs",ncmd,&y);
1059     lucmd[lusize] = "_getargs";
1060     luval[lusize] = x;
1061     luidx[lusize] = y;
1062     lutab[lusize] = cmdtab;
1063     if (++lusize > LUCACHE) return;
1064 
1065     x = lookup(iftab,"<",nif,&y);
1066     lucmd[lusize] = "<";
1067     luval[lusize] = x;
1068     luidx[lusize] = y;
1069     lutab[lusize] = iftab;
1070     if (++lusize > LUCACHE) return;
1071 
1072     x = lookup(cmdtab,"_putargs",ncmd,&y);
1073     lucmd[lusize] = "_putargs";
1074     luval[lusize] = x;
1075     luidx[lusize] = y;
1076     lutab[lusize] = cmdtab;
1077     if (++lusize > LUCACHE) return;
1078 
1079     x = lookup(cmdtab,"asg",ncmd,&y);
1080     lucmd[lusize] = "asg";
1081     luval[lusize] = x;
1082     luidx[lusize] = y;
1083     lutab[lusize] = cmdtab;
1084     if (++lusize > LUCACHE) return;
1085 
1086     x = lookup(cmdtab,"else",ncmd,&y);
1087     lucmd[lusize] = "else";
1088     luval[lusize] = x;
1089     luidx[lusize] = y;
1090     lutab[lusize] = cmdtab;
1091 #endif /* USE_LUCACHE */
1092 }
1093 
1094 VOID
cmdini()1095 cmdini() {
1096     int i = 0, x = 0, y = 0, z = 0, skip = 0;
1097     char * p;
1098 #ifdef TTSPDLIST
1099     long * ss = NULL;
1100     extern int nspd;
1101     extern struct keytab * spdtab;
1102 #endif /* TTSPDLIST */
1103 
1104 #ifndef NOSPL
1105 /*
1106   On stack to allow recursion!
1107 */
1108     char vnambuf[VNAML];                /* Buffer for variable names */
1109 #endif /* NOSPL */
1110 
1111     if (cmdinited)                      /* Already initialized */
1112       return;                           /* Don't do it again */
1113 
1114     for (i = 0; i < CMDSTKL; i++)       /* Prompt strings for each */
1115       prstring[i] = NULL;               /* command level */
1116 
1117 #ifndef NOCSETS
1118     p = getenv("K_CHARSET");            /* Set default file character set */
1119     if (p) {                            /* from environment */
1120         x = lookup(fcstab,p,nfilc,&y);
1121         if (x > -1)
1122           fcharset = x;
1123     }
1124 #endif /* NOCSETS */
1125 
1126     p = getenv("K_INFO_DIRECTORY");     /* Find Kermit info directory */
1127     if (p && *p && strlen(p) <= CKMAXPATH)
1128       makestr(&k_info_dir,p);
1129     if (!k_info_dir) {
1130         p = getenv("K_INFO_DIR");
1131         if (p && *p && strlen(p) <= CKMAXPATH)
1132           makestr(&k_info_dir,p);
1133     }
1134 #ifdef UNIX
1135     if (k_info_dir) {                   /* Look for Kermit docs directory */
1136         if (zchki(k_info_dir) == -2) {
1137             char xbuf[CKMAXPATH+32], *s = "";
1138             if (ckrchar(k_info_dir) != '/')
1139               s = "/";
1140             ckmakmsg(xbuf,CKMAXPATH+32,k_info_dir,s,"ckubwr.txt",NULL);
1141             if (zchki(xbuf) < 0)
1142               makestr(&k_info_dir,NULL);
1143         }
1144     }
1145     if (!k_info_dir) {
1146         char xbuf[CKMAXPATH+32];
1147         int i;
1148         for (i = 0; *(txtdir[i]); i++) {
1149             ckmakmsg(xbuf,CKMAXPATH+32,txtdir[i],"ckubwr.txt",NULL,NULL);
1150             if (zchki(xbuf) > 0) {
1151                 makestr(&k_info_dir,txtdir[i]);
1152                 debug(F110,"k_info_dir 1",k_info_dir,0);
1153                 break;
1154             }
1155             ckmakmsg(xbuf,CKMAXPATH+32,
1156                      txtdir[i],"kermit/","ckubwr.txt",NULL);
1157             if (zchki(xbuf) > 0) {
1158                 ckmakmsg(xbuf,CKMAXPATH+32,txtdir[i],"kermit/",NULL,NULL);
1159                 makestr(&k_info_dir,xbuf);
1160                 debug(F110,"k_info_dir 2",k_info_dir,0);
1161                 break;
1162             }
1163             ckmakmsg(xbuf,CKMAXPATH+32,
1164                      txtdir[i],"ckermit/","ckubwr.txt",NULL);
1165             if (zchki(xbuf) > 0) {
1166                 ckmakmsg(xbuf,CKMAXPATH+32,txtdir[i],"ckermit/",NULL,NULL);
1167                 makestr(&k_info_dir,xbuf);
1168                 debug(F110,"k_info_dir 3",k_info_dir,0);
1169                 break;
1170             }
1171         }
1172         if (k_info_dir) {               /* Make sure it ends with "/" */
1173             if (ckrchar(k_info_dir) != '/') {
1174                 char xbuf[CKMAXPATH+32];
1175                 ckmakmsg(xbuf,CKMAXPATH+32,k_info_dir,"/",NULL,NULL);
1176                 makestr(&k_info_dir,xbuf);
1177             }
1178         }
1179     }
1180 #else
1181 #ifdef OS2
1182     {
1183         char xdir[CKMAXPATH+8], *s = "";
1184         extern char startupdir[];
1185         xdir[0] = NUL;
1186         if (ckrchar(startupdir) != '/')
1187           s = "/";
1188         if (strlen(s) + strlen(startupdir) + 5 < CKMAXPATH + 8 )
1189           ckmakmsg(xdir,CKMAXPATH+8,s,startupdir,"DOC/",NULL);
1190         makestr(&k_info_dir,xdir);
1191     }
1192 #endif /* OS2 */
1193 #endif /* UNIX */
1194 
1195 #ifdef TTSPDLIST
1196     if (!spdtab && (ss = ttspdlist())) { /* Get speed list if necessary */
1197         int j, k, m = 0, n;             /* Create sorted keyword table */
1198         char buf[16];
1199         char * p;
1200         if ((spdtab =
1201              (struct keytab *) malloc(sizeof(struct keytab) * ss[0]))) {
1202             for (i = 1; i <= ss[0]; i++) { /* ss[0] = number of elements */
1203                 if (ss[i] < 1L) break;     /* Shouldn't happen */
1204                 buf[0] = NUL;              /* Make string */
1205                 sprintf(buf,"%ld",ss[i]);  /* SAFE */
1206                 if (ss[i] == 8880L)
1207                   ckstrncpy(buf,"75/1200",sizeof(buf));
1208                 if (ss[i] == 134L)
1209                   ckstrncat(buf,".5",16);
1210                 n = strlen(buf);
1211                 if ((n > 0) && (p = (char *)malloc(n+1))) {
1212                     if (m > 0) {        /* Have at least one in list */
1213                         for (j = 0;     /* Find slot */
1214                              j < m && strcmp(buf,spdtab[j].kwd) > 0;
1215                              j++
1216                              )
1217                           ;
1218                         if (j < m) {    /* Must insert */
1219                             for (k = m-1; k >= j; k--) { /* Move others down */
1220                                 spdtab[k+1].kwd = spdtab[k].kwd;
1221                                 spdtab[k+1].flgs = spdtab[k].flgs;
1222                                 spdtab[k+1].kwval = spdtab[k].kwval;
1223                             }
1224                         }
1225                     } else              /* First one */
1226                       j = 0;
1227                     ckstrncpy(p,buf,n+1); /* Add new speed */
1228                     spdtab[j].kwd = p;
1229                     spdtab[j].flgs = 0;
1230                     spdtab[j].kwval = (int) ss[i] / 10;
1231                     m++;                /* Count this one */
1232                 }
1233             }
1234         }
1235         nspd = m;
1236     }
1237 #endif /* TTSPDLIST */
1238 
1239 #ifndef NOSPL
1240     /* Allocate INPUT command buffer */
1241     if (!inpbuf) {
1242         if (!(inpbuf = (char *) malloc(INPBUFSIZ+8)))
1243           fatal("cmdini: no memory for INPUT buffer");
1244     }
1245     for (x = 0; x < INPBUFSIZ; x++)     /* Initialize it */
1246       inpbuf[x] = NUL;
1247     inpbp = inpbuf;                     /* Initialize pointer */
1248     inbufsize = INPBUFSIZ;              /* and size. */
1249 #endif /* NOSPL */
1250 
1251 #ifdef DCMDBUF
1252     if (cmsetup() < 0) fatal("Can't allocate command buffers!");
1253 
1254 #ifndef NOSPL
1255     /* Allocate command stack allowing command parser to call itself */
1256 
1257     if (!(cmdstk = (struct cmdptr *) malloc(sizeof(struct cmdptr)*CMDSTKL)))
1258       fatal("cmdini: no memory for cmdstk");
1259     if (!(ifcmd = (int *) malloc(sizeof(int)*CMDSTKL)))
1260       fatal("cmdini: no memory for ifcmd");
1261     if (!(count = (int *) malloc(sizeof(int)*CMDSTKL)))
1262       fatal("cmdini: no memory for count");
1263     if (!(iftest = (int *) malloc(sizeof(int)*CMDSTKL)))
1264       fatal("cmdini: no memory for iftest");
1265     if (!(intime = (int *) malloc(sizeof(int)*CMDSTKL)))
1266       fatal("cmdini: no memory for intime");
1267     if (!(inpcas = (int *) malloc(sizeof(int)*CMDSTKL)))
1268       fatal("cmdini: no memory for inpcas");
1269     if (!(takerr = (int *) malloc(sizeof(int)*CMDSTKL)))
1270       fatal("cmdini: no memory for takerr");
1271     if (!(merror = (int *) malloc(sizeof(int)*CMDSTKL)))
1272       fatal("cmdini: no memory for merror");
1273     if (!(xquiet = (int *) malloc(sizeof(int)*CMDSTKL)))
1274       fatal("cmdini: no memory for xquiet");
1275     if (!(xvarev = (int *) malloc(sizeof(int)*CMDSTKL)))
1276       fatal("cmdini: no memory for xvarev");
1277     if (!kermrc)
1278       if (!(kermrc = (char *) malloc(KERMRCL+1)))
1279         fatal("cmdini: no memory for kermrc");
1280 #ifdef CK_APC
1281 /* Application Program Command buffer */
1282     if (!(apcbuf = malloc(APCBUFLEN + 1)))
1283         fatal("cmdini: no memory for apcbuf");
1284 #endif /* CK_APC */
1285 #endif /* NOSPL */
1286 
1287 /* line[] and tmpbuf[] are the two string buffers used by the command parser */
1288 
1289     if (!(line = malloc(LINBUFSIZ + 1)))
1290         fatal("cmdini: no memory for line");
1291     if (!(tmpbuf = malloc(LINBUFSIZ + 1)))
1292         fatal("cmdini: no memory for tmpbuf");
1293 #endif /* DCMDBUF */
1294 
1295 #ifndef NOSPL
1296 #ifdef CK_MINPUT
1297     {                                   /* Initialize MINPUT pointers */
1298         int i;
1299         extern char *ms[];
1300         for (i = 0; i < MINPMAX; i++)
1301           ms[i] = NULL;
1302     }
1303 #endif /* CK_MINPUT */
1304 
1305     if (macini() < 0)                   /* Allocate macro buffers */
1306       fatal("Can't allocate macro buffers!");
1307 
1308     ifcmd[0] = 0;                       /* Command-level related variables. */
1309     iftest[0] = 0;                      /* Initialize variables at top level */
1310     count[0] = 0;                       /* of stack... */
1311     intime[0] = 0;
1312     inpcas[0] = 0;
1313     takerr[0] = 0;
1314     merror[0] = 0;
1315     xquiet[0] = quiet;
1316     xvarev[0] = vareval;
1317 #endif /* NOSPL */
1318 
1319 #ifndef NOSPL
1320     cmdlvl = 0;                         /* Initialize the command stack */
1321     xcmdsrc = CMD_KB;
1322     cmdstk[cmdlvl].src = CMD_KB;        /* Source is console */
1323     cmdstk[cmdlvl].lvl = 0;             /* Level is 0 */
1324     cmdstk[cmdlvl].ccflgs = 0;          /* No flags */
1325 #endif /* NOSPL */
1326 
1327     tlevel = -1;                        /* Take file level = keyboard */
1328     for (i = 0; i < MAXTAKE; i++)       /* Initialize command file names */
1329       tfnam[i] = NULL;
1330 
1331     cmsetp(ckprompt);                   /* Set up C-Kermit's prompt */
1332                                         /* Can't set IKSD prompt here since */
1333                                         /* we do not yet know if we are IKSD */
1334 #ifndef NOSPL
1335 
1336     initmac();                          /* Initialize macro table */
1337 
1338 /* Predefine built-in one-line macros */
1339 
1340     addmac("ibm-linemode",m_ibm);       /* IBM-LINEMODE */
1341     addmac("fatal",m_fat);              /* FATAL macro */
1342     y = addmac("fast",m_fast);          /* FAST macro */
1343     addmac("cautious",m_cautious);      /* CAUTIOUS macro */
1344     addmac("robust",m_robust);          /* ROBUST macro */
1345 #ifdef OS2
1346     addmac("manual",m_manual);          /* MANUAL macro */
1347 #endif /* OS2 */
1348 #ifdef VMS
1349     addmac("purge",m_purge);            /* PURGE macro */
1350 #endif /* VMS */
1351 
1352 /*
1353   Predefine built-in multiline macros; these are top-level commands
1354   that are implemented internally as macros.  NOTE: When adding a new
1355   one of these, remember to update the END and RETURN commands to
1356   account for it, or else END and RETURN from within it won't work right.
1357 */
1358     x = addmmac("_forx",for_def);       /* FOR macro */
1359     if (x > -1) mactab[x].flgs = CM_INV;
1360     x = addmmac("_forz",foz_def);       /* Other FOR macro */
1361     if (x > -1) mactab[x].flgs = CM_INV;
1362     x = addmmac("_xif",xif_def);        /* XIF macro */
1363     if (x > -1) mactab[x].flgs = CM_INV;
1364     x = addmmac("_while",whil_def);     /* WHILE macro */
1365     if (x > -1) mactab[x].flgs = CM_INV;
1366     x = addmmac("_switx",sw_def);       /* SWITCH macro */
1367     if (x > -1) mactab[x].flgs = CM_INV;
1368 
1369 /* Fill in command-line argument vector */
1370 
1371     sprintf(vnambuf,"\\&@[%d]",xargs);  /* SAFE */
1372     if (inserver) {                     /* But hidden in IKSD */
1373         y = -1;
1374         xargs = 0;
1375     } else
1376       y = arraynam(vnambuf,&x,&z);      /* goes in array \&@[] */
1377 
1378     tmpbuf[0] = NUL;
1379     if (y > -1) {
1380         int j = -1;
1381         int yy = 0;
1382         dclarray((char)x,z);            /* Declare the array */
1383 #ifndef NOTAKEARGS
1384         /* Macro argument vector */
1385         sprintf(vnambuf,"\\&_[%d]",z);  /* SAFE */
1386         yy = arraynam(vnambuf,&x,&z);   /* goes in array \&_[] */
1387         if (yy > -1)                    /* Name is OK */
1388           dclarray((char)x,z);          /* Declare the array */
1389 #endif /* NOTAKEARGS */
1390         skip = 0;
1391         for (i = 0; i < xargs; i++) {   /* Fill the arrays */
1392             sprintf(vnambuf,"\\&@[%d]",i); /* SAFE */
1393             addmac(vnambuf,xargv[i]);
1394             if (cfilef && i == 0)
1395               continue;
1396 #ifdef KERBANG
1397             if (skip) {
1398                 j = 0;
1399                 skip = 0;
1400                 continue;
1401             }
1402 #endif /* KERBANG */
1403             if (j < 0 &&                /* Assign items after "=" or "--"*/
1404                 (!strcmp(xargv[i],"=") || !strcmp(xargv[i],"--"))
1405                 ) {
1406                 j = 0;                  /* to \%1..\%9 */
1407 #ifdef KERBANG
1408             } else if (j < 0 &&
1409                        (!strcmp(xargv[i],"+") ||
1410                         !strncmp(xargv[i],"+ ",2) ||
1411                         !strncmp(xargv[i],"+\t",2))
1412                         ) {
1413                 skip = 1;
1414                 continue;
1415 #endif /* KERBANG */
1416             } else if (j > -1) {
1417                 j++;
1418                 if (j <= 9) {
1419                     vnambuf[0] = '\\';
1420                     vnambuf[1] = '%';
1421                     vnambuf[2] = (char)(j+'0');
1422                     vnambuf[3] = NUL;
1423                     addmac(vnambuf,xargv[i]);
1424                 }
1425                 if (yy > -1) {
1426                     char c, * p;
1427                     int flag = 0;
1428                     p = xargv[i];
1429                     makestr(&(toparg[j]),p);
1430                     while ((c = *p++)) { if (c == SP) { flag++; break; } }
1431                     if (flag)
1432                       ckstrncat(tmpbuf,"\"",TMPBUFSIZ);
1433                     ckstrncat(tmpbuf,xargv[i],TMPBUFSIZ);
1434                     if (flag)
1435                       ckstrncat(tmpbuf,"\"",TMPBUFSIZ);
1436                     ckstrncat(tmpbuf," ",TMPBUFSIZ);
1437                 }
1438             }
1439         }
1440         if (cfilef) {
1441             addmac("\\%0",cmdfil);
1442             if (yy > -1)
1443               makestr(&(toparg[0]),cmdfil);
1444         } else {
1445             addmac("\\%0",xargv[0]);
1446             if (yy > -1)
1447               makestr(&(toparg[0]),xargv[0]);
1448         }
1449         if (yy > -1) {
1450             topargc = (j < 0) ? 1 : j + 1;
1451             topxarg = toparg;
1452 #ifdef COMMENT
1453             /* This needs work */
1454             if (!cfilef)
1455               makestr(&topline,tmpbuf);
1456 #endif /* COMMENT */
1457         } else {
1458             topargc = 0;
1459             topxarg = NULL;
1460         }
1461         a_dim[0] = topargc - 1;
1462         a_ptr[0] = topxarg;
1463 	debug(F111,"a_dim[0]","A",a_dim[0]);
1464     }
1465     *vnambuf = NUL;
1466 #endif /* NOSPL */
1467 
1468     luinit();                           /* Initialize lookup() cache */
1469 
1470 /* Get our home directory now.  This needed in lots of places. */
1471 
1472     cmdinited = 1;
1473 }
1474 
1475 #ifdef NT
1476 _PROTOTYP(char * GetAppData,(int));
1477 #endif /* NT */
1478 
1479 VOID
doinit()1480 doinit() {
1481 #ifdef CKROOT
1482 extern int ckrooterr;
1483 #endif /* CKROOT */
1484     int x = 0, ok = 0;
1485 #ifdef OS2
1486     char * ptr = 0;
1487 #endif /* OS2 */
1488 
1489     if (!cmdinited)
1490       cmdini();
1491 
1492 #ifdef MAC
1493     return;                             /* Mac Kermit has no init file */
1494 
1495 #else /* !MAC */
1496 
1497 /* If skipping init file ('-Y' on Kermit command line), return now. */
1498 
1499     if (noinit) {
1500         kermrc[0] = '\0';
1501         inidir[0] = '\0';
1502 /*
1503   But returning from here results in inidir[] never being set to anything.
1504   Instead it should be set to wherever the init file *would* have been
1505   executed from.  So this bit of code should be removed, and then we should
1506   sprinkle "if (noinit)" tests throughout the following code until we have
1507   set inidir[], and then return without actually taking the init file.
1508 */
1509         return;
1510     }
1511 
1512 #ifdef OS2
1513 /*
1514   The -y init file must be fully specified or in the current directory.
1515   KERMRC is looked for via INIT, DPATH and PATH in that order.  Finally, our
1516   own executable file path is taken and the .EXE suffix is replaced by .INI
1517   and this is tried as the initialization file.
1518 */
1519 #ifdef CK_LOGIN
1520     debug(F101,"doinit inserver","",inserver);
1521     debug(F101,"doinit isguest","",isguest);
1522     debug(F110,"doinit anonfile",anonfile,0);
1523 
1524     if (isguest && anonfile) {
1525       ckstrncpy(line, anonfile, LINBUFSIZ+1);
1526     } else
1527 #endif /* CK_LOGIN */
1528       if (rcflag) {
1529           ckstrncpy(line,kermrc,LINBUFSIZ+1);
1530 #ifdef CK_LOGIN
1531       } else if (inserver) {
1532           char * appdata = NULL;
1533 #ifdef NT
1534           appdata = GetAppData(1);
1535           if ( appdata ) {
1536               ckmakmsg(line,LINBUFSIZ+1,appdata,
1537                         "Kermit 95/k95.ini",NULL,NULL);
1538               if ( zchki(line) < 0 )
1539                   line[0] = '\0';
1540           }
1541           if (line[0] == 0) {
1542               appdata = GetAppData(0);
1543               if ( appdata ) {
1544                   ckmakmsg(line,LINBUFSIZ+1,appdata,
1545                             "Kermit 95/k95.ini",NULL,NULL);
1546                   if ( zchki(line) < 0 )
1547                       line[0] = '\0';
1548               }
1549           }
1550 #endif /* NT */
1551           if (line[0] == 0) {
1552               appdata = zhome();
1553               if ( appdata ) {
1554                   ckmakmsg(line,LINBUFSIZ+1,appdata,
1555 #ifdef NT
1556                           "k95.ini",
1557 #else /* NT */
1558                           "k2.ini",
1559 #endif /* NT */
1560                            NULL,NULL);
1561                   if ( zchki(line) < 0 )
1562                       line[0] = '\0';
1563               }
1564           }
1565           debug(F110,"doinit inserver inifile",line,0);
1566 #endif /* CK_LOGIN */
1567     } else {
1568         char * env = 0;
1569 #ifdef NT
1570         env = getenv("K95.KSC");
1571 #else
1572         env = getenv("K2.KSC");
1573 #endif /* NT */
1574         if (!env) {
1575 #ifdef NT
1576             env = getenv("K95.INI");
1577 #else
1578             env = getenv("K2.INI");
1579 #endif /* NT */
1580         }
1581         if (!env)
1582           env = getenv("CKERMIT.INI");
1583         if (!env)
1584           env = getenv("CKERMIT_INI");
1585         line[0] = '\0';
1586 
1587         debug(F110,"doinit env",env,0);
1588         if (env)
1589           ckstrncpy(line,env,LINBUFSIZ+1);
1590 
1591 #ifdef NT
1592         if (line[0] == 0) {
1593             env = GetAppData(1);
1594             if ( env ) {
1595                 ckmakmsg(line,LINBUFSIZ+1,env,"Kermit 95/k95.ini",NULL,NULL);
1596                 if ( zchki(line) < 0 )
1597                     line[0] = '\0';
1598             }
1599         }
1600         if (line[0] == 0) {
1601             env = GetAppData(0);
1602             if ( env ) {
1603                 ckmakmsg(line,LINBUFSIZ+1,env,"Kermit 95/k95.ini",NULL,NULL);
1604                 if ( zchki(line) < 0 )
1605                     line[0] = '\0';
1606             }
1607         }
1608 #endif /* NT */
1609 
1610         if (line[0] == 0) {
1611             env = zhome();
1612             if ( env ) {
1613                 ckmakmsg(line,LINBUFSIZ+1,env,
1614 #ifdef NT
1615                           "k95.ini",
1616 #else /* NT */
1617                           "k2.ini",
1618 #endif /* NT */
1619                           NULL,NULL);
1620                 if ( zchki(line) < 0 )
1621                     line[0] = '\0';
1622             }
1623         }
1624 
1625         if (line[0] == 0)
1626           _searchenv(kermrc,"INIT",line);
1627         if (line[0] == 0)
1628           _searchenv(kermrc,"DPATH",line);
1629         if (line[0] == 0)
1630           _searchenv(kermrc,"PATH",line);
1631         if (line[0] == 0) {
1632             char *pgmptr = GetLoadPath();
1633             if (pgmptr && strlen(pgmptr) < LINBUFSIZ-8) {
1634                 lp = strrchr(pgmptr, '\\');
1635                 if (lp) {
1636                     strncpy(line, pgmptr, lp - pgmptr);
1637 #ifdef NT
1638                     strcpy(line + (lp - pgmptr), "/k95.ini");
1639 #else /* NT */
1640                     strcpy(line + (lp - pgmptr), "/k2.ini");
1641 #endif /* NT */
1642                 } else {
1643                     lp = strrchr(pgmptr, '.');
1644                     if (lp) {
1645                         strncpy(line, pgmptr, lp - pgmptr);
1646                         strcpy(line + (lp - pgmptr), ".ini");
1647                     }
1648                 }
1649             }
1650         }
1651     }
1652 
1653 #ifdef CKROOT
1654     if (!zinroot(line)) {
1655         debug(F110,"doinit setroot violation",line,0);
1656         return;
1657     }
1658 #endif /* CKROOT */
1659 
1660     debug(F110,"doinit fopen()",line,0);
1661     if ((tfile[0] = fopen(line,"r")) != NULL) {
1662         ok = 1;
1663         tlevel = 0;
1664         tfline[tlevel] = 0;
1665         tfblockstart[tlevel] = 1;
1666         if (tfnam[tlevel] = malloc(strlen(line)+1))
1667           strcpy(tfnam[tlevel],line);   /* safe */
1668 #ifndef NOSPL
1669         cmdlvl++;
1670         xcmdsrc = CMD_TF;
1671         cmdstk[cmdlvl].src = CMD_TF;
1672         cmdstk[cmdlvl].lvl = tlevel;
1673         cmdstk[cmdlvl].ccflgs = 0;
1674         ifcmd[cmdlvl] = 0;
1675         iftest[cmdlvl] = 0;
1676         count[cmdlvl] =  count[cmdlvl-1]; /* Inherit from previous level */
1677         intime[cmdlvl] = intime[cmdlvl-1];
1678         inpcas[cmdlvl] = inpcas[cmdlvl-1];
1679         takerr[cmdlvl] = takerr[cmdlvl-1];
1680         merror[cmdlvl] = merror[cmdlvl-1];
1681         xquiet[cmdlvl] = quiet;
1682         xvarev[cmdlvl] = vareval;
1683 #endif /* NOSPL */
1684         debug(F110,"doinit init file",line,0);
1685     } else {
1686         debug(F100,"doinit no init file","",0);
1687     }
1688     ckstrncpy(kermrc,line,KERMRCL);
1689     for (ptr = kermrc; *ptr; ptr++)     /* Convert backslashes to slashes */
1690        if (*ptr == '\\')
1691          *ptr = '/';
1692 #else /* not OS2 */
1693     lp = line;
1694     lp[0] = '\0';
1695     debug(F101,"doinit rcflag","",rcflag);
1696 #ifdef GEMDOS
1697     zkermini(line, rcflag, kermrc);
1698 #else
1699 #ifdef VMS
1700     {
1701 	int x;
1702 	x = zkermini(line,LINBUFSIZ,kermrc);
1703 	debug(F111,"CUSTOM zkermini",line,x);
1704 	if (x == 0)
1705 	  line[0] = NUL;
1706     }
1707 #else /* not VMS */
1708 #ifdef CK_LOGIN
1709     debug(F101,"doinit isguest","",isguest);
1710     if (isguest)
1711       ckstrncpy(lp, anonfile ? anonfile : kermrc, LINBUFSIZ);
1712     else
1713 #endif /* CK_LOGIN */
1714       if (rcflag) {                     /* If init file name from cmd line */
1715           ckstrncpy(lp,kermrc,LINBUFSIZ); /* use it, */
1716       } else {                          /* otherwise... */
1717 #ifdef CK_INI_A                         /* If we've a system-wide init file */
1718           /* And it takes precedence over the user's... */
1719           ckstrncpy(lp,CK_SYSINI,KERMRCL); /* Use it */
1720           if (zchki(lp) < 0) {          /* (if it exists...) */
1721 #endif /* CK_INI_A */
1722               char * homdir;
1723               char * env = 0;
1724               line[0] = NUL;
1725 
1726               /* Add support for environment variable */
1727               env = getenv("CKERMIT.INI");
1728               if (!env)
1729                 env = getenv("CKERMIT_INI");
1730               if (env)
1731                 ckstrncpy(lp,env,KERMRCL);
1732 
1733               if (lp[0] == 0) {
1734                   homdir = zhome();
1735                   if (homdir) {         /* Home directory for init file. */
1736                       ckstrncpy(lp,homdir,KERMRCL);
1737 #ifdef STRATUS
1738                       ckstrncat(lp,">",KERMRCL);/* VOS dirsep */
1739 #else
1740                       if (lp[0] == '/') ckstrncat(lp,"/",KERMRCL);
1741 #endif /* STRATUS */
1742                   }
1743                   ckstrncat(lp,kermrc,KERMRCL);/* Append default file name */
1744               }
1745 #ifdef CK_INI_A
1746           }
1747 #endif /* CK_INI_A */
1748 #ifdef CK_INI_B                         /* System-wide init defined? */
1749           /* But user's ini file takes precedence */
1750           if (zchki(lp) < 0)            /* If user doesn't have her own, */
1751             ckstrncpy(lp,CK_SYSINI,KERMRCL); /* use system-wide one. */
1752 #endif /* CK_INI_B */
1753       }
1754 #endif /* VMS */
1755 #endif /* GEMDOS */
1756 
1757 #ifdef AMIGA
1758     reqoff();                           /* Disable requestors */
1759 #endif /* AMIGA */
1760 
1761 #ifdef USE_CUSTOM
1762     /* If no init file was found, execute the customization file */
1763     debug(F111,"CUSTOM 1",line,rcflag);
1764     if ((!line[0] || zchki(line) < 0) && !rcflag) {
1765 	int x;
1766 #ifdef OS2
1767 	x = ckmakestr(line,LINBUFSIZ,GetAppData(1),"/","K95CUSTOM.INI",NULL);
1768 	debug(F111,"CUSTOM 2",line,x);
1769 	if (zchki(line) < 0) {
1770 	    x = ckmakestr(line,LINBUFSIZ,GetAppData(0),"/","K95USER.INI",NULL);
1771 	    debug(F111,"CUSTOM 3",line,x);
1772 	}
1773 #else  /* OS2 */
1774 	x = ckstrncpy(line,zhome(),LINBUFSIZ);
1775 #ifndef VMS
1776 	/* VMS zhome() returns "SYS$LOGIN:" */
1777 	if (line[x-1] != DIRSEP) {
1778 	    line[x++] = DIRSEP;
1779 	    line[x] = NUL;
1780 	}
1781 #endif /* VMS */
1782 	x = ckstrncat(line,MYCUSTOM,LINBUFSIZ);
1783 	debug(F111,"CUSTOM 4",line,x);
1784 #endif /* OS2 */
1785     }
1786     debug(F110,"CUSTOM 5",line,0);
1787 #endif /* USE_CUSTOM */
1788 
1789 #ifdef CKROOT
1790     if (!zinroot(line)) {
1791         debug(F110,"doinit setroot violation",line,0);
1792         return;
1793     }
1794 #endif /* CKROOT */
1795 
1796     debug(F110,"doinit ini file is",line,0);
1797     if ((tfile[0] = fopen(line,"r")) != NULL) { /* Try to open init file. */
1798         ok = 1;
1799         tlevel = 0;
1800         tfline[tlevel] = 0;
1801         tfblockstart[tlevel] = 1;
1802         if ((tfnam[tlevel] = malloc(strlen(line)+1)))
1803           strcpy(tfnam[tlevel],line);   /* safe */
1804 
1805         ckstrncpy(kermrc,line,KERMRCL);
1806 
1807 #ifndef NOSPL
1808         cmdlvl++;
1809         ifcmd[cmdlvl] = 0;
1810         iftest[cmdlvl] = 0;
1811         count[cmdlvl] =  count[cmdlvl-1]; /* Inherit from previous level */
1812         intime[cmdlvl] = intime[cmdlvl-1];
1813         inpcas[cmdlvl] = inpcas[cmdlvl-1];
1814         takerr[cmdlvl] = takerr[cmdlvl-1];
1815         merror[cmdlvl] = merror[cmdlvl-1];
1816         xquiet[cmdlvl] = quiet;
1817         xvarev[cmdlvl] = vareval;
1818         debug(F101,"doinit open ok","",cmdlvl);
1819         xcmdsrc = CMD_TF;
1820         cmdstk[cmdlvl].src = CMD_TF;
1821         cmdstk[cmdlvl].lvl = tlevel;
1822         cmdstk[cmdlvl].ccflgs = 0;
1823 #endif /* NOSPL */
1824     } else if (rcflag) {
1825         /* Print an error message only if a specific file was asked for. */
1826         printf("?%s - %s\n", ck_errstr(), line);
1827     }
1828 
1829 #ifdef datageneral
1830 /* If CKERMIT.INI not found in home directory, look in searchlist */
1831     if (/* homdir && */ (tlevel < 0)) {
1832         ckstrncpy(lp,kermrc,LINBUFSIZ);
1833         if ((tfile[0] = fopen(line,"r")) != NULL) {
1834             ok = 1;
1835             tlevel = 0;
1836             tfline[tlevel] = 0;
1837             tfblockstart[tlevel] = 1;
1838             if (tfnam[tlevel] = malloc(strlen(line)+1))
1839               strcpy(tfnam[tlevel],line); /* safe */
1840 #ifndef NOSPL
1841             cmdlvl++;
1842             xcmdsrc = CMD_TF;
1843             cmdstk[cmdlvl].src = CMD_TF;
1844             cmdstk[cmdlvl].lvl = tlevel;
1845             cmdstk[cmdlvl].ccflgs = 0;
1846             ifcmd[cmdlvl] = 0;
1847             iftest[cmdlvl] = 0;
1848             count[cmdlvl] =  count[cmdlvl-1]; /* Inherit from previous level */
1849             intime[cmdlvl] = intime[cmdlvl-1];
1850             inpcas[cmdlvl] = inpcas[cmdlvl-1];
1851             takerr[cmdlvl] = takerr[cmdlvl-1];
1852             merror[cmdlvl] = merror[cmdlvl-1];
1853             xquiet[cmdlvl] = quiet;
1854 	    xvarev[cmdlvl] = vareval;
1855 #endif /* NOSPL */
1856         }
1857     }
1858 #endif /* datageneral */
1859 
1860 #ifdef AMIGA                            /* Amiga... */
1861     reqpop();                           /* Restore requestors */
1862 #endif /* AMIGA */
1863 #endif /* OS2 */
1864 #endif /* MAC */
1865 
1866     /* Assign value to inidir */
1867 
1868     if (!ok) {
1869         inidir[0] = NUL;
1870     } else {
1871         ckstrncpy(inidir, kermrc, CCHMAXPATH);
1872         x = strlen(inidir);
1873         if (x > 0) {
1874             int i;
1875             for (i = x - 1; i > 0; i-- ) {
1876                 if (ISDIRSEP(inidir[i])) {
1877                     inidir[i+1] = NUL;
1878                     break;
1879                 }
1880             }
1881         }
1882 #ifdef NT
1883         GetShortPathName(inidir,inidir,CCHMAXPATH);
1884 #endif /* NT */
1885     }
1886 }
1887 
1888 VOID
doiksdinit()1889 doiksdinit() {
1890 #ifdef CK_SSL
1891     /* IKSD doesn't request client certs */
1892     ssl_verify_flag = SSL_VERIFY_NONE;
1893 #endif /* CK_SSL */
1894 
1895     if (!cmdinited)
1896       cmdini();
1897 
1898 #ifdef IKSDCONF
1899 #ifdef OS2
1900     line[0] = '\0';
1901     _searchenv(iksdconf,"INIT",line);
1902     if (line[0] == 0)
1903       _searchenv(iksdconf,"DPATH",line);
1904     if (line[0] == 0)
1905       _searchenv(iksdconf,"PATH",line);
1906     if (line[0] == 0) {
1907         char *pgmptr = GetLoadPath();
1908         if (pgmptr && strlen(pgmptr) < LINBUFSIZ-8) {
1909             lp = strrchr(pgmptr, '\\');
1910             if (lp) {
1911                 strncpy(line, pgmptr, lp - pgmptr);
1912                 strcpy(line + (lp - pgmptr), "\\");
1913                 strcpy(line + (lp - pgmptr + 1), iksdconf);
1914             } else {
1915                 lp = strrchr(pgmptr, '.');
1916                 if (lp) {
1917                     strncpy(line, pgmptr, lp - pgmptr);
1918                     strcpy(line + (lp - pgmptr), ".ksc");
1919                 }
1920             }
1921         }
1922     }
1923     debug(F110,"doiksdinit() line",line,0);
1924     tfile[0] = fopen(line,"r");
1925 #else /* OS2 */
1926     tfile[0] = fopen(iksdconf,"r");
1927 #endif /* OS2 */
1928     if (tfile[0] != NULL) {
1929         tlevel = 0;
1930         tfline[tlevel] = 0;
1931         tfblockstart[tlevel] = 1;
1932 #ifdef OS2
1933         if (tfnam[tlevel] = malloc(strlen(line)+1))
1934           strcpy(tfnam[tlevel],line);
1935 #else /* OS2 */
1936         if ((tfnam[tlevel] = malloc(strlen(iksdconf)+1)))
1937           strcpy(tfnam[tlevel],iksdconf);
1938 #endif /* OS2 */
1939 #ifndef NOSPL
1940         cmdlvl++;
1941         xcmdsrc = CMD_TF;
1942         cmdstk[cmdlvl].src = CMD_TF;
1943         cmdstk[cmdlvl].lvl = tlevel;
1944         cmdstk[cmdlvl].ccflgs = 0;
1945         ifcmd[cmdlvl]  = 0;
1946         iftest[cmdlvl] = 0;
1947         count[cmdlvl]  = count[cmdlvl-1]; /* Inherit from previous level */
1948         intime[cmdlvl] = intime[cmdlvl-1];
1949         inpcas[cmdlvl] = inpcas[cmdlvl-1];
1950         takerr[cmdlvl] = takerr[cmdlvl-1];
1951         merror[cmdlvl] = merror[cmdlvl-1];
1952         xquiet[cmdlvl] = quiet;
1953 	xvarev[cmdlvl] = vareval;
1954 #endif /* NOSPL */
1955         debug(F110,"doiksdinit file ok",tfnam[tlevel],0);
1956     } else {
1957         debug(F110,"doiksdinit open failed",tfnam[tlevel],0);
1958     }
1959 #endif /* IKSDCONF */
1960 }
1961 
1962 #ifndef NOSPL
1963 /*
1964   G E T N C M
1965 
1966   Get next command from current macro definition.  Command is copied
1967   into string pointed to by argument s, max length n.   Returns:
1968    0 if a string was copied;
1969   -1 if there was no string to copy.
1970 */
1971 int
getncm(s,n)1972 getncm(s,n) char *s; int n; {
1973     int y = 0;				/* Character counter */
1974     int quote = 0;
1975     int kp = 0;				/* Brace up-down counter */
1976     int pp = 0;				/* Parenthesis up-down counter */
1977 #ifndef NODQMACRO
1978     int dq = 0;				/* Doublequote counter */
1979 #endif /* NODQMACRO */
1980     char *s2;                           /* Copy of destination pointer */
1981 
1982     s2 = s;                             /* Initialize string pointers */
1983     *s = NUL;                           /* and destination buffer */
1984 
1985     /* debug(F010,"getncm entry",macp[maclvl],0); */
1986 
1987     for (y = 0;                         /* Loop for n bytes max */
1988          macp[maclvl] && *macp[maclvl] && y < n;
1989          y++, s++, macp[maclvl]++) {
1990 
1991         *s = *macp[maclvl];             /* Get next char from macro def */
1992 
1993 #ifndef COMMENT
1994 /*
1995   This is to allow quoting of parentheses, commas, etc, in function
1996   arguments, but it breaks just about everything else.  DON'T REMOVE THIS
1997   COMMENT!  (Otherwise you'll wind up adding the same code again and breaking
1998   everything again.)  <-- The preceding warning should be obsolete since the
1999   statements below have been fixed, but in case of fire, remove the "n" from
2000   the <#>ifndef above.  NEW WARNING: code added 12 Apr 2002 to exempt the
2001   opening brace in \{nnn} from being treated as a quoted brace.
2002 */
2003         if (!quote && *s == CMDQ) {
2004             quote = 1;
2005             continue;
2006         }
2007         if (quote) {
2008 	    int notquote = 0;
2009             quote = 0;
2010 	    if (*s == '{') {		/* Check for \{nnn} (8.0.203) */
2011 		char c, * p;
2012 		p = macp[maclvl] + 1;
2013 		while ((c = *p++)) {
2014 		    if (isdigit(c))
2015 		      continue;
2016 		    else if (c == '}') {
2017 			notquote++;
2018 			break;
2019 		    } else {
2020 			break;
2021 		    }
2022 		}
2023 	    }
2024 	    if (notquote == 0)
2025 	      continue;
2026         }
2027 #endif /* COMMENT */
2028 
2029 /*
2030   Allow braces around macro definition to prevent commas from being turned to
2031   end-of-lines and also treat any commas within parens as text so that
2032   multiple-argument functions won't cause the command to break prematurely.
2033   19 Oct 2001: Similar treatment was added for doublequotes, so
2034 
2035      define foo { echo "one, two, three" }
2036 
2037   would work as expected.  This doesn't seem to have broken anything but
2038   if something comes up later, rebuild with NODQMACRO defined.
2039 */
2040         if (*s == '{') kp++;            /* Count braces */
2041         if (*s == '}' && kp > 0) kp--;
2042         if (*s == '(') pp++;            /* Count parentheses. */
2043         if (*s == ')' && pp > 0) pp--;
2044 #ifndef NODQMACRO
2045 #ifndef COMMENT
2046 	/* Too many false positives */
2047 	/* No, not really -- this is indeed the best we can do */
2048 	/* Reverted to this method Sun May 11 18:43:45 2003 */
2049 	if (*s == '"') dq = 1 - dq;     /* Account for doublequotes */
2050 #else  /* Fri Apr  4 13:21:29 2003 */
2051 	/* The code below breaks the SWITCH statement */
2052 	/* There is no way to make this work -- it would require */
2053 	/* building in all the knowledge of command parser. */
2054         if (dblquo && (*s == '"')) {    /* Have doublequote */
2055             if (dq == 1) {		/* Close quote only if... */
2056                 if ((*(macp[maclvl]+1) == SP) || /* followed by space or... */
2057 		    (!*(macp[maclvl]+1)) ||      /* at end or ... */
2058 		    /* Next char is command separator... */
2059 		    /* Sun May 11 17:24:12 2003 */
2060 		    (kp < 1 && pp < 1 && (*(macp[maclvl]+1) == ','))
2061 		    )
2062                   dq = 0;		/* Close the quote */
2063             } else if (dq == 0) {
2064                 /* Open quote only if at beginning or preceded by space */
2065                 if (s > s2) {
2066                     if (*(s-1) == SP)
2067                       dq = 1;
2068                 } else if (s == s2) {
2069                       dq = 1;
2070                 }
2071             }
2072         }
2073 #endif /* COMMENT */
2074 #endif /* NODQMACRO */
2075         if (*s == ',' && pp <= 0 && kp <= 0
2076 #ifndef NODQMACRO
2077             && dq == 0
2078 #endif /* NODQMACRO */
2079             ) {
2080             macp[maclvl]++;             /* Comma not in {} or () */
2081             /* debug(F110,"next cmd",s,0); */
2082             kp = pp = 0;                /* so we have the next command */
2083             break;
2084         }
2085     }                                   /* Reached end. */
2086 #ifdef COMMENT
2087     /* DON'T DO THIS - IT BREAKS EVERYTHING */
2088     *s = NUL;
2089 #endif /* COMMENT */
2090     if (*s2 == NUL) {                   /* If nothing was copied, */
2091         /* debug(F100,"getncm eom","",0); */
2092         popclvl();                      /* pop command level. */
2093         return(-1);
2094     } else {                            /* otherwise, tack CR onto end */
2095         *s++ = CR;
2096         *s = '\0';
2097         /* debug(F110,"getncm OK",s,0); */
2098         if (mecho && pflag)             /* If MACRO ECHO ON, echo the cmd */
2099           printf("%s\n",s2);
2100     }
2101     return(0);
2102 }
2103 
2104 /*  D O M A C  --  Define and then execute a macro */
2105 
2106 int
domac(name,def,flags)2107 domac(name, def, flags) char *name, *def; int flags; {
2108     int x, m;
2109 #ifndef NOLOCAL
2110 #ifdef OS2
2111     extern int term_io;
2112     int term_io_sav = term_io;
2113     term_io = 0;                        /* Disable Terminal Emulator I/O */
2114 #endif /* OS2 */
2115 #endif /* NOLOCAL */
2116     m = maclvl;                         /* Current macro stack level */
2117     x = addmac(name, def);              /* Define a new macro */
2118     if (x > -1) {                       /* If successful, */
2119         dodo(x,NULL,flags);             /* start it (increments maclvl). */
2120         while (maclvl > m) {            /* Keep going till done with it, */
2121             debug(F101,"domac loop maclvl 1","",maclvl);
2122             sstate = (CHAR) parser(1);  /* parsing & executing each command, */
2123             debug(F101,"domac loop maclvl 2","",maclvl);
2124             if (sstate) proto();        /* including protocol commands. */
2125         }
2126         debug(F101,"domac loop exit maclvl","",maclvl);
2127     }
2128 #ifndef NOLOCAL
2129 #ifdef OS2
2130     term_io = term_io_sav;
2131 #endif /* OS2 */
2132 #endif /* NOLOCAL */
2133     return(success);
2134 }
2135 #endif /* NOSPL */
2136 
2137 /*
2138   G E T N C T
2139 
2140   Get next command from TAKE (command) file.
2141 
2142   Call with:
2143    s     Pointer to buffer to read into
2144    n     Length of buffer
2145    f     File descriptor of file to read from
2146    flag  0 == keep line terminator on and allow continuation
2147          1 == discard line terminator and don't allow continuation
2148 
2149   Call with flag == 0 to read a command from a TAKE file;
2150   Call with flag != 0 to read a line from a dialing or network directory.
2151 
2152   In both cases, trailing comments and/or trailing whitespace is/are stripped.
2153   If flag == 0, continued lines are combined into one line.  A continued line
2154   is one that ends in hypen, or any line in a "block", which starts with "{"
2155   at the end of a line and ends with a matching "}" at the beginning of a
2156   subsequent line; blocks may be nested.
2157 
2158   Returns:
2159    0 if a string was copied,
2160   -1 on EOF,
2161   -2 on malloc failure
2162   -3 if line is not properly terminated
2163   -4 if (possibly continued) line is too long.
2164 */
2165 static int lpxlen = 0;
2166 
2167 int
getnct(s,n,f,flag)2168 getnct(s,n,f,flag) char *s; int n; FILE *f; int flag; {
2169     int i = 0, len = 0, buflen = 0;
2170     char c = NUL, cc = NUL, ccl = NUL, ccx = NUL, *s2 = NULL;
2171     char *lp = NULL, *lpx = NULL, *lp2 = NULL, *lp3 = NULL, *lastcomma = NULL;
2172     char * prev = NULL;
2173     int bc = 0;                         /* Block counter */
2174     int firstread = 1;
2175 
2176     s2 = s;                             /* Remember original pointer */
2177     prev = s2;				/* Here too */
2178     buflen = n;                         /* Remember original buffer length */
2179 
2180     if (n < 0)
2181       return(-2);
2182 
2183     /* Allocate a line buffer only if we don't have one that's big enough */
2184 
2185     debug(F111,"getnct",ckitoa(lpxlen),n);
2186 
2187     if (lpx && (n > lpxlen)) {          /* Have one already */
2188         debug(F101,"getnct new buffer","",lpxlen);
2189         free(lpx);                      /* But it's not big enough */
2190         lpx = NULL;                     /* Free current one */
2191         lpxlen = 0;
2192     }
2193     if (!lpx) {                         /* Get new one */
2194         if (!(lpx = (char *) malloc(n))) {
2195             debug(F101,"getnct malloc failure","",0);
2196             printf("?Memory allocation failure [getnct:%d]\n",n);
2197             return(-2);
2198         }
2199         lpxlen = n;
2200     }
2201     lp2 = lpx;
2202 #ifdef KLUDGE
2203     /* NOTE: No longer used as of 14 Aug 2000 */
2204     lp2++;
2205 #endif /* KLUDGE */
2206 
2207     while (1) {                         /* Loop to read lines from file */
2208         debug(F101,"getnct while (1)","",n);
2209         if (fgets(lp2,n,f) == NULL) {   /* Read a line into lp2 */
2210             debug(F110,"getnct EOF",s2,0); /* EOF */
2211             free(lpx);                  /* Free temporary storage */
2212             lpx = NULL;
2213             *s = NUL;                   /* Make destination be empty */
2214             return(-1);                 /* Return failure code */
2215         }
2216         if (firstread) {               /* Beginning of a block or statement */
2217             tfblockstart[tlevel] = tfline[tlevel];
2218             firstread = 0;
2219         }
2220 #ifndef NODIAL
2221         if (flag)                       /* Count this line */
2222           dirline++;
2223         else
2224 #endif /* NODIAL */
2225           tfline[tlevel]++;
2226         len = strlen(lp2) - 1;          /* Position of line terminator */
2227         if (len == 0 && lp2[0] != '\n') { /* Last line in file has one char */
2228             lp2[++len] = '\n';          /* that is not a newline */
2229             lp2[len] = NUL;
2230         }
2231         debug(F010,"getnct",lp2,0);
2232         if (len < 0)
2233           len = 0;
2234         if (techo && pflag) {            /* If TAKE ECHO ON, */
2235             if (flag) {
2236                 printf("%3d. %s",             /* echo it this line. */
2237 #ifndef NODIAL
2238                     flag ? dirline :
2239 #endif /* NODIAL */
2240                     tfline[tlevel],
2241                     lp2
2242                     );
2243             } else {
2244                 printf("%3d. %3d. %s",             /* echo it this line. */
2245                     tfline[tlevel],
2246                     tfblockstart[tlevel],
2247                     lp2
2248                     );
2249             }
2250         }
2251         lp3 = lp2;                      /* Working pointer */
2252         i = len;                        /* Get first nonwhitespace character */
2253         while (i > 0 && (*lp3 == SP || *lp3 == HT)) {
2254             i--;
2255             lp3++;
2256         }
2257         if (i == 0 && bc > 0)           /* Blank line in {...} block */
2258           continue;
2259 
2260         /* Isolate, remove, and check terminator */
2261 
2262         c = lp2[len];                   /* Value of line terminator */
2263         /* debug(F101,"getnct terminator","",c); */
2264         if (c < LF || c > CR) {         /* It's not a terminator */
2265             /* debug(F111,"getnct bad line",lp2,c); */
2266             if (feof(f) && len > 0 && len < n) {
2267                 /* Kludge Alert... */
2268                 if (!quiet)
2269                   printf("WARNING: Last line of %s lacks terminator\n",
2270                          s2 == cmdbuf ? "command file" : "directory file");
2271                 c = lp2[++len] = '\n';  /* No big deal - supply one. */
2272             } else {                    /* Something's wrong, fail. */
2273                 free(lpx);
2274                 lpx = NULL;
2275                 return(-3);
2276             }
2277         }
2278         /* Trim trailing whitespace */
2279 
2280         for (i = len - 1; i > -1 && lp2[i] <= SP; i--) /* Trim */
2281           ;
2282         /* debug(F101,"getnct i","",i); */
2283         lp2[i+1] = NUL;                 /* Terminate the string */
2284         /* debug(F110,"getnct lp2",lp2,0); */
2285         lp = lp2;                       /* Make a working pointer */
2286 
2287         /* Remove trailing or full-line comment */
2288 
2289         while ((cc = *lp)) {
2290             if (cc == ';' || cc == '#') { /* Comment introducer? */
2291                 if (lp == lp2) {        /* First char on line */
2292                     *lp = NUL;
2293                     break;
2294                 } else if (*(lp - 1) == SP || *(lp - 1) == HT) {
2295                     lp--;
2296                     *lp = NUL;  /* Or preceded by whitespace */
2297                     break;
2298                 }
2299             }
2300             lp++;
2301         }
2302         if (lp > lp2)
2303           lp--;                         /* Back up over the NUL */
2304 
2305         /* Now trim any space that preceded the comment */
2306 
2307         while ((*lp == SP || *lp == HT) && lp >= lp2) {
2308             *lp = NUL;
2309             if (lp <= lp2)
2310               break;
2311             lp--;
2312         }
2313         /* debug(F110,"getnct comment trimmed",lp2,0); */
2314 
2315         len = strlen(lp2);              /* Length after trimming */
2316 
2317         if (n - len < 2) {              /* Check remaining space */
2318             debug(F111,"getnct command too long",s2,buflen);
2319             printf("?Line too long, maximum length: %d.\n",buflen);
2320             free(lpx);
2321             return(-4);
2322         }
2323         ccl = (len > 0) ? lp2[len-1] : 0;     /* Last character in line */
2324         ccx = (len > 1) ? lp2[len-2] : 0;     /* Penultimate char in line */
2325 
2326 #ifdef COMMENT
2327         /* Line containing only whitespace and ,- */
2328         if ((len > 1) && (lp3 == lp2+len-2) && (ccl == '-') && (ccx == ','))
2329           continue;
2330 #endif /* COMMENT */
2331 
2332 #ifdef KLUDGE
2333 /*
2334   If it is a command and it begins with a token (like ! or .) that is not
2335   followed by a space, insert a space now; otherwise cmkey() can get mighty
2336   confused.
2337 */
2338         if (s == s2 && !flag) {
2339             char *p = toktab;
2340             while (*p) {
2341                 if (*p == *lp3 && *(p+1) != SP) {
2342                     debug(F110,"getnct token",p,0);
2343                     *lp3-- = SP;
2344                     *lp3 = *p;
2345                     if (lp3 < lp2) {
2346                         lp2--;
2347                         len++;
2348                     }
2349                     break;
2350                 } else
2351                   p++;
2352             }
2353         }
2354 #endif /* KLUDGE */
2355         lp = lp2;
2356 
2357         while ((*s++ = *lp++))          /* Copy result to target buffer */
2358           n--;                          /* accounting for length */
2359         s--;                            /* Back up over the NUL */
2360 
2361         /* Check whether this line is continued */
2362 
2363         if (flag)                       /* No line continuation when flag=1 */
2364           break;                        /* So break out of read-lines loop */
2365 
2366 #ifdef COMMENT
2367         debug(F000,"getnct first char","",*lp3);
2368         debug(F000,"getnct last char","",ccl);
2369         debug(F000,"getnct next-to-last char","",ccx);
2370 #endif /* COMMENT */
2371 
2372         if (bc > 0 && *lp3 == '}') {    /* First char on line is '}' */
2373             bc--;			/* Decrement block counter */
2374         }
2375 
2376         if (bc == 0 &&                  /* Line is continued if bc > 0 */
2377 #ifdef COMMENT
2378             /* Not supported as of C-Kermit 6.0 */
2379             ccl != CMDQ &&              /* or line ends with CMDQ */
2380 #endif /* COMMENT */
2381             ccl != '-'  &&              /* or line ends with dash */
2382             ccl != '{') {               /* or line ends with opening brace */
2383             break;                      /* None of those, we're done. */
2384         }
2385         if (ccl == '-' || ccl == '{')   /* Continuation character */
2386           if (ccx == CMDQ)              /* But it's quoted */
2387             break;                      /* so ignore it */
2388 
2389         if (ccl == '{') {               /* Last char on line is '{'? */
2390             bc++;                       /* Count the block opener. */
2391         } else if (ccl == '-') {        /* Explicit continue? */
2392             char c, * ss;
2393             int state = 0, nn;
2394             s--;                        /* Yes, back up over terminators */
2395             n++;                        /* and over continuation character */
2396             nn = n;                     /* Save current count */
2397             ss = s;                     /* and pointer */
2398             s--;                        /* Back up over dash */
2399             n++;
2400             while (state < 2 && s >= prev) { /* Check for "{,-" */
2401                 n++;
2402                 c = *s--;
2403                 if (c <= SP)
2404                   continue;
2405                 if (c != ',' && c != '{')
2406                   break;
2407                 switch (state) {
2408                   case 0:               /* Looking for comma */
2409                     if (c == ',')
2410                       state = 1;
2411                     break;
2412                   case 1:               /* Looking for left brace */
2413                     if (c == '{') {
2414                         state = 2;
2415                         s += 2;
2416                         *s = NUL;
2417                         bc++;
2418                     }
2419                     break;
2420                 }
2421             }
2422             if (state != 2) { s = ss; n = nn; }
2423             *s = NUL;
2424         } else {                        /* None of those but (bc > 0) */
2425             lastcomma = s;
2426             *s++ = ',';                 /* and insert a comma */
2427             n--;
2428         }
2429 #ifdef COMMENT
2430         debug(F101,"getnct bc","",bc);
2431         debug(F100,"getnct continued","",0);
2432 #endif /* COMMENT */
2433 
2434         *s = NUL;
2435         prev = s;
2436 
2437     } /* read-lines while loop */
2438 
2439     if (lastcomma)
2440       *lastcomma = SP;
2441     if (!flag)                          /* Tack line terminator back on */
2442       *s++ = c;
2443     *s++ = NUL;                         /* Terminate the string */
2444     untab(s2);                          /* Done, convert tabs to spaces */
2445 #ifdef DEBUG
2446     if (!flag) {
2447         debug(F010,"CMD(F)",s2,0);
2448     }
2449 #endif /* DEBUG */
2450     {
2451         int i = 0; char *s = s2; char prev = '\0'; char c = '\0';
2452         while (*s) {   /* Save beginning of this command for error messages */
2453             c = *s++;
2454             if (c == '\n' || c == '\r') c = SP;
2455             if (c == SP && prev == SP) /* Squeeze spaces */
2456               continue;
2457             lasttakeline[i++] = c;
2458             prev = c;
2459             if (i > TMPBUFSIZ-5) {
2460                 lasttakeline[i++] = '.';
2461                 lasttakeline[i++] = '.';
2462                 lasttakeline[i++] = '.';
2463                 lasttakeline[i++] = NUL;
2464                 break;
2465             }
2466         }
2467         i = (int)strlen((char *)lasttakeline) - 1;
2468         while (i > 0 && lasttakeline[i] == SP) { /* Trim treailing spaces */
2469             lasttakeline[i] = NUL;
2470             i--;
2471         }    }
2472     free(lpx);                          /* Free temporary storage */
2473     return(0);                          /* Return success */
2474 }
2475 
2476 VOID
shostack()2477 shostack() {                            /* Dump the command stack */
2478     int i;
2479     char *p;
2480 #ifndef NOSPL
2481     for (i = cmdlvl; i > 0; i--) {
2482         if (cmdstk[i].src == CMD_TF) {
2483             p = tfnam[cmdstk[i].lvl];
2484             if (zfnqfp(p,TMPBUFSIZ,tmpbuf))
2485               p = tmpbuf;
2486             printf(" %2d. File  : %s (line %d)\n",
2487                    i,
2488                    p,
2489                    tfline[cmdstk[i].lvl]
2490                    );
2491         } else if (cmdstk[i].src == CMD_MD) {
2492             char * m;
2493             m = m_arg[cmdstk[i].lvl][0]; /* Name of this macro */
2494             if (i > 0) {                 /* Special handling for 2-level */
2495                 char *s;                 /* built-in macros... */
2496                 s = m_arg[cmdstk[i-1].lvl][0]; /* Name next level up */
2497                 if (s && cmdstk[i-1].src == CMD_MD) {
2498                     if (!strcmp(s,"_forx"))
2499                       m = "FOR";
2500                     else if (!strcmp(s,"_xif"))
2501                       m = "XIF";
2502                     else if (!strcmp(s,"_while"))
2503                       m = "WHILE";
2504                     else if (!strcmp(s,"_switx"))
2505                       m = "SWITCH";
2506                 }
2507             }
2508             printf(" %2d. Macro : %s\n",i,m);
2509         } else if (cmdstk[i].src == CMD_KB) {
2510             printf(" %2d. Prompt:\n",i);
2511         } else {
2512             printf(" %2d. ERROR : Command source unknown\n",i);
2513         }
2514     }
2515 #else
2516     for (i = tlevel; i > -1; i--) {
2517         p = tfnam[i];
2518         if (zfnqfp(p,TMPBUFSIZ,tmpbuf))
2519           p = tmpbuf;
2520         printf(" %2d. File  : %s (line %d)\n",
2521                i,
2522                p,
2523                tfline[i]
2524                );
2525     }
2526 #endif /* NOSPL */
2527     if (i == 0)
2528       printf(" %2d. Prompt: (top level)\n",0);
2529 }
2530 
2531 /* For command error messages - avoid dumping out the contents of some */
2532 /* some huge FOR loop if it contains a syntax error. */
2533 
2534 static char *
cmddisplay(s,cx)2535 cmddisplay(s, cx) char * s; int cx; {
2536     static char buf[80];
2537     if ((int)strlen(s) > 70) {
2538 	sprintf(buf,"%.64s...",s);	/* SAFE */
2539 	s = buf;
2540     }
2541     return(s);
2542 }
2543 
2544 static VOID
cmderr()2545 cmderr() {
2546     if (xcmdsrc > 0) {
2547 	switch (cmd_err) {		/* SET COMMAND ERROR-DISPLAY */
2548 	  case 0:
2549 	    break;
2550 	  case 1:
2551 	  case 2:
2552 	    if (tlevel > -1) {
2553 #ifndef NOSPL
2554 		if (xcmdsrc == 2)
2555 		  printf(
2556 "In macro or block defined in file: %s starting about line %d\n",
2557 			 tfnam[tlevel] ? tfnam[tlevel] : "", tfline[tlevel]
2558 			 );
2559 		else
2560 #endif /* NOSPL */
2561 		  printf("File: %s, Line: %d\n",
2562 			 tfnam[tlevel] ? tfnam[tlevel] : "", tfline[tlevel]
2563 			 );
2564 	    }
2565 #ifndef NOSPL
2566 	    if (cmd_err == 2) {
2567 		if (cmdstk[cmdlvl].src == CMD_MD) { /* Executing a macro? */
2568 		    int m;
2569 		    m = cmdstk[cmdlvl].lvl;
2570 		    if (mlook(mactab,m_arg[m][0],nmac) >= 0)
2571 		      printf("Macro name: %s\n", m_arg[m][0]);
2572 		}
2573 	    }
2574 #endif /* NOSPL */
2575 	    break;
2576 
2577 	  case 3:
2578 	    printf("Command stack:\n");
2579 	    shostack();
2580 	}
2581     }
2582 }
2583 
2584 /*  P A R S E R  --  Top-level interactive command parser.  */
2585 
2586 /*
2587   Call with:
2588     m = 0 for normal behavior: keep parsing and executing commands
2589           until an action command is parsed, then return with a
2590           Kermit start-state as the value of this function.
2591     m = 1 to parse only one command, can also be used to call parser()
2592           recursively.
2593     m = 2 to read but do not execute one command.
2594   In all cases, parser() returns:
2595     0     if no Kermit protocol action required
2596     > 0   with a Kermit protocol start-state.
2597     < 0   upon error.
2598 */
2599 int
parser(m)2600 parser(m) int m; {
2601     int tfcode, xx, yy, zz;             /* Workers */
2602     int is_tn = 0;
2603     int cdlost = 0;
2604 
2605 #ifndef NOSPL
2606     int inlevel;                        /* Level we were called at */
2607     extern int askflag, echostars;
2608 #endif /* NOSPL */
2609     char *cbp;                          /* Command buffer pointer */
2610 #ifdef MAC
2611     extern char *lfiles;                /* Fake extern cast */
2612 #endif /* MAC */
2613     extern int interrupted;
2614 #ifndef NOXFER
2615     extern int sndcmd, getcmd, fatalio, clearrq;
2616 #endif /* NOXFER */
2617 
2618 #ifdef AMIGA
2619     reqres();                           /* Restore AmigaDOS requestors */
2620 #endif /* AMIGA */
2621 
2622 #ifdef OS2
2623     if (cursor_save > -1) {             /* Restore cursor if it was */
2624         cursorena[VCMD] = cursor_save;  /* turned off during file transfer */
2625         cursor_save = -1;
2626     }
2627 #endif /* OS2 */
2628 
2629 #ifdef IKSDB
2630     if (ikdbopen) slotstate(what,"COMMAND PROMPT","",""); /* IKSD database */
2631 #endif /* IKSDB */
2632 
2633     is_tn = (local && network && IS_TELNET()) ||
2634       (!local && sstelnet);
2635 
2636     if (!xcmdsrc)                       /* If at top (interactive) level ... */
2637       concb((char)escape);              /* put console in 'cbreak' mode. */
2638 
2639 #ifdef CK_TMPDIR
2640 /* If we were cd'd temporarily to another device or directory ... */
2641     if (f_tmpdir) {
2642         int x;
2643         x = zchdir((char *) savdir);    /* ... restore previous directory */
2644         f_tmpdir = 0;                   /* and remember we did it. */
2645         debug(F111,"parser tmpdir restoring",savdir,x);
2646     }
2647 #endif /* CK_TMPDIR */
2648 
2649 #ifndef NOSPL
2650     inlevel = cmdlvl;           /* Current macro level */
2651 #ifdef DEBUG
2652     if (deblog) {
2653         debug(F101,"&parser entry maclvl","",maclvl);
2654         debug(F101,"&parser entry inlevel","",inlevel);
2655         debug(F101,"&parser entry tlevel","",tlevel);
2656         debug(F101,"&parser entry cmdlvl","",cmdlvl);
2657         debug(F101,"&parser entry m","",m);
2658     }
2659 #endif /* DEBUG */
2660 #endif /* NOSPL */
2661 
2662 #ifndef NOXFER
2663     ftreset();                          /* Reset global file settings */
2664 #endif /* NOXFER */
2665 /*
2666   sstate becomes nonzero when a command has been parsed that requires some
2667   action from the protocol module.  Any non-protocol actions, such as local
2668   directory listing or terminal emulation, are invoked directly from below.
2669 */
2670     sstate = 0;                         /* Start with no start state. */
2671 
2672 #ifndef NOXFER
2673 #ifndef NOSPL
2674     query = 0;                          /* QUERY not active */
2675 #endif /* NOSPL */
2676 #ifndef NOHINTS
2677     if (!success) {
2678         if (local && !network && carrier != CAR_OFF) {
2679             int x;                      /* Serial connection */
2680             x = ttgmdm();               /* with carrier checking */
2681             if (x > -1) {
2682                 if (!(x & BM_DCD)) {
2683                     cdlost = 1;
2684                     fatalio = 1;
2685                 }
2686             }
2687         }
2688     }
2689 #ifdef DEBUG
2690     if (deblog) {
2691         debug(F101,"parser top what","",what);
2692         debug(F101,"parser top interrupted","",interrupted);
2693         debug(F101,"parser top cdlost","",cdlost);
2694         debug(F101,"parser top sndcmd","",sndcmd);
2695         debug(F101,"parser top getcmd","",getcmd);
2696     }
2697 #endif /* DEBUG */
2698     if (cdlost && !interrupted && (sndcmd || getcmd)) {
2699         printf("?Connection broken (carrier signal lost)\n");
2700     }
2701     if (sndcmd && protocol == PROTO_K &&
2702 	!success && hints && !interrupted && !fatalio && !xcmdsrc) {
2703         int x = 0, n = 0;
2704         printf("\n*************************\n");
2705         printf("SEND-class command failed.\n");
2706         printf(" Packets sent: %d\n", spackets);
2707         printf(" Retransmissions: %d\n",retrans);
2708         printf(" Timeouts: %d\n", timeouts);
2709         printf(" Damaged packets: %d\n", crunched);
2710         if (epktrcvd) {
2711             printf(" Transfer canceled by receiver.\n");
2712             printf(" Receiver's message: \"%s\"\n",(char *)epktmsg);
2713             n++;
2714         } else {
2715             if (epktmsg) if (*epktmsg) {
2716                 printf(" Fatal Kermit Protocol Error: %s\n",epktmsg);
2717                 n++;
2718             }
2719         }
2720         if (local && !network && carrier != CAR_OFF) {
2721             int xx;                     /* Serial connection */
2722             xx = ttgmdm();              /* with carrier checking */
2723             if (xx > -1) {
2724                 if (!(xx & BM_DCD))
2725                   cdlost = 1;
2726             }
2727         }
2728 
2729 #ifdef UNIX
2730         if (errno != 0)
2731 #endif /* UNIX */
2732           {
2733               printf(" Most recent local OS error: \"%s\"\n",ck_errstr());
2734               n++;
2735           }
2736         printf(
2737    "\nHINTS... If the preceding error message%s not explain the failure:\n",
2738                (n > 1) ? "s do" : " does"
2739                );
2740 #ifndef NOLOCAL
2741         if (local) {
2742             if (rpackets == 0) {
2743                 printf(" . Did you start a Kermit receiver on the far end?\n");
2744             } else {
2745                 printf(
2746                 " . Try changing the remote Kermit's FLOW-CONTROL setting.\n");
2747                 if (!network && mdmtyp > 0)
2748                   if ((3 * crunched) > spackets)
2749                     printf(
2750                 " . Try placing a new call to get a cleaner connection.\n");
2751             }
2752         } else if (rpackets > 0) {
2753             if (flow == FLO_NONE)
2754              printf(" . Give me a SET FLOW XON/XOFF command and try again.\n");
2755             else
2756              printf(" . Give me a SET FLOW NONE command and try again.\n");
2757         }
2758         x++;
2759 #endif /* NOLOCAL */
2760 
2761         if ((3 * timeouts) > spackets)
2762           printf(" . Adjust the timeout method (see HELP SET SEND).\n");
2763         if ((3 * retrans) > spackets)
2764           printf(" . Increase the retry limit (see HELP SET RETRY).\n");
2765 
2766 #ifdef CK_SPEED
2767         if (prefixing != PX_ALL && rpackets > 2) {
2768             printf(" . Try it again with: SET PREFIXING ALL\n");
2769             x++;
2770         }
2771 #endif /* CK_SPEED */
2772 #ifdef STREAMING
2773         if (streamed) {
2774             printf(" . Try it again with: SET STREAMING OFF\n");
2775             x++;
2776         } else if (reliable) {
2777             printf(" . Try it again with: SET RELIABLE OFF\n");
2778             x++;
2779         }
2780 #endif /* STREAMING */
2781 
2782 #ifdef CK_SPEED
2783         if (clearrq > 0 && prefixing == PX_NON) {
2784             printf(" . Try it again with: SET CLEAR-CHANNEL OFF\n");
2785             x++;
2786         }
2787 #endif /* CK_SPEED */
2788         if (!parity) {
2789             printf(" . Try it again with: SET PARITY SPACE\n");
2790             x++;
2791         }
2792         printf(" . %sive a ROBUST command and try again.\n",
2793                (x > 0) ? "As a last resort, g" : "G"
2794                );
2795         printf("Also:\n");
2796         printf(" . Be sure the source file has read permission.\n");
2797         printf(" . Be sure the target directory has write permission.\n");
2798 /*
2799         if the file was 2G or larger make sure other Kermit supports LFs...
2800 */
2801         printf(" . Be sure the target disk has sufficient space.\n");
2802         printf("(Use SET HINTS OFF to suppress hints.)\n");
2803         printf("*************************\n\n");
2804     }
2805     debug(F101,"topcmd","",topcmd);
2806     if (getcmd && protocol == PROTO_K &&
2807 	!success && hints && !interrupted && !fatalio && !xcmdsrc) {
2808         int x = 0;
2809         extern int urpsiz, wslotr;
2810         printf("\n*************************\n");
2811         printf("RECEIVE- or GET-class command failed.\n");
2812         printf(" Packets received: %d\n", rpackets);
2813         printf(" Damaged packets: %d\n", crunched);
2814         printf(" Timeouts: %d\n", timeouts);
2815         if (rpackets > 0)
2816           printf(" Packet length: %d\n", urpsiz);
2817         if (epktrcvd) {
2818             printf(" Transfer canceled by sender.\n");
2819             printf(" Sender's message: \"%s\"\n",(char *)epktmsg);
2820             if (ckindex("not found",(char *)epktmsg,0,0,0) ||
2821                 ckindex("no such",(char *)epktmsg,0,0,0)) {
2822                 printf(" Did you spell the filename right?\n");
2823                 printf(" Is the other Kermit CD'd to the right directory?\n");
2824             }
2825         }
2826 #ifdef UNIX
2827         if (errno != 0)
2828 #endif /* UNIX */
2829         {
2830              (VOID) ckstrncpy(tmpbuf,ck_errstr(),TMPBUFSIZ);
2831              printf(" Most recent local error: \"%s\"\n",tmpbuf);
2832         }
2833 #ifdef COMMENT
2834         printf(
2835    "\nHINTS... If the preceding error message%s not explain the failure:\n",
2836                epktrcvd ? "s do" : " does"
2837                );
2838 #ifndef NOLOCAL
2839         if (local) {
2840             if (topcmd == XXGET)
2841               printf(" . Did you start a Kermit SERVER on the far end?\n");
2842             if (rpackets == 0) {
2843                 if (topcmd != XXGET)
2844                   printf(" . Did you start a Kermit SENDer on the far end?\n");
2845             } else {
2846                 printf(
2847                 " . Choose a different FLOW-CONTROL setting and try again.\n");
2848             }
2849         } else if (topcmd == XXGET)
2850           printf(" . Is the other Kermit in (or does it have) SERVER mode?\n");
2851         if (rpackets > 0 && urpsiz > 90)
2852           printf(" . Try smaller packets (SET RECEIVE PACKET-LENGTH).\n");
2853         if (rpackets > 0 && wslotr > 1 && !streamed)
2854           printf(" . Try a smaller window size (SET WINDOW).\n");
2855         if (!local && rpackets > 0) {
2856             if (flow == FLO_NONE)
2857              printf(" . Give me a SET FLOW XON/XOFF command and try again.\n");
2858             else
2859              printf(" . Give me a SET FLOW NONE command and try again.\n");
2860         }
2861         x++;
2862 #endif /* NOLOCAL */
2863 #ifdef STREAMING
2864         if (streamed) {
2865             printf(" . Try it again with: SET STREAMING OFF\n");
2866             x++;
2867         } else if (reliable && local) {
2868             printf(" . Try it again with: SET RELIABLE OFF\n");
2869             x++;
2870         } else
2871 #endif /* STREAMING */
2872         if (!parity) {
2873             printf(" . Try it again with: SET PARITY SPACE\n");
2874             x++;
2875         }
2876         printf((x > 0) ?
2877                " . As a last resort, give a ROBUST command and try again.\n" :
2878                " . Give a ROBUST command and try again.\n"
2879                );
2880 #endif  /* COMMENT */
2881         printf("Also:\n");
2882         printf(" . Be sure the target directory has write permission.\n");
2883         printf(" . Be sure the target disk has sufficient space.\n");
2884         printf(" . Try telling the %s to SET PREFIXING ALL.\n",
2885                topcmd == XXGET ? "server" : "sender"
2886                );
2887         printf(" . Try giving a ROBUST command to the %s.\n",
2888                topcmd == XXGET ? "server" : "sender"
2889                );
2890         printf("(Use SET HINTS OFF to suppress hints.)\n");
2891         printf("*************************\n\n");
2892     }
2893 #endif /* NOHINTS */
2894     getcmd = 0;
2895     sndcmd = 0;
2896     interrupted = 0;
2897 #endif /* NOXFER */
2898 
2899     while (sstate == 0) {               /* Parse cmds until action requested */
2900         debug(F100,"parse top","",0);
2901 	what = W_COMMAND;		/* Now we're parsing commands. */
2902 	rcdactive = 0;			/* REMOTE CD not active */
2903 	keepallchars = 0;		/* MINPUT not active */
2904 
2905 #ifdef OS2
2906         if (apcactive == APC_INACTIVE)
2907           WaitCommandModeSem(-1);
2908 #endif /* OS2 */
2909 #ifdef IKS_OPTION
2910         if ((local &&
2911              !xcmdsrc &&
2912              is_tn &&
2913              TELOPT_ME(TELOPT_KERMIT) &&
2914              TELOPT_SB(TELOPT_KERMIT).kermit.me_start) ||
2915             (!local &&
2916              !cmdadl &&
2917              TELOPT_ME(TELOPT_KERMIT) &&
2918              TELOPT_SB(TELOPT_KERMIT).kermit.me_start)
2919             ) {
2920             tn_siks(KERMIT_STOP);
2921         }
2922 #endif /* IKS_OPTION */
2923 
2924 #ifndef NOXFER
2925         if (autopath) {
2926             fnrpath = PATH_AUTO;
2927             autopath = 0;
2928         }
2929         remfile = 0;                    /* Clear these in case REMOTE */
2930         remappd = 0;                    /* command was interrupted... */
2931         rempipe = 0;
2932         makestr(&snd_move,g_snd_move);  /* Restore these */
2933         makestr(&rcv_move,g_rcv_move);
2934         makestr(&snd_rename,g_snd_rename);
2935         makestr(&rcv_rename,g_rcv_rename);
2936 #endif /* NOXFER */
2937 
2938     /* Take requested action if there was an error in the previous command */
2939 
2940         setint();
2941         debug(F101,"parser tlevel","",tlevel);
2942         debug(F101,"parser cmd_rows","",cmd_rows);
2943 
2944 #ifndef NOLOCAL
2945         debug(F101,"parser wasclosed","",wasclosed);
2946         if (wasclosed) {                /* If connection was just closed */
2947 #ifndef NOSPL
2948             int k;
2949             k = mlook(mactab,"on_close",nmac); /* Look up "on_close" */
2950             if (k >= 0) {               /* If found, */
2951                 /* printf("ON_CLOSE CMD LOOP\n"); */
2952                 dodo(k,ckitoa(whyclosed),0); /* Set it up */
2953             }
2954 #endif /* NOSPL */
2955             whyclosed = WC_REMO;
2956             wasclosed = 0;
2957         }
2958 #endif /* NOLOCAL */
2959 
2960 #ifndef NOSPL
2961         xxdot = 0;                      /* Clear this... */
2962 
2963         debug(F101,"parser success","",success);
2964         if (success == 0) {
2965             if (cmdstk[cmdlvl].src == CMD_TF && takerr[cmdlvl]) {
2966                 printf("Command file terminated by error.\n");
2967                 popclvl();
2968                 if (cmdlvl == 0) return(0);
2969             }
2970             if (cmdstk[cmdlvl].src == CMD_MD && merror[cmdlvl]) {
2971                 printf("Command error: macro terminated.\n");
2972                 popclvl();
2973                 if (m && (cmdlvl < inlevel))
2974                   return((int) sstate);
2975             }
2976         }
2977         nulcmd = (m == 2);
2978         debug(F101,"parser nulcmd","",nulcmd);
2979 #else
2980         if (success == 0 && tlevel > -1 && takerr[tlevel]) {
2981             printf("Command file terminated by error.\n");
2982             popclvl();
2983             cmini(ckxech);              /* Clear the cmd buffer. */
2984             if (tlevel < 0)             /* Just popped out of cmd files? */
2985               return(0);                /* End of init file or whatever. */
2986         }
2987 #endif /* NOSPL */
2988 
2989 #ifdef MAC
2990         /* Check for TAKE initiated by menu. */
2991         if ((tlevel == -1) && lfiles)
2992             startlfile();
2993 #endif /* MAC */
2994 
2995         /* If in TAKE file, check for EOF */
2996 #ifndef NOSPL
2997 #ifdef MAC
2998         if
2999 #else
3000         while
3001 #endif /* MAC */
3002           ((cmdstk[cmdlvl].src == CMD_TF)  /* If end of take file */
3003                && (tlevel > -1)
3004                && feof(tfile[tlevel])) {
3005             popclvl();                  /* pop command level */
3006             cmini(ckxech);              /* and clear the cmd buffer. */
3007             if (cmdlvl == 0) {          /* Just popped out of all cmd files? */
3008                 return(0);              /* End of init file or whatever. */
3009             }
3010         }
3011 #ifdef MAC
3012         miniparser(1);
3013         if (sstate == 'a') {            /* if cmd-. cancel */
3014             debug(F100, "parser: cancel take due to sstate", "", sstate);
3015             sstate = '\0';
3016             dostop();
3017             return(0);                  /* End of init file or whatever. */
3018         }
3019 #endif /*  MAC */
3020 
3021 #else /* NOSPL */
3022         if ((tlevel > -1) && feof(tfile[tlevel])) { /* If end of take */
3023             popclvl();                  /* Pop up one level. */
3024             cmini(ckxech);              /* and clear the cmd buffer. */
3025             if (tlevel < 0)             /* Just popped out of cmd files? */
3026               return(0);                /* End of init file or whatever. */
3027         }
3028 #endif /* NOSPL */
3029 
3030 
3031 #ifndef NOSPL
3032         debug(F101,"parser cmdlvl","",cmdlvl);
3033         debug(F101,"parser cmdsrc","",cmdstk[cmdlvl].src);
3034 
3035         if (cmdstk[cmdlvl].src == CMD_MD) { /* Executing a macro? */
3036             debug(F100,"parser macro","",0);
3037             maclvl = cmdstk[cmdlvl].lvl; /* Get current level */
3038             debug(F101,"parser maclvl","",maclvl);
3039             cbp = cmdbuf;               /* Copy next cmd to command buffer. */
3040             *cbp = NUL;
3041             if (*savbuf) {              /* In case then-part of 'if' command */
3042                 ckstrncpy(cbp,savbuf,CMDBL); /* was saved, restore it. */
3043                 *savbuf = '\0';
3044             } else {                    /* Else get next cmd from macro def */
3045                 if (getncm(cbp,CMDBL) < 0) {
3046 #ifdef DEBUG
3047                     if (deblog) {
3048                         debug(F101,"parser end of macro m","",m);
3049                         debug(F101,"parser end of macro cmdlvl","",cmdlvl);
3050                         debug(F101,"parser end of macro inlevel","",inlevel);
3051                     }
3052 #endif /* DEBUG */
3053                     if (m && (cmdlvl < inlevel))
3054                       return((int) sstate);
3055                     else /* if (!m) */ continue;
3056                 }
3057             }
3058             debug(F010,"CMD(M)",cmdbuf,0);
3059 
3060         } else if (cmdstk[cmdlvl].src == CMD_TF)
3061 #else
3062           if (tlevel > -1)
3063 #endif /* NOSPL */
3064           {
3065 #ifndef NOSPL
3066             debug(F111,"parser savbuf",savbuf,tlevel);
3067             if (*savbuf) {              /* In case THEN-part of IF command */
3068                 ckstrncpy(cmdbuf,savbuf,CMDBL); /* was saved, restore it. */
3069                 *savbuf = '\0';
3070             } else
3071 #endif /* NOSPL */
3072 
3073               /* Get next line from TAKE file */
3074 
3075               if ((tfcode = getnct(cmdbuf,CMDBL,tfile[tlevel],0)) < 0) {
3076                   debug(F111,"parser tfcode",tfile[tlevel],tfcode);
3077                   if (tfcode < -1) {    /* Error */
3078                       printf("?Error in TAKE command file: %s\n",
3079                              (tfcode == -2) ? "Memory allocation failure" :
3080                              "Line too long or contains NUL characters"
3081                              );
3082                       dostop();
3083                   }
3084                   continue;             /* -1 means EOF */
3085               }
3086 
3087         /* If interactive, get next command from user. */
3088 
3089         } else {                        /* User types it in. */
3090             if (pflag) prompt(xxstring);
3091             cmini(ckxech);
3092         }
3093 
3094     /* Now we know where next command is coming from. Parse and execute it. */
3095 
3096         repars = 1;                     /* 1 = command needs parsing */
3097 #ifndef NOXFER
3098         displa = 0;                     /* Assume no file transfer display */
3099 #endif /* NOXFER */
3100 
3101         while (repars) {                /* Parse this cmd until entered. */
3102 
3103             debug(F101,"parser top of while loop","",0);
3104 	    xaskmore = saveask;		/* Restore global more-prompting */
3105 	    diractive = 0;		/* DIR command not active */
3106 	    cdactive = 0;		/* CD command not active */
3107 #ifndef NOSPL
3108 	    askflag = 0;		/* ASK command not active */
3109 	    echostars = 0;		/* Nor ASKQ */
3110 	    debok = 1;			/* Undisable debugging */
3111 #endif /* NOSPL */
3112 
3113 #ifdef RECURSIVE
3114             /* In case of "send /recursive ./?<Ctrl-U>" etc */
3115             recursive = 0;              /* This is never sticky */
3116 #endif /* RECURSIVE */
3117             xfiletype = -1;             /* Reset this between each command */
3118 #ifndef NOMSEND
3119             addlist = 0;
3120 #endif /* NOMSEND */
3121 #ifdef CK_RECALL
3122             on_recall = 1;
3123 #endif /* CK_RECALL */
3124             /* This might have been changed by a switch */
3125             if (g_matchdot > -1) {
3126                 matchdot = g_matchdot;
3127                 g_matchdot = -1;
3128             }
3129             cmres();                    /* Reset buffer pointers. */
3130 
3131 #ifdef OS2
3132 #ifdef COMMENT
3133             /* we check to see if a macro is waiting to be executed */
3134             /* if so, we call domac on it */
3135             if (cmdmac) {
3136                 ckstrncpy(cmdbuf, cmdmac, CMDBL);
3137                 free(cmdmac);
3138                 cmdmac = NULL;
3139             }
3140 #endif /* COMMENT */
3141 #endif /* OS2 */
3142 #ifndef NOXFER
3143             bye_active = 0;
3144 #endif /* NOXFER */
3145             havetoken = 0;
3146             xx = cmkey2(cmdtab,ncmd,"Command","",toktab,xxstring,1);
3147             debug(F101,"top-level cmkey2","",xx);
3148             if (xx == -5) {
3149                 yy = chktok(toktab);
3150                 debug(F101,"top-level cmkey token","",yy);
3151 #ifndef COMMENT
3152                 /* Either way makes absolutely no difference */
3153                 debug(F110,"NO UNGWORD",atmbuf,0);
3154                 /* ungword(); */
3155 #else
3156                 debug(F110,"TOKEN UNGWORD",atmbuf,0);
3157                 ungword();
3158 #endif /* COMMENT */
3159                 switch (yy) {
3160                   case '#': xx = XXCOM; break; /* Comment */
3161                   case ';': xx = XXCOM; break; /* Comment */
3162 #ifndef NOSPL
3163                   case '.': xx = XXDEF; xxdot = 1; break; /* Assignment */
3164                   case ':': xx = XXLBL; break; /* GOTO label */
3165 #endif /* NOSPL */
3166 
3167 #ifndef NOPUSH
3168 #ifdef CK_REDIR
3169                   case '<':
3170 #endif /* CK_REDIR */
3171                   case '@':
3172                   case '!':
3173                     if (nopush) {
3174                         char *s; int x;
3175                         if ((x = cmtxt("Text to be ignored","",&s,NULL)) < 0)
3176                           return(x);
3177                         success = 0;
3178                         xx = XXCOM;
3179                     } else {
3180                         switch(yy) {
3181 #ifdef CK_REDIR
3182                           case '<': xx = XXFUN; break; /* REDIRECT */
3183 #endif /* CK_REDIR */
3184                           case '@':
3185                           case '!': xx = XXSHE; break; /* Shell escape */
3186                         }
3187                     }
3188                     break;
3189 #endif /* NOPUSH */
3190 #ifdef CK_RECALL
3191                   case '^': xx = XXREDO;  break;
3192 #endif /* CK_RECALL */
3193 #ifndef NOSPL
3194                   case '{': xx = XXMACRO; break;
3195                   case '(': xx = XXSEXP;  break;
3196 #endif /* NOSPL */
3197 
3198                   default:
3199                     if (!quiet && !cmd_err) {
3200                         printf("\n?Not a valid command or token - \"%s\"\n",
3201 			       cmddisplay((char *)cmdbuf,xx)
3202 			       );
3203 			/* cmderr(); */ newerrmsg("");
3204                     }
3205                     xx = -2;
3206                 }
3207                 havetoken = 1;
3208                 debug(F101,"HAVE TOKEN","",xx);
3209             }
3210             if (xx > -1) {
3211                 topcmd = xx;            /* Top-level command index */
3212 #ifndef NOSPL
3213                 if (maclvl > -1)
3214                   lastcmd[maclvl] = xx;
3215 #endif /* NOSPL */
3216                 debug(F101,"topcmd","",topcmd);
3217                 debug(F101,"cmflgs","",cmflgs);
3218             }
3219 
3220 #ifndef NOSPL
3221             /* Special handling for IF..ELSE */
3222 
3223             debug(F101,"cmdlvl","",cmdlvl);
3224             debug(F101,"ifcmd[cmdlvl]","",ifcmd[cmdlvl]);
3225 
3226             if (ifcmd[cmdlvl])          /* Count stmts after IF */
3227               ifcmd[cmdlvl]++;
3228             if (ifcmd[cmdlvl] > 2 && xx != XXELS && xx != XXCOM)
3229               ifcmd[cmdlvl] = 0;
3230 
3231             /* Execute the command and take action based on return code. */
3232 
3233             if (nulcmd) {               /* Ignoring this command? */
3234                 xx = XXCOM;             /* Make this command a comment. */
3235             }
3236             fnsuccess = 1;              /* For catching \function() errors */
3237 #endif /* NOSPL */
3238 
3239             debug(F101,"calling docmd()","",xx);
3240             zz = docmd(xx);             /* Parse rest of command & execute. */
3241 
3242 #ifndef NOSPL
3243 	    {				/* For \v(lastcommand) */
3244 		extern char * prevcmd;
3245 		/* The exception list kind of a hack but let's try it... */
3246 		if (ckstrcmp(cmdbuf,"_getarg",7,0) &&
3247 		    ckstrcmp(cmdbuf,"if ",3,0) &&
3248 		    ckstrcmp(cmdbuf,"xif ",4,0) &&
3249 		    ckstrcmp(cmdbuf,"do _if",6,0) &&
3250 		    ckstrcmp(cmdbuf,"_assign _if",11,0))
3251 		  ckstrncpy(prevcmd,cmdbuf,CMDBL);
3252 	    }
3253 #endif	/* NOSPL */
3254 
3255 #ifndef NOSPL
3256             if (fnerror && !fnsuccess)
3257               success = 0;
3258 #endif /* NOSPL */
3259             debug(F101,"docmd returns","",zz);
3260             /* debug(F011,"cmdbuf",cmdbuf,30); */
3261             /* debug(F011,"atmbuf",atmbuf,30); */
3262 #ifdef MAC
3263             if (tlevel > -1) {
3264                 if (sstate == 'a') {    /* if cmd-. cancel */
3265                     debug(F110, "parser: cancel take, sstate:", "a", 0);
3266                     sstate = '\0';
3267                     dostop();
3268                     return(0);          /* End of init file or whatever. */
3269                 }
3270             }
3271 #endif /* MAC */
3272 
3273             switch (zz) {
3274               case -4:                  /* EOF (e.g. on redirected stdin) */
3275                 doexit(GOOD_EXIT,xitsta); /* ...exit successfully */
3276               case -1:                  /* Reparse needed */
3277                 repars = 1;             /* Just set reparse flag and... */
3278                 continue;
3279 #ifdef OS2
3280               case -7:                  /* They typed a disk letter */
3281                 if (!zchdir((char *)cmdbuf)) {
3282                     perror((char *)cmdbuf);
3283                     success = 0;
3284                 } else success = 1;
3285                 repars = 0;
3286                 continue;
3287 
3288 #endif /* OS2 */
3289 /*
3290   Changed 2013-12-06 fdc: Previously the failing command was echoed only in
3291   the -6 and -9 cases.  This made it difficult to know exactly which command
3292   had failed when a macro or command file was being executed and the failing
3293   command had already issued its own error message and returned -9.  Now we
3294   include -9 in the caselist for this code, but we echo the failing command
3295   only if Kermit is not at top level.  So now, even though the error message
3296   is imprecise about *where* the failing command was, at least it shows the
3297   failing command.
3298 */
3299 	      case -9:			/* Bad, error message already done */
3300               case -6:                  /* Invalid command given w/no args */
3301               case -2:			/* Invalid command given w/args */
3302 		if (zz == -2 || zz == -6 || (zz == -9 && cmdlvl > 0)) {
3303 		    int x = 0;
3304 		    char * eol = "";
3305 		    x = strlen(cmdbuf);	/* Avoid blank line */
3306 #ifdef COMMENT
3307 		    if (x > 0) {
3308 			if (cmdbuf[x-1] != LF)
3309 			  eol = "\n";
3310 			printf("?Invalid: %s%s",
3311 			       cmddisplay(cmdbuf,xx),eol
3312 			       );
3313 		    } else
3314 		      printf("?Invalid\n");
3315 #else
3316                     if (x > 0)
3317                       newerrmsg("Syntax error");
3318 #endif  /* COMMENT */
3319 		}
3320 		success = 0;
3321 		debug(F110,"top-level cmkey failed",cmdbuf,0);
3322 		/* If in background w/ commands coming stdin, terminate */
3323 		if (pflag == 0 && tlevel < 0)
3324 		  fatal("Kermit command error in background execution");
3325 /*
3326   Command retry feature, edit 190.  If we're at interactive prompting level,
3327   reprompt the user with as much of the command as didn't fail.
3328 */
3329 #ifdef CK_RECALL
3330 		if (cm_retry && !xcmdsrc) { /* If at top level */
3331 		    int len;
3332 		    char *p, *s;
3333 		    len = strlen(cmdbuf); /* Length of command buffer */
3334 		    p = malloc(len + 1);  /* Allocate space for copy */
3335 		    if (p) {              /* If we got the space copy */
3336 			strcpy(p,cmdbuf); /* the command buffer (SAFE). */
3337 			/* Chop off final field, the one that failed. */
3338 			s = p + len - 1;          /* Point to end */
3339 			while (*s == SP && s > p) /* Trim blanks */
3340 			  s--;
3341 			while (*s != SP && s > p) /* Trim last field */
3342 			  s--;
3343 			if (s > p)        /* Keep the space */
3344 			  s++;            /* after last good field */
3345 			if (s >= p)       /* Cut off remainder */
3346 			  *s = NUL;
3347 			cmini(ckxech);    /* Reinitialize the parser */
3348 			ckstrncpy(cmdbuf,p,CMDBL); /* Copy result back */
3349 			free(p);          /* Free temporary storage */
3350 			p = NULL;
3351 			prompt(xxstring); /* Reprint the prompt */
3352 			printf("%s",cmdbuf); /* Reprint partial command */
3353 			repars = 1;          /* Force reparse */
3354 			continue;
3355 		    }
3356 		} else
3357 #endif /* CK_RECALL */
3358                   /* cmderr(); */ newerrmsg("");
3359 
3360 		cmini(ckxech);		/* (fall thru) */
3361 
3362 	      case -3:			/* Empty command OK at top level */
3363 		repars = 0;		/* Don't need to reparse. */
3364 		continue;		/* Go back and get another command. */
3365 
3366 	      default:			/* Command was successful. */
3367 #ifndef NOSPL
3368 		debug(F101,"parser preparing to continue","",maclvl);
3369 #endif /* NOSPL */
3370 		debug(F101,"parser success","",success);
3371 		repars = 0;		/* Don't need to reparse. */
3372 		continue;		/* Go back and get another command. */
3373 	    }
3374         }
3375 #ifndef NOSPL
3376         debug(F101,"parser breaks out of while loop","",maclvl);
3377         if (m && (cmdlvl < inlevel))  return((int) sstate);
3378 #endif /* NOSPL */
3379     }
3380 
3381 /* Got an action command, return start state. */
3382 
3383     return((int) sstate);
3384 }
3385 
3386 #ifndef NOSPL
3387 /*
3388   OUTPUT command.
3389   Buffering and pacing added by L.I. Kirby, 5A(189), June 1993.
3390 */
3391 #define OBSIZE 80                       /* Size of local character buffer */
3392 
3393 static int obn;                         /* Buffer offset (high water mark) */
3394 static char obuf[OBSIZE+1];             /* OUTPUT buffer. */
3395 static char *obp;                       /* Pointer to output buffer. */
3396 _PROTOTYP( static int oboc, (char) );
3397 _PROTOTYP( static int xxout, (char *, int) );
3398 
3399 static int
3400 #ifdef CK_ANSIC
xxout(char * obuf,int obsize)3401 xxout(char *obuf, int obsize)
3402 #else
3403 xxout(obuf, obsize) char *obuf; int obsize;
3404 #endif /* CK_ANSIC */
3405 /* xxout */ {                           /* OUTPUT command's output function */
3406     int i, rc;
3407 
3408     debug(F101,"xxout obsize","",obsize);
3409     debug(F101,"xxout pacing","",pacing);
3410     debug(F111,"xxout string",obuf,strlen(obuf));
3411 
3412     rc = 0;                             /* Initial return code. */
3413     if (!obuf || (obsize <= 0))         /* Nothing to output. */
3414       goto xxout_x;                     /* Return successfully */
3415 
3416     rc = -1;                              /* Now assume failure */
3417     if (pacing == 0) {                    /* Is pacing enabled? */
3418         if ((local ?                      /* No, write entire string at once */
3419              ttol((CHAR *)obuf, obsize) : /* to communications device */
3420              conxo(obsize, obuf))         /* or to console */
3421             != obsize)
3422           goto xxout_x;
3423     } else {
3424         for (i = 0; i < obsize; i++) {  /* Write individual chars */
3425             if ((local ? ttoc(obuf[i]) : conoc(obuf[i])) < 0)
3426               goto xxout_x;
3427             msleep(pacing);
3428         }
3429     }
3430     if (duplex) {
3431 #ifdef OS2
3432         if (inecho && local) {
3433 #ifndef NOLOCAL
3434             for (i = 0; i < obsize; i++) { /* Write to emulator */
3435                 scriptwrtbuf((USHORT)obuf[i]); /* which also logs session */
3436             }
3437 #endif /* NOLOCAL */
3438             conxo(obsize,obuf);
3439         } else if (seslog) {            /* or log session here */
3440             logstr((char *) obuf, obsize);
3441         }
3442 #else /* OS2 */
3443         if (seslog) {
3444             logstr((char *) obuf, obsize);
3445         }
3446         if (inecho && local) {
3447             conxo(obsize,obuf);
3448         }
3449 #endif /* OS2 */
3450     }
3451     rc = 0;                             /* Success */
3452   xxout_x:
3453     obn = 0;                            /* Reset count */
3454     obp = obuf;                         /* and pointers */
3455     return(rc);                         /* return our return code */
3456 }
3457 
3458 #ifdef COMMENT
3459 /*
3460   Macros for OUTPUT command execution, to make it go faster.
3461 */
3462 #define obfls() ((xxout(obuf,obn)<0)?-1:0)
3463 #define oboc(c) ((*obp++=(char)(c)),*obp=0,(((++obn)>=OBSIZE)?obfls():0))
3464 
3465 #else /* The macros cause some compilers to generate bad code. */
3466 
3467 static int
3468 #ifdef CK_ANSIC
oboc(char c)3469 oboc(char c)
3470 #else
3471 oboc(c) char c;
3472 #endif /* CK_ANSIC */
3473 /* oboc */ {                            /* OUTPUT command's output function */
3474 
3475     *obp++ = c;                         /* Deposit character */
3476     *obp = NUL;                         /* Flush buffer if it's now full */
3477 
3478     return(((++obn) >= OBSIZE) ? xxout(obuf,obn) : 0);
3479 }
3480 #endif /* COMMENT */
3481 
3482 /*  Routines for handling local variables -- also see popclvl().  */
3483 
3484 VOID
freelocal(m)3485 freelocal(m) int m; {                   /* Free local variables */
3486     struct localvar * v, * tv;          /* at macro level m... */
3487     debug(F101,"freelocal level","",m);
3488     if (m < 0) return;
3489     v = localhead[m];                   /* List head for level m */
3490     while (v) {
3491         if (v->lv_name)                 /* Variable name */
3492           free(v->lv_name);
3493         if (v->lv_value)                /* Value */
3494           free(v->lv_value);
3495         tv = v;                         /* Save pointer to this node */
3496         v = v->lv_next;                 /* Get next one */
3497         if (tv)                         /* Free this one */
3498           free((char *)tv);
3499     }
3500     localhead[m] = (struct localvar *) NULL; /* Done, set list head to NULL */
3501 }
3502 
3503 #define MAXLOCALVAR 64
3504 
3505 /* Return a pointer to the definition of a user-defined variable */
3506 
3507 static char *
vardef(s,isarray,x1,x2)3508 vardef(s,isarray,x1,x2) char * s; int * isarray, * x1, * x2; {
3509     char * p;
3510     char c;
3511     *isarray = 0;
3512     if (!s) return(NULL);
3513     if (!*s) return(NULL);
3514     p = s;
3515     if (*s == CMDQ) {
3516         p++;
3517         if (!*p)
3518           return(NULL);
3519         if ((c = *p) == '%') {          /* Scalar variable. */
3520             c = *++p;                   /* Get ID character. */
3521             p = "";                     /* Assume definition is empty */
3522             if (!c)
3523               return(NULL);
3524             if (c >= '0' && c <= '9') { /* Digit for macro arg */
3525                 if (maclvl < 0)         /* Digit variables are global */
3526                   return(g_var[c]);     /* if no macro is active */
3527                 else                    /* otherwise */
3528                   return(m_arg[maclvl][c - '0']); /* they're on the stack */
3529             } else if (isalpha(c)) {
3530                 if (isupper(c)) c -= ('a'-'A');
3531                 return(g_var[c]);           /* Letter for global variable */
3532             } else
3533               return(NULL);
3534         } else if (c == '&') {          /* Array reference. */
3535             int x, vbi, d;
3536             x = arraynam(p,&vbi,&d);    /* Get name and subscript */
3537             if (x > -1 || d == -17) {
3538                 *isarray = 1;
3539                 *x1 = vbi;
3540                 *x2 = (d == -17) ? 0 : d;
3541             }
3542             if (x < 0)
3543               return(NULL);
3544             if (chkarray(vbi,d) >= 0) {	/* Array is declared? */
3545                 vbi -= ARRAYBASE;       /* Convert name to index */
3546                 if (a_dim[vbi] >= d) {  /* If subscript in range */
3547                     char **ap;
3548                     ap = a_ptr[vbi];
3549                     return((ap) ? ap[d] : NULL);
3550                 }
3551             }
3552         }
3553         return(NULL);
3554     } else {
3555         int k;
3556         k = mxlook(mactab,s,nmac);
3557         return((k > -1) ? mactab[k].mval : NULL);
3558     }
3559 }
3560 
3561 
3562 int
addlocal(p)3563 addlocal(p) char * p; {
3564     int x, z, isarray = 0;
3565     char * s;
3566     struct localvar * v, *prev = (struct localvar *)NULL;
3567     extern int tra_asg; int tra_tmp;
3568 
3569     tra_tmp = tra_asg;
3570 
3571     s = vardef(p,&isarray,&x,&z);       /* Get definition of variable */
3572     if (isarray) {                      /* Arrays are handled specially */
3573         pusharray(x,z);
3574         return(0);
3575     }
3576     if (!s) s = "";
3577     if ((v = localhead[cmdlvl])) {      /* Already have some at this level? */
3578         while (v) {                     /* Find end of list */
3579             prev = v;
3580             v = v->lv_next;
3581         }
3582     }
3583     v = (struct localvar *) malloc(sizeof(struct localvar));
3584     if (!v) {
3585         printf("?Failure to allocate storage for local variables");
3586         return(-9);
3587     }
3588     if (!localhead[cmdlvl])             /* If first, set list head */
3589       localhead[cmdlvl] = v;
3590     else                                /* Otherwise link previous to this */
3591       prev->lv_next = v;
3592     prev = v;                           /* And make this previous */
3593     v->lv_next = (struct localvar *) NULL; /* No next yet */
3594 
3595     if (!(v->lv_name = (char *) malloc((int) strlen(p) + 1)))
3596       return(-1);
3597     strcpy(v->lv_name, p);              /* Copy name into new node (SAFE) */
3598 
3599     if (*s) {
3600         if (!(v->lv_value = (char *) malloc((int) strlen(s) + 1)))
3601           return(-1);
3602         strcpy(v->lv_value, s);         /* Copy value into new node (SAFE) */
3603     } else
3604       v->lv_value = NULL;
3605 
3606     tra_asg = 0;
3607     delmac(p,1);                        /* Delete the original macro */
3608     tra_asg = tra_tmp;
3609     return(0);
3610 }
3611 
3612 int
dolocal()3613 dolocal() {                             /* Do the LOCAL command */
3614     int i, x;
3615     char * s;
3616     char * list[MAXLOCALVAR+2];         /* Up to 64 variables per line */
3617 
3618     if ((x = cmtxt("Variable name(s)","",&s,NULL)) < 0)
3619       return(x);
3620 
3621     xwords(s,MAXLOCALVAR,list,0);       /* Break up line into "words" */
3622 
3623     /* Note: Arrays do not use the localhead list, but have their own stack */
3624 
3625     for (i = 1; i < MAXLOCALVAR && list[i]; i++) { /* Go through the list */
3626         if (addlocal(list[i]) < 0)
3627           goto localbad;
3628     }
3629     return(success = 1);
3630 
3631   localbad:
3632     printf("?Failure to allocate storage for local variables");
3633     freelocal(cmdlvl);
3634     return(-9);
3635 }
3636 
3637 /*  D O O U T P U T  --  Returns 0 on failure, 1 on success */
3638 
3639 #ifndef NOKVERBS
3640 #define K_BUFLEN 30
3641 #define SEND_BUFLEN 255
3642 #define sendbufd(x) { osendbuf[sendndx++] = x;\
3643  if (sendndx == SEND_BUFLEN) {dooutput(s,cx); sendndx = 0;}}
3644 #endif /* NOKVERBS */
3645 
3646 int outesc = 1;                         /* Process special OUTPUT escapes */
3647 
3648 int
dooutput(s,cx)3649 dooutput(s, cx) char *s; int cx; {
3650 #ifdef SSHBUILTIN
3651     extern int ssh_cas;
3652     extern char * ssh_cmd;
3653 #endif /* SSHBUILTIN */
3654     int x, xx, y, quote;                /* Workers */
3655     int is_tn = 0;
3656 
3657     is_tn = (local && network && IS_TELNET()) ||
3658       (!local && sstelnet);
3659 
3660     debug(F111,"dooutput s",s,(int)strlen(s));
3661 
3662     if (local) {                        /* Condition external line */
3663 #ifdef NOLOCAL
3664         goto outerr;
3665 #else
3666 	if (ttchk() < 0) {
3667 	    if (!network) {
3668 		if (carrier != CAR_OFF) {
3669 		    int x;
3670 		    x = ttgmdm();
3671 		    if ((x > -1) && ((x & BM_DCD) == 0)) {
3672 			printf(
3673 "?Carrier signal required but not present - Try SET CARRIER-WATCH OFF.\n"
3674                               );
3675 			return(0);
3676 		    }
3677 		} else {
3678 		    printf(
3679 "?Problem with serial port or modem or cable - Try SHOW COMMUNICATIONS.\n"
3680                           );
3681 		    return(0);
3682 		}
3683 	    }
3684 	    printf("?Connection %s %s is not open or not functioning.\n",
3685 		   network ? "to" : "on",
3686 		   ttname
3687 		   );
3688 	    return(0);
3689 	}
3690         if (ttvt(speed,flow) < 0) {
3691             printf("?OUTPUT initialization error\n");
3692             return(0);
3693         }
3694 #endif /* NOLOCAL */
3695     }
3696 #ifdef SSHBUILTIN
3697     if ( network && nettype == NET_SSH && ssh_cas && ssh_cmd &&
3698          !(strcmp(ssh_cmd,"kermit") && strcmp(ssh_cmd,"sftp"))) {
3699         if (!quiet)
3700             printf("?SSH Subsystem active: %s\n", ssh_cmd);
3701         return(0);
3702     }
3703 #endif /* SSHBUILTIN */
3704 
3705     if (!cmdgquo()) {                   /* COMMAND QUOTING OFF */
3706         x = strlen(s);                  /* Just send the string literally */
3707         xx = local ? ttol((CHAR *)s,x) : conxo(x,s);
3708         return(success = (xx == x) ? 1 : 0);
3709     }
3710     quote = 0;                          /* Initialize backslash (\) quote */
3711     obn = 0;                            /* Reset count */
3712     obp = obuf;                         /* and pointers */
3713 
3714   outagain:
3715     while ((x = *s++)) {                /* Loop through the string */
3716         y = 0;                          /* Error code, 0 = no error. */
3717         debug(F000,"dooutput","",x);
3718         if (quote) {                    /* This character is quoted */
3719 #ifndef NOKVERBS
3720            if (x == 'k' || x == 'K') {  /* \k or \K */
3721                extern struct keytab kverbs[];
3722                extern int nkverbs;
3723                extern char * keydefptr;
3724                extern int keymac;
3725                extern int keymacx;
3726                int x, y, brace = 0;
3727                int pause;
3728                char * p, * b;
3729                char kbuf[K_BUFLEN + 1]; /* Key verb name buffer */
3730                char osendbuf[SEND_BUFLEN +1];
3731                int  sendndx = 0;
3732 
3733                if (xxout(obuf,obn) < 0) /* Flush buffer */
3734                  goto outerr;
3735                debug(F100,"OUTPUT KVERB","",0); /* Send a KVERB */
3736                {                        /* Have K verb? */
3737                    if (!*s) {
3738                        break;
3739                    }
3740 /*
3741   We assume that the verb name is {braced}, or it extends to the end of the
3742   string, s, or it ends with a space, control character, or backslash.
3743 */
3744                    p = kbuf;            /* Copy verb name into local buffer */
3745                    x = 0;
3746                    while ((x++ < K_BUFLEN) && (*s > SP) && (*s != CMDQ)) {
3747                        if (brace && *s == '}') {
3748                            break;
3749                        }
3750                        *p++ = *s++;
3751                    }
3752                    if (*s && !brace)    /* If we broke because of \, etc, */
3753                      s--;               /*  back up so we get another look. */
3754                    brace = 0;
3755                    *p = NUL;            /* Terminate. */
3756                    p = kbuf;            /* Point back to beginning */
3757                    debug(F110,"dooutput kverb",p,0);
3758                    y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
3759                    debug(F101,"dooutput lookup",0,y);
3760                    if (y > -1) {
3761                        if (sendndx) {
3762                            dooutput(osendbuf,cx);
3763                            sendndx = 0;
3764                        }
3765                        dokverb(VCMD,y);
3766 #ifndef NOSPL
3767                    } else {             /* Is it a macro? */
3768                        y = mxlook(mactab,p,nmac);
3769                        if (y > -1) {
3770                            cmpush();
3771                            keymac = 1;  /* Flag for key macro active */
3772                            keymacx = y; /* Key macro index */
3773                            keydefptr = s; /* Where to resume next time */
3774                            debug(F111,"dooutput mxlook",keydefptr,y);
3775                            parser(1);
3776                            cmpop();
3777                        }
3778 #endif /* NOSPL */
3779                    }
3780                }
3781                quote = 0;
3782                continue;
3783            } else
3784 #endif /* NOKVERBS */
3785              if (outesc && (x == 'n' || x == 'N')) { /* \n or \N */
3786                  if (xxout(obuf,obn) < 0) /* Flush buffer */
3787                    goto outerr;
3788                  debug(F100,"OUTPUT NUL","",0); /* Send a NUL */
3789                  if (local)
3790                    ttoc(NUL);
3791                  else
3792                    conoc(NUL);
3793                  quote = 0;
3794                  continue;
3795 
3796              } else if (outesc && (x == 'b' || x == 'B')) { /* \b or \B */
3797 
3798                 if (xxout(obuf,obn) < 0) /* Flush buffer first */
3799                   goto outerr;
3800                 debug(F100,"OUTPUT BREAK","",0);
3801 #ifndef NOLOCAL
3802                 ttsndb();               /* Send BREAK signal */
3803 #else
3804                  if (local)
3805                    ttoc(NUL);
3806                  else
3807                    conoc(NUL);
3808 #endif /* NOLOCAL */
3809                 quote = 0;              /* Turn off quote flag */
3810                 continue;               /* and not the b or B */
3811 #ifdef CK_LBRK
3812              } else if (outesc && (x == 'l' || x == 'L')) { /* \l or \L */
3813                  if (xxout(obuf,obn) < 0) /* Flush buffer first */
3814                    goto outerr;
3815                  debug(F100,"OUTPUT Long BREAK","",0);
3816 #ifndef NOLOCAL
3817                  ttsndlb();             /* Send Long BREAK signal */
3818 #else
3819                  if (local)
3820                    ttoc(NUL);
3821                  else
3822                    conoc(NUL);
3823 #endif /* NOLOCAL */
3824                  quote = 0;             /* Turn off quote flag */
3825                  continue;              /* and not the l or L */
3826 #endif /* CK_LBRK */
3827 
3828              } else if (x == CMDQ) {    /* Backslash itself */
3829                  debug(F100,"OUTPUT CMDQ","",0);
3830                  xx = oboc(dopar(CMDQ)); /* Output the backslash. */
3831                  if (xx < 0)
3832                    goto outerr;
3833                  quote = 0;
3834                  continue;
3835 
3836              } else {                   /* if \ not followed by special esc */
3837                 /* Note: Atari ST compiler won't allow macro call in "if ()" */
3838                  xx = oboc(dopar(CMDQ)); /* Output the backslash. */
3839                  if (xx < 0)
3840                    goto outerr;
3841                  quote = 0;             /* Turn off quote flag */
3842              }
3843         } else if (x == CMDQ) {         /* This is the quote character */
3844             quote = 1;                  /* Go back and get next character */
3845             continue;                   /* which is quoted */
3846         }
3847         xx = oboc(dopar((char)x));      /* Output this character */
3848         debug(F111,"dooutput",obuf,obn);
3849         if (xx < 0)
3850           goto outerr;
3851 #ifdef COMMENT
3852         if (seslog && duplex) {         /* Log the character if log is on */
3853             logchar((char)x);
3854         }
3855 #endif /* COMMENT */
3856         if (x == '\015') {              /* String contains carriage return */
3857             int stuff = -1, stuff2 = -1;
3858             if (tnlm) {                 /* TERMINAL NEWLINE ON */
3859                 stuff = LF;             /* Stuff LF */
3860             }
3861 #ifdef TNCODE
3862             /* TELNET NEWLINE ON/OFF/RAW */
3863             if (is_tn) {
3864                 switch (TELOPT_ME(TELOPT_BINARY) ? /* NVT or BINARY */
3865                         tn_b_nlm :
3866                         tn_nlm
3867                         ) {
3868                   case TNL_CR:
3869                     break;
3870                   case TNL_CRNUL:
3871                     stuff2 = stuff;
3872                     stuff  = NUL;
3873                     break;
3874                   case TNL_CRLF:
3875                     stuff2 = stuff;
3876                     stuff = LF;
3877                     break;
3878                 }
3879             }
3880 #endif /* TNCODE */
3881             if (stuff > -1) {           /* Stuffing another character... */
3882                 xx = oboc(dopar((CHAR)stuff));
3883                 if (xx < 0)
3884                   goto outerr;
3885 #ifdef COMMENT
3886                 if (seslog && duplex) { /* Log stuffed char if appropriate */
3887                     logchar((char)stuff);
3888                 }
3889 #endif /* COMMENT */
3890             }
3891             if (stuff2 > -1) {          /* Stuffing another character... */
3892                 xx = oboc(dopar((CHAR)stuff2));
3893                 if (xx < 0)
3894                   goto outerr;
3895 #ifdef COMMENT
3896                 if (seslog && duplex) { /* Log stuffed char if appropriate */
3897                     logchar((char)stuff2);
3898                 }
3899 #endif /* COMMENT */
3900             }
3901             if (xxout(obuf,obn) < 0)    /* Flushing is required here! */
3902               goto outerr;
3903         }
3904     }
3905     if (cx == XXLNOUT) {
3906         s = "\015";
3907         cx = 0;
3908         goto outagain;
3909     }
3910     if (quote == 1)                     /* String ended with backslash */
3911       xx = oboc(dopar(CMDQ));
3912 
3913     if (obn > 0)                        /* OUTPUT done */
3914       if (xxout(obuf,obn) < 0)          /* Flush the buffer if necessary. */
3915         goto outerr;
3916     return(1);
3917 
3918 outerr:                                 /* OUTPUT command error handler */
3919     if (msgflg) printf("?OUTPUT execution error\n");
3920     return(0);
3921 
3922 /* Remove "local" OUTPUT macro defininitions */
3923 
3924 #ifdef COMMENT
3925 /* No more macros ... */
3926 #undef oboc
3927 #undef obfls
3928 #endif /* COMMENT */
3929 }
3930 #endif /* NOSPL */
3931 
3932 /* Display version herald and initial prompt */
3933 
3934 VOID
herald()3935 herald() {
3936     int x = 0, i;
3937     extern int srvcdmsg;
3938     extern char * cdmsgfile[];
3939     char * ssl;
3940     char * krb4;
3941     char * krb5;
3942 
3943 #ifndef NOCMDL
3944     extern char * bannerfile;
3945     debug(F110,"herald bannerfile",bannerfile,0);
3946     if (bannerfile) {
3947         concb((char)escape);
3948         if (dotype(bannerfile,1,0,0,NULL,0,NULL,0,0,NULL,0) > 0) {
3949             debug(F111,"herald","srvcdmsg",srvcdmsg);
3950             if (srvcdmsg) {
3951                 for (i = 0; i < 8; i++) {
3952                     debug(F111,"herald cdmsgfile[i]",cdmsgfile[i],i);
3953                     if (zchki(cdmsgfile[i]) > -1) {
3954                         printf("\n");
3955                         dotype(cdmsgfile[i],
3956                                xaskmore,0,0,NULL,0,NULL,0,0,NULL,0);
3957                         break;
3958                     }
3959                 }
3960             }
3961             return;
3962         }
3963     }
3964 #endif /* NOCMDL */
3965 
3966 #ifdef COMMENT
3967     /* The following generates bad code in SCO compilers. */
3968     /* Observed in both OSR5 and Unixware 2 -- after executing this */
3969     /* statement when all conditions are false, x has a value of -32. */
3970     if (noherald || quiet || bgset > 0 || (bgset != 0 && backgrd != 0))
3971       x = 1;
3972 #else
3973     x = 0;
3974     if (noherald || quiet)
3975       x = 1;
3976     else if (bgset > 0)
3977       x = 1;
3978     else if (bgset < 0 && backgrd > 0)
3979       x = 1;
3980 #endif /* COMMENT */
3981 
3982     ssl = "";
3983     krb4 = "";
3984     krb5 = "";
3985 #ifdef CK_AUTHENTICATION
3986 #ifdef CK_SSL
3987     ssl = "+SSL";
3988 #endif	/* CK_SSL */
3989 #ifdef KRB4
3990     krb4 = "+KRB4";
3991 #endif	/* KRB4 */
3992 #ifdef KRB5
3993     krb5 = "+KRB5";
3994 #endif	/* KRB5 */
3995 #endif	/* CK_AUTHENTICATION */
3996 
3997     if (x == 0) {
3998 #ifdef datageneral
3999         printf("%s, for%s\n",versio,ckxsys);
4000 #else
4001 #ifdef OSK
4002         printf("%s, for%s\n",versio,ckxsys);
4003 #else
4004 #ifdef CK_64BIT
4005         printf("%s, for%s%s%s%s (64-bit)\n\r",versio,ckxsys,ssl,krb4,krb5);
4006 #else
4007         printf("%s, for%s%s%s%s\n\r",versio,ckxsys,ssl,krb4,krb5);
4008 #endif/* CK_64BIT */
4009 #endif /* OSK */
4010 #endif /* datageneral */
4011         printf(" Copyright (C) 1985, %s,\n", ck_cryear);
4012         printf("  Trustees of Columbia University in the City of New York.\n");
4013 #ifdef COMMENT
4014 #ifdef OS2
4015        shoreg();
4016 #endif /* OS2 */
4017 #endif /* COMMENT */
4018 
4019         if (!quiet && !backgrd) {
4020 #ifdef COMMENT
4021 /* "Default file-transfer mode is AUTOMATIC" is useless information... */
4022             char * s;
4023             extern int xfermode;
4024 #ifdef VMS
4025             s = "AUTOMATIC";
4026 #else
4027             if (xfermode == XMODE_A) {
4028                 s = "AUTOMATIC";
4029             } else {
4030                 s = gfmode(binary,1);
4031             }
4032             if (!s) s = "";
4033 #endif /* VMS */
4034             if (*s)
4035               printf("Default file-transfer mode is %s\n", s);
4036 #endif /* COMMENT */
4037 
4038             debug(F111,"herald","srvcdmsg",srvcdmsg);
4039             if (srvcdmsg) {
4040                 for (i = 0; i < 8; i++) {
4041                     debug(F111,"herald cdmsgfile[i]",cdmsgfile[i],i);
4042                     if (zchki(cdmsgfile[i]) > -1) {
4043                         printf("\n");
4044                         dotype(cdmsgfile[i],
4045                                xaskmore,0,0,NULL,0,NULL,0,0,NULL,0);
4046                         break;
4047                     }
4048                 }
4049             }
4050             printf("Type ? or HELP for help.\n");
4051         }
4052     }
4053 }
4054 
4055 /*  G F M O D E  --  Get File (transfer) Mode  */
4056 
4057 char *
gfmode(binary,upcase)4058 gfmode(binary,upcase) int binary, upcase; {
4059     char * s;
4060     switch (binary) {
4061       case XYFT_T: s = upcase ? "TEXT" : "text"; break;
4062 #ifdef VMS
4063       case XYFT_B: s = upcase ? "BINARY FIXED" : "binary fixed"; break;
4064       case XYFT_I: s = upcase ? "IMAGE" : "image"; break;
4065       case XYFT_L: s = upcase ? "LABELED" : "labeled"; break;
4066       case XYFT_U: s = upcase ? "BINARY UNDEF" : "binary undef"; break;
4067 #else
4068 #ifdef MAC
4069       case XYFT_B: s = upcase ? "BINARY" : "binary"; break;
4070       case XYFT_M: s = upcase ? "MACBINARY" : "macbinary"; break;
4071 #else
4072       case XYFT_B: s = upcase ? "BINARY" : "binary"; break;
4073 #ifdef CK_LABELED
4074       case XYFT_L: s = upcase ? "LABELED" : "labeled"; break;
4075 #endif /* CK_LABELED */
4076 #endif /* MAC */
4077 #endif /* VMS */
4078       case XYFT_X: s = upcase ? "TENEX" : "tenex"; break;
4079       default: s = "";
4080     }
4081     return(s);
4082 }
4083 
4084 #ifndef NOSPL
4085 static int
isaa(s)4086 isaa(s) char * s; {                     /* Is associative array */
4087     char c;
4088     int x;
4089     if (!s) s = "";
4090     if (!*s) return(0);
4091     s++;
4092     while ((c = *s++)) {
4093         if (c == '<') {
4094             x = strlen(s);
4095             return ((*(s+x-1) == '>') ? 1 : 0);
4096         }
4097     }
4098     return(0);
4099 }
4100 
4101 /*  M L O O K  --  Lookup the macro name in the macro table  */
4102 
4103 /*
4104   Call this way:  v = mlook(table,word,n);
4105 
4106     table - a 'struct mtab' table.
4107     word  - the target string to look up in the table.
4108     n     - the number of elements in the table.
4109 
4110   The keyword table must be arranged in ascending alphabetical order, and
4111   all letters must be lowercase.
4112 
4113   Returns the table index, 0 or greater, if the name was found, or:
4114 
4115    -3 if nothing to look up (target was null),
4116    -2 if ambiguous,
4117    -1 if not found.
4118 
4119   A match is successful if the target matches a keyword exactly, or if
4120   the target is a prefix of exactly one keyword.  It is ambiguous if the
4121   target matches two or more keywords from the table.
4122 */
4123 int
mlook(table,cmd,n)4124 mlook(table,cmd,n) struct mtab table[]; char *cmd; int n; {
4125     register int i;
4126     int v, w, cmdlen = 0;
4127     char c = 0, c1, * s;
4128     if (!cmd) cmd = "";
4129 
4130     for (s = cmd; *s; s++) cmdlen++;    /* (instead of strlen) */
4131     debug(F111,"MLOOK",cmd,cmdlen);
4132 
4133     c1 = *cmd;
4134     if (isupper(c1))
4135       c1 = tolower(c1);
4136     if (cmdlen < 1)
4137       return(-3);
4138 
4139 /* Not null, look it up */
4140 
4141     if (n < 12) {                       /* Not worth it for small tables */
4142         i = 0;
4143     } else {                            /* Binary search for where to start */
4144         int lo = 0;
4145         int hi = n;
4146         int count = 0;
4147         while (lo+2 < hi && ++count < 12) {
4148             i = lo + ((hi - lo) / 2);
4149             c = *(table[i].kwd);
4150             if (isupper(c)) c = tolower(c);
4151             if (c < c1) {
4152                 lo = i;
4153             } else {
4154                 hi = i;
4155             }
4156         }
4157         i = (c < c1) ? lo+1 : lo;
4158     }
4159     for ( ; i < n-1; i++) {
4160         s = table[i].kwd;
4161         if (!s) s = "";
4162         if (!*s) continue;              /* Empty table entry */
4163         c = *s;
4164         if (isupper(c)) c = tolower(c);
4165         if (c1 != c) continue;          /* First char doesn't match */
4166         if (!ckstrcmp(s,cmd,-1,0))      /* Have exact match? */
4167           return(i);
4168         v = !ckstrcmp(s,cmd,cmdlen,0);
4169         w = ckstrcmp(table[i+1].kwd,cmd,cmdlen,0);
4170         if (v && w)                     /* Have abbreviated match? */
4171           return(i);
4172         if (v)                          /* Ambiguous? */
4173           return(-2);
4174         if (w > 0)                      /* Past our alphabetic area? */
4175           return(-1);
4176     }
4177 
4178 /* Last (or only) element */
4179 
4180     if (!ckstrcmp(table[n-1].kwd,cmd,cmdlen,0))
4181       return(n-1);
4182 
4183     return(-1);
4184 }
4185 
4186 /* mxlook is like mlook, but an exact full-length match is required */
4187 
4188 int
mxlook(table,cmd,n)4189 mxlook(table,cmd,n) char *cmd; struct mtab table[]; int n; {
4190     register int i;
4191     int w, cmdlen = 0, one = 0;
4192     register char c = 0, c1, * s;
4193 
4194     if (!cmd) cmd = "";                 /* Check args */
4195 
4196     for (s = cmd; *s; s++) cmdlen++;    /* (instead of strlen) */
4197     debug(F111,"MXLOOK",cmd,cmdlen);
4198 
4199     c1 = *cmd;                          /* First char of string to look up */
4200     if (isupper(c1))
4201       c1 = tolower(c1);
4202     if (!*(cmd+1))                      /* Special handling for 1-char names */
4203       one = 1;
4204 
4205     if (cmdlen < 1)                     /* Nothing to look up */
4206       return(-3);
4207 
4208     if (n < 12) {                       /* Not worth it for small tables */
4209         i = 0;
4210     } else {                            /* Binary search for where to start */
4211         int lo = 0;
4212         int hi = n;
4213         int count = 0;
4214         while (lo+2 < hi && ++count < 12) {
4215             i = lo + ((hi - lo) / 2);
4216             c = *(table[i].kwd);
4217             if (isupper(c)) c = tolower(c);
4218             if (c < c1) {
4219                 lo = i;
4220             } else {
4221                 hi = i;
4222             }
4223         }
4224         i = (c < c1) ? lo+1 : lo;
4225     }
4226     for ( ; i < n; i++) {               /* Look thru table */
4227         s = table[i].kwd;               /* This entry */
4228         if (!s) s = "";
4229         if (!*s) continue;              /* Empty table entry */
4230         c = *s;
4231         if (isupper(c)) c = tolower(c);
4232         if (c1 != c) continue;          /* First char doesn't match */
4233         if (one) {                      /* Name is one char long */
4234             if (!*(s+1))
4235               return(i);                /* So is table entry */
4236         }
4237 #ifdef COMMENT
4238         if (((int)strlen(s) == cmdlen) &&
4239             (!ckstrcmp(s,cmd,cmdlen,0))) return(i);
4240 #else
4241         w = ckstrcmp(s,cmd,-1,0);
4242         if (!w) {
4243             debug(F111,"MXLOOK",mactab[i].mval,i);
4244             return(i);
4245         }
4246         if (w > 0) return(-1);
4247 #endif /* COMMENT */
4248     }
4249     return(-1);
4250 }
4251 
4252 /* mxxlook is like mxlook, but case-sensitive */
4253 
4254 int
mxxlook(table,cmd,n)4255 mxxlook(table,cmd,n) char *cmd; struct mtab table[]; int n; {
4256     int i, cmdlen;
4257     if (!cmd) cmd = "";
4258     if (((cmdlen = strlen(cmd)) < 1) || (n < 1)) return(-3);
4259     /* debug(F111,"mxxlook target",cmd,n); */
4260     for (i = 0; i < n; i++) {
4261         if (((int)strlen(table[i].kwd) == cmdlen) &&
4262             (!strncmp(table[i].kwd,cmd,cmdlen)))
4263           return(i);
4264     }
4265     return(-1);
4266 }
4267 
4268 static int
traceval(nam,val)4269 traceval(nam, val) char * nam, * val; { /* For TRACE command */
4270     if (val)
4271       printf(">>> %s: \"%s\"\n", nam, val);
4272     else
4273       printf(">>> %s: (undef)\n", nam);
4274     return(0);
4275 }
4276 
4277 #ifdef USE_VARLEN                       /* Not used */
4278 
4279 /*  V A R L E N  --  Get length of variable's value.
4280 
4281   Given a variable name, return the length of its definition or 0 if the
4282   variable is not defined.  If it is defined, set argument s to point to its
4283   definition.  Otherwise set s to NULL.
4284 */
4285 int
varlen(nam,s)4286 varlen(nam,s) char *nam; char **s; {    /* Length of value of variable */
4287     int x, z;
4288     char *p = NULL, c;
4289 
4290     *s = NULL;
4291     if (!nam) return(0);                /* Watch out for null pointer */
4292     if (*nam == CMDQ) {
4293         nam++;
4294         if (*nam == '%') {              /* If it's a variable name */
4295             if (!(c = *(nam+1))) return(0); /* Get letter or digit */
4296             p = (char *)0;              /* Initialize value pointer */
4297             if (maclvl > -1 && c >= '0' && c <= '9') { /* Digit? */
4298                 p = m_arg[maclvl][c - '0']; /* Pointer from macro-arg table */
4299             } else {                    /* It's a global variable */
4300                 if (c < 33 || c > GVARS) return(0);
4301                 p = g_var[c];           /* Get pointer from global-var table */
4302             }
4303         } else if (*nam == '&') {               /* An array reference? */
4304             char **q;
4305             if (arraynam(nam,&x,&z) < 0) /* If syntax is bad */
4306               return(-1);               /* return -1. */
4307             x -= ARRAYBASE;             /* Convert name to number. */
4308             if ((q = a_ptr[x]) == NULL) /* If array not declared, */
4309               return(0);                /* return -2. */
4310             if (z > a_dim[x])           /* If subscript out of range, */
4311               return(0);                /* return -3. */
4312             p = q[z];
4313         }
4314     } else {                            /* Macro */
4315         z = isaa(nam);
4316         x = z ? mxxlook(mactab,nam,nmac) : mlook(mactab,nam,nmac);
4317         if (x < 0)
4318           return(0);
4319         p = mactab[x].mval;
4320     }
4321     if (p)
4322       *s = p;
4323     else
4324       p = "";
4325     return((int)strlen(p));
4326 }
4327 #endif /* USE_VARLEN */
4328 
4329 /*
4330   This routine is for the benefit of those compilers that can't handle
4331   long string constants or continued lines within them.  Long predefined
4332   macros like FOR, WHILE, and XIF have their contents broken up into
4333   arrays of string pointers.  This routine concatenates them back into a
4334   single string again, and then calls the real addmac() routine to enter
4335   the definition into the macro table.
4336 */
4337 int
addmmac(nam,s)4338 addmmac(nam,s) char *nam, *s[]; {       /* Add a multiline macro definition */
4339     int i, x, y; char *p;
4340     x = 0;                              /* Length counter */
4341     for (i = 0; (y = (int)strlen(s[i])) > 0; i++) { /* Add up total length */
4342         debug(F111,"addmmac line",s[i],y);
4343         x += y;
4344     }
4345     debug(F101,"addmmac lines","",i);
4346     debug(F101,"addmmac loop exit","",y);
4347     debug(F111,"addmmac length",nam,x);
4348     if (x < 0) return(-1);
4349 
4350     p = malloc(x+1);                    /* Allocate space for all of it. */
4351     if (!p) {
4352         printf("?addmmac malloc error: %s\n",nam);
4353         debug(F110,"addmmac malloc error",nam,0);
4354         return(-1);
4355     }
4356     *p = '\0';                          /* Start off with null string. */
4357     for (i = 0; *s[i]; i++)             /* Concatenate them all together. */
4358       ckstrncat(p,s[i],x+1);
4359     y = (int)strlen(p);                 /* Final precaution. */
4360     debug(F111,"addmmac constructed string",p,y);
4361     if (y == x) {
4362         y = addmac(nam,p);              /* Add result to the macro table. */
4363     } else {
4364         debug(F100,"addmmac length mismatch","",0);
4365         printf("\n!addmmac internal error!\n");
4366         y = -1;
4367     }
4368     free(p);                            /* Free the temporary copy. */
4369     return(y);
4370 }
4371 
4372 static char evalmacrobuf[TMPBUFSIZ];
4373 VOID
evalmacroarg(p)4374 evalmacroarg(p) char **p; {
4375     char * s = evalmacrobuf;
4376     int t = TMPBUFSIZ;
4377     (VOID) zzstring(*p,&s,&t);
4378     *p = evalmacrobuf;
4379 }
4380 
4381 /* Here is the real addmac routine. */
4382 
4383 /* Returns -1 on failure, macro table index >= 0 on success. */
4384 
4385 int mtchanged = 0;
4386 
4387 int
addmac(nam,def)4388 addmac(nam,def) char *nam, *def; {      /* Add a macro to the macro table */
4389     int i, x, y, z, namlen, deflen, flag = 0;
4390     int replacing = 0, deleting = 0;
4391     char * p = NULL, c, *s;
4392     extern int tra_asg; int tra_tmp;
4393 
4394     if (!nam) return(-1);
4395     if (!*nam) return(-1);
4396 
4397 #ifdef IKSD
4398     if (inserver &&
4399 #ifdef IKSDCONF
4400         iksdcf
4401 #else /* IKSDCONF */
4402         1
4403 #endif /* IKSDCONF */
4404         ) {
4405         if (!ckstrcmp("on_exit",nam,-1,0) ||
4406             !ckstrcmp("on_logout",nam,-1,0))
4407           return(-1);
4408     }
4409 #endif /* IKSD */
4410 
4411     namlen = 0;
4412     p = nam;
4413     while (*p++) namlen++;              /* (instead of strlen) */
4414 
4415     tra_tmp = tra_asg;                  /* trace... */
4416     debug(F111,"addmac nam",nam,namlen);
4417     if (!def) {                         /* Watch out for null pointer */
4418         deflen = 0;
4419         debug(F111,"addmac def","(null pointer)",deflen);
4420     } else {
4421         deflen = 0;
4422         p = def;
4423         while (*p++) deflen++;          /* (instead of strlen) */
4424         debug(F010,"addmac def",def,0);
4425     }
4426 #ifdef USE_VARLEN                       /* NOT USED */
4427     /* This does not boost performance much because varlen() does a lot */
4428     x = varlen(nam,&s);
4429     if (x > 0 && x >= deflen) {
4430         strcpy(s,def);                  /* NOT USED */
4431         flag = 1;
4432         p = s;
4433     }
4434 #endif /* USE_VARLEN */
4435 
4436     if (*nam == CMDQ) nam++;            /* Backslash quote? */
4437     if (*nam == '%') {                  /* Yes, if it's a variable name, */
4438         if (!(c = *(nam + 1))) return(-1); /* Variable name letter or digit */
4439         if (!flag) {
4440             tra_asg = 0;
4441             delmac(nam,0);              /* Delete any old value. */
4442             tra_asg = tra_tmp;
4443         }
4444         if (deflen < 1) {               /* Null definition */
4445             p = NULL;                   /* Better not malloc or strcpy! */
4446         } else if (!flag) {             /* A substantial definition */
4447             p = malloc(deflen + 1);     /* Allocate space for it */
4448             if (!p) {
4449                 printf("?addmac malloc error 2\n");
4450                 return(-1);
4451             } else strcpy(p,def);       /* Copy def into new space (SAFE) */
4452         }
4453 
4454         /* Now p points to the definition, or is a null pointer */
4455 
4456         if (c >= '0' && c <= '9') {     /* \%0-9 variable */
4457             if (maclvl < 0) {           /* Are we calling or in a macro? */
4458                 g_var[c] = p;           /* No, it's top level one */
4459                 makestr(&(toparg[c - '0']),p); /* Take care \&_[] too */
4460             } else {                    /* Yes, it's a macro argument */
4461                 m_arg[maclvl][c - '0'] = p; /* Assign the value */
4462                 makestr(&(m_xarg[maclvl][c - '0']),p); /* And a copy here */
4463             }
4464         } else {                        /* It's a \%a-z variable */
4465             if (c < 33 || (unsigned int)c > GVARS) return(-1);
4466             if (isupper(c)) c = (char) tolower(c);
4467             g_var[c] = p;               /* Put pointer in global-var table */
4468         }
4469         if (tra_asg) traceval(nam,p);
4470         return(0);
4471     } else if (*nam == '&') {           /* An array reference? */
4472         char **q = NULL;
4473         int rc = 0;
4474         if ((y = arraynam(nam,&x,&z)) < 0) /* If syntax is bad */
4475           return(-1);                   /* return -1. */
4476         if (chkarray(x,z) < 0)          /* If array not declared or */
4477           rc = -2;                      /* subscript out of range, ret -2 */
4478         if (!flag) {
4479             tra_asg = 0;
4480             delmac(nam,0);              /* Delete any old value. */
4481             tra_asg = tra_tmp;
4482         }
4483         x -= ARRAYBASE;                 /* Convert name letter to index. */
4484         if (x > 'z' - ARRAYBASE + 1)
4485           rc = -1;
4486         if (rc != -1) {
4487             if ((q = a_ptr[x]) == NULL) /* If array not declared, */
4488               return(-3);               /* return -3. */
4489         }
4490         if (rc < 0)
4491           return(rc);
4492         if (!flag) {
4493             if (deflen > 0) {
4494                 if ((p = malloc(deflen+1)) == NULL) { /* Allocate space */
4495                     printf("addmac macro error 7: %s\n",nam);
4496                     return(-4);         /* for new def, return -4 on fail. */
4497                 }
4498                 strcpy(p,def);          /* Copy def into new space (SAFE). */
4499             } else p = NULL;
4500         }
4501         q[z] = p;                       /* Store pointer to it. */
4502         if (x == 0) {                   /* Arg vector array */
4503             if (z >= 0 && z <= 9) {     /* Copy values to corresponding  */
4504                 if (maclvl < 0) {       /* \%1..9 variables. */
4505                     makestr(&(toparg[z]),p);
4506                 } else {
4507                     makestr(&(m_arg[maclvl][z]),p);
4508                 }
4509             }
4510         }
4511         if (tra_asg) traceval(nam,p);
4512         return(0);                      /* Done. */
4513     }
4514 /* Not a macro argument or a variable, so it's a macro definition */
4515 
4516 #ifdef USE_VARLEN
4517     if (flag) {
4518         if (tra_asg) traceval(nam,p);
4519         return(0);
4520     }
4521 #endif /* USE_VARLEN */
4522     x = isaa(nam) ?                     /* If it's an associative array */
4523       mxxlook(mactab,nam,nmac) :        /* look it up this way */
4524         mxlook(mactab,nam,nmac);        /* otherwise this way. */
4525     if (x > -1) {                       /* If found... */
4526         if (deflen > 0)                 /* and a new definition was given */
4527           replacing = 1;                /* we're replacing */
4528         else                            /* otherwise */
4529           deleting = 1;                 /* we're deleting */
4530     }
4531     if (deleting) {                     /* Deleting... */
4532         if (delmac(nam,0) < 0)
4533           return(-1);
4534         mtchanged++;
4535         if (tra_asg) traceval(nam,p);
4536         return(0);
4537     } else if (deflen < 1)              /* New macro with no definition */
4538       return(0);                        /* Nothing to do. */
4539 
4540     if (replacing) {                    /* Replacing an existing macro */
4541         if (mactab[x].mval) {           /* If it currently has a definition, */
4542             free(mactab[x].mval);       /* free it. */
4543             mactab[x].mval = NULL;
4544         }
4545         mtchanged++;
4546         y = x;                          /* Replacement index. */
4547 
4548     } else {                            /* Adding a new macro... */
4549         char c1, c2;                    /* Use fast lookup to find the */
4550         c1 = *nam;                      /* alphabetical slot. */
4551         if (isupper(c1)) c1 = (char) tolower(c1);
4552 
4553         if (nmac < 5) {                 /* Not worth it for small tables */
4554             y = 0;
4555         } else {                        /* First binary search to find */
4556             int lo = 0;                 /* where to start */
4557             int hi = nmac;
4558             int count = 0;
4559             char c = 0;
4560             while (lo+2 < hi && ++count < 12) {
4561                 y = lo + ((hi - lo) / 2);
4562                 c = *(mactab[y].kwd);
4563                 if (isupper(c)) c = (char) tolower(c);
4564                 if (c < c1) {
4565                     lo = y;
4566                 } else {
4567                     hi = y;
4568                 }
4569             }
4570             y = (c < c1) ? lo+1 : lo;
4571         }
4572 
4573         /* Now search linearly from starting location */
4574         for ( ; y < MAC_MAX && mactab[y].kwd != NULL; y++) {
4575             c2 = *(mactab[y].kwd);
4576             if (isupper(c2)) c2 = (char) tolower(c2);
4577             if (c1 > c2)
4578               continue;
4579             if (c1 < c2)
4580               break;
4581             if (ckstrcmp(nam,mactab[y].kwd,-1,0) <= 0)
4582               break;
4583         }
4584         if (y == MAC_MAX) {             /* Macro table is full. */
4585             debug(F101,"addmac table overflow","",y);
4586             printf("?Macro table overflow\n");
4587             return(-1);
4588         }
4589         if (mactab[y].kwd != NULL) {    /* Must insert */
4590             for (i = nmac; i > y; i--) { /* Move the rest down one slot */
4591                 mactab[i].kwd = mactab[i-1].kwd;
4592                 mactab[i].mval = mactab[i-1].mval;
4593                 mactab[i].flgs = mactab[i-1].flgs;
4594             }
4595         }
4596         mtchanged++;
4597         p = malloc(namlen + 1);         /* Allocate space for name */
4598         if (!p) {
4599             printf("?Addmac: Out of memory - \"%s\"\n",nam);
4600             return(-1);
4601         }
4602         strcpy(p,nam);                  /* Copy name into new space (SAFE) */
4603         mactab[y].kwd = p;              /* Add pointer to table */
4604     }
4605     if (deflen > 0) {                   /* If we have a definition */
4606         p = malloc(deflen + 1);         /* Get space */
4607         if (p == NULL) {
4608             printf("?Space exhausted - \"%s\"\n", nam);
4609             if (mactab[y].kwd) {
4610                 free(mactab[y].kwd);
4611                 mactab[y].kwd = NULL;
4612             }
4613             return(-1);
4614         } else {
4615             strcpy(p,def);              /* Copy the definition (SAFE) */
4616         }
4617     } else {                            /* definition is empty */
4618         p = NULL;
4619     }
4620     mactab[y].mval = p;                 /* Macro points to definition */
4621     mactab[y].flgs = 0;                 /* No flags */
4622     if (!replacing)                     /* If new macro */
4623       nmac++;                           /* count it */
4624     if (tra_asg) traceval(nam,p);
4625     return(y);
4626 }
4627 
4628 int
xdelmac(x)4629 xdelmac(x) int x; {                     /* Delete a macro given its index */
4630     int i;
4631     extern int tra_asg;
4632     if (x < 0) return(x);
4633     if (tra_asg)
4634       traceval(mactab[x].kwd,NULL);
4635 
4636     if (mactab[x].kwd) {                /* Free the storage for the name */
4637         free(mactab[x].kwd);
4638         mactab[x].kwd = NULL;
4639     }
4640     if (mactab[x].mval) {               /* and for the definition */
4641         free(mactab[x].mval);
4642         mactab[x].mval = NULL;
4643     }
4644     for (i = x; i < nmac; i++) {        /* Now move up the others. */
4645         mactab[i].kwd = mactab[i+1].kwd;
4646         mactab[i].mval = mactab[i+1].mval;
4647         mactab[i].flgs = mactab[i+1].flgs;
4648     }
4649     nmac--;                             /* One less macro */
4650 
4651     mactab[nmac].kwd = NULL;            /* Delete last item from table */
4652     mactab[nmac].mval = NULL;
4653     mactab[nmac].flgs = 0;
4654     mtchanged++;
4655     return(0);
4656 }
4657 
4658 int
delmac(nam,exact)4659 delmac(nam,exact) char *nam; int exact; { /* Delete the named macro */
4660     int x, z;
4661     char *p, c;
4662     extern int tra_asg;
4663 
4664     if (!nam) return(0);                /* Watch out for null pointer */
4665     debug(F110,"delmac nam",nam,0);
4666 #ifdef IKSD
4667     if ( inserver &&
4668 #ifdef IKSDCONF
4669         iksdcf
4670 #else /* IKSDCONF */
4671         1
4672 #endif /* IKSDCONF */
4673         ) {
4674         if (!ckstrcmp("on_exit",nam,-1,0) ||
4675             !ckstrcmp("on_logout",nam,-1,0))
4676           return(-1);
4677     }
4678 #endif /* IKSD */
4679 
4680     if (*nam == CMDQ) nam++;
4681     if (*nam == '%') {                  /* If it's a variable name */
4682         if (!(c = *(nam+1))) return(0); /* Get variable name letter or digit */
4683         p = (char *)0;                  /* Initialize value pointer */
4684         if (maclvl < 0 && c >= '0' && c <= '9') { /* Top-level digit? */
4685             p = toparg[c - '0'];
4686             if (p) if (p != g_var[c]) {
4687                 free(p);
4688                 toparg[c - '0'] = NULL;
4689             }
4690             p = g_var[c];
4691             g_var[c] = NULL;            /* Zero the table entry */
4692         } else if (maclvl > -1 && c >= '0' && c <= '9') { /* Digit? */
4693             p = m_xarg[maclvl][c - '0'];
4694             if (p) if (p != g_var[c]) {
4695                 free(p);
4696                 m_xarg[maclvl][c - '0'] = NULL;
4697             }
4698             p = m_arg[maclvl][c - '0']; /* Get pointer from macro-arg table */
4699             m_arg[maclvl][c - '0'] = NULL; /* Zero the table pointer */
4700         } else {                        /* It's a global variable */
4701             if (c < 33 || (unsigned int)c > GVARS) return(0);
4702             p = g_var[c];               /* Get pointer from global-var table */
4703             g_var[c] = NULL;            /* Zero the table entry */
4704         }
4705         if (p) {
4706             debug(F010,"delmac def",p,0);
4707             free(p);                    /* Free the storage */
4708             p = NULL;
4709         } else debug(F110,"delmac def","(null pointer)",0);
4710         if (tra_asg) traceval(nam,NULL);
4711         return(0);
4712     }
4713     if (*nam == '&') {                  /* An array reference? */
4714         char **q;
4715         if (arraynam(nam,&x,&z) < 0)    /* If syntax is bad */
4716           return(-1);                   /* return -1. */
4717         x -= ARRAYBASE;                 /* Convert name to number. */
4718         if ((q = a_ptr[x]) == NULL)     /* If array not declared, */
4719           return(-2);                   /* return -2. */
4720         if (z > a_dim[x])               /* If subscript out of range, */
4721           return(-3);                   /* return -3. */
4722         if (q[z]) {                     /* If there is an old value, */
4723             debug(F010,"delmac def",q[z],0);
4724             if (x != 0)                 /* Macro arg vector is just a copy */
4725               free(q[z]);               /* Others are real so free them */
4726             q[z] = NULL;
4727             if (x == 0) {               /* Arg vector array */
4728                 if (z >= 0 && z <= 9) { /* Copy values to corresponding  */
4729                     if (maclvl < 0) {   /* \%1..9 variables. */
4730                         makestr(&(toparg[z]),NULL);
4731                     } else {
4732                         makestr(&(m_arg[maclvl][z]),NULL);
4733                     }
4734                 }
4735             }
4736             if (tra_asg) traceval(nam,NULL);
4737         } else debug(F010,"delmac def","(null pointer)",0);
4738     }
4739 
4740    /* Not a variable or an array, so it must be a macro. */
4741 
4742     z = isaa(nam);
4743     debug(F111,"delmac isaa",nam,z);
4744     debug(F111,"delmac exact",nam,exact);
4745     x = z ? mxxlook(mactab,nam,nmac) :
4746       exact ? mxlook(mactab,nam,nmac) :
4747         mlook(mactab,nam,nmac);
4748     if (x < 0) {
4749         debug(F111,"delmac mlook",nam,x);
4750         return(x);
4751     }
4752     return(xdelmac(x));
4753 }
4754 
4755 VOID
initmac()4756 initmac() {                             /* Init macro & variable tables */
4757     int i, j, x;
4758 
4759     nmac = 0;                           /* No macros */
4760     for (i = 0; i < MAC_MAX; i++) {     /* Initialize the macro table */
4761         mactab[i].kwd = NULL;
4762         mactab[i].mval = NULL;
4763         mactab[i].flgs = 0;
4764     }
4765     mtchanged++;
4766     x = (MAXARGLIST + 1) * sizeof(char **);
4767     for (i = 0; i < MACLEVEL; i++) {    /* Init the macro argument tables */
4768         m_xarg[i] = (char **) malloc(x);
4769         mrval[i] = NULL;                /* Macro return value */
4770         /* Pointer to entire argument vector, level i, for \&_[] array */
4771         for (j = 0; j <= MAXARGLIST; j++) { /* Macro argument list */
4772             if (j < 10)                 /* For the \%0..\%9 variables */
4773               m_arg[i][j] = NULL;       /* Pointer to arg j, level i. */
4774             if (m_xarg[i])              /* For \&_[] - all args. */
4775               m_xarg[i][j] = NULL;
4776         }
4777     }
4778     for (i = 0; i < GVARS; i++) {       /* And the global variables table */
4779         g_var[i] = NULL;
4780     }
4781     /* And the table of arrays */
4782     for (i = 0; i < (int) 'z' - ARRAYBASE + 1; i++) {
4783         a_ptr[i] = (char **) NULL;      /* Null pointer for each */
4784         a_dim[i] = 0;                   /* and a dimension of zero */
4785         a_link[i] = -1;
4786         for (j = 0; j < CMDSTKL; j++) {
4787             aa_ptr[j][i] = (char **) NULL;
4788             aa_dim[j][i] = 0;
4789         }
4790     }
4791 }
4792 
4793 int
popclvl()4794 popclvl() {                             /* Pop command level, return cmdlvl */
4795     extern int tra_cmd;
4796     struct localvar * v;
4797     int i, topcmd;
4798     debug(F101,"popclvl cmdlvl","",cmdlvl);
4799     if (cmdlvl > 0) {
4800         if ((v = localhead[cmdlvl])) {  /* Did we save any variables? */
4801             while (v) {                 /* Yes */
4802                 if (v->lv_value)        /* Copy old ones back */
4803                   addmac(v->lv_name,v->lv_value);
4804                 else
4805                   delmac(v->lv_name,1);
4806                 v = v->lv_next;
4807             }
4808             freelocal(cmdlvl);          /* Free local storage */
4809         }
4810         /* Automatic arrays do not use the localhead list */
4811 
4812         for (i = 0; i < 28; i++) {      /* Free any local arrays */
4813             if (aa_ptr[cmdlvl][i]) {	/* Does this one exist? */
4814                 dclarray((char)(i+ARRAYBASE),-1); /* Destroy global one */
4815                 a_ptr[i] = aa_ptr[cmdlvl][i];
4816                 a_dim[i] = aa_dim[cmdlvl][i];
4817                 aa_ptr[cmdlvl][i] = (char **)NULL;
4818                 aa_dim[cmdlvl][i] = 0;
4819             } else if (aa_dim[cmdlvl][i] == -23) { /* Secret code */
4820                 /*
4821                   A local array declared at this level when there was no
4822                   array of the same name at any higher level.  See comment
4823                   in pusharray().
4824                 */
4825                 dclarray((char)(i+ARRAYBASE),-1);
4826                 a_ptr[i] = (char **)NULL; /* Delete top-level array */
4827                 a_dim[i] = 0;             /* created by pusharray - Feb 2016 */
4828                 aa_ptr[cmdlvl][i] = (char **)NULL;
4829                 aa_dim[cmdlvl][i] = 0;
4830             }
4831             /* Otherwise do nothing - it is a local array that was declared */
4832             /* at a level above this one so leave it alone. */
4833         }
4834     }
4835     if (cmdlvl < 1) {                   /* If we're already at top level */
4836         cmdlvl = 0;                     /* just make sure all the */
4837         tlevel = -1;                    /* stack pointers are set right */
4838         maclvl = -1;                    /* and return */
4839     } else if (cmdstk[cmdlvl].src == CMD_TF) { /* Reading from TAKE file? */
4840         debug(F101,"popclvl tlevel","",tlevel);
4841         if (tlevel > -1) {              /* Yes, */
4842             fclose(tfile[tlevel]);      /* close it */
4843 
4844             if (tra_cmd)
4845               printf("[%d] -F: \"%s\"\n",cmdlvl,tfnam[tlevel]);
4846             debug(F111,"CMD -F",tfnam[tlevel],cmdlvl);
4847             if (tfnam[tlevel]) {        /* free storage for name */
4848                 free(tfnam[tlevel]);
4849                 tfnam[tlevel] = NULL;
4850             }
4851             tlevel--;                   /* and pop take level */
4852             cmdlvl--;                   /* and command level */
4853             quiet = xquiet[cmdlvl];
4854             vareval = xvarev[cmdlvl];
4855         } else
4856           tlevel = -1;
4857     } else if (cmdstk[cmdlvl].src == CMD_MD) { /* In a macro? */
4858         topcmd = lastcmd[maclvl];
4859         debug(F101,"popclvl maclvl","",maclvl);
4860         if (maclvl > -1) {              /* Yes, */
4861 #ifdef COMMENT
4862             int i;
4863             char **q;
4864 #endif /* COMMENT */
4865             macp[maclvl] = "";          /* set macro pointer to null string */
4866             *cmdbuf = '\0';             /* clear the command buffer */
4867 
4868             if ((maclvl > 0) &&         /* 2 May 1999 */
4869                 (m_arg[maclvl-1][0]) &&
4870                 (!strncmp(m_arg[maclvl-1][0],"_xif",4) ||
4871                  !strncmp(m_arg[maclvl-1][0],"_for",4) ||
4872                  !strncmp(m_arg[maclvl-1][0],"_swi",4) ||
4873                  !strncmp(m_arg[maclvl-1][0],"_whi",4)) &&
4874                 mrval[maclvl+1]) {
4875                 makestr(&(mrval[maclvl-1]),mrval[maclvl+1]);
4876             }
4877             if (maclvl+1 < MACLEVEL) {
4878                 if (mrval[maclvl+1]) {  /* Free any deeper return values. */
4879                     free(mrval[maclvl+1]);
4880                     mrval[maclvl+1] = NULL;
4881                 }
4882             }
4883             if (tra_cmd)
4884               printf("[%d] -M: \"%s\"\n",cmdlvl,m_arg[cmdstk[cmdlvl].lvl][0]);
4885             debug(F111,"CMD -M",m_arg[cmdstk[cmdlvl].lvl][0],cmdlvl);
4886 
4887             maclvl--;                   /* Pop macro level */
4888             cmdlvl--;                   /* and command level */
4889             debug(F101,"popclvl mac new maclvl","",maclvl);
4890             debug(F010,"popclvl mac mrval[maclvl+1]",mrval[maclvl+2],0);
4891 
4892             quiet = xquiet[cmdlvl];
4893 	    vareval = xvarev[cmdlvl];
4894             if (maclvl > -1) {
4895                 a_ptr[0] = m_xarg[maclvl];
4896                 a_dim[0] = n_xarg[maclvl] - 1;
4897 		debug(F111,"a_dim[0]","B",a_dim[0]);
4898             } else {
4899                 a_ptr[0] = topxarg;
4900                 a_dim[0] = topargc - 1;
4901 		debug(F111,"a_dim[0]","C",a_dim[0]);
4902             }
4903         } else {
4904             maclvl = -1;
4905         }
4906 #ifndef NOSEXP
4907         debug(F101,"popclvl topcmd","",topcmd);
4908         if (topcmd == XXSEXP) {
4909             extern char * sexpval;
4910             makestr(&(mrval[maclvl+1]),sexpval);
4911         }
4912 #endif /* NOSEXP */
4913     } else {
4914         cmdlvl--;
4915     }
4916     debug(F101,"popclvl cmdlvl","",cmdlvl);
4917     if (prstring[cmdlvl]) {
4918         cmsetp(prstring[cmdlvl]);
4919         makestr(&(prstring[cmdlvl]),NULL);
4920     }
4921 #ifndef MAC
4922     if (cmdlvl < 1 || xcmdsrc == CMD_KB) { /* If at prompt */
4923         setint();
4924         concb((char)escape);            /* Go into cbreak mode */
4925     }
4926 #endif /* MAC */
4927     xcmdsrc = cmdstk[cmdlvl].src;
4928     debug(F101,"popclvl xcmdsrc","",xcmdsrc);
4929     debug(F101,"popclvl tlevel","",tlevel);
4930     return(cmdlvl < 1 ? 0 : cmdlvl);    /* Return command level */
4931 }
4932 #else /* No script programming language */
popclvl()4933 int popclvl() {                         /* Just close current take file. */
4934     if (tlevel > -1) {                  /* if any... */
4935         if (tfnam[tlevel]) {
4936             free(tfnam[tlevel]);
4937             tfnam[tlevel] = NULL;
4938         }
4939         fclose(tfile[tlevel--]);
4940     }
4941     if (tlevel == -1) {                 /* And if back at top level */
4942         setint();
4943         concb((char)escape);            /* and go back into cbreak mode. */
4944     }
4945     xcmdsrc = tlevel > -1 ? CMD_TF : 0;
4946     return(tlevel + 1);
4947 }
4948 #endif /* NOSPL */
4949 
4950 
4951 #ifndef NOSPL
4952 static int
iseom(m)4953 iseom(m) char * m; {                    /* Test if at end of macro def */
4954     if (!m)
4955       m = "";
4956     debug(F111,"iseom",m,maclvl);
4957     while (*m) {
4958         /* Anything but Space and Comma means more macro is left */
4959         if ((*m > SP) && (*m != ',')) {
4960             debug(F111,"iseom return",m,0);
4961             return(0);
4962         }
4963         m++;
4964     }
4965     debug(F111,"iseom return",m,1);
4966     return(1);                          /* Nothing left */
4967 }
4968 #endif /* NOSPL */
4969 
4970 /* Pop all command levels that can be popped */
4971 
4972 int
prepop()4973 prepop() {
4974     if (cmdlvl > 0) {                   /* If command level is > 0 and... */
4975         while (
4976 #ifndef NOSPL
4977                ((cmdstk[cmdlvl].src == CMD_TF) && /* Command source is file */
4978 #endif /* NOSPL */
4979             (tlevel > -1) &&
4980             feof(tfile[tlevel]))        /* And at end of file... */
4981 #ifndef NOSPL
4982                /* Or command source is macro... */
4983                || ((cmdstk[cmdlvl].src == CMD_MD) &&
4984                 (maclvl > -1) &&
4985                 iseom(macp[maclvl])))  /* and at end of macro, then... */
4986 #endif /* NOSPL */
4987         {
4988               popclvl();                /* pop command level. */
4989         }
4990     }
4991     return(cmdlvl < 1 ? 0 : cmdlvl);    /* Return command level */
4992 }
4993 
4994 /* STOP - get back to C-Kermit prompt, no matter where from. */
4995 
4996 int
dostop()4997 dostop() {
4998     extern int cmddep;
4999     while (popclvl()) ;         /* Pop all macros & take files */
5000 #ifndef NOSPL
5001     if (cmddep > -1)            /* And all recursive cmd pkg invocations */
5002       while (cmpop() > -1) ;
5003 #endif /* NOSPL */
5004     cmini(ckxech);              /* Clear the command buffer. */
5005     return(0);
5006 }
5007 
5008 /* Close the given log */
5009 
5010 int
doclslog(x)5011 doclslog(x) int x; {
5012     int y;
5013     switch (x) {
5014 #ifdef DEBUG
5015       case LOGD:
5016         if (deblog <= 0) {
5017             printf("?Debugging log wasn't open\n");
5018             return(0);
5019         }
5020         debug(F100,"Debug Log Closed","",0L);
5021         *debfil = '\0';
5022         deblog = 0;
5023         return(zclose(ZDFILE));
5024 #endif /* DEBUG */
5025 
5026 #ifndef NOXFER
5027       case LOGP:
5028         if (pktlog <= 0) {
5029             printf("?Packet log wasn't open\n");
5030             return(0);
5031         }
5032         *pktfil = '\0';
5033         pktlog = 0;
5034         return(zclose(ZPFILE));
5035 #endif /* NOXFER */
5036 
5037 #ifndef NOLOCAL
5038       case LOGS:
5039         if (seslog <= 0) {
5040             printf("?Session log wasn't open\n");
5041             return(0);
5042         }
5043         *sesfil = '\0';
5044         setseslog(0);
5045         return(zclose(ZSFILE));
5046 #endif /* NOLOCAL */
5047 
5048 #ifdef TLOG
5049       case LOGT: {
5050 #ifdef IKSD
5051           extern int iklogopen, xferlog;
5052 #endif /* IKSD */
5053           if (tralog <= 0
5054 #ifdef IKSD
5055               && !iklogopen
5056 #endif /* IKSD */
5057               ) {
5058               if (msgflg)
5059                 printf("?Transaction log wasn't open\n");
5060               return(0);
5061           }
5062 #ifdef IKSD
5063           if (iklogopen && !inserver) {
5064               close(xferlog);
5065               iklogopen = 0;
5066           }
5067 #endif /* IKSD */
5068           if (tralog) {
5069               tlog(F100,"Transaction Log Closed","",0L);
5070               zclose(ZTFILE);
5071           }
5072           *trafil = '\0';
5073           tralog = 0;
5074           return(1);
5075       }
5076 #endif /* TLOG */
5077 
5078 #ifdef CKLOGDIAL
5079       case LOGM:
5080         if (dialog <= 0) {
5081             if (msgflg) printf("?Connection log wasn't open\n");
5082             return(0);
5083         }
5084         *diafil = '\0';
5085         dialog = 0;
5086         return(zclose(ZDIFIL));
5087 #endif /* CKLOGDIAL */
5088 
5089 #ifndef NOSPL
5090       case LOGW:                        /* WRITE file */
5091       case LOGR:                        /* READ file */
5092         y = (x == LOGR) ? ZRFILE : ZWFILE;
5093         if (chkfn(y) < 1)               /* If no file to close */
5094           return(1);                    /* succeed silently. */
5095         return(zclose(y));              /* Otherwise, close the file. */
5096 #endif /* NOSPL */
5097 
5098       default:
5099         printf("\n?Unexpected log designator - %d\n", x);
5100         return(0);
5101     }
5102 }
5103 
5104 static int slc = 0;                     /* Screen line count */
5105 
5106 char *
showstring(s)5107 showstring(s) char * s; {
5108     return(s ? s : "(null)");
5109 }
5110 
5111 char *
showoff(x)5112 showoff(x) int x; {
5113     return(x ? "on" : "off");
5114 }
5115 
5116 char *
showooa(x)5117 showooa(x) int x; {
5118     switch (x) {
5119       case SET_OFF:  return("off");
5120       case SET_ON:   return("on");
5121       case SET_AUTO: return("automatic");
5122       default:       return("(unknown)");
5123     }
5124 }
5125 
5126 #ifdef GEMDOS
isxdigit(c)5127 isxdigit(c) int c; {
5128     return(isdigit(c) ||
5129            (c >= 'a' && c <= 'f') ||
5130            (c >= 'A' && c <= 'F'));
5131 }
5132 #endif /* GEMDOS */
5133 
5134 #ifndef NOSETKEY
5135 #ifdef OS2
5136 static struct keytab shokeytab[] = {    /* SHOW KEY modes */
5137     "all",    1, 0,
5138     "one",    0, 0
5139 };
5140 static int nshokey = (sizeof(shokeytab) / sizeof(struct keytab));
5141 
5142 #define SHKEYDEF TT_MAX+5
5143 struct keytab shokeymtab[] = {
5144     "aaa",       TT_AAA,     CM_INV,    /* AnnArbor */
5145     "adm3a",     TT_ADM3A,   0,         /* LSI ADM-3A */
5146     "adm5",      TT_ADM5,    0,         /* LSI ADM-5 */
5147     "aixterm",   TT_AIXTERM, 0,         /* IBM AIXterm */
5148     "annarbor",  TT_AAA,     0,         /* AnnArbor */
5149     "ansi-bbs",  TT_ANSI,    0,         /* ANSI.SYS (BBS) */
5150     "at386",     TT_AT386,   0,         /* Unixware ANSI */
5151     "avatar/0+", TT_ANSI,    0,         /* AVATAR/0+ */
5152     "ba80",      TT_BA80,    0,         /* Nixdorf BA80 */
5153     "be",        TT_BEOS,    CM_INV|CM_ABR,
5154     "beos-ansi", TT_BEOS,    CM_INV,    /* BeOS ANSI */
5155     "beterm",    TT_BEOS,    0,         /* BeOS Console */
5156     "d200",      TT_DG200,   CM_INV|CM_ABR, /* Data General DASHER 200 */
5157     "d210",      TT_DG210,   CM_INV|CM_ABR, /* Data General DASHER 210 */
5158     "d217",      TT_DG217,   CM_INV|CM_ABR, /* Data General DASHER 217 */
5159     "default",   SHKEYDEF,   0,
5160     "dg200",     TT_DG200,   0,         /* Data General DASHER 200 */
5161     "dg210",     TT_DG210,   0,         /* Data General DASHER 210 */
5162     "dg217",     TT_DG217,   0,         /* Data General DASHER 217 */
5163     "emacs",     TT_KBM_EMACS,   0,     /* Emacs mode */
5164     "h19",       TT_H19,     CM_INV,    /* Heath-19 */
5165     "heath19",   TT_H19,     0,         /* Heath-19 */
5166     "hebrew",    TT_KBM_HEBREW, 0,      /* Hebrew mode */
5167     "hft",       TT_HFT,     0,         /* IBM HFT */
5168     "hp2621a",   TT_HP2621,  0,         /* HP 2621A */
5169     "hpterm",    TT_HPTERM,  0,         /* HP TERM */
5170     "hz1500",    TT_HZL1500, 0,         /* Hazeltine 1500 */
5171     "ibm3151",   TT_IBM31,   0,         /* IBM 3101-xx,3161 */
5172     "linux",     TT_LINUX,   0,         /* Linux */
5173     "qansi",     TT_QANSI,   0,         /* QNX ANSI */
5174     "qnx",       TT_QNX,     0,         /* QNX */
5175     "russian",   TT_KBM_RUSSIAN, 0,     /* Russian mode */
5176     "scoansi",   TT_SCOANSI, 0,         /* SCO ANSI */
5177     "sni-97801", TT_97801,   0,         /* Sinix 97801 */
5178     "sun",       TT_SUN,     0,         /* Sun Console */
5179 #ifdef OS2PM
5180 #ifdef COMMENT
5181     "tek4014", TT_TEK40, 0,
5182 #endif /* COMMENT */
5183 #endif /* OS2PM */
5184     "tty",     TT_NONE,  0,
5185     "tvi910+", TT_TVI910, 0,
5186     "tvi925",  TT_TVI925, 0,
5187     "tvi950",  TT_TVI950, 0,
5188     "vc404",   TT_VC4404, 0,
5189     "vc4404",  TT_VC4404, CM_INV,
5190     "vip7809", TT_VIP7809, 0,
5191     "vt100",   TT_VT100, 0,
5192     "vt102",   TT_VT102, 0,
5193     "vt220",   TT_VT220, 0,
5194     "vt220pc", TT_VT220PC, 0,
5195     "vt320",   TT_VT320, 0,
5196     "vt320pc", TT_VT320PC, 0,
5197     "vt52",    TT_VT52,  0,
5198     "wp",      TT_KBM_WP, 0,
5199     "wy160",   TT_WY160,  0,
5200     "wy30",    TT_WY30,  0,
5201     "wy370",   TT_WY370, 0,
5202     "wy50",    TT_WY50,  0,
5203     "wy60",    TT_WY60,  0,
5204     "wyse30",  TT_WY30,  CM_INV,
5205     "wyse370", TT_WY370, CM_INV,
5206     "wyse50",  TT_WY50,  CM_INV,
5207     "wyse60",  TT_WY60,  CM_INV
5208 };
5209 int nshokeym = (sizeof(shokeymtab) / sizeof(struct keytab));
5210 #endif /* OS2 */
5211 
5212 VOID
5213 #ifdef OS2
shokeycode(c,m)5214 shokeycode(c,m) int c, m;
5215 #else
5216 shokeycode(c) int c;
5217 #endif
5218 /* shokeycode */ {
5219     KEY ch;
5220     CHAR *s;
5221 #ifdef OS2
5222     int i;
5223     con_event km;
5224 #else /* OS2 */
5225     int km;
5226 #endif /* OS2 */
5227 
5228 #ifdef OS2
5229     extern int mskkeys;
5230     char * mstr = "";
5231 
5232     if (c >= KMSIZE) {
5233         bleep(BP_FAIL);
5234         return;
5235     }
5236 #else /* OS2 */
5237     printf(" Key code \\%d => ", c);
5238 #endif /* OS2 */
5239 
5240 #ifndef OS2
5241     km = mapkey(c);
5242 
5243 #ifndef NOKVERBS
5244     if (IS_KVERB(km)) {                 /* \Kverb? */
5245         int i, kv;
5246         kv = km & ~(F_KVERB);
5247         printf("Verb: ");
5248         for (i = 0; i < nkverbs; i++)
5249           if (kverbs[i].kwval == kv) {
5250               printf("\\K%s",kverbs[i].kwd);
5251               break;
5252           }
5253         printf("\n");
5254     } else
5255 #endif /* NOKVERBS */
5256       if (IS_CSI(km)) {
5257           int xkm = km & 0xFF;
5258           if (xkm <= 32 || xkm >= 127)
5259             printf("String: \\{27}[\\{%d}\n",xkm);
5260           else
5261             printf("String: \\{27}[%c\n",xkm);
5262       } else if (IS_ESC(km)) {
5263           int xkm = km & 0xFF;
5264           if (xkm <= 32 || xkm >= 127)
5265             printf("String: \\{27}\\{%d}\n",xkm);
5266           else
5267             printf("String: \\{27}%c\n",xkm);
5268       } else if (macrotab[c]) {         /* See if there's a macro */
5269           printf("String: ");           /* If so, display its definition */
5270           s = macrotab[c];
5271           shostrdef(s);
5272           printf("\n");
5273 #ifndef NOKVERBS
5274     } else if (km >= 0x100) {           /* This means "undefined" */
5275         printf("Undefined\n");
5276 #endif /* NOKVERBS */
5277     } else {                            /* No macro, show single character */
5278         printf("Character: ");
5279         ch = km;
5280         if (ch < 32 || ch == 127
5281 #ifdef OS2
5282             || ch > 255
5283 #endif /* OS2 */
5284 #ifndef NEXT
5285 #ifndef AUX
5286 #ifndef XENIX
5287 #ifndef OS2
5288             || (ch > 127 && ch < 160)
5289 #endif /* OS2 */
5290 #endif /* XENIX */
5291 #endif /* AUX */
5292 #endif /* NEXT */
5293             )
5294 /*
5295   These used to be %d, but gcc 1.93 & later complain about type mismatches.
5296   %u is supposed to be totally portable.
5297 */
5298           printf("\\%u",(unsigned int) ch);
5299         else printf("%c \\%u",(CHAR) (ch & 0xff),(unsigned int) ch);
5300         if (ch == (KEY) c)
5301           printf(" (self, no translation)\n");
5302         else
5303           printf("\n");
5304     }
5305 #else /* OS2 */
5306     if (m < 0) {
5307         km = mapkey(c);
5308         mstr = "default";
5309     } else {
5310         km = maptermkey(c,m);
5311         for (i = 0; i < nshokeym; i++) {
5312             if (m == shokeymtab[i].kwval) {
5313                 mstr = shokeymtab[i].kwd;
5314                 break;
5315             }
5316         }
5317     }
5318     s = keyname(c);
5319     debug(F111,"shokeycode mstr",mstr,m);
5320     debug(F111,"shokeycode keyname",s,c);
5321     printf(" %sKey code \\%d %s (%s) => ",
5322             mskkeys ? "mskermit " : "",
5323             mskkeys ? cktomsk(c) : c,
5324             s == NULL ? "" : s, mstr);
5325 
5326     switch (km.type) {
5327 #ifndef NOKVERBS
5328       case kverb: {
5329           int i, kv;
5330           kv = km.kverb.id & ~(F_KVERB);
5331           printf("Verb: ");
5332           for (i = 0; i < nkverbs; i++) {
5333               if (kverbs[i].kwval == kv) {
5334                   printf("\\K%s",kverbs[i].kwd);
5335                   break;
5336               }
5337           }
5338           printf("\n");
5339           break;
5340       }
5341 #endif /* NOKVERBS */
5342       case csi: {
5343           int xkm = km.csi.key & 0xFF;
5344           if (xkm <= 32 || xkm >= 127)
5345             printf("String: \\{27}[\\{%d}\n",xkm);
5346           else
5347             printf("String: \\{27}[%c\n",xkm);
5348           break;
5349       }
5350       case esc: {
5351           int xkm = km.esc.key & 0xFF;
5352           if (xkm <= 32 || xkm >= 127)
5353             printf("String: \\{%d}\\{%d}\n",ISDG200(tt_type)?30:27,xkm);
5354           else
5355             printf("String: \\{%d}%c\n",ISDG200(tt_type)?30:27,xkm);
5356           break;
5357       }
5358       case macro: {
5359           printf("String: ");           /* Macro, display its definition */
5360           shostrdef(km.macro.string);
5361           printf("\n");
5362           break;
5363       }
5364       case literal: {
5365           printf("Literal string: ");   /* Literal, display its definition */
5366           shostrdef(km.literal.string);
5367           printf("\n");
5368           break;
5369       }
5370       case error: {
5371           if (c >= 0x100) {
5372               printf("Undefined\n");
5373           } else {
5374               printf("Character: ");
5375               ch = c;
5376               if (ch < 32 || ch == 127 || ch > 255
5377 #ifndef NEXT
5378 #ifndef AUX
5379 #ifndef XENIX
5380 #ifndef OS2
5381                    || (ch > 127 && ch < 160)
5382 #endif /* OS2 */
5383 #endif /* XENIX */
5384 #endif /* AUX */
5385 #endif /* NEXT */
5386                    )
5387 /*
5388   These used to be %d, but gcc 1.93 & later complain about type mismatches.
5389   %u is supposed to be totally portable.
5390 */
5391                   printf("\\%u",(unsigned int) ch);
5392               else printf("%c \\%u",(CHAR) (ch & 0xff),(unsigned int) ch);
5393               printf(" (self, no translation)\n");
5394           }
5395           break;
5396       }
5397       case key: {
5398           printf("Character: ");
5399           ch = km.key.scancode;
5400           if (ch < 32 || ch == 127 || ch > 255
5401 #ifndef NEXT
5402 #ifndef AUX
5403 #ifndef XENIX
5404 #ifndef OS2
5405               || (ch > 127 && ch < 160)
5406 #else
5407                || (ch > 127)
5408 #endif /* OS2 */
5409 #endif /* XENIX */
5410 #endif /* AUX */
5411 #endif /* NEXT */
5412               )
5413 /*
5414   These used to be %d, but gcc 1.93 & later complain about type mismatches.
5415   %u is supposed to be totally portable.
5416 */
5417             printf("\\%u",(unsigned int) ch);
5418           else printf("%c \\%u",(CHAR) (ch & 0xff),(unsigned int) ch);
5419           if (ch == (KEY) c)
5420             printf(" (self, no translation)\n");
5421           else
5422             printf("\n");
5423           break;
5424       }
5425     }
5426 #endif /* OS2 */
5427 }
5428 #endif /* NOSETKEY */
5429 
5430 VOID
shostrdef(s)5431 shostrdef(s) CHAR * s; {
5432     CHAR ch;
5433     if (!s) s = (CHAR *)"";
5434     while ((ch = *s++)) {
5435         if (ch < 32 || ch == 127 || ch == 255
5436 /*
5437   Systems whose native character sets have graphic characters in C1...
5438 */
5439 #ifndef NEXT                            /* NeXT */
5440 #ifndef AUX                             /* Macintosh */
5441 #ifndef XENIX                           /* IBM PC */
5442 #ifdef OS2
5443 /*
5444   It doesn't matter whether the local host can display 8-bit characters;
5445   they are not portable among character-sets and fonts.  Who knows what
5446   would be displayed...
5447 */
5448             || (ch > 127)
5449 #else /* OS2 */
5450             || (ch > 127 && ch < 160)
5451 #endif /* OS2 */
5452 #endif /* XENIX */
5453 #endif /* AUX */
5454 #endif /* NEXT */
5455             )
5456           printf("\\{%d}",ch);          /* Display control characters */
5457         else putchar((char) ch);        /* in backslash notation */
5458     }
5459 }
5460 
5461 #define xxdiff(v,sys) strncmp(v,sys,strlen(sys))
5462 
5463 #ifndef NOSHOW
5464 VOID
shover()5465 shover() {
5466 #ifdef OS2
5467     extern char ckxsystem[];
5468 #endif /* OS2 */
5469     extern char *ck_patch, * cklibv;
5470     printf("\nVersions:\n %s\n",versio);
5471     printf(" Numeric: %ld\n",vernum);
5472 #ifdef OS2
5473     printf(" Operating System: %s\n", ckxsystem);
5474 #else /* OS2 */
5475     printf(" Built for: %s\n", ckxsys);
5476 #ifdef CK_UTSNAME
5477     if (unm_nam[0])
5478       printf(" Running on: %s %s %s %s\n", unm_nam,unm_ver,unm_rel,unm_mch);
5479 #endif /* CK_UTSNAME */
5480     printf(" Patches: %s\n", *ck_patch ? ck_patch : "(none)");
5481 #endif /* OS2 */
5482     if (xxdiff(ckxv,ckxsys))
5483       printf(" %s for%s\n",ckxv,ckxsys);
5484     else
5485       printf(" %s\n",ckxv);
5486     if (xxdiff(ckzv,ckzsys))
5487       printf(" %s for%s\n",ckzv,ckzsys);
5488     else
5489       printf(" %s\n",ckzv);
5490     printf(" %s\n",cklibv);
5491     printf(" %s\n",protv);
5492     printf(" %s\n",fnsv);
5493     printf(" %s\n %s\n",cmdv,userv);
5494 #ifndef NOCSETS
5495     printf(" %s\n",xlav);
5496 #endif /* NOCSETS */
5497 #ifndef MAC
5498 #ifndef NOLOCAL
5499     printf(" %s\n",connv);
5500 #ifdef OS2
5501     printf(" %s\n",ckyv);
5502 #endif /* OS2 */
5503 #endif /* NOLOCAL */
5504 #endif /* MAC */
5505 #ifndef NODIAL
5506     printf(" %s\n",dialv);
5507 #endif /* NODIAL */
5508 #ifndef NOSCRIPT
5509     printf(" %s\n",loginv);
5510 #endif /* NOSCRIPT */
5511 #ifdef NETCONN
5512     printf(" %s\n",cknetv);
5513 #ifdef OS2
5514     printf(" %s\n",ckonetv);
5515 #ifdef CK_NETBIOS
5516     printf(" %s\n",ckonbiv);
5517 #endif /* CK_NETBIOS */
5518 #endif /* OS2 */
5519 #endif /* NETCONN */
5520 #ifdef TNCODE
5521     printf(" %s\n",cktelv);
5522 #endif /* TNCODE */
5523 #ifdef SSHBUILTIN
5524     printf(" %s\n",cksshv);
5525 #ifdef SFTP_BUILTIN
5526     printf(" %s\n",cksftpv);
5527 #endif /* SFTP_BUILTIN */
5528 #endif /* SSHBUILTIN */
5529 #ifdef OS2
5530 #ifdef OS2MOUSE
5531     printf(" %s\n",ckomouv);
5532 #endif /* OS2MOUSE */
5533 #endif /* OS2 */
5534 #ifdef NEWFTP
5535     printf(" %s\n",ckftpv);
5536 #endif /* NEWFTP */
5537 #ifdef CK_AUTHENTICATION
5538     printf(" %s\n",ckathv);
5539 #endif /* CK_AUTHENTICATION */
5540 #ifdef CK_ENCRYPTION
5541 #ifdef CRYPT_DLL
5542     printf(" %s\n",ck_crypt_dll_version());
5543 #else /* CRYPT_DLL */
5544     printf(" %s\n",ckcrpv);
5545 #endif /* CRYPT_DLL */
5546 #endif /* CK_ENCRYPTION */
5547 #ifdef CK_SSL
5548     printf(" %s\n",cksslv);
5549 #endif /* CK_SSL */
5550     printf("\n");
5551 }
5552 
5553 #ifdef CK_LABELED
5554 VOID
sholbl()5555 sholbl() {
5556 #ifdef VMS
5557     printf("VMS Labeled File Features:\n");
5558     printf(" acl %s (ACL info %s)\n",
5559            showoff(lf_opts & LBL_ACL),
5560            lf_opts & LBL_ACL ? "preserved" : "discarded");
5561     printf(" backup-date %s (backup date/time %s)\n",
5562            showoff(lf_opts & LBL_BCK),
5563            lf_opts & LBL_BCK ? "preserved" : "discarded");
5564     printf(" name %s (original filename %s)\n",
5565            showoff(lf_opts & LBL_NAM),
5566            lf_opts & LBL_NAM ? "preserved" : "discarded");
5567     printf(" owner %s (original file owner id %s)\n",
5568            showoff(lf_opts & LBL_OWN),
5569            lf_opts & LBL_OWN ? "preserved" : "discarded");
5570     printf(" path %s (original file's disk:[directory] %s)\n",
5571            showoff(lf_opts & LBL_PTH),
5572            lf_opts & LBL_PTH ? "preserved" : "discarded");
5573 #else
5574 #ifdef OS2
5575     printf("OS/2 Labeled File features (attributes):\n");
5576     printf(" archive:   %s\n", showoff(lf_opts & LBL_ARC));
5577     printf(" extended:  %s\n", showoff(lf_opts & LBL_EXT));
5578     printf(" hidden:    %s\n", showoff(lf_opts & LBL_HID));
5579     printf(" read-only: %s\n", showoff(lf_opts & LBL_RO ));
5580     printf(" system:    %s\n", showoff(lf_opts & LBL_SYS));
5581 #endif /* OS2 */
5582 #endif /* VMS */
5583 }
5584 #endif /* CK_LABELED */
5585 
5586 VOID
shotcs(csl,csr)5587 shotcs(csl,csr) int csl, csr; {         /* Show terminal character set */
5588 #ifndef NOCSETS
5589 #ifdef OS2
5590 #ifndef NOTERM
5591     extern struct _vtG G[4], *GL, *GR;
5592     extern int decnrcm, sni_chcode;
5593     extern int tt_utf8, dec_nrc, dec_kbd, dec_lang;
5594     extern prncs;
5595 
5596     printf(" Terminal character-sets:\n");
5597     if (IS97801(tt_type_mode)) {
5598         if (cmask == 0377)
5599           printf("     Mode: 8-bit Mode\n");
5600         else
5601           printf("     Mode: 7-bit Mode\n");
5602         printf("     CH.CODE is %s\n",sni_chcode?"On":"Off");
5603     } else if (ISVT100(tt_type_mode)) {
5604         if (decnrcm)
5605           printf("     Mode: 7-bit National Mode\n");
5606         else
5607           printf("     Mode: 8-bit Multinational Mode\n");
5608     }
5609     if ( isunicode() )
5610         printf("    Local: Unicode display / %s input\n",
5611                 csl == TX_TRANSP ? "transparent" :
5612                 csl == TX_UNDEF ? "undefined" : txrinfo[csl]->keywd);
5613     else
5614         printf("    Local: %s\n",
5615                 csl == TX_TRANSP ? "transparent" :
5616                 csl == TX_UNDEF ? "undefined" : txrinfo[csl]->keywd);
5617 
5618     if ( tt_utf8 ) {
5619         printf("   Remote: UTF-8\n");
5620     } else {
5621         printf("   Remote: %sG0: %s (%s)\n",
5622            GL == &G[0] ? "GL->" : GR == &G[0] ? "GR->" : "    ",
5623            txrinfo[G[0].designation]->keywd,
5624            G[0].designation == TX_TRANSP ? "" :
5625            G[0].size == cs94 ? "94 chars" :
5626            G[0].size == cs96 ? "96 chars" : "multi-byte");
5627         printf("           %sG1: %s (%s)\n",
5628            GL == &G[1] ? "GL->" : GR == &G[1] ? "GR->" : "    ",
5629            txrinfo[G[1].designation]->keywd,
5630            G[1].designation == TX_TRANSP ? "" :
5631            G[1].size == cs94 ? "94 chars" :
5632            G[1].size == cs96 ? "96 chars" : "multi-byte");
5633         printf("           %sG2: %s (%s)\n",
5634            GL == &G[2] ? "GL->" : GR == &G[2] ? "GR->" : "    ",
5635            txrinfo[G[2].designation]->keywd,
5636            G[2].designation == TX_TRANSP ? "" :
5637            G[2].size == cs94 ? "94 chars" :
5638            G[2].size == cs96 ? "96 chars" : "multi-byte");
5639         printf("           %sG3: %s (%s)\n",
5640            GL == &G[3] ? "GL->" : GR == &G[3] ? "GR->" : "    ",
5641            txrinfo[G[3].designation]->keywd,
5642            G[3].designation == TX_TRANSP ? "" :
5643            G[3].size == cs94 ? "94 chars" :
5644            G[3].size == cs96 ? "96 chars" : "multi-byte");
5645     }
5646     printf("\n");
5647     printf(" Keyboard character-sets:\n");
5648     printf("   Multinational: %s\n",txrinfo[dec_kbd]->keywd);
5649     printf("        National: %s\n",txrinfo[dec_nrc]->keywd);
5650     printf("\n");
5651     printf(" Printer character-set: %s\n",txrinfo[prncs]->keywd);
5652 #endif /* NOTERM */
5653 #else /* OS2 */
5654 #ifndef MAC
5655     char *s;
5656 
5657     debug(F101,"TERM LOCAL CSET","",csl);
5658     debug(F101,"TERM REMOTE CSET","",csr);
5659     printf(" Terminal character-set: ");
5660     if (tcs_transp) {                   /* No translation */
5661         printf("transparent\n");
5662     } else {                            /* Translation */
5663         printf("%s (remote) %s (local)\n",
5664                fcsinfo[csr].keyword,fcsinfo[csl].keyword);
5665         if (csr != csl) {
5666             switch(gettcs(csr,csl)) {
5667               case TC_USASCII:  s = "ascii";        break;
5668               case TC_1LATIN:   s = "latin1-iso";   break;
5669               case TC_2LATIN:   s = "latin2-iso";   break;
5670               case TC_CYRILL:   s = "cyrillic-iso"; break;
5671               case TC_JEUC:     s = "japanese-euc"; break;
5672               case TC_HEBREW:   s = "hebrew-iso";   break;
5673               case TC_GREEK:    s = "greek-iso";    break;
5674               case TC_9LATIN:   s = "latin9-iso";   break;
5675               default:          s = "transparent";  break;
5676             }
5677             if (strcmp(s,fcsinfo[csl].keyword) &&
5678                 strcmp(s,fcsinfo[csr].keyword))
5679               printf("                         (via %s)\n",s);
5680         }
5681     }
5682 #endif /* MAC */
5683 #endif /* OS2 */
5684 #endif /* NOCSETS */
5685 }
5686 
5687 #ifndef NOLOCAL
5688 #ifdef OS2
5689 extern char htab[];
5690 VOID
shotabs()5691 shotabs() {
5692     int i,j,k,n;
5693 
5694     printf("Tab Stops:\n\n");
5695     for (i = 0, j = 1, k = VscrnGetWidth(VCMD); i < MAXTERMCOL; ) {
5696         do {
5697             printf("%c",htab[++i]=='T'?'T':'-');
5698         } while (i % k && i < MAXTERMCOL);
5699         printf("\n");
5700         for ( ; j <= i; j++) {
5701             switch ( j%10 ) {
5702 	      case 1:
5703                 printf("%c",j == 1 ? '1' : '.');
5704                 break;
5705 	      case 2:
5706 	      case 3:
5707 	      case 4:
5708 	      case 5:
5709 	      case 6:
5710 	      case 7:
5711                 printf("%c",'.');
5712                 break;
5713 	      case 8:
5714                 n = (j+2)/100;
5715                 if (n)
5716 		  printf("%d",n);
5717                 else
5718 		  printf("%c",'.');
5719                 break;
5720 	      case 9:
5721                 n = (j+1)%100/10;
5722                 if (n)
5723 		  printf("%d",n);
5724                 else if (j>90)
5725 		  printf("0");
5726                 else
5727 		  printf("%c",'.');
5728                 break;
5729 	      case 0:
5730                 printf("0");
5731                 break;
5732             }
5733         }
5734         printf("\n");
5735     }
5736 #ifdef COMMENT
5737     for (i = 1; i <= 70; i++)
5738       printf("%c",htab[i]=='T'?'T':'-');
5739     printf("\n1.......10........20........30........40........50........60\
5740 ........70\n\n");
5741     for (; i <= 140; i++)
5742       printf("%c",htab[i]=='T'?'T':'-');
5743     printf("\n........80........90.......100.......110.......120.......130\
5744 .......140\n\n");
5745     for (; i <= 210; i++)
5746       printf("%c",htab[i]=='T'?'T':'-');
5747     printf("\n.......150.......160.......170.......180.......190.......200\
5748 .......210\n\n");
5749     for (; i <= 255; i++)
5750       printf("%c",htab[i]=='T'?'T':'-');
5751     printf("\n.......220.......230.......240.......250..255\n");
5752 #endif
5753 
5754 }
5755 #endif /* OS2 */
5756 #endif /* NOLOCAL */
5757 
5758 #ifdef OS2MOUSE
5759 VOID
shomou()5760 shomou() {
5761     int button, event, id, i;
5762     char * name = "";
5763 
5764     printf("Mouse settings:\n");
5765     printf("   Button Count:   %d\n",mousebuttoncount());
5766     printf("   Active:         %s\n\n",showoff(tt_mouse));
5767 
5768     for (button = 0; button < MMBUTTONMAX; button++)
5769       for (event = 0; event < MMEVENTSIZE; event++)
5770         if (mousemap[button][event].type != error)
5771           switch (mousemap[button][event].type) {
5772             case key:
5773               printf("   %s = Character: %c \\%d\n",
5774                      mousename(button,event),
5775                      mousemap[button][event].key.scancode,
5776                      mousemap[button][event].key.scancode );
5777               break;
5778             case kverb:
5779               id = mousemap[button][event].kverb.id & ~(F_KVERB);
5780               if (id != K_IGNORE) {
5781                   for (i = 0; i< nkverbs; i++)
5782                     if (id == kverbs[i].kwval) {
5783                         name = kverbs[i].kwd;
5784                         break;
5785                     }
5786                   printf("   %s = Kverb: \\K%s\n",
5787                          mousename(button,event),
5788                          name
5789                          );
5790               }
5791               break;
5792             case macro:
5793               printf("   %s = Macro: ",
5794                      mousename(button,event) );
5795               shostrdef(mousemap[button][event].macro.string);
5796               printf("\n");
5797               break;
5798           }
5799 }
5800 #endif /* OS2MOUSE */
5801 
5802 #ifndef NOLOCAL
5803 VOID
shotrm()5804 shotrm() {
5805     char *s;
5806     extern char * getiact();
5807     extern int tt_print, adl_err;
5808 #ifndef NOTRIGGER
5809     extern char * tt_trigger[];
5810 #endif /* NOTRIGGER */
5811 #ifdef CKTIDLE
5812     extern char * tt_idlesnd_str;
5813     extern int tt_idlesnd_tmo;
5814     extern int tt_idlelimit, tt_idleact;
5815 #endif /* CKTIDLE */
5816 #ifdef OS2
5817     extern int wy_autopage, autoscroll, sgrcolors, colorreset, user_erasemode,
5818       decscnm, decscnm_usr, tt_diff_upd, tt_senddata,
5819       wy_blockend, marginbell, marginbellcol, tt_modechg, dgunix;
5820     int lines = 0;
5821 #ifdef KUI
5822     extern CKFLOAT tt_linespacing[];
5823     extern tt_cursor_blink;
5824 #endif /* KUI */
5825 #ifdef PCFONTS
5826     int i;
5827     char *font;
5828 
5829     if (IsOS2FullScreen()) {            /* Determine the font name */
5830         if (!os2LoadPCFonts()) {
5831             for (i = 0; i < ntermfont; i++) {
5832                 if (tt_font == term_font[i].kwval) {
5833                     font = term_font[i].kwd;
5834                     break;
5835                 }
5836             }
5837         } else {
5838             font = "(DLL not available)";
5839         }
5840     } else {
5841         font =     "(full screen only)";
5842     }
5843 #endif /* PCFONTS */
5844 #ifdef KUI
5845     char font[64] = "(unknown)";
5846     if ( ntermfont > 0 ) {
5847         int i;
5848         for (i = 0; i < ntermfont; i++) {
5849             if (tt_font == term_font[i].kwval) {
5850                 ckstrncpy(font,term_font[i].kwd,59);
5851                 ckstrncat(font," ",64);
5852                 ckstrncat(font,ckitoa(tt_font_size/2),64);
5853                 if ( tt_font_size % 2 )
5854                     ckstrncat(font,".5",64);
5855                 break;
5856             }
5857         }
5858     }
5859 #endif /* KUI */
5860 
5861     printf("Terminal parameters:\n");
5862     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5863     printf(" %19s: %1d%-12s  %13s: %1d%-14s\n",
5864            "Bytesize: Command",
5865            (cmdmsk == 0377) ? 8 : 7,
5866            " bits","Terminal",
5867            (cmask == 0377) ? 8 : 7," bits");
5868     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5869     printf(" %19s: %-13s","Type",
5870            (tt_type >= 0 && tt_type <= max_tt) ?
5871            tt_info[tt_type].x_name :
5872            "unknown" );
5873     if (tt_type >= 0 && tt_type <= max_tt)
5874       if (strlen(tt_info[tt_type].x_id))
5875         printf("  %13s: <ESC>%s","ID",tt_info[tt_type].x_id);
5876     printf("\n");
5877     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5878     printf(" %19s: %-13s  %13s: %-15s\n","Echo",
5879            duplex ? "local" : "remote","Locking-shift",showoff(sosi));
5880     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5881     printf(" %19s: %-13s  %13s: %-15s\n","Newline-mode", showoff(tnlm),
5882 	   "Cr-display",tt_crd ? "crlf" : "normal");
5883     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5884     printf(" %19s: %-13s  %13s: %-15s\n","Cursor",
5885 #ifdef KUI
5886 	    (tt_cursor == 2) ? (tt_cursor_blink ?
5887 				 "full (*)" : "full (.)") :
5888 	    (tt_cursor == 1) ? (tt_cursor_blink ?
5889 				 "half (*)" : "half (.)") :
5890 	    (tt_cursor_blink ? "underline (*)" : "underline (.)"),
5891 #else /* KUI */
5892            (tt_cursor == 2) ? "full" :
5893            (tt_cursor == 1) ? "half" : "underline",
5894 #endif /* KUI */
5895 #ifdef CK_AUTODL
5896            "autodownload",autodl == TAD_ON ?
5897            (adl_err ? "on, error stop" : "on, error continue") :
5898            autodl == TAD_ASK ?
5899            (adl_err ? "ask, error stop" : "ask, error continue") :
5900            "off"
5901 #else /* CK_AUTODL */
5902            "", ""
5903 #endif /* CK_AUTODL */
5904            );
5905     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5906     printf(" %19s: %-13s  %13s: %-15s\n","Arrow-keys",
5907            tt_arrow ? "application" : "cursor",
5908            "Keypad-mode", tt_keypad ? "application" : "numeric"
5909            );
5910 
5911     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5912 
5913     /* Just to make sure we are using current info */
5914     updanswerbk();
5915 
5916     /*
5917        This line doesn't end with '\n' because the answerback string
5918        is terminated with a newline
5919     */
5920     printf(" %19s: %-13s  %13s: %-15s","Answerback",
5921            showoff(tt_answer),"response",answerback);
5922     switch (tt_bell) {
5923       case XYB_NONE:
5924         s = "none";
5925         break;
5926       case XYB_VIS:
5927         s= "visible";
5928         break;
5929       case XYB_AUD | XYB_BEEP:
5930         s="beep";
5931         break;
5932       case XYB_AUD | XYB_SYS:
5933         s="system sounds";
5934         break;
5935       default:
5936         s="(unknown)";
5937     }
5938     printf(" %19s: %-13s  %13s: %-15s\n","Bell",s,
5939            "Wrap",showoff(tt_wrap));
5940     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5941     printf(" %19s: %-13s  %13s: %-15s\n","Autopage",showoff(wy_autopage),
5942            "Autoscroll",showoff(autoscroll));
5943     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5944     printf(" %19s: %-13s  %13s: %-15s\n","SGR Colors",showoff(sgrcolors),
5945            "ESC[0m color",colorreset?"default-color":"current-color");
5946     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5947     printf(" %19s: %-13s  %13s: %-15s\n",
5948             "Erase color",user_erasemode?"default-color":"current-color",
5949            "Screen mode",decscnm?"reverse":"normal");
5950     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5951 
5952     printf(" %19s: %-13d  %13s: %-15d\n","Transmit-timeout",tt_ctstmo,
5953            "Output-pacing",tt_pacing);
5954     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5955 
5956     printf(" %19s: %-13d  %13s: %s\n","Idle-timeout",tt_idlelimit,
5957            "Idle-action", getiact());
5958 
5959     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5960     printf(" %19s: %-13s  %13s: %-15s\n","Send data",
5961           showoff(tt_senddata),"End of Block", wy_blockend?"crlf/etx":"us/cr");
5962     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5963 #ifndef NOTRIGGER
5964     printf(" %19s: %-13s  %13s: %d seconds\n","Auto-exit trigger",
5965            tt_trigger[0],"Output pacing",tt_pacing );
5966     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5967 #endif /* NOTRIGGER */
5968     printf(" %19s: %-13s  %13s: %-15d\n","Margin bell",
5969            showoff(marginbell),"at column", marginbellcol);
5970     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5971     switch (tt_modechg) {
5972       case TVC_DIS: s = "disabled"; break;
5973       case TVC_ENA: s = "enabled";  break;
5974       case TVC_W95: s = "win95-restricted"; break;
5975       default: s = "(unknown)";
5976     }
5977     printf(" %19s: %-13s  %13s: %-15s\n","DG Unix mode",
5978            showoff(dgunix),"Video change", s);
5979     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
5980 
5981 #ifdef CK_APC
5982     if (apcstatus == APC_ON) s = "on";
5983     else if (apcstatus == APC_OFF) s = "off";
5984     else if (apcstatus == APC_ON|APC_UNCH) s = "unchecked";
5985     else if (apcstatus == APC_ON|APC_NOINP) s = "no-input";
5986     else if (apcstatus == APC_ON|APC_UNCH|APC_NOINP) s = "unchecked-no-input";
5987     printf(" %19s: %-13s  %13s: %-15s\n",
5988            "APC", s,
5989 #ifdef PCFONTS
5990            "Font (VGA)",font
5991 #else /* PCFONTS */
5992 #ifdef KUI
5993            "Font",font
5994 #else
5995            "Font","(not supported)"
5996 #endif /* KUI */
5997 #endif /* PCFONTS */
5998 
5999            );
6000 #endif /* CK_APC */
6001     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
6002 
6003 #ifdef CK_TTGWSIZ                       /* Console terminal screen size */
6004     if (tt_cols[VTERM] < 0 || tt_rows[VTERM] < 0)
6005       ttgwsiz();                        /* Try to get latest size */
6006 #endif /* CK_TTGWSIZ */
6007     printf(" %19s: %-13d  %13s: %-15d\n","Height",tt_rows[VTERM],
6008            "Width",tt_cols[VTERM]);
6009     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
6010 #ifdef KUI
6011     printf(" %19s: %-12f  %14s: %-15d\n","Line spacing",tt_linespacing[VTERM],
6012            "Display Height",VscrnGetDisplayHeight(VTERM));
6013     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
6014 #endif /* KUI */
6015     printf(" %19s: %-13s  %13s: %d lines\n","Roll-mode",
6016           tt_roll[VTERM]?"insert":"overwrite","Scrollback", tt_scrsize[VTERM]);
6017     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
6018 
6019     if (updmode == tt_updmode)
6020       if (updmode == TTU_FAST)
6021         s = "fast (fast)";
6022       else
6023         s = "smooth (smooth)";
6024     else
6025       if (updmode == TTU_FAST)
6026         s = "fast (smooth)";
6027       else
6028         s = "smooth (fast)";
6029 
6030     printf(" %19s: %-13s  %13s: %d ms\n","Screen-update: mode",s,
6031            "interval",tt_update);
6032     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
6033     printf(" %19s: %-13s  %13s: %-15s\n",
6034            "Screen-optimization",showoff(tt_diff_upd),
6035            "Status line",showoff(tt_status[VTERM]));
6036     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
6037     printf(" %19s: %-13s  %13s: %-15s\n","Debug",
6038            showoff(debses),"Session log", seslog? sesfil : "(none)" );
6039     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
6040 
6041     /* Display colors (should become SHOW COLORS) */
6042     {
6043         USHORT row, col;
6044         char * colors[16] = {
6045             "black","blue","green","cyan","red","magenta","brown","lgray",
6046             "dgray","lblue","lgreen","lcyan","lred","lmagent","yellow","white"
6047         };
6048         printf("\n");
6049         if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
6050 
6051         printf(" Color:");
6052 #ifndef ONETERMUPD
6053         GetCurPos(&row, &col);
6054         WrtCharStrAtt("border",    6, row, 9, &colorborder );
6055         WrtCharStrAtt("debug",     5, row, 17, &colordebug );
6056         WrtCharStrAtt("helptext",  8, row, 25, &colorhelp );
6057         WrtCharStrAtt("reverse",   7, row, 34, &colorreverse );
6058         WrtCharStrAtt("select",    6, row, 42, &colorselect );
6059         WrtCharStrAtt("status",    6, row, 50, &colorstatus );
6060         WrtCharStrAtt("terminal",  8, row, 58, &colornormal );
6061         WrtCharStrAtt("underline", 9, row, 67, &colorunderline );
6062 #endif /* ONETERMUPD */
6063         row = VscrnGetCurPos(VCMD)->y+1;
6064         VscrnWrtCharStrAtt(VCMD, "border",    6, row, 9, &colorborder );
6065         VscrnWrtCharStrAtt(VCMD, "debug",     5, row, 17, &colordebug );
6066         VscrnWrtCharStrAtt(VCMD, "helptext",  8, row, 25, &colorhelp );
6067         VscrnWrtCharStrAtt(VCMD, "reverse",   7, row, 34, &colorreverse );
6068         VscrnWrtCharStrAtt(VCMD, "select",    6, row, 42, &colorselect );
6069         VscrnWrtCharStrAtt(VCMD, "status",    6, row, 50, &colorstatus );
6070         VscrnWrtCharStrAtt(VCMD, "terminal",  8, row, 58, &colornormal );
6071         VscrnWrtCharStrAtt(VCMD, "underline",  9, row, 67, &colorunderline );
6072         printf("\n");
6073         if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
6074 
6075         /* Foreground color names */
6076         printf("%6s: %-8s%-8s%-9s%-8s%-8s%-8s%-9s%-9s\n","fore",
6077                 "",
6078                 colors[colordebug&0x0F],
6079                 colors[colorhelp&0x0F],
6080                 colors[colorreverse&0x0F],
6081                 colors[colorselect&0x0F],
6082                 colors[colorstatus&0x0F],
6083                 colors[colornormal&0x0F],
6084                 colors[colorunderline&0x0F]);
6085         if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
6086 
6087         /* Background color names */
6088         printf("%6s: %-8s%-8s%-9s%-8s%-8s%-8s%-9s%-9s\n","back",
6089                 colors[colorborder],
6090                 colors[colordebug>>4],
6091                 colors[colorhelp>>4],
6092                 colors[colorreverse>>4],
6093                 colors[colorselect>>4],
6094                 colors[colorstatus>>4],
6095                 colors[colornormal>>4],
6096                 colors[colorunderline>>4] );
6097         if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
6098         printf("\n");
6099         if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
6100         printf(" Color:");
6101 #ifndef ONETERMUPD
6102         GetCurPos(&row, &col);
6103         WrtCharStrAtt("graphic",   7, row, 9, &colorgraphic );
6104         WrtCharStrAtt("command",   7, row, 17, &colorcmd );
6105         WrtCharStrAtt("italic",    6, row, 26, &coloritalic );
6106 #endif /* ONETERMUPD */
6107         row = VscrnGetCurPos(VCMD)->y+1;
6108         VscrnWrtCharStrAtt(VCMD, "graphic",   7, row, 9,  &colorgraphic );
6109         VscrnWrtCharStrAtt(VCMD, "command",   7, row, 17, &colorcmd );
6110         VscrnWrtCharStrAtt(VCMD, "italic",    6, row, 26, &coloritalic );
6111         printf("\n");
6112         if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
6113 
6114         /* Foreground color names */
6115         printf("%6s: %-8s%-8s%-8s\n","fore",
6116                 colors[colorgraphic&0x0F],
6117                 colors[colorcmd&0x0F],
6118                 colors[coloritalic&0x0F]);
6119         if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
6120 
6121         /* Background color names */
6122         printf("%6s: %-8s%-8s%-8s\n","back",
6123                 colors[colorgraphic>>4],
6124                 colors[colorcmd>>4],
6125                 colors[coloritalic>>4]);
6126         if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
6127     }
6128     printf("\n");
6129     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
6130     {
6131         extern int trueblink, truedim, truereverse, trueunderline, trueitalic;
6132         printf(
6133 	    " Attribute:  \
6134 blink: %-3s  dim: %-3s  italic: %-3s  reverse: %-3s  underline: %-3s\n",
6135 	    trueblink?"on":"off", truedim?"on":"off", trueitalic?"on":"off",
6136 	    truereverse?"on":"off", trueunderline?"on":"off");
6137         if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
6138     }
6139     {
6140         extern vtattrib WPattrib;
6141         printf(" ASCII Protected chars: %s%s%s%s%s%s%s\n",
6142                 WPattrib.blinking?"blink ":"",
6143                 WPattrib.italic?"italic ":"",
6144                 WPattrib.reversed?"reverse ":"",
6145                 WPattrib.underlined?"underline ":"",
6146                 WPattrib.bold?"bold ":"",
6147                 WPattrib.dim?"dim ":"",
6148                 WPattrib.invisible?"invisible ":"");
6149         if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
6150     }
6151 
6152     printf("\n");
6153     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
6154     (VOID) shoesc(escape);
6155     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
6156     printf(" See SHOW CHARACTER-SETS for character-set info\n");
6157     if (++lines > cmd_rows - 3) { if (!askmore()) return; else lines = 0; }
6158 
6159 #else /* OS2 */   /* Beginning of new non-OS2 version */
6160 
6161     printf("\n");
6162     printf("Terminal parameters:\n");
6163     printf(" %19s: %1d%-12s  %13s: %1d%-14s\n",
6164            "Bytesize: Command",
6165            (cmdmsk == 0377) ? 8 : 7,
6166            " bits","Terminal",
6167            (cmask == 0377) ? 8 : 7," bits");
6168     s = getenv("TERM");
6169 #ifdef XPRINT
6170     printf(" %19s: %-13s  %13s: %-15s\n",
6171            "Type",
6172            s ? s : "(unknown)",
6173            "Print",
6174            showoff(tt_print)
6175            );
6176 #else
6177     printf(" %19s: %-13s\n","Type", s ? s : "(unknown)");
6178 #endif /* XPRINT */
6179     printf(" %19s: %-13s  %13s: %-15s\n","Echo",
6180            duplex ? "local" : "remote","Locking-shift",showoff(sosi));
6181     printf(" %19s: %-13s  %13s: %-15s\n","Newline-mode",
6182            showoff(tnlm),"Cr-display",tt_crd ? "crlf" : "normal");
6183 
6184 #ifdef CK_APC
6185     if (apcstatus == APC_ON) s = "on";
6186     else if (apcstatus == APC_OFF) s = "off";
6187     else if (apcstatus == (APC_ON|APC_UNCH)) s = "unchecked";
6188     else if (apcstatus == (APC_ON|APC_NOINP)) s = "no-input";
6189     else if (apcstatus == (APC_ON|APC_UNCH|APC_NOINP))
6190       s = "unchecked-no-input";
6191     printf(" %19s: %-13s  %13s: %-15s\n",
6192            "APC", s,
6193 #ifdef CK_AUTODL
6194            "Autodownload", autodl ?
6195            (adl_err ? "on, error stop" : "on, error continue") : "off"
6196 #else
6197            "",""
6198 #endif /* CK_AUTODL */
6199            );
6200 #endif /* CK_APC */
6201 
6202 #ifdef CK_TTGWSIZ                       /* Console terminal screen size */
6203     ttgwsiz();                          /* Try to get latest size */
6204     printf(" %19s: %-13d  %13s: %-15d\n","Height",tt_rows, "Width", tt_cols);
6205 #endif /* CK_TTGWSIZ */
6206 
6207     printf(" %19s: %-13s  %13s: %-15s\n","Debug",
6208            showoff(debses),"Session log", seslog? sesfil : "(none)" );
6209 
6210 #ifdef CKTIDLE
6211     printf(" %19s: %-13d  %13s: %s\n","Idle-timeout",tt_idlelimit,
6212            "Idle-action", getiact());
6213 #endif /* CKTIDLE */
6214 
6215     printf(" %19s: %-13s  ","Lf-display", tt_lfd ? "crlf" : "normal");
6216 #ifdef UNIX
6217 #ifndef NOJC
6218     printf("%13s: %-15s","Suspend", showoff(xsuspend));
6219 #endif /* NOJC */
6220 #endif /* UNIX */
6221     printf("\n");
6222 
6223 #ifndef NOTRIGGER
6224     printf(" %19s: %-13s\n","Trigger",
6225            tt_trigger[0] ? tt_trigger[0] : "(none)");
6226 #endif /* NOTRIGGER */
6227     printf("\n");
6228 
6229     (VOID) shoesc(escape);
6230 #ifndef NOCSETS
6231     shotcs(tcsl,tcsr);          /* Show terminal character sets */
6232 #endif /* NOCSETS */
6233 
6234 #endif /* OS2 */
6235 }
6236 
6237 VOID
shmdmlin()6238 shmdmlin() {                            /* Briefly show modem & line */
6239 #ifndef NODIAL
6240 #ifndef MINIDIAL
6241 #ifdef OLDTBCODE
6242     extern int tbmodel;
6243     _PROTOTYP( char * gtbmodel, (void) );
6244 #endif /* OLDTBCODE */
6245 #endif /* MINIDIAL */
6246 #endif /* NODIAL */
6247     if (local)
6248 #ifdef OS2
6249       printf(" Port: %s, Modem type: ",ttname);
6250 #else
6251       printf(" Line: %s, Modem type: ",ttname);
6252 #endif /* OS2 */
6253     else
6254       printf(
6255 #ifdef OS2
6256 " Communication device not yet selected with SET PORT\n Modem type: "
6257 #else
6258 " Communication device not yet selected with SET LINE\n Modem type: "
6259 #endif /* OS2 */
6260              );
6261 #ifndef NODIAL
6262     printf("%s",gmdmtyp());
6263 #ifndef MINIDIAL
6264 #ifdef OLDTBCODE
6265     if (tbmodel) printf(" (%s)",gtbmodel()); /* Telebit model info */
6266 #endif /* OLDTBCODE */
6267 #endif /* MINIDIAL */
6268 #else
6269     printf("(disabled)");
6270 #endif /* NODIAL */
6271 }
6272 
6273 #ifdef CK_TAPI
6274 void
shotapi(int option)6275 shotapi(int option) {
6276     int rc=0,k ;
6277     char *s=NULL;
6278     LPDEVCFG        lpDevCfg = NULL;
6279     LPCOMMCONFIG    lpCommConfig = NULL;
6280     LPMODEMSETTINGS lpModemSettings = NULL;
6281     DCB *           lpDCB = NULL;
6282     extern struct keytab * tapiloctab;  /* Microsoft TAPI Locations */
6283     extern int ntapiloc;
6284     extern struct keytab * tapilinetab; /* Microsoft TAPI Line Devices */
6285     extern int ntapiline;
6286     extern int tttapi;                  /* TAPI in use */
6287     extern int tapipass;                /* TAPI Passthrough mode */
6288     extern int tapiconv;                /* TAPI Conversion mode */
6289     extern int tapilights;
6290     extern int tapipreterm;
6291     extern int tapipostterm;
6292     extern int tapimanual;
6293     extern int tapiinactivity;
6294     extern int tapibong;
6295     extern int tapiusecfg;
6296     extern char tapiloc[];
6297     extern int tapilocid;
6298     extern int TAPIAvail;
6299 
6300     if (!TAPIAvail) {
6301         printf("TAPI Support not enabled\r\n");
6302         return;
6303     }
6304     switch (option) {
6305       case 0:
6306         printf("TAPI Settings:\n");
6307         printf("  Line:                      %s\n",
6308                tttapi ? ttname : "(none in use)");
6309 
6310         cktapiBuildLocationTable(&tapiloctab, &ntapiloc);
6311         if (tapilocid == -1)
6312           tapilocid = cktapiGetCurrentLocationID();
6313 
6314         /* Find the current tapiloc entry */
6315         /* and use it as the default. */
6316         for (k = 0; k < ntapiloc; k++) {
6317             if (tapiloctab[k].kwval == tapilocid)
6318               break;
6319         }
6320         if (k >= 0 && k < ntapiloc)
6321           s = tapiloctab[k].kwd;
6322         else
6323           s = "(unknown)";
6324         printf("  Location:                  %s\n",s);
6325         printf("  Modem-dialing:             %s\n",tapipass?"off":"on");
6326         printf("  Phone-number-conversions:  %s\n",
6327                 tapiconv==CK_ON?"on":tapiconv==CK_AUTO?"auto":"off");
6328         printf("  Modem-lights:              %s %s\n",tapilights?"on ":"off",
6329                 tapipass?"(n/a)":"");
6330         printf("  Predial-terminal:          %s %s\n",tapipreterm?"on ":"off",
6331                 tapipass?"(n/a)":"");
6332         printf("  Postdial-terminal:         %s %s\n",tapipostterm?"on ":"off",
6333                 tapipass?"(n/a)":"");
6334         printf("  Manual-dial:               %s %s\n",tapimanual?"on ":"off",
6335                 tapipass?"(n/a)":"");
6336         printf("  Inactivity-timeout:        %d seconds %s\n",tapiinactivity,
6337                 tapipass?"(n/a)":"");
6338         printf("  Wait-for-bong:             %d seconds %s\n",tapibong,
6339                 tapipass?"(n/a)":"");
6340         printf("  Use-windows-configuration: %s %s\n",
6341                 tapiusecfg?"on ":"off", tapipass?"(n/a)":"");
6342         printf("\n");
6343 
6344 #ifdef BETATEST
6345         if (tapipass) {
6346 printf("K-95 uses the TAPI Line in an exclusive mode.  Other applications\n");
6347 printf("may open the device but may not place calls nor answer calls.\n");
6348 printf("Dialing is performed using the K-95 dialing procedures.  SET MODEM\n");
6349 printf("TYPE TAPI after the SET TAPI LINE command to activate the modem\n");
6350 printf("definition associated with the active TAPI LINE device.\n\n");
6351 
6352         } else {
6353 
6354 printf("K-95 uses the TAPI Line in a cooperative mode.  Other applications\n");
6355 printf("may open the device, place and answer calls.  Dialing is performed\n");
6356 printf("by TAPI.  K-95 SET MODEM commands are not used.\n\n");
6357         }
6358 
6359         if (tapiconv == CK_ON ||
6360             tapiconv == CK_AUTO && !tapipass) {
6361 printf(
6362 "Phone numbers are converted from canonical to dialable form by TAPI\n");
6363 printf("using the dialing rules specified in the TAPI Dialing Properties\n");
6364 printf("dialog.\n\n");
6365 
6366         } else {
6367 
6368 printf(
6369 "Phone numbers are converted from canonical to dialable form by K-95\n");
6370 printf(
6371 "using the dialing rules specified with the SET DIAL commands.  TAPI\n");
6372 printf(
6373 "Dialing Properties are imported automaticly upon startup and whenever\n");
6374 printf("the TAPI Dialing Properties are altered or when the TAPI Location\n");
6375 printf("is changed.\n\n");
6376         }
6377 #endif /* BETATEST */
6378 
6379         if (tapipass) {
6380             printf("Type SHOW MODEM to see MODEM configuration.\n");
6381             if (tapiconv == CK_ON)
6382               printf("Type SHOW DIAL to see DIAL-related items.\n");
6383         } else {
6384             if (tapiconv == CK_ON || tapiconv == CK_AUTO)
6385               printf("Type SHOW DIAL to see DIAL-related items.\n");
6386         }
6387         break;
6388       case 1:
6389         cktapiDisplayTapiLocationInfo();
6390         break;
6391       case 2:
6392         rc = cktapiGetModemSettings(&lpDevCfg,&lpModemSettings,
6393                                      &lpCommConfig,&lpDCB);
6394         if (rc) {
6395             cktapiDisplayModemSettings(lpDevCfg,lpModemSettings,
6396                                          lpCommConfig,lpDCB);
6397         } else {
6398             printf("?Unable to retrieve Modem Settings\n");
6399         }
6400         break;
6401       case 3: {
6402           HANDLE hModem = GetModemHandleFromLine((HLINE)0);
6403           if (hModem)
6404             DisplayCommProperties(hModem);
6405           else
6406             printf("?Unable to retrieve a valid Modem Handle\n");
6407           CloseHandle(hModem);
6408           break;
6409       }
6410     }
6411     printf("\n");
6412 }
6413 #endif /* CK_TAPI */
6414 #endif /* NOLOCAL */
6415 
6416 #ifdef PATTERNS
6417 static VOID
shopat()6418 shopat() {
6419     extern char * binpatterns[], * txtpatterns[];
6420     extern int patterns, filepeek;
6421     char **p, *s;
6422     int i, j, k, n, flag, width;
6423 #ifdef CK_TTGWSIZ
6424     ttgwsiz();                          /* Try to get latest size */
6425 #ifdef OS2
6426     width = tt_cols[VCMD];
6427 #else /* OS2 */
6428     width = tt_cols;
6429 #endif /* OS2 */
6430     if (width < 1)
6431 #endif /* CK_TTGWSIZ */
6432       width = 80;
6433     printf("\n");
6434     printf(" Set file type:            %s\n",gfmode(binary,1));
6435     printf(" Set file patterns:        %s", showooa(patterns));
6436 #ifdef CK_LABELED
6437     if (binary == XYFT_L)
6438       printf(" (but SET FILE TYPE LABELED overrides)\n");
6439     else
6440 #endif /* CK_LABELED */
6441 #ifdef VMS
6442     if (binary == XYFT_I)
6443       printf(" (but SET FILE TYPE IMAGE overrides)\n");
6444     else
6445 #endif /* VMS */
6446     if (filepeek)
6447       printf(" (but SET FILE SCAN ON overrides)\n");
6448     else
6449       printf("\n");
6450     printf(" Maximum patterns allowed: %d\n", FTPATTERNS);
6451     for (k = 0; k < 2; k++) {           /* For each kind of patter */
6452         printf("\n");
6453         if (k == 0) {                   /* binary... */
6454             printf(" File binary-patterns: ");
6455             p = binpatterns;
6456         } else {                        /* text... */
6457             printf(" File text-patterns:   ");
6458             p = txtpatterns;
6459         }
6460         if (!p[0]) {
6461             printf("(none)\n");
6462         } else {
6463             printf("\n ");
6464             n = 2;
6465             for (i = 0; i < FTPATTERNS; i++) { /* For each pattern */
6466                 if (!p[i])              /* Done */
6467                   break;
6468                 s = p[i];               /* Look for embedded space */
6469                 for (j = 0, flag = 1; *s; s++, j++) /* and also get length */
6470                   if (*s == SP)
6471                     flag = 3;
6472                 n += j + flag;          /* Length of this line */
6473                 if (n >= width - 1) {
6474                     printf("\n ");
6475                     n = j+2;
6476                 }
6477                 printf(flag == 3 ? " {%s}" : " %s", p[i]);
6478             }
6479             if (n > 2)
6480               printf("\n");
6481         }
6482     }
6483     printf("\n");
6484 }
6485 #endif /* PATTERNS */
6486 
6487 #ifndef NOSPL
6488 static VOID
shooutput()6489 shooutput() {
6490     printf(" Output pacing:          %d (milliseconds)\n",pacing);
6491     printf(" Output special-escapes: %s\n", showoff(outesc));
6492 }
6493 
6494 static VOID
shoinput()6495 shoinput() {
6496 #ifdef CKFLOAT
6497     extern char * inpscale;
6498 #endif	/* CKFLOAT */
6499 
6500 #ifdef CK_AUTODL
6501     printf(" Input autodownload:     %s\n", showoff(inautodl));
6502 #endif /* CK_AUTODL */
6503     printf(" Input cancellation:     %s\n", showoff(inintr));
6504     printf(" Input case:             %s\n", inpcas[cmdlvl] ?
6505            "observe" : "ignore");
6506     printf(" Input buffer-length:    %d\n", inbufsize);
6507     printf(" Input echo:             %s\n", showoff(inecho));
6508     printf(" Input silence:          %d (seconds)\n", insilence);
6509 #ifdef OS2
6510     printf(" Input terminal:         %s\n", showoff(interm));
6511 #endif /* OS2 */
6512     printf(" Input timeout:          %s\n", intime[cmdlvl] ?
6513            "quit" : "proceed");
6514 #ifdef CKFLOAT
6515     printf(" Input scale-factor:     %s\n", inpscale ? inpscale : "1.0");
6516 #endif	/* CKFLOAT */
6517 
6518     if (instatus < 0)
6519       printf(" Last INPUT:             -1 (INPUT command not yet given)\n");
6520     else
6521       printf(" Last INPUT:             %d (%s)\n", instatus,i_text[instatus]);
6522 }
6523 #endif /* NOSPL */
6524 
6525 #ifndef NOSPL
6526 int
showarray()6527 showarray() {
6528 #ifdef COMMENT
6529     char * p, * q, ** ap;
6530     int i;
6531 #endif /* COMMENT */
6532     char *s; int x = 0, y;
6533     int range[2];
6534 
6535     if ((y = cmfld("Array name","",&s,NULL)) < 0)
6536       if (y != -3)
6537         return(y);
6538     ckstrncpy(line,s,LINBUFSIZ);
6539     s = line;
6540     if ((y = cmcfm()) < 0)
6541       return(y);
6542     if (*s) {
6543         char ** ap;
6544         if ((x = arraybounds(s,&(range[0]),&(range[1]))) < 0) {
6545             printf("?Bad array: %s\n",s);
6546             return(-9);
6547         }
6548         ap = a_ptr[x];
6549         if (!ap) {
6550             printf("Array not declared: %s\n", s);
6551             return(success = 1);
6552         } else {
6553             int i, n, max;
6554             max = (range[1] > 0) ?
6555               range[1] :
6556                 ((range[0] > 0) ? range[0] : a_dim[x]);
6557             if (range[0] < 0)
6558               range[0] = 0;
6559             if (max > a_dim[x])
6560               max = a_dim[x];
6561             n = 1;
6562             printf("\\&%c[]: Dimension = %d",arrayitoa(x),a_dim[x]);
6563             if (a_link[x] > -1)
6564               printf(" (Link to \\&%c[])",arrayitoa(a_link[x]));
6565             printf("\n");
6566             for (i = range[0]; i <= max; i++) {
6567                 if (ap[i]) {
6568                     printf("%3d. %s\n",i,ap[i]);
6569                     if (xaskmore) {
6570                         if (cmd_cols > 0) {
6571                             x = strlen(ap[i]) + 5;
6572                             y = (x % cmd_cols) ? 1 : 0;
6573                             n += (x / cmd_cols) + y;
6574                         } else {
6575                             n++;
6576                         }
6577                         if (n > (cmd_rows - 3)) {
6578                             if (!askmore())
6579                               break;
6580                             else
6581                               n = 0;
6582                         }
6583                     }
6584                 }
6585             }
6586         }
6587         return(1);
6588     }
6589 
6590     /* All arrays - just show name and dimension */
6591 
6592     for (y = 0; y < (int) 'z' - ARRAYBASE + 1; y++) {
6593         if (a_ptr[y]) {
6594             if (x == 0) printf("Declared arrays:\n");
6595             x = 1;
6596             printf(" \\&%c[%d]",
6597                    (y == 1) ? 64 : y + ARRAYBASE, a_dim[y]);
6598             if (a_link[y] > -1)
6599               printf(" => \\&%c[]",arrayitoa(a_link[y]));
6600             printf("\n");
6601         }
6602         if (!x) printf(" No arrays declared\n");
6603     }
6604     return(1);
6605 }
6606 #endif /* NOSPL */
6607 
6608 int
doshow(x)6609 doshow(x) int x; {
6610     int y, z, i; long zz;
6611     extern int optlines;
6612     char *s;
6613 #ifdef OS2
6614     extern int os2gks;
6615     extern int tt_kb_mode;
6616 #endif /* OS2 */
6617     extern int srvcdmsg;
6618     extern char * cdmsgstr, * ckcdpath;
6619     char fnbuf[100];
6620 
6621 #ifndef NOSETKEY
6622     if (x == SHKEY) {                   /* SHOW KEY */
6623         int c;
6624 #ifdef OS2
6625         if ((x = cmkey(shokeytab,nshokey,"How many keys should be shown?",
6626                         "one",xxstring)) < 0) return(x);
6627         switch (tt_kb_mode) {
6628           case KBM_EM:
6629             s = "emacs";
6630             break;
6631           case KBM_HE:
6632             s = "hebrew";
6633             break;
6634           case KBM_RU:
6635             s = "russian";
6636             break;
6637           case KBM_EN:
6638           default:
6639             s = "default";
6640             break;
6641         }
6642         if ((z = cmkey(shokeymtab,nshokeym,"Which definition should be shown?",
6643                         s,xxstring)) < 0) return(z);
6644         if (z == SHKEYDEF)
6645           z = -1;
6646 #endif /* OS2 */
6647 
6648         if ((y = cmcfm()) < 0) return(y);
6649 
6650 #ifdef IKSD
6651         if (inserver) {
6652             printf("Sorry, command disabled.\r\n");
6653             return(success = 0);
6654         }
6655 #endif /* IKSD */
6656 
6657 #ifdef MAC
6658         printf("Not implemented\n");
6659         return(0);
6660 #else /* Not MAC */
6661 #ifdef OS2
6662         if (x) {
6663             con_event evt;
6664             for (c = 0; c < KMSIZE; c++) {
6665                 evt = (z < 0) ? mapkey(c) : maptermkey(c,z);
6666                 if (evt.type != error) {
6667                     shokeycode(c,z);
6668                 }
6669             }
6670         } else {
6671 #endif /* OS2 */
6672             printf(" Press key: ");
6673 #ifdef UNIX
6674 #ifdef NOSETBUF
6675             fflush(stdout);
6676 #endif /* NOSETBUF */
6677 #endif /* UNIX */
6678             conbin((char)escape);       /* Put terminal in binary mode */
6679 #ifdef OS2
6680             os2gks = 0;                 /* Raw scancode processing */
6681 #endif /* OS2 */
6682             c = congks(0);              /* Get character or scan code */
6683 #ifdef OS2
6684             os2gks = 1;                 /* Cooked scancode processing */
6685 #endif /* OS2 */
6686             concb((char)escape);        /* Restore terminal to cbreak mode */
6687             if (c < 0) {                /* Check for error */
6688                 printf("?Error reading key\n");
6689                 return(0);
6690             }
6691 #ifndef OS2
6692 /*
6693   Do NOT mask when it can be a raw scan code, perhaps > 255
6694 */
6695             c &= cmdmsk;                /* Apply command mask */
6696 #endif /* OS2 */
6697             printf("\n");
6698 #ifdef OS2
6699             shokeycode(c,z);
6700 #else /* OS2 */
6701             shokeycode(c);
6702 #endif /* OS2 */
6703 #ifdef OS2
6704         }
6705 #endif /* OS2 */
6706         return(1);
6707 #endif /* MAC */
6708     }
6709 #ifndef NOKVERBS
6710     if (x == SHKVB) {                   /* SHOW KVERBS */
6711         if ((y = cmcfm()) < 0) return(y);
6712 #ifdef IKSD
6713         if (inserver) {
6714             printf("Sorry, command disabled.\r\n");
6715             return(success = 0);
6716         }
6717 #endif /* IKSD */
6718         printf("\nThe following %d keyboard verbs are available:\n\n",nkverbs);
6719         kwdhelp(kverbs,nkverbs,"","\\K","",3,0);
6720         printf("\n");
6721         return(1);
6722     }
6723 #ifdef OS2
6724     if (x == SHUDK) {                   /* SHOW UDKs */
6725         extern void showudk(void);
6726         if ((y = cmcfm()) < 0) return(y);
6727 #ifdef IKSD
6728         if (inserver) {
6729             printf("Sorry, command disabled.\r\n");
6730             return(success = 0);
6731         }
6732 #endif /* IKSD */
6733         showudk();
6734         return(1);
6735     }
6736 #endif /* OS2 */
6737 #endif /* NOKVERBS */
6738 #endif /* NOSETKEY */
6739 
6740 #ifndef NOSPL
6741     if (x == SHMAC) {                   /* SHOW MACRO */
6742         struct FDB kw, fl, cm;
6743         int i, k, n = 0, left, flag, confirmed = 0;
6744         char * p, *q[64];
6745         for (i = 0; i < nmac; i++) {    /* copy the macro table */
6746             mackey[i].kwd = mactab[i].kwd; /* into a regular keyword table */
6747             mackey[i].kwval = i;        /* with value = pointer to macro tbl */
6748             mackey[i].flgs = mactab[i].flgs;
6749         }
6750         p = line;
6751         left = LINBUFSIZ;
6752         while (!confirmed && n < 64) {
6753             cmfdbi(&kw,                 /* First FDB - macro table */
6754                    _CMKEY,              /* fcode */
6755                    "Macro name",        /* hlpmsg */
6756                    "",                  /* default */
6757                    "",                  /* addtl string data */
6758                    nmac,                /* addtl numeric data 1: tbl size */
6759                    0,                   /* addtl numeric data 2: 4 = cmswi */
6760                    xxstring,            /* Processing function */
6761                    mackey,              /* Keyword table */
6762                    &fl                  /* Pointer to next FDB */
6763                    );
6764             cmfdbi(&fl,                 /* 2nd FDB - something not in mactab */
6765                    _CMFLD,              /* fcode */
6766                    "",                  /* hlpmsg */
6767                    "",                  /* default */
6768                    "",                  /* addtl string data */
6769                    0,                   /* addtl numeric data 1 */
6770                    0,                   /* addtl numeric data 2 */
6771                    xxstring,
6772                    NULL,
6773                    &cm
6774                    );
6775             cmfdbi(&cm,                 /* 3rd FDB - Confirmation */
6776                    _CMCFM,              /* fcode */
6777                    "",                  /* hlpmsg */
6778                    "",                  /* default */
6779                    "",                  /* addtl string data */
6780                    0,                   /* addtl numeric data 1 */
6781                    0,                   /* addtl numeric data 2 */
6782                    NULL,
6783                    NULL,
6784                    NULL
6785                    );
6786             x = cmfdb(&kw);             /* Parse something */
6787             if (x < 0)
6788               return(x);
6789             s = atmbuf;                 /* What the user typed */
6790             switch (cmresult.fcode) {
6791               case _CMKEY:              /* If it was a keyword */
6792                 y = mlook(mactab,atmbuf,nmac); /* get full name */
6793                 if (y > -1)
6794                   s = mactab[y].kwd;    /* (fall thru on purpose...) */
6795               case _CMFLD:
6796                 k = ckstrncpy(p,s,left) + 1; /* Copy result to list */
6797                 left -= k;
6798                 if (left <= 0) {
6799                     *p = NUL;
6800                     break;
6801                 }
6802                 q[n++] = p;             /* Point to this item */
6803                 p += k;                 /* Move buffer pointer past it */
6804                 break;
6805               case _CMCFM:              /* End of command */
6806                 confirmed++;
6807               default:
6808                 break;
6809             }
6810         }
6811         if (n == 0) {
6812             printf("Macros:\n");
6813             slc = 1;
6814             for (y = 0; y < nmac; y++)
6815               if (shomac(mactab[y].kwd,mactab[y].mval) < 0) break;
6816             return(1);
6817         }
6818         slc = 0;
6819         for (i = 0; i < n; i++) {
6820             flag = 0;
6821             s = q[i];
6822             if (!s) s = "";
6823             if (!*s) continue;
6824             if (iswild(s)) {            /* Pattern match */
6825                 for (k = 0, x = 0; x < nmac; x++) {
6826                     if (ckmatch(s,mactab[x].kwd,0,1)) {
6827                         shomac(mactab[x].kwd,mactab[x].mval);
6828                         k++;
6829                     }
6830                 }
6831                 if (!k)
6832                   x = -1;
6833                 else
6834                   continue;
6835             } else {                    /* Exact match */
6836                 x = mxlook(mactab,s,nmac);
6837                 flag = 1;
6838             }
6839             if (flag && x == -1)
6840               x = mlook(mactab,s,nmac);
6841             switch (x) {
6842               case -3:                  /* Nothing to look up */
6843               case -1:                  /* Not found */
6844                 printf("%s - (not defined)\n",s);
6845                 break;
6846               case -2:                  /* Ambiguous, matches more than one */
6847                 printf("%s - ambiguous\n",s);
6848                 break;
6849               default:                  /* Matches one exactly */
6850                 shomac(mactab[x].kwd,mactab[x].mval);
6851                 break;
6852             }
6853         }
6854         return(1);
6855     }
6856 #endif /* NOSPL */
6857 
6858 /*
6859   Other SHOW commands only have two fields.  Get command confirmation here,
6860   then handle with big switch() statement.
6861 */
6862 #ifndef NOSPL
6863     if (x != SHBUI && x != SHARR)
6864 #endif /* NOSPL */
6865       if (x == SHFUN) {                 /* For SHOW FUNCTIONS */
6866           int y;
6867           if ((y = cmtxt("Match string for function names","",&s,NULL)) < 0)
6868             return(y);
6869           fnbuf[0] = NUL;
6870           if (!s) s = "";
6871           if (*s) ckstrncpy(fnbuf,s,100);
6872       } else {
6873           if ((y = cmcfm()) < 0)
6874             return(y);
6875       }
6876 #ifdef COMMENT
6877     /* This restriction is too general. */
6878 #ifdef IKSD
6879     if (inserver &&
6880 #ifdef CK_LOGIN
6881         isguest
6882 #else
6883         0
6884 #endif /* CK_LOGIN */
6885         ) {
6886         printf("Sorry, command disabled.\r\n");
6887         return(success = 0);
6888     }
6889 #endif /* IKSD */
6890 #endif /* COMMENT */
6891 
6892     switch (x) {
6893 
6894 #ifdef ANYX25
6895 #ifndef IBMX25
6896       case SHPAD:
6897         shopad(0);
6898         break;
6899 #endif /* IBMX25 */
6900 #endif /* ANYX25 */
6901 
6902       case SHNET:
6903 #ifdef NOLOCAL
6904         printf(" No network support in this version of C-Kermit.\n");
6905 #else
6906 #ifndef NETCONN
6907         printf(" No network support in this version of C-Kermit.\n");
6908 #else
6909         shonet();
6910 #endif /* NETCONN */
6911 #endif /* NOLOCAL */
6912         break;
6913 
6914       case SHPAR:
6915         shopar();
6916         break;
6917 
6918 #ifndef NOXFER
6919       case SHATT:
6920         shoatt();
6921         break;
6922 #endif /* NOXFER */
6923 
6924 #ifndef NOSPL
6925       case SHCOU:
6926         printf(" %d\n",count[cmdlvl]);
6927         break;
6928 #endif /* NOSPL */
6929 
6930 #ifndef NOSERVER
6931       case SHSER:                       /* Show Server */
6932         i = 0;
6933 #ifndef NOFRILLS
6934         printf("Function:          Status:\n");
6935         i++;
6936         printf(" GET                %s\n",nm[en_get]);
6937         i++;
6938         printf(" SEND               %s\n",nm[en_sen]);
6939         i++;
6940         printf(" MAIL               %s\n",nm[inserver ? 0 : en_mai]);
6941         i++;
6942         printf(" PRINT              %s\n",nm[inserver ? 0 : en_pri]);
6943         i++;
6944 #ifndef NOSPL
6945         printf(" REMOTE ASSIGN      %s\n",nm[en_asg]);
6946         i++;
6947 #endif /* NOSPL */
6948         printf(" REMOTE CD/CWD      %s\n",nm[en_cwd]);
6949         i++;
6950 #ifdef ZCOPY
6951         printf(" REMOTE COPY        %s\n",nm[en_cpy]);
6952         i++;
6953 #endif /* ZCOPY */
6954         printf(" REMOTE DELETE      %s\n",nm[en_del]);
6955         printf(" REMOTE DIRECTORY   %s\n",nm[en_dir]);
6956         printf(" REMOTE HOST        %s\n",nm[inserver ? 0 : en_hos]);
6957         i += 3;
6958 #ifndef NOSPL
6959         printf(" REMOTE QUERY       %s\n",nm[en_que]);
6960         i++;
6961 #endif /* NOSPL */
6962         printf(" REMOTE MKDIR       %s\n",nm[en_mkd]);
6963         printf(" REMOTE RMDIR       %s\n",nm[en_rmd]);
6964         printf(" REMOTE RENAME      %s\n",nm[en_ren]);
6965         printf(" REMOTE SET         %s\n",nm[en_set]);
6966         printf(" REMOTE SPACE       %s\n",nm[en_spa]);
6967         printf(" REMOTE TYPE        %s\n",nm[en_typ]);
6968         printf(" REMOTE WHO         %s\n",nm[inserver ? 0 : en_who]);
6969         printf(" BYE                %s\n",nm[en_bye]);
6970         printf(" FINISH             %s\n",nm[en_fin]);
6971         printf(" EXIT               %s\n",nm[en_xit]);
6972         printf(" ENABLE             %s\n",nm[en_ena]);
6973         i += 11;
6974 #endif /* NOFRILLS */
6975         if (i > cmd_rows - 3) { if (!askmore()) return(1); else i = 0; }
6976         printf("Server timeout:      %d\n",srvtim);
6977         if (++i > cmd_rows - 3) { if (!askmore()) return(1); else i = 0; }
6978         printf("Server idle-timeout: %d\n",srvidl);
6979         if (++i > cmd_rows - 3) { if (!askmore()) return(1); else i = 0; }
6980         printf("Server keepalive     %s\n", showoff(srvping));
6981         if (++i > cmd_rows - 3) { if (!askmore()) return(1); else i = 0; }
6982         printf("Server cd-message    %s\n", showoff(srvcdmsg));
6983         if (srvcdmsg && cdmsgstr)
6984           printf("Server cd-message    %s\n", cdmsgstr);
6985         if (++i > cmd_rows - 3) { if (!askmore()) return(1); else i = 0; }
6986         printf("Server display:      %s\n", showoff(srvdis));
6987         if (++i > cmd_rows - 3) { if (!askmore()) return(1); else i = 0; }
6988         printf("Server login:        ");
6989         if (!x_user) {
6990             printf("(none)\n");
6991         } else {
6992             printf("\"%s\", \"%s\", \"%s\"\n",
6993                    x_user,
6994                    x_passwd ? x_passwd : "",
6995                    x_acct ? x_acct : ""
6996                    );
6997         }
6998         if (++i > cmd_rows - 3) { if (!askmore()) return(1); else i = 0; }
6999         printf("Server get-path: ");
7000         if (ngetpath == 0) {
7001             printf("    (none)\n");
7002         } else {
7003             printf("\n");
7004             i += 3;
7005             for (x = 0; x < ngetpath; x++) {
7006                 if (getpath[x]) printf(" %d. %s\n", x, getpath[x]);
7007                 if (++i > (cmd_rows - 3)) { /* More than a screenful... */
7008                     if (!askmore())
7009                       break;
7010                     else
7011                       i = 0;
7012                 }
7013             }
7014         }
7015         break;
7016 #endif /* NOSERVER */
7017 
7018       case SHSTA:                       /* Status of last command */
7019         printf(" %s\n", success ? "SUCCESS" : "FAILURE");
7020         return(0);                      /* Don't change it */
7021 
7022       case SHSTK: {                     /* Stack for MAC debugging */
7023 #ifdef MAC
7024           long sp;
7025           sp = -1;
7026           loadA0 ((char *)&sp);         /* set destination address */
7027           SPtoaA0();                    /* move SP to destination */
7028           printf("Stack at 0x%x\n", sp);
7029           show_queue();                 /* more debugging */
7030           break;
7031 #else
7032           shostack();
7033 #endif /* MAC */
7034           break;
7035       }
7036 
7037 
7038 #ifndef NOLOCAL
7039 #ifdef OS2
7040       case SHTAB:                       /* SHOW TABS */
7041 #ifdef IKSD
7042         if (inserver) {
7043             printf("Sorry, command disabled.\r\n");
7044             return(success = 0);
7045         }
7046 #endif /* IKSD */
7047         shotabs();
7048         break;
7049 #endif /* OS2 */
7050 
7051       case SHTER:                       /* SHOW TERMINAL */
7052 #ifdef IKSD
7053         if (inserver) {
7054             printf("Sorry, command disabled.\r\n");
7055             return(success = 0);
7056         }
7057 #endif /* IKSD */
7058         shotrm();
7059         break;
7060 
7061 #ifdef OS2
7062       case SHVSCRN:                     /* SHOW Virtual Screen - for debug */
7063         shovscrn();
7064         break;
7065 #endif /* OS2 */
7066 #endif /* NOLOCAL */
7067 
7068 #ifdef OS2MOUSE
7069       case SHMOU:                       /* SHOW MOUSE */
7070 #ifdef IKSD
7071         if (inserver) {
7072             printf("Sorry, command disabled.\r\n");
7073             return(success = 0);
7074         }
7075 #endif /* IKSD */
7076         shomou();
7077         break;
7078 #endif /* OS2MOUSE */
7079 
7080 #ifndef NOFRILLS
7081       case SHVER:
7082         shover();
7083         break;
7084 #endif /* NOFRILLS */
7085 
7086 #ifndef NOSPL
7087       case SHBUI:                       /* Built-in variables */
7088 	line[0] = NUL;
7089         if ((y = cmtxt("Variable name or pattern","",&s,xxstring)) < 0)
7090           return(y);
7091         ckstrncpy(line,s,LINBUFSIZ);
7092         /* if (line[0]) ckstrncat(line,"*",LINBUFSIZ); */
7093 
7094       case SHFUN:                       /* or built-in functions */
7095 #ifdef CK_TTGWSIZ
7096 #ifdef OS2
7097         if (tt_cols[VTERM] < 0 || tt_rows[VTERM] < 0)
7098           ttgwsiz();
7099 #else /* OS2 */
7100         if (ttgwsiz() > 0) {            /* Get current screen size */
7101             if (tt_rows > 0 && tt_cols > 0) {
7102                 cmd_rows = tt_rows;
7103                 cmd_cols = tt_cols;
7104             }
7105         }
7106 #endif /* OS2 */
7107 #endif /* CK_TTGWSIZ */
7108 
7109         if (x == SHFUN) {               /* Functions */
7110             printf("\nThe following functions are available:\n\n");
7111             kwdhelp(fnctab,nfuncs,(char *)fnbuf,"\\F","()",3,8);
7112             printf("\n");
7113 #ifndef NOHELP
7114             printf(
7115 "HELP FUNCTION <name> gives the calling conventions of the given function.\n\n"
7116                    );
7117 #endif /* NOHELP */
7118             break;
7119         } else {                        /* Variables */
7120 	    int j, flag = 0, havearg = 0;
7121 	    struct stringarray * q = NULL;
7122 	    char ** pp;
7123 	    if (line[0]) {		/* Have something to search for */
7124 		havearg = 1;		/* Maybe a list of things */
7125                 q = cksplit(1,0,line,NULL,"_-^$*?[]{}",0,0,0,0);
7126 		if (!q) break;
7127 		pp = q->a_head;
7128 	    }
7129 	    i = 0;
7130 	    for (y = 0; y < nvars; y++) {
7131 		if ((vartab[y].flgs & CM_INV))
7132 		  continue;
7133 		if (havearg) {		/* If I have something to match */
7134 		    char * s2;
7135 		    for (flag = 0, j = 1; j <= q->a_size && !flag; j++) {
7136 			s2 = pp[j] ? pp[j] : "";
7137 #ifdef COMMENT
7138 /* This is not needed because it's what the 4 arg does in ckmatch() */
7139 			len = strlen(s2);
7140 			if (len > 0) {
7141 			    if (s2[len-1] != '$') {/* To allow anchors */
7142 				ckmakmsg(line,LINBUFSIZ,pp[j],"*",NULL,NULL);
7143 				s2 = line;
7144 			    }
7145 			}
7146 #endif /* COMMENT */
7147 			if (ckmatch(s2,vartab[y].kwd,0,4) > 0) {
7148 			    flag = 1;	/* Matches */
7149 			    break;
7150 			}
7151 		    }
7152 		    if (!flag)		/* Doesn't match */
7153 		      continue;
7154 		}
7155 		s = nvlook(vartab[y].kwd);
7156 		printf(" \\v(%s) = ",vartab[y].kwd);
7157 		if (vartab[y].kwval == VN_NEWL) { /* \v(newline) */
7158 		    while (*s)		/* Show control chars symbolically */
7159 		      printf("\\{%d}",*s++);
7160 		    printf("\n");
7161 		} else if (vartab[y].kwval == VN_IBUF  || /* \v(input) */
7162 			   vartab[y].kwval == VN_QUE   || /* \v(query) */
7163 #ifdef OS2
7164 			   vartab[y].kwval == VN_SELCT || /* \v(select) */
7165 #endif /* OS2 */
7166 			   (vartab[y].kwval >= VN_M_AAA && /* modem ones */
7167 			    vartab[y].kwval <= VN_M_ZZZ)
7168 			   ) {
7169 		    int r = 12;		/* This one can wrap around */
7170 		    char buf[10];
7171 		    while (*s) {
7172 			if (isprint(*s)) {
7173 			    buf[0] = *s;
7174 			    buf[1] = NUL;
7175 			    r++;
7176 			} else {
7177 			    sprintf(buf,"\\{%d}",*s); /* SAFE */
7178 			    r += (int) strlen(buf);
7179 			}
7180 			if (r >= cmd_cols - 1) {
7181 			    printf("\n");
7182 			    r = 0;
7183 			    i++;
7184 			}
7185 			printf("%s",buf);
7186 			s++;
7187 		    }
7188 		    printf("\n");
7189 		} else
7190 		  printf("%s\n",s);
7191 		if (++i > (cmd_rows - 3)) { /* More than a screenful... */
7192 		    if ((y >= nvars - 1) || !askmore())
7193 		      break;
7194 		    else
7195 		      i = 0;
7196 		}
7197 	    }
7198         }
7199         break;
7200 
7201       case SHVAR:                       /* Global variables */
7202         x = 0;                          /* Variable count */
7203         slc = 1;                        /* Screen line count for "more?" */
7204         for (y = 33; y < GVARS; y++)
7205           if (g_var[y]) {
7206               if (x++ == 0) printf("Global variables:\n");
7207               sprintf(line," \\%%%c",y); /* SAFE */
7208               if (shomac(line,g_var[y]) < 0) break;
7209           }
7210         if (!x) printf(" No variables defined\n");
7211         break;
7212 
7213       case SHARG: {                     /* Args */
7214           char * s, * s1, * s2, * tmpbufp;
7215           int t;
7216           if (maclvl > -1) {
7217               printf("Macro arguments at level %d (\\v(argc) = %d):\n",
7218                      maclvl,
7219                      macargc[maclvl]
7220                      );
7221               for (y = 0; y < macargc[maclvl]; y++) {
7222                   s1 = m_arg[maclvl][y];
7223                   if (!s1) s1 = "(NULL)";
7224                   s2 = m_xarg[maclvl][y];
7225                   if (!s2) s2 = "(NULL)";
7226 #ifdef COMMENT
7227                   if (y < 10)
7228                     printf(" \\%%%d = %s\n",y,s1);
7229                   else
7230                     printf(" \\&_[%d] = %s\n",y,s2);
7231 #else
7232                   printf(" \\&_[%d] = %s\n",y,s2);
7233 #endif  /* COMMENT */
7234               }
7235           } else {
7236               printf("Top-level arguments (\\v(argc) = %d):\n", topargc);
7237               for (y = 0; y < topargc; y++) {
7238                   s1 = g_var[y + '0'];
7239                   if (!s1) s1 = "(NULL)";
7240                   s2 = toparg[y];
7241                   if (!s2) s2 = "(NULL)";
7242                   if (y < 10 && g_var[y])
7243                     printf(" \\%%%d = %s\n",y,s1);
7244                   if (toparg[y])
7245                     printf(" \\&_[%d] = %s\n",y,s2);
7246               }
7247           }
7248         }
7249         break;
7250 
7251       case SHARR:                       /* Arrays */
7252         return(showarray());
7253 #endif /* NOSPL */
7254 
7255 #ifndef NOXFER
7256       case SHPRO:                       /* Protocol parameters */
7257         shoparp();
7258         printf("\n");
7259         break;
7260 #endif /* NOXFER */
7261 
7262 #ifndef NOLOCAL
7263       case SHCOM:                       /* Communication parameters */
7264         printf("\n");
7265         shoparc();
7266 #ifdef OS2
7267         {
7268             int i;
7269             char *s = "(unknown)";
7270             for (i = 0; i < nprty; i++)
7271               if (prtytab[i].kwval == priority) {
7272                   s = prtytab[i].kwd;
7273                   break;
7274               }
7275             printf(" Priority: %s\n", s );
7276         }
7277 #endif /* OS2 */
7278 
7279         printf("\n");
7280 #ifdef NETCONN
7281         if (!network
7282 #ifdef IKSD
7283              && !inserver
7284 #endif /* IKSD */
7285              ) {
7286 #endif /* NETCONN */
7287             shomdm();
7288             printf("\n");
7289 #ifdef NETCONN
7290         }
7291 #endif /* NETCONN */
7292 
7293 #ifndef NODIAL
7294 #ifdef IKSD
7295         if ( !inserver )
7296 #endif /* IKSD */
7297         {
7298             printf("Type SHOW DIAL to see DIAL-related items.\n");
7299             printf("Type SHOW MODEM to see modem-related items.\n");
7300 #ifdef CK_TAPI
7301             printf("Type SHOW TAPI to see TAPI-related items.\n");
7302 #endif /* CK_TAPI */
7303             printf("\n");
7304         }
7305 #endif /* NODIAL */
7306         break;
7307 #endif /* NOLOCAL */
7308 
7309       case SHFIL:                       /* File parameters */
7310         shofil();
7311         /* printf("\n"); */             /* (out o' space) */
7312         break;
7313 
7314 #ifndef NOCSETS
7315       case SHLNG:                       /* Languages */
7316         shoparl();
7317         break;
7318 #endif /* NOCSETS */
7319 
7320 #ifndef NOSPL
7321       case SHSCR:                       /* Scripts */
7322         printf(" Command quoting:        %s\n", showoff(cmdgquo()));
7323         printf(" Take  echo:             %s\n", showoff(techo));
7324         printf(" Take  error:            %s\n", showoff(takerr[cmdlvl]));
7325         printf(" Macro echo:             %s\n", showoff(mecho));
7326         printf(" Macro error:            %s\n", showoff(merror[cmdlvl]));
7327         printf(" Quiet:                  %s\n", showoff(quiet));
7328         printf(" Variable evaluation:    %s [\\%%x and \\&x[] variables]\n",
7329 	       vareval ? "recursive" : "simple");
7330         printf(" Function diagnostics:   %s\n", showoff(fndiags));
7331         printf(" Function error:         %s\n", showoff(fnerror));
7332 #ifdef CKLEARN
7333         {
7334             extern char * learnfile;
7335             extern int learning;
7336             if (learnfile) {
7337                 printf(" LEARN file:             %s (%s)\n",
7338                        learnfile,
7339                        learning ? "ON" : "OFF"
7340                        );
7341             } else
7342               printf(" LEARN file:             (none)\n");
7343         }
7344 #endif /* CKLEARN */
7345         shoinput();
7346         shooutput();
7347 #ifndef NOSCRIPT
7348         printf(" Script echo:            %s\n", showoff(secho));
7349 #endif /* NOSCRIPT */
7350         printf(" Command buffer length:  %d\n", CMDBL);
7351         printf(" Atom buffer length:     %d\n", ATMBL);
7352         break;
7353 #endif /* NOSPL */
7354 
7355 #ifndef NOXMIT
7356       case SHXMI:
7357         printf("\n");
7358         printf(" File type:                       %s\n",
7359                binary ? "binary" : "text");
7360 #ifndef NOCSETS
7361         printf(" File character-set:              %s\n",
7362                fcsinfo[fcharset].keyword);
7363 #ifdef OS2
7364         if ( isunicode() ) {
7365         printf(" Terminal Character (remote):     %s\n",
7366               tt_utf8 ? "utf-8" : tcsr == TX_TRANSP ? "transparent" :
7367               tcsr == TX_UNDEF ? "undefined" : txrinfo[tcsr]->keywd);
7368         printf(" Terminal Character (local):      %s\n",
7369               tcsl == TX_TRANSP ? "transparent" :
7370               tcsl == TX_UNDEF ? "undefined" : txrinfo[tcsl]->keywd);
7371         } else {
7372         printf(" Terminal Character (remote):     %s\n",
7373               tt_utf8 ? "utf-8" : tcsr == TX_TRANSP ? "transparent" :
7374               tcsr == TX_UNDEF ? "undefined" : txrinfo[tcsr]->keywd);
7375         printf(" Terminal Character (local):      %s\n",
7376               tcsl == TX_TRANSP ? "transparent" :
7377               tcsl == TX_UNDEF ? "undefined" : txrinfo[tcsl]->keywd);
7378         }
7379 #else /* OS2 */
7380         printf(" Terminal character-set (remote): %s\n",
7381                fcsinfo[tcsr].keyword);
7382         printf(" Terminal character-set (local):  %s\n",
7383                fcsinfo[tcsl].keyword);
7384 #endif /* OS2 */
7385 #endif /* NOCSETS */
7386         printf(" Terminal bytesize:               %d\n",
7387                (cmask == 0xff) ? 8 : 7);
7388         printf(" Terminal echo:                   %s\n",
7389                duplex ? "local" : "remote");
7390         printf(" Transmit EOF:                    ");
7391         if (*xmitbuf == NUL) {
7392             printf("(none)\n");
7393         } else {
7394             char *p;
7395             p = xmitbuf;
7396             while (*p) {
7397                 if (*p < SP)
7398                   printf("^%c",ctl(*p));
7399                 else
7400                   printf("%c",*p);
7401                 p++;
7402             }
7403             printf("\n");
7404         }
7405         if (xmitf)
7406           printf(" Transmit Fill:                   %d\n", xmitf);
7407         else
7408           printf(" Transmit Fill:                   (none)\n");
7409         printf(" Transmit Linefeed:               %s\n",showoff(xmitl));
7410         if (xmitp)
7411           printf(" Transmit Prompt:                 %d (%s)\n",
7412                  xmitp,
7413                  chartostr(xmitp)
7414                  );
7415         else
7416           printf(" Transmit Prompt:                 (none)\n");
7417         printf(" Transmit Echo:                   %s\n", showoff(xmitx));
7418         printf(" Transmit Locking-Shift:          %s\n", showoff(xmits));
7419         printf(" Transmit Pause:                  %d (millisecond%s)\n",
7420                xmitw,
7421                (xmitw == 1) ? "" : "s"
7422                );
7423         printf(" Transmit Timeout:                %d (second%s)\n",
7424                xmitt,
7425                (xmitt == 1) ? "" : "s"
7426                );
7427         printf("\n");
7428         break;
7429 #endif /* NOXMIT */
7430 
7431 #ifndef NODIAL
7432       case SHMOD:                       /* SHOW MODEM */
7433 #ifdef IKSD
7434         if (inserver) {
7435             printf("Sorry, command disabled.\r\n");
7436             return(success = 0);
7437         }
7438 #endif /* IKSD */
7439         shomodem();                     /* Show SET MODEM items */
7440         break;
7441 #endif /* NODIAL */
7442 
7443 #ifndef MAC
7444       case SHDFLT:
7445         printf("%s\n",zgtdir());
7446         break;
7447 #endif /* MAC */
7448 
7449 #ifndef NOLOCAL
7450       case SHESC:
7451 #ifdef IKSD
7452         if (inserver) {
7453             printf("Sorry, command disabled.\r\n");
7454             return(success = 0);
7455         }
7456 #endif /* IKSD */
7457         return(shoesc(escape));
7458 
7459 #ifndef NODIAL
7460       case SHDIA:                       /* SHOW DIAL */
7461 #ifdef IKSD
7462         if (inserver) {
7463             printf("Sorry, command disabled.\r\n");
7464             return(success = 0);
7465         }
7466 #endif /* IKSD */
7467         shmdmlin();
7468         printf(", speed: ");
7469         if ((zz = ttgspd()) < 0) {
7470             printf("unknown");
7471         } else {
7472             if (zz == 8880) printf("75/1200"); else printf("%ld",zz);
7473         }
7474         if (carrier == CAR_OFF) s = "off";
7475         else if (carrier == CAR_ON) s = "on";
7476         else if (carrier == CAR_AUT) s = "auto";
7477         else s = "unknown";
7478         printf(", carrier: %s", s);
7479         if (carrier == CAR_ON) {
7480             if (cdtimo) printf(", timeout: %d sec", cdtimo);
7481             else printf(", timeout: none");
7482         }
7483         printf("\n");
7484         doshodial();
7485         if (local
7486 #ifdef NETCONN
7487             && !network
7488 #endif /* NETCONN */
7489             ) {
7490             printf("Type SHOW MODEM to see modem settings.\n");
7491 #ifdef CK_TAPI
7492             printf("Type SHOW TAPI to see TAPI-related items\n");
7493 #endif /* CK_TAPI */
7494             printf("Type SHOW COMMUNICATIONS to see modem signals.\n");
7495         }
7496         break;
7497 #endif /* NODIAL */
7498 #endif /* NOLOCAL */
7499 
7500 #ifndef NOXFER
7501 #ifdef CK_LABELED
7502       case SHLBL:                       /* Labeled file info */
7503         sholbl();
7504         break;
7505 #endif /* CK_LABELED */
7506 #endif /* NOXFER */
7507 
7508       case SHCSE:                       /* Character sets */
7509 #ifdef NOCSETS
7510         printf(
7511 " Character set translation is not supported in this version of C-Kermit\n");
7512 #else
7513         shocharset();
7514 #ifndef NOXFER
7515         printf("\n Unknown-Char-Set: %s\n",
7516                unkcs ? "Keep" : "Discard");
7517 #endif /* NOXFER */
7518 #ifdef OS2
7519         printf("\n");
7520 #endif /* OS2 */
7521         shotcs(tcsl,tcsr);
7522         printf("\n");
7523 #ifdef OS2
7524         /* PC Code Page information */
7525         {
7526             char cpbuf[128];
7527             int cplist[16], cps;
7528             int activecp;
7529             cps = os2getcplist(cplist, sizeof(cplist));
7530 
7531             sprintf(cpbuf,              /* SAFE */
7532                     "%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d",
7533                      cps > 1 ? cplist[1] : 0,
7534                      cps > 2 ? cplist[2] : 0, cps > 3 ? cplist[3] : 0,
7535                      cps > 4 ? cplist[4] : 0, cps > 5 ? cplist[5] : 0,
7536                      cps > 6 ? cplist[6] : 0, cps > 7 ? cplist[7] : 0,
7537                      cps > 8 ? cplist[8] : 0, cps > 9 ? cplist[9] : 0,
7538                      cps > 10 ? cplist[10] : 0, cps > 11 ? cplist[11] : 0,
7539                      cps > 12 ? cplist[12] : 0
7540                      );
7541             printf(" Code Pages:\n");
7542             activecp = os2getcp();
7543             if ( activecp ) {
7544               printf("     Active: %d\n",activecp);
7545               if (!isWin95())
7546                 printf("  Available: %s\n",cpbuf);
7547             } else
7548               printf("     Active: n/a\n");
7549             printf("\n");
7550         }
7551 #endif /* OS2 */
7552 #endif /* NOCSETS */
7553         break;
7554 
7555       case SHFEA:                       /* Features */
7556         shofea();
7557         break;
7558 
7559 #ifdef CK_SPEED
7560       case SHCTL:                       /* Control-Prefix table */
7561         shoctl();
7562         break;
7563 #endif /* CK_SPEED */
7564 
7565       case SHEXI: {
7566           extern int exithangup, exitmsg;
7567           printf("\n Exit warning %s\n", xitwarn ?
7568                  (xitwarn == 1 ? "on" : "always") : "off");
7569           printf(" Exit message: %s\n", exitmsg ?
7570                  (exitmsg == 1 ? "on" : "stderr") : "off");
7571           printf(" Exit on-disconnect: %s\n", showoff(exitonclose));
7572           printf(" Exit hangup: %s\n", showoff(exithangup));
7573           printf(" Current exit status: %d\n\n", xitsta);
7574           break;
7575       }
7576       case SHPRT: {
7577 #ifdef PRINTSWI
7578           extern int printtimo, printertype, noprinter;
7579           extern char * printterm, * printsep;
7580           extern int prncs;
7581 #ifdef BPRINT
7582           extern int printbidi;
7583 #endif /* BPRINT */
7584 #endif /* PRINTSWI */
7585 
7586 #ifdef IKSD
7587         if (inserver &&
7588 #ifdef CK_LOGIN
7589             isguest
7590 #else /* CK_LOGIN */
7591             0
7592 #endif /* CK_LOGIN */
7593              ) {
7594             printf("Sorry, command disabled.\r\n");
7595             return(success = 0);
7596         }
7597 #endif /* IKSD */
7598 #ifdef PRINTSWI
7599           if (noprinter) {
7600               printf("Printer: (none)\n\n");
7601               break;
7602           }
7603 #endif /* PRINTSWI */
7604 
7605           printf("Printer: %s%s\n",
7606 
7607                  printpipe ? "| " : "",
7608                  printername ? printername :
7609 #ifdef OS2
7610                  "PRN"
7611 #else
7612                  "(default)"
7613 #endif /* OS2 */
7614                  );
7615 #ifdef PRINTSWI
7616 #ifdef BPRINT
7617           if (printbidi) {
7618               printf(" /BIDIRECTIONAL\n");
7619               if (pportspeed > 0)
7620                 printf(" /SPEED:%ld\n",pportspeed);
7621               printf(" /PARITY:%s\n",parnam((char)pportparity));
7622               printf(" /FLOW:%s\n",
7623                      pportflow == FLO_NONE ? "NONE" :
7624                      (pportflow == FLO_RTSC ? "RTS/CTS" : "XON/XOFF")
7625                      );
7626           } else
7627             printf(" /OUTPUT-ONLY\n");
7628 #endif /* BPRINT */
7629           switch (printertype) {
7630             case PRT_NON: printf(" /NONE\n"); break;
7631             case PRT_FIL: printf(" /FILE\n"); break;
7632             case PRT_PIP: printf(" /PIPE\n"); break;
7633             case PRT_DOS: printf(" /DOS-DEVICE\n"); break;
7634             case PRT_WIN: printf(" /WINDOWS-QUEUE\n"); break;
7635           }
7636           printf(" /TIMEOUT:%d\n",printtimo);
7637           if (printterm) {
7638               printf(" /END-OF-JOB-STRING:");
7639               shostrdef(printterm);
7640               printf("\n");
7641           } else
7642             printf(" /END-OF-JOB-STRING:(none)\n");
7643           printf(" /JOB-HEADER-FILE:%s\n",printsep ? printsep : "(none)");
7644           printf(" /CHARACTER-SET: %s\n",txrinfo[prncs]->keywd);
7645 #endif /* PRINTSWI */
7646           printf("\n");
7647           break;
7648       }
7649 
7650       case SHCMD: {
7651 #ifdef DOUBLEQUOTING
7652           extern int dblquo;
7653 #endif /* DOUBLEQUOTING */
7654 #ifdef CK_AUTODL
7655           printf(" Command autodownload: %s\n",showoff(cmdadl));
7656 #else
7657           printf(" Command autodownload: (not available)\n");
7658 #endif /* CK_AUTODL */
7659           printf(" Command bytesize: %d bits\n", (cmdmsk == 0377) ? 8 : 7);
7660           printf(" Command error-display: %d\n", cmd_err);
7661 #ifdef CK_RECALL
7662           printf(" Command recall-buffer-size: %d\n",cm_recall);
7663 #else
7664           printf(" Command recall-buffer not available in this version\n");
7665 #endif /* CK_RECALL */
7666 #ifdef CK_RECALL
7667           printf(" Command retry: %s\n",showoff(cm_retry));
7668 #else
7669           printf(" Command retry not available in this version\n");
7670 #endif /* CK_RECALL */
7671           printf(" Command interruption: %s\n", showoff(cmdint));
7672           printf(" Command quoting: %s\n", showoff(cmdgquo()));
7673 #ifdef DOUBLEQUOTING
7674           printf(" Command doublequoting: %s\n", showoff(dblquo));
7675 #endif /* DOUBLEQUOTING */
7676           printf(" Command more-prompting: %s\n", showoff(xaskmore));
7677           printf(" Command height: %d\n", cmd_rows);
7678           printf(" Command width:  %d\n", cmd_cols);
7679 #ifndef IKSDONLY
7680 #ifdef OS2
7681           printf(" Command statusline: %s\n",showoff(tt_status[VCMD]));
7682 #endif /* OS2 */
7683 #endif /* IKSDONLY */
7684 #ifdef LOCUS
7685           printf(" Locus:          %s",
7686                  autolocus ? (autolocus == 2 ? "ask" : "auto") :
7687 		 (locus ? "local" : "remote"));
7688           if (autolocus)
7689             printf(" (%s)", locus ? "local" : "remote");
7690           printf("\n");
7691 #endif /* LOCUS */
7692           printf(" Hints:          %s\n", showoff(hints));
7693           printf(" Quiet:          %s\n", showoff(quiet));
7694           printf(" Maximum command length: %d\n", CMDBL);
7695 #ifndef NOSPL
7696           {
7697               char * s;
7698               int k;
7699               printf(" Maximum number of macros: %d\n", MAC_MAX);
7700               printf(" Macros defined: %d\n", nmac);
7701               printf(" Maximum macro depth: %d\n", MACLEVEL);
7702               printf(" Maximum TAKE depth: %d\n", MAXTAKE);
7703               s = "(not defined)";
7704               k = mlook(mactab,"on_unknown_command",nmac);
7705               if (k > -1) if (mactab[k].mval) s = mactab[k].mval;
7706               printf(" ON_UNKNOWN_COMMAND: %s\n",s);
7707           }
7708 #endif /* NOSPL */
7709 #ifdef UNIX
7710 #ifndef NOJC
7711           printf(" Suspend: %s\n", showoff(xsuspend));
7712 #endif /* NOJC */
7713 #endif /* UNIX */
7714           printf(" Access to external commands and programs%s allowed\n",
7715 #ifndef NOPUSH
7716                  !nopush ? "" :
7717 #endif /* NOPUSH */
7718                   " not");
7719           break;
7720       }
7721 
7722 #ifndef NOSPL
7723       case SHALRM:
7724         if (ck_alarm)
7725           printf("Alarm at %s %s\n",alrm_date,alrm_time);
7726         else
7727           printf("(no alarm set)\n");
7728         break;
7729 #endif /* NOSPL */
7730 
7731 #ifndef NOMSEND
7732       case SHSFL: {
7733           extern struct filelist * filehead;
7734           if (!filehead) {
7735               printf("send-list is empty\n");
7736           } else {
7737               struct filelist * flp;
7738               char * s;
7739               flp = filehead;
7740               while (flp) {
7741                   s = flp->fl_alias;
7742                   if (!s) s = "(none)";
7743                   printf("%s, mode: %s, alias: %s\n",
7744                          flp->fl_name,
7745                          gfmode(flp->fl_mode,0),
7746                          s
7747                          );
7748                   flp = flp->fl_next;
7749               }
7750           }
7751       }
7752       break;
7753 #endif /* NOMSEND */
7754 
7755 #ifdef CKXXCHAR
7756       case SHDBL:
7757         shodbl();
7758         break;
7759 #endif /* CKXXCHAR */
7760 
7761 #ifndef NOPUSH
7762 #ifndef NOFRILLS
7763       case SHEDIT:
7764         if (!editor[0]) {
7765             s = getenv("EDITOR");
7766             if (s) ckstrncpy(editor,s,CKMAXPATH);
7767         }
7768         printf("\n editor:  %s\n", editor[0] ? editor : "(none)");
7769         if (editor[0]) {
7770             printf(" options: %s\n", editopts[0] ? editopts : "(none)");
7771             printf(" file:    %s\n", editfile[0] ? editfile : "(none)");
7772         }
7773         printf("\n");
7774         break;
7775 
7776 #ifdef BROWSER
7777       case SHBROWSE:
7778         if (!browser[0]) {
7779             s = getenv("BROWSER");
7780             if (s) ckstrncpy(browser,s,CKMAXPATH);
7781         }
7782         printf("\n browser: %s\n", browser[0] ? browser : "(none)");
7783         if (browser[0]) {
7784             printf(" options: %s\n", browsopts[0] ? browsopts : "(none)");
7785             printf(" url:     %s\n", browsurl[0] ? browsurl : "(none)");
7786         }
7787         printf("\n");
7788         break;
7789 #endif /* BROWSER */
7790 #endif /*  NOFRILLS */
7791 #endif /* NOPUSH */
7792 
7793 #ifndef NOLOCAL
7794 #ifdef CK_TAPI
7795       case SHTAPI:                      /* TAPI options */
7796 #ifdef IKSD
7797         if (inserver) {
7798             printf("Sorry, command disabled.\r\n");
7799             return(success = 0);
7800         }
7801 #endif /* IKSD */
7802         shotapi(0);
7803         break;
7804       case SHTAPI_L:                    /* TAPI Locations */
7805 #ifdef IKSD
7806         if (inserver) {
7807             printf("Sorry, command disabled.\r\n");
7808             return(success = 0);
7809         }
7810 #endif /* IKSD */
7811         shotapi(1);
7812         break;
7813       case SHTAPI_M:                    /* TAPI Modem */
7814 #ifdef IKSD
7815         if (inserver) {
7816             printf("Sorry, command disabled.\r\n");
7817             return(success = 0);
7818         }
7819 #endif /* IKSD */
7820         shotapi(2);
7821         break;
7822       case SHTAPI_C:                    /* TAPI Comm */
7823 #ifdef IKSD
7824         if (inserver) {
7825             printf("Sorry, command disabled.\r\n");
7826             return(success = 0);
7827         }
7828 #endif /* IKSD */
7829         shotapi(3);
7830         break;
7831 #endif /* CK_TAPI */
7832 
7833       case SHTCP:                       /* SHOTCP */
7834         printf("\n");
7835         shotcp(0);
7836         printf("\n");
7837         break;
7838 
7839 #ifdef TNCODE
7840       case SHTEL:                       /* TELNET */
7841         printf("\n");
7842         shotel(0);
7843         printf("\n");
7844         break;
7845 
7846       case SHTOPT:                      /* TELNET OPTIONS */
7847         printf("\n");
7848         shotopt(0);
7849         printf("\n");
7850         break;
7851 #endif /* TNCODE */
7852 
7853       case SHOTMPDIR:                   /* TEMPORARY DIRECTORY */
7854       {
7855           extern char * tempdir;
7856           if (!tempdir) {
7857               printf(" (none)\n");
7858           } else if (!*tempdir) {
7859               printf(" (none)\n");
7860           } else {
7861               printf(" %s\n", tempdir);
7862           }
7863           break;
7864       }
7865 #ifdef CK_TRIGGER
7866       case SHTRIG: {
7867           extern char * tt_trigger[], * triggerval;
7868           int i;
7869           if (!tt_trigger[0]) {
7870               printf(" Triggers: (none)\n");
7871           } else {
7872               printf(" Triggers:\n");
7873               for (i = 0; i < TRIGGERS; i++) {
7874                   if (!tt_trigger[i])
7875                     break;
7876                   printf("  \"%s\"\n",tt_trigger[i]);
7877               }
7878               printf(" Most recent trigger encountered: ");
7879               if (triggerval)
7880                 printf("\"%s\"\n",triggerval);
7881               else
7882                 printf("(none)\n");
7883           }
7884           break;
7885       }
7886 #endif /* CK_TRIGGER */
7887 #endif /* NOLOCAL */
7888 
7889 #ifndef NOSPL
7890       case SHINP:
7891         shoinput();
7892         break;
7893 #endif /* NOSPL */
7894 
7895       case SHLOG: {
7896 #ifndef MAC
7897 #ifdef IKSD
7898           if (inserver &&
7899 #ifdef CK_LOGIN
7900               isguest
7901 #else /* CK_LOGIN */
7902               0
7903 #endif /* CK_LOGIN */
7904              ) {
7905             printf("Sorry, command disabled.\r\n");
7906             return(success = 0);
7907         }
7908 #endif /* IKSD */
7909 #ifdef DEBUG
7910           printf("\n Debug log:       %s", deblog ? debfil : "(none)");
7911 	  {
7912 	      extern int debtim;
7913 	      if (debtim) printf(" (timestamps)");
7914 	      printf("\n");
7915 	  }
7916 #endif /* DEBUG */
7917 #ifndef NOXFER
7918           printf(" Packet log:      %s\n",   pktlog ? pktfil : "(none)");
7919 #endif /* NOXFER */
7920 #ifndef NOLOCAL
7921           printf(" Session log:     %s",   seslog ? sesfil : "(none)");
7922 	  {
7923 	      extern int sessft, slogts, slognul;
7924 	      switch (sessft) {
7925 		case XYFT_T: printf(" (text)"); break;
7926 		case XYFT_B: printf(" (binary)"); break;
7927 		case XYFT_D: printf(" (debug)"); break;
7928 	      }
7929 	      if (slogts) printf("(timestamped)");
7930 	      if (slognul) printf("(null-padded)");
7931 	      printf("\n");
7932 	  }
7933 
7934 #endif /* NOLOCAL */
7935 #ifdef TLOG
7936           printf(" Transaction log: %s (%s)\n",
7937                  (tralog ? (*trafil ? trafil : "(none)") : "(none)"),
7938                  (tlogfmt ? ((tlogfmt == 2) ? "ftp" : "verbose") : "brief")
7939                  );
7940 #endif /* TLOG */
7941 #ifdef CKLOGDIAL
7942             printf(" Connection log:  %s\n", dialog ? diafil : "(none)");
7943 #endif /* CKLOGDIAL */
7944           printf("\n");
7945 #endif /* MAC */
7946           break;
7947       }
7948 
7949 #ifndef NOSPL
7950       case SHOUTP:                      /* OUTPUT */
7951         shooutput();
7952         break;
7953 #endif /* NOSPL */
7954 
7955 #ifdef PATTERNS
7956       case SHOPAT:                      /* PATTERNS */
7957         shopat();
7958         break;
7959 #endif /* PATTERNS */
7960 
7961 #ifdef STREAMING
7962       case SHOSTR: {                    /* STREAMING */
7963           extern int streamrq, clearrq, cleared;
7964           extern long tfcps;
7965           debug(F101,"SHOW RELIABLE reliable","",reliable);
7966           printf("\n Reliable:     %s\n",showooa(reliable));
7967           printf(" Clearchannel: %s\n",showooa(clearrq));
7968           printf(" Streaming:    %s\n\n",showooa(streamrq));
7969           if ((!local && (streamrq == SET_ON)) ||
7970               (streamrq == SET_AUTO && reliable))
7971             printf(" Streaming will be done if requested.\n");
7972           else if ((streamrq == SET_OFF) ||
7973                    ((streamrq == SET_AUTO) && !reliable))
7974             printf(" Streaming will not be requested and will not be done.\n");
7975           else if ((streamrq == SET_ON) ||
7976                    ((streamrq == SET_AUTO) && reliable))
7977             printf(
7978 " Streaming will be requested and will be done if the other Kermit agrees.\n");
7979           printf(" Last transfer: %sstreaming%s, %ld cps.\n",
7980                  streamed > 0 ? "" : "no ",
7981                  cleared ? ", clearchannel" : "",
7982                  tfcps
7983                  );
7984           printf("\n");
7985           break;
7986       }
7987 #endif /* STREAMING */
7988 
7989       case SHOIKS:
7990         return(sho_iks());
7991         break;
7992 
7993 #ifdef CK_AUTHENTICATION
7994       case SHOAUTH:
7995         return(sho_auth(0));
7996 #endif /* CK_AUTHENTICATION */
7997 
7998 #ifndef NOFTP
7999       case SHOFTP: {
8000 #ifdef IKSD
8001         if (inserver) {
8002             printf("Sorry, command disabled.\r\n");
8003             return(success = 0);
8004         }
8005 #endif /* IKSD */
8006 #ifdef SYSFTP
8007         {
8008             extern char ftpapp[], ftpopts[];
8009             printf(" ftp-client:  %s\n", ftpapp[0] ? ftpapp : "(none)");
8010             if (ftpapp[0])
8011               printf(" ftp options: %s\n", ftpopts[0] ? ftpopts : "(none)");
8012         }
8013 #else
8014 #ifdef NEWFTP
8015         shoftp(0);
8016 #else
8017         printf("(No FTP client included in this version of Kermit.)\n");
8018 #endif /* NEWFTP */
8019 #endif /* SYSFTP */
8020         break;
8021       }
8022 #endif /* NOFTP */
8023 
8024 #ifndef NOCMDL
8025       case SHXOPT: {
8026 #ifdef IKSDB
8027           extern int dbenabled;
8028           extern char * dbfile, * dbdir;
8029 #endif /* IKSDB */
8030 #ifdef CKWTMP
8031           extern int ckxwtmp;
8032           extern char * wtmpfile;
8033 #endif /* CKWTMP */
8034 #ifdef CK_LOGIN
8035           extern int ckxanon, xferlog, logintimo;
8036           extern char * xferfile;
8037 #ifdef UNIX
8038           extern int ckxpriv;
8039 #endif /* UNIX */
8040 #ifdef CK_PERMS
8041           extern int ckxperms;
8042 #endif /* CK_PERMS */
8043 #endif /* CK_LOGIN */
8044           extern char * bannerfile, * helpfile;
8045 
8046 #ifdef IKSD
8047           if (inserver &&
8048 #ifdef CK_LOGIN
8049               isguest
8050 #else /* CK_LOGIN */
8051               0
8052 #endif /* CK_LOGIN */
8053               ) {
8054               printf("Sorry, command disabled.\r\n");
8055               return(success = 0);
8056           }
8057 #endif /* IKSD */
8058           printf("\n");
8059           if (!cmdint)
8060             printf(" --nointerrupts\n");
8061           printf(" --bannerfile=%s\n",bannerfile ? bannerfile : "(null)");
8062           printf(" --cdfile:%s\n",cdmsgstr ? cdmsgstr : "(null)");
8063           printf(" --cdmessage:%d\n",srvcdmsg);
8064           printf(" --helpfile:%d\n",helpfile);
8065           if (inserver) {
8066               printf("\n");
8067               break;
8068           }
8069 #ifdef CKSYSLOG
8070 #ifdef SYSLOGLEVEL
8071           printf(" --syslog:%d (forced)\n",ckxsyslog);
8072 #else
8073           printf(" --syslog:%d\n",ckxsyslog);
8074 #endif /* SYSLOGLEVEL */
8075 #endif /* CKSYSLOG */
8076 #ifdef CKWTMP
8077           printf(" --wtmplog:%d\n",ckxwtmp);
8078           printf(" --wtmpfile=%s\n",wtmpfile ? wtmpfile : "(null)");
8079 #endif /* CKWTMP */
8080 #ifdef IKSD
8081 #ifdef CK_LOGIN
8082           printf(" --anonymous:%d\n",ckxanon);
8083 #ifdef UNIX
8084           printf(" --privid:%d\n",ckxpriv);
8085 #endif /* UNIX */
8086 #ifdef CK_PERMS
8087           printf(" --permission:%04o\n",ckxperms);
8088 #endif /* CK_PERMS */
8089           printf(" --initfile:%s\n",anonfile ? anonfile : "(null)");
8090           printf(" --userfile:%s\n",userfile ? userfile : "(null)");
8091           printf(" --root:%s\n",anonroot ? anonroot : "(null)");
8092           printf(" --xferlog=%d\n",xferlog);
8093           printf(" --xferfile=%s\n",xferfile ? xferfile : "(null)");
8094           printf(" --timeout=%d\n",logintimo);
8095 #endif /* CK_LOGIN */
8096 #ifdef IKSDB
8097           printf(" --database=%d\n",dbenabled);
8098           printf(" --dbfile=%s\n",dbfile ? dbfile : "(null)");
8099           if (dbdir)
8100             printf("   (db directory=[%s])\n",dbdir);
8101 #endif /* IKSDB */
8102 #ifdef IKSDCONF
8103           printf(" IKSD conf=%s\n",iksdconf);
8104 #endif /* IKSDCONF */
8105 #endif /* IKSD */
8106           printf("\n");
8107           break;
8108       }
8109 #endif /* NOCMDL */
8110 
8111       case SHCD: {
8112 	  extern char * myhome;
8113 	  s = getenv("CDPATH");
8114 	  if (!s) s = "(none)";
8115 	  printf("\n current directory:  %s\n", zgtdir());
8116 	  printf(" previous directory: %s\n", prevdir ? prevdir : "(none)");
8117 	  printf(" cd home:            %s\n", homepath());
8118 	  printf(" cd path:            %s\n", ckcdpath ? ckcdpath : s);
8119 	  printf(" cd message:         %s\n", showoff(srvcdmsg & 2));
8120 	  printf(" server cd-message:  %s\n", showoff(srvcdmsg & 1));
8121 	  printf(" cd message file:    %s\n\n",cdmsgstr ? cdmsgstr : "(none)");
8122 	  break;
8123       }
8124 #ifndef NOCSETS
8125       case SHASSOC:
8126         (VOID) showassoc();
8127         break;
8128 #endif /* NOCSETS */
8129 
8130 #ifdef CKLOGDIAL
8131       case SHCONNX:
8132 #ifdef NEWFTP
8133         if (ftpisconnected()) {
8134             extern char cxlogbuf[];
8135             dologshow(W_FTP | 1);
8136             if (cxlogbuf[0])
8137               dologshow(1);
8138         } else {
8139 #endif /* NEWFTP */
8140             dologshow(1);
8141 #ifdef NEWFTP
8142         }
8143 #endif /* NEWFTP */
8144         break;
8145 #endif /* CKLOGDIAL */
8146 
8147       case SHOPTS:
8148         optlines = 0;
8149 #ifndef NOFRILLS
8150         (VOID) showdelopts();
8151 #endif /* NOFRILLS */
8152 #ifdef DOMYDIR
8153         (VOID) showdiropts();
8154 #endif /* DOMYDIR */
8155 #ifdef CKPURGE
8156         (VOID) showpurgopts();
8157 #endif /* CKPURGE */
8158         (VOID) showtypopts();
8159         break;
8160 
8161 #ifndef NOLOCAL
8162       case SHOFLO:
8163         (VOID) shoflow();
8164         break;
8165 #endif /* NOLOCAL */
8166 
8167 #ifndef NOXFER
8168       case SHOXFER:
8169         (VOID) shoxfer();
8170         break;
8171 #endif /* NOXFER */
8172 
8173 #ifdef CK_RECALL
8174       case SHHISTORY:
8175         (VOID) cmhistory();
8176         break;
8177 #endif /* CK_RECALL */
8178 
8179 #ifndef NOSEXP
8180 #ifndef NOSPL
8181       case SHSEXP:
8182         (VOID) shosexp();
8183         break;
8184 #endif /* NOSPL */
8185 #endif /* NOSEXP */
8186 
8187 #ifdef ANYSSH
8188       case SHOSSH:
8189         (VOID) shossh();
8190         break;
8191 #endif /* ANYSSH */
8192 
8193 #ifdef KUI
8194       case SHOGUI:
8195         (VOID) shogui();
8196         break;
8197 #endif /* KUI */
8198 
8199 #ifndef NOFRILLS
8200 #ifndef NORENAME
8201       case SHOREN:
8202         (VOID) shorename();
8203         break;
8204 #endif	/* NORENAME */
8205 #endif	/* NOFRILLS */
8206 
8207       case SHOLOC: {
8208 #ifdef HAVE_LOCALE
8209 	char *s;
8210 	extern int nolocale;
8211         printf("\n");
8212 
8213 	printf("Locale %s:\n", nolocale ? "disabled" : "enabled");
8214 
8215 #ifdef COMMENT
8216 	s = setlocale(LC_ALL, NULL);
8217         if (!s) s = "";
8218 	printf("LC_ALL=%s\n",s);
8219 #endif /* COMMENT */
8220 
8221 	s = setlocale(LC_COLLATE, NULL);
8222         if (!s) s = "";
8223 	printf("  LC_COLLATE=\"%s\"\n",s);
8224 
8225 	s = setlocale(LC_CTYPE, NULL);
8226         if (!s) s = "";
8227 	printf("  LC_CTYPE=\"%s\"\n",s);
8228 
8229 	s = setlocale(LC_MONETARY, NULL);
8230         if (!s) s = "";
8231 	printf("  LC_MONETARY=\"%s\"\n",s);
8232 
8233 	s = setlocale(LC_MESSAGES, NULL);
8234         if (!s) s = "";
8235 	printf("  LC_MESSAGES=\"%s\"\n",s);
8236 
8237 	s = setlocale(LC_NUMERIC, NULL);
8238         if (!s) s = "";
8239 	printf("  LC_NUMERIC=\"%s\"\n",s);
8240 
8241 	s = setlocale(LC_TIME, NULL);
8242         if (!s) s = "";
8243 	printf("  LC_TIME=\"%s\"\n",s);
8244 
8245 	printf("  LANG=\"%s\"\n",getenv("LANG"));
8246         printf("\n");
8247 #else
8248         printf("\n");
8249         printf("  Locale support is not included in this version of Kermit\n");
8250         printf("\n");
8251 #endif /* HAVE_LOCALE */
8252 
8253 	break;
8254       }
8255       default:
8256         printf("\nNothing to show...\n");
8257         return(-2);
8258 
8259     }
8260     return(success = 1);
8261 }
8262 
8263 #ifndef NOXFER
8264 int
shoatt()8265 shoatt() {
8266     printf("Attributes: %s\n", showoff(atcapr));
8267     if (!atcapr) return(0);
8268     printf(" Blocksize: %s\n", showoff(atblki));
8269     printf(" Date: %s\n", showoff(atdati));
8270     printf(" Disposition: %s\n", showoff(atdisi));
8271     printf(" Encoding (Character Set): %s\n", showoff(atenci));
8272     printf(" Length: %s\n", showoff(atleni));
8273     printf(" Type (text/binary): %s\n", showoff(attypi));
8274     printf(" System ID: %s\n", showoff(atsidi));
8275     printf(" System Info: %s\n", showoff(atsysi));
8276 #ifdef CK_PERMS
8277     printf(" Permissions In:  %s\n", showoff(atlpri));
8278     printf(" Permissions Out: %s\n", showoff(atlpro));
8279 #endif /* CK_PERMS */
8280 #ifdef STRATUS
8281     printf(" Format: %s\n", showoff(atfrmi));
8282     printf(" Creator: %s\n", showoff(atcrei));
8283     printf(" Account: %s\n", showoff(atacti));
8284 #endif /* STRATUS */
8285     return(0);
8286 }
8287 #endif /* NOXFER */
8288 
8289 #ifndef NOSPL
8290 int                                     /* SHOW MACROS */
shomac(s1,s2)8291 shomac(s1, s2) char *s1, *s2; {
8292     int x, n, pp;
8293     pp = 0;                             /* Parenthesis counter */
8294 
8295     debug(F110,"shomac s1",s1,0);
8296     debug(F110,"shomac s2",s2,0);
8297 
8298 #ifdef IKSD
8299     if ( inserver &&
8300 #ifdef IKSDCONF
8301         iksdcf
8302 #else /* IKSDCONF */
8303         1
8304 #endif /* IKSDCONF */
8305         ) {
8306         if (!ckstrcmp("on_exit",s1,-1,0) ||
8307             !ckstrcmp("on_logout",s1,-1,0))
8308           return(0);
8309     }
8310 #endif /* IKSD */
8311 
8312     if (!s1)
8313       return(0);
8314     else
8315       printf("%s = ",s1);               /* Print blank line and macro name */
8316     n = (int)strlen(s1) + 4;            /* Width of current line */
8317     if (!s2) s2 = "(not defined)";
8318 
8319     while ((x = *s2++)) {               /* Loop thru definition */
8320         if (x == '(') pp++;             /* Treat commas within parens */
8321         if (x == ')') pp--;             /* as ordinary text */
8322         if (pp < 0) pp = 0;             /* Outside parens, */
8323         if (x == ',' && pp == 0) {      /* comma becomes comma-dash-NL. */
8324             putchar(',');
8325             putchar('-');
8326             x = '\n';
8327         }
8328         if (inserver && (x == '\n'))    /* Send CR before LF */
8329           putchar(CR);
8330         putchar((CHAR)x);               /* Output the character */
8331         if (x == '\n') {                /* If it was a newline */
8332 #ifdef UNIX
8333 #ifdef NOSETBUF
8334             fflush(stdout);
8335 #endif /* NOSETBUF */
8336 #endif /* UNIX */
8337             putchar(' ');               /* Indent the next line 1 space */
8338             while(*s2 == ' ') s2++;     /* skip past leading blanks */
8339             n = 2;                      /* restart the character counter */
8340             slc++;                      /* and increment the line counter. */
8341         } else if (++n > (cmd_cols - 1)) { /* If line is too wide */
8342             putchar('-');               /* output a dash */
8343             if (inserver)
8344               putchar(CR);              /* and a carriage return */
8345             putchar(NL);                /* and a newline */
8346 #ifdef UNIX
8347 #ifdef NOSETBUF
8348             fflush(stdout);
8349 #endif /* NOSETBUF */
8350 #endif /* UNIX */
8351             n = 1;                      /* and restart the char counter */
8352             slc++;                      /* and increment the line counter */
8353         }
8354         if (n < 3 && slc > (cmd_rows - 3)) { /* If new line and screen full */
8355             if (!askmore()) return(-1); /* ask if they want more. */
8356             n = 1;                      /* They do, start a new line */
8357             slc = 0;                    /* and restart line counter */
8358         }
8359     }
8360     if (inserver)
8361       putchar(CR);
8362     putchar(NL);                        /* End of definition */
8363     if (++slc > (cmd_rows - 3)) {
8364         if (!askmore()) return(-1);
8365         slc = 0;
8366     }
8367     return(0);
8368 }
8369 #endif /* NOSPL */
8370 #endif /* NOSHOW */
8371 
8372 int x_ifnum = 0;                        /* Flag for IF NUMERIC active */
8373 
8374 #ifndef NOSPL
8375 /* Evaluate an arithmetic expression. */
8376 /* Code adapted from ev, by Howie Kaye of Columbia U & others. */
8377 
8378 static int xerror = 0;
8379 int divbyzero = 0;
8380 static char *cp;
8381 static CK_OFF_T tokval;
8382 static char curtok;
8383 static CK_OFF_T expval;
8384 
8385 #define LONGBITS (8*sizeof (CK_OFF_T))
8386 #define NUMBER 'N'
8387 #define N_EOT 'E'
8388 
8389 /*
8390  Replacement for strchr() and index(), neither of which seem to be universal.
8391 */
8392 
8393 static char *
8394 #ifdef CK_ANSIC
windex(char * s,char c)8395 windex(char * s, char c)
8396 #else
8397 windex(s,c) char *s, c;
8398 #endif /* CK_ANSIC */
8399 /* windex */ {
8400     while (*s != NUL && *s != c) s++;
8401     if (*s == c) return(s); else return(NULL);
8402 }
8403 
8404 
8405 /*
8406  g e t t o k
8407 
8408  Returns the next token.  If token is a NUMBER, sets tokval appropriately.
8409 */
8410 static char
gettok()8411 gettok() {
8412     char tbuf[80] /* ,*tp */ ;          /* Buffer to accumulate number */
8413 
8414     while (isspace(*cp))                /* Skip past leading spaces */
8415       cp++;
8416 
8417     debug(F110,"GETTOK",cp,0);
8418 
8419     switch (*cp) {
8420       case '$':                         /* ??? */
8421       case '+':                         /* Add */
8422       case '-':                         /* Subtract or Negate */
8423       case '@':                         /* Greatest Common Divisor */
8424       case '*':                         /* Multiply */
8425       case '/':                         /* Divide */
8426       case '%':                         /* Modulus */
8427       case '<':                         /* Left shift */
8428       case '>':                         /* Right shift */
8429       case '&':                         /* And */
8430       case '|':                         /* Or */
8431       case '#':                         /* Exclusive Or */
8432       case '~':                         /* Not */
8433       case '^':                         /* Exponent */
8434       case '!':                         /* Factorial */
8435       case '(':                         /* Parens for grouping */
8436       case ')': return(*cp++);          /* operator, just return it */
8437       case '\n':
8438       case '\0': return(N_EOT);         /* End of line, return that */
8439     }
8440 #ifdef COMMENT
8441 /* This is the original code, which allows only integer numbers. */
8442 
8443     if (isxdigit(*cp)) {                /* Digit, must be a number */
8444         int radix = 10;                 /* Default radix */
8445         for (tp = tbuf; isxdigit(*cp); cp++)
8446           *tp++ = (char) (isupper(*cp) ? tolower(*cp) : *cp);
8447         *tp = '\0';                     /* End number */
8448         switch(isupper(*cp) ? tolower(*cp) : *cp) { /* Examine break char */
8449           case 'h':
8450           case 'x': radix = 16; cp++; break; /* if radix signifier... */
8451           case 'o':
8452           case 'q': radix = 8; cp++; break;
8453           case 't': radix = 2; cp++; break;
8454         }
8455         for (tp = tbuf, tokval = 0; *tp != '\0'; tp++)  {
8456             int dig;
8457             dig = *tp - '0';            /* Convert number */
8458             if (dig > 10) dig -= 'a'-'0'-10;
8459             if (dig >= radix) {
8460                 if (cmdlvl == 0 && !x_ifnum && !xerror)
8461                   printf("?Invalid digit '%c' in number\n",*tp);
8462                 xerror = 1;
8463                 return(NUMBER);
8464             }
8465             tokval = radix*tokval + dig;
8466         }
8467         return(NUMBER);
8468     }
8469     if (cmdlvl == 0 && !x_ifnum && !xerror)
8470       printf("Invalid character '%c' in input\n",*cp);
8471     xerror = 1;
8472     cp++;
8473     return(gettok());
8474 #else
8475 /* This code allows non-numbers to be treated as macro names */
8476     {
8477         int i, x;
8478         char * s, * cp1;
8479         cp1 = cp;
8480         tp = tbuf;
8481         for (i = 0; i < 80; i++) {
8482             /* Look ahead to next break character */
8483             /* pretty much anything that is not in the switch() above. */
8484             if (isalpha(*cp) || isdigit(*cp) ||
8485                 *cp == '_' || *cp == ':' || *cp == '.' ||
8486                 *cp == '[' || *cp == ']' ||
8487                 *cp == '{' || *cp == '}'
8488                 )
8489               tbuf[i] = *cp++;
8490             else
8491               break;
8492         }
8493         if (i >= 80) {
8494             printf("Too long - \"%s\"\n", cp1);
8495             xerror = 1;
8496             cp++;
8497             return(gettok());
8498         }
8499         if (xerror) return(NUMBER);
8500 
8501         tbuf[i] = NUL;
8502         s = tbuf;
8503         if (!isdigit(tbuf[0])) {
8504             char * s2 = NULL;
8505             x = mxlook(mactab,tbuf,nmac);
8506             debug(F111,"gettok mxlook",tbuf,x);
8507             if (x < 0) {
8508                 if (cmdlvl == 0 && !x_ifnum && !xerror)
8509                   printf("Bad number - \"%s\"\n",tbuf);
8510                 xerror = 1;
8511                 cp++;
8512                 return(gettok());
8513             }
8514             s2 = mactab[x].mval;
8515             if (!s2) s2 = "";
8516             if (*s2) s = s2;
8517         }
8518 #ifdef CKFLOAT
8519         x = isfloat(s,0);
8520 #else
8521         x = chknum(s);
8522 #endif /* CKFLOAT */
8523         if (x > 0) {
8524             tokval = ckatofs(s);
8525         } else {
8526             if (cmdlvl == 0 && !x_ifnum && !xerror)
8527               printf("Bad number - \"%s\"\n",tbuf);
8528             xerror = 1;
8529             cp++;
8530             return(gettok());
8531         }
8532         return(NUMBER);
8533     }
8534 #endif /* COMMENT */
8535 }
8536 
8537 static CK_OFF_T
8538 #ifdef CK_ANSIC
expon(CK_OFF_T x,CK_OFF_T y)8539 expon(CK_OFF_T x, CK_OFF_T y)
8540 #else
8541 expon(x,y) CK_OFF_T x,y;
8542 #endif /* CK_ANSIC */
8543 /* expon */ {
8544     CK_OFF_T result = 1;
8545     int sign = 1;
8546     if (y < 0) return(0);
8547     if (x < 0) {
8548         x = -x;
8549         if (y & 1) sign = -1;
8550     }
8551     while (y != 0) {
8552         if (y & 1) result *= x;
8553         y >>= 1;
8554         if (y != 0) x *= x;
8555   }
8556   return(result * sign);
8557 }
8558 
8559 /*
8560  * factor ::= simple | simple ^ factor
8561  *
8562  */
8563 static VOID
factor()8564 factor() {
8565     CK_OFF_T oldval;
8566     simple();
8567     if (curtok == '^') {
8568         oldval = expval;
8569         curtok = gettok();
8570         factor();
8571         expval = expon(oldval,expval);
8572     }
8573 }
8574 
8575 /*
8576  * termp ::= NULL | {*,/,%,&} factor termp
8577  *
8578  */
8579 static VOID
termp()8580 termp() {
8581     while (curtok == '*' || curtok == '/' || curtok == '%' || curtok == '&') {
8582         CK_OFF_T oldval;
8583         char op;
8584         op = curtok;
8585         curtok = gettok();              /* skip past operator */
8586         oldval = expval;
8587         factor();
8588         switch(op) {
8589           case '*': expval = oldval * expval; break;
8590           case '/':
8591           case '%':
8592             if (expval == 0) {
8593                 if (!x_ifnum)
8594                   printf("?Divide by zero\n");
8595                 xerror = 1;
8596                 divbyzero = 1;
8597                 expval = -1;
8598             } else
8599               expval = (op == '/') ? (oldval / expval) : (oldval % expval);
8600             break;
8601           case '&':
8602             expval = oldval & expval; break;
8603         }
8604     }
8605 }
8606 
8607 static CK_OFF_T
8608 #ifdef CK_ANSIC
fact(CK_OFF_T x)8609 fact(CK_OFF_T x)
8610 #else
8611 fact(x) CK_OFF_T x;
8612 #endif /* CK_ANSIC */
8613 /* fact */ {                            /* factorial */
8614     CK_OFF_T result = 1;
8615     while (x > 1)
8616       result *= x--;
8617     return(result);
8618 }
8619 
8620 /*
8621  * term ::= factor termp
8622  *
8623  */
8624 static VOID
term()8625 term() {
8626     factor();
8627     termp();
8628 }
8629 
8630 static CK_OFF_T
8631 #ifdef CK_ANSIC
gcd(CK_OFF_T x,CK_OFF_T y)8632 gcd(CK_OFF_T x, CK_OFF_T y)
8633 #else
8634 gcd(x,y) CK_OFF_T x,y;
8635 #endif /* CK_ANSIC */
8636 /* gcd */ {                             /* Greatest Common Divisor */
8637     int nshift = 0;
8638     if (x < 0) x = -x;
8639     if (y < 0) y = -y;                  /* validate arguments */
8640     if (x == 0 || y == 0) return(x + y);    /* this is bogus */
8641 
8642     while (!((x & 1) | (y & 1))) {      /* get rid of powers of 2 */
8643         nshift++;
8644         x >>= 1;
8645         y >>= 1;
8646     }
8647     while (x != 1 && y != 1 && x != 0 && y != 0) {
8648         while (!(x & 1)) x >>= 1;       /* eliminate unnecessary */
8649         while (!(y & 1)) y >>= 1;       /* powers of 2 */
8650         if (x < y) {                    /* force x to be larger */
8651             CK_OFF_T t;
8652             t = x;
8653             x = y;
8654             y = t;
8655         }
8656         x -= y;
8657     }
8658     if (x == 0 || y == 0) return((x + y) << nshift); /* gcd is non-zero one */
8659     else return((CK_OFF_T) 1 << nshift);    /* else gcd is 1 */
8660 }
8661 
8662 /*
8663  * exprp ::= NULL | {+,-,|,...} term exprp
8664  *
8665  */
8666 static VOID
exprp()8667 exprp() {
8668     while (windex("+-|<>#@",curtok) != NULL) {
8669         CK_OFF_T oldval;
8670         char op;
8671         op = curtok;
8672         curtok = gettok();              /* skip past operator */
8673         oldval = expval;
8674         term();
8675         switch(op) {
8676           case '+' : expval = oldval + expval; break;
8677           case '-' : expval = oldval - expval; break;
8678           case '|' : expval = oldval | expval; break;
8679           case '#' : expval = oldval ^ expval; break;
8680           case '@' : expval = gcd(oldval,expval); break;
8681           case '<' : expval = oldval << expval; break;
8682           case '>' : expval = oldval >> expval; break;
8683         }
8684     }
8685 }
8686 
8687 /*
8688  * expr ::= term exprp
8689  *
8690  */
8691 static VOID
expr()8692 expr() {
8693     term();
8694     exprp();
8695 }
8696 
8697 static CK_OFF_T
xparse()8698 xparse() {
8699     curtok = gettok();
8700     expr();
8701 #ifdef COMMENT
8702     if (curtok == '$') {
8703         curtok = gettok();
8704         if (curtok != NUMBER) {
8705             if (cmdlvl == 0 && !x_ifnum)
8706               printf("?Illegal radix\n");
8707             xerror = 1;
8708             return(0);
8709         }
8710         curtok = gettok();
8711     }
8712 #endif /* COMMENT */
8713     if (curtok != N_EOT) {
8714         if (cmdlvl == 0 && !x_ifnum && !xerror)
8715           printf("?Extra characters after expression\n");
8716         xerror = 1;
8717     }
8718     return(expval);
8719 }
8720 
8721 char *                                  /* Silent front end for evala() */
evalx(s)8722 evalx(s) char *s; {
8723     char * p;
8724     int t;
8725     t = x_ifnum;
8726     x_ifnum = 1;
8727     p = evala(s);
8728     x_ifnum = t;
8729     return(p);
8730 }
8731 
8732 char *
evala(s)8733 evala(s) char *s; {
8734     CK_OFF_T v;				/* Numeric value */
8735     if (!s) return("");
8736     xerror = 0;                         /* Start out with no error */
8737     divbyzero = 0;
8738     cp = s;                             /* Make the argument global */
8739     v = xparse();                       /* Parse the string */
8740     return(xerror ? "" : ckfstoa(v));	/* Return empty string on error */
8741 }
8742 
8743 /*
8744  * simplest ::= NUMBER | ( expr )
8745  *
8746  */
8747 static VOID
simplest()8748 simplest() {
8749     char * p;
8750     p = cp;
8751     if (curtok == NUMBER)
8752       expval = tokval;
8753     else if (curtok == '(') {
8754         curtok = gettok();              /* skip over paren */
8755         expr();
8756         if (curtok != ')') {
8757             if (cmdlvl == 0 && !x_ifnum && !xerror)
8758               printf("?Missing right parenthesis\n");
8759             xerror = 1;
8760         }
8761         debug(F110,"GETTOK SIMPLEST ()",p,0);
8762 
8763     } else {
8764         if (cmdlvl == 0 && !x_ifnum && !xerror)
8765           printf("?Operator unexpected\n");
8766         xerror = 1;
8767     }
8768     curtok = gettok();
8769 }
8770 
8771 /*
8772  * simpler ::= simplest | simplest !
8773  *
8774  */
8775 static VOID
simpler()8776 simpler() {
8777     simplest();
8778     if (curtok == '!') {
8779         curtok = gettok();
8780         expval = fact(expval);
8781     }
8782 }
8783 
8784 /*
8785  * simple ::= {-,~,!} simpler | simpler
8786  *
8787  */
8788 
8789 static VOID
simple()8790 simple() {
8791     if (curtok == '-' || curtok == '~' || curtok == '!' || curtok == '+') {
8792         int op = curtok;
8793         curtok = gettok();              /* skip over - sign */
8794         simpler();                      /* parse the factor again */
8795         if (op != '+')
8796           expval = (op == '-') ? -expval : ((op == '!') ? !expval : ~expval);
8797     } else simpler();
8798 }
8799 
8800 /*  D C L A R R A Y  --  Declare an array  */
8801 /*
8802   Call with:
8803    char a = single character designator for the array, e.g. "a".
8804    int  n = size of array.  -1 means to undeclare the array.
8805   Returns:
8806    0 or greater on success, having created the requested array with
8807      with n+1 elements, 0..n.  If an array of the same name existed
8808      previously, it is destroyed.  The new array has all its elements
8809      initialized to NULL pointers.  When an array is successfully created,
8810      the return value is its index (0 = 'a', 1 = 'b', and so on.)
8811   -1 on failure (because 'a' out of range or malloc failure).
8812 */
8813 int
8814 #ifdef CK_ANSIC
dclarray(char a,int n)8815 dclarray(char a, int n)
8816 #else
8817 dclarray(a,n) char a; int n;
8818 #endif /* CK_ANSIC */
8819 /* dclarray */ {
8820     char c, **p; int i, n2, rc;
8821 
8822     if (a > 63 && a < 91) a += 32;      /* Convert letters to lowercase */
8823     if (a < ARRAYBASE || a > 122)       /* Verify name */
8824       return(-1);
8825 
8826     if (n < 0)                          /* Check arg */
8827       return(-1);
8828     if (n+1 < 0)                        /* MAXINT+1 wraps around */
8829       return(-1);
8830 
8831     c = a;
8832     a -= ARRAYBASE;                     /* Convert name to number */
8833     rc = a;				/* Array index will be return code */
8834     if ((p = a_ptr[a]) != NULL) {       /* Delete old array of same name */
8835         if (a_link[a] > -1) {           /* Is it a link? */
8836             if (n == 0) {               /* If we're just deleting it */
8837                 a_ptr[a] = (char **) NULL; /* clear all the info. */
8838                 a_dim[a] = 0;
8839                 a_link[a] = -1;
8840                 return(0);
8841             }                           /* Not deleting */
8842             a = a_link[a];              /* Switch to linked-to array */
8843         }
8844         n2 = a_dim[a];                  /* Real array */
8845         for (i = 0; i <= n2; i++) {     /* First delete its elements */
8846             if (p[i]) {
8847                 free(p[i]);
8848                 p[i] = NULL;
8849             }
8850         }
8851         free((char *)a_ptr[a]);         /* Then the element list */
8852         if (n == 0) {                   /* If undeclaring this array... */
8853             for (i = 0; i < 122 - ARRAYBASE; i++) { /* Any linked arrays? */
8854                 if (i != a && a_link[i] == a) {     /* Find them */
8855                     a_ptr[i] = (char **) NULL;      /* and remove them */
8856                     a_dim[i] = 0;
8857                     a_link[i] = -1;
8858                 }
8859             }
8860         }
8861         a_ptr[a] = (char **) NULL;      /* Remove pointer to element list */
8862         a_dim[a] = 0;                   /* Set dimension at zero. */
8863         a_link[a] = -1;                 /* Unset link word */
8864     }
8865     if (n < 0)				/* If only undeclaring, */
8866       return(0);			/*  we're done. */
8867     p = (char **) malloc((n+1) * sizeof(char **)); /* Allocate for new array */
8868     if (p == NULL) return(-1);          /* Check */
8869     a_ptr[a] = p;                       /* Save pointer to member list */
8870     a_dim[a] = n;                       /* Save dimension */
8871     for (i = 0; i <= n; i++)            /* Initialize members to null */
8872       p[i] = NULL;
8873     for (i = 0; i < (int) 'z' - ARRAYBASE; i++) { /* Any linked arrays? */
8874         if (i != a && a_link[i] == a) { /* Find and update them */
8875             a_ptr[i] = p;
8876             a_dim[i] = n;
8877         }
8878     }
8879     return(rc);
8880 }
8881 
8882 /*  X A R R A Y  -- Convert array name to array index  */
8883 
8884 int
xarray(s)8885 xarray(s) char * s; {
8886     char buf[8];
8887     int x;
8888     char c;
8889 
8890     if (!s) s = "";
8891     debug(F110,"xarray",s,0);
8892     if (!*s)
8893       return(-1);
8894     x = strlen(s);
8895 
8896     buf[0] = NUL;
8897     buf[1] = NUL;
8898     buf[2] = s[0];
8899     buf[3] = (x > 0) ? s[1] : NUL;
8900     buf[4] = (x > 1) ? s[2] : NUL;
8901     buf[5] = (x > 2) ? s[3] : NUL;
8902     buf[6] = NUL;
8903     debug(F110,"xarray buf[3]",&buf[3],0);
8904     s = buf+2;
8905     if (*s == '&') {
8906         buf[1] = CMDQ;
8907         s--;
8908     } else if (*s != CMDQ) {
8909         buf[0] = CMDQ;
8910         buf[1] = '&';
8911         s = buf;
8912     }
8913     debug(F110,"xarray s",s,0);
8914     c = *(s+2);
8915     if (isupper(c))
8916       c = tolower(c);
8917     if (c == '@')
8918       c = 96;
8919     x = (int)c - ARRAYBASE;
8920     if (*(s+3) == '[')
8921       *(s+3) = NUL;
8922     if (x < 0) {
8923 	return(-1);
8924     }
8925     if (x > ('z' - ARRAYBASE)) {
8926 	debug(F101,"xarray x out of range","",x);
8927 	return(-1);
8928     }
8929     if (*(s+3)) {
8930 	debug(F110,"xarray syntax",s,0);
8931 	return(-1);
8932     }
8933     return(x);
8934 }
8935 
8936 /*
8937   boundspair() -- parses blah[n:m]
8938 
8939   For use with array segment specifiers and compact substring notation.
8940   Ignores the "blah" part, gets the values of n and m, which can be
8941   numbers, variables, or arithmetic expressions; anything that resolves
8942   to a number.
8943 
8944   Call with:
8945    s    - string to parse
8946    sep  - array of permissible bounds separator chars
8947    lo   - pointer to low-bound result (or -1)
8948    hi   - pointer to hi-bound result (or -1)
8949    zz   - pointer to separator char that was encountered (or NUL)
8950   Returns:
8951    -1 on failure
8952     0 on success
8953 */
8954 
8955 int
8956 #ifdef CK_ANSIC
boundspair(char * s,char * sep,int * lo,int * hi,char * zz)8957 boundspair(char *s, char *sep, int *lo, int *hi, char *zz)
8958 #else
8959 boundspair(s,sep,lo,hi,zz) char *s, *sep, *zz; int *lo, *hi;
8960 #endif /* CK_ANSIC */
8961 {
8962     int i, x, y, range[2], bc = 0;
8963     char c = NUL, *s2 = NULL, buf[256], *p, *q, *r, *e[2], *tmp = NULL;
8964 
8965     debug(F110,"boundspair s",s,0);
8966     debug(F110,"boundspair sep",sep,0);
8967 
8968     *lo = -1;                           /* Default bounds */
8969     *hi = -1;
8970     *zz = 0;				/* Default bounds separator */
8971 
8972     range[0] = -1;                      /* It's OK -- get contents */
8973     range[1] = -1;                      /* of subscript brackets */
8974     if (!s) s = "";
8975     if (!*s)
8976       return(-1);
8977     makestr(&tmp,s);                    /* Make a pokeable copy */
8978     p = tmp;
8979     q = NULL;
8980     r = NULL;
8981     for (p = s; *p; p++) {		/* Get the two elements */
8982 	if (*p == '[') {
8983 	    bc++;			/* Bracket counter */
8984 	    if (bc == 1 && !q) q = p+1;
8985 	} else if (*p == ']') {
8986 	    bc--;
8987 	    if (bc == 0 && q) *p = NUL;
8988 	} else if (bc == 1) {		/* If within brackers */
8989 	    s2 = ckstrchr(sep,*p);	/* Check for separator */
8990 	    if (s2) {
8991 		debug(F000,"boundspair *s2","",*s2);
8992 		if (c) {
8993 		    debug(F000,"boundspair","Too many separators",*s2);
8994 		    makestr(&tmp,NULL);
8995 		    return(-1);
8996 		}
8997 		c = *s2;		/* Separator character */
8998 		*p = NUL;
8999 		r = p+1;
9000 	    }
9001 	}
9002     }
9003     if (bc == 0 && !q) {
9004 	/* This allows such constructions as "show array a" */
9005 	debug(F110,"boundspair","no brackets",0);
9006 	makestr(&tmp,NULL);
9007 	return(0);
9008     }
9009     if (bc != 0 || !q) {
9010 	debug(F110,"boundspair","unbalanced or missing brackets",0);
9011 	makestr(&tmp,NULL);
9012 	return(-1);
9013     }
9014     if (!q) q = "";
9015     if (!*q) q = "-1";
9016     if (!r) r = "";
9017     if (!*r) r = "-1";
9018 
9019     e[0] = q;
9020     e[1] = r;
9021 
9022     debug(F000,"boundspair c","",c);
9023     debug(F110,"boundspair q",q,0);
9024     debug(F110,"boundspair r",r,0);
9025 
9026     for (i = 0; i < 2 && e[i]; i++) {
9027 	y = 255;			/* Expand variables, etc. */
9028 	s = buf;
9029 	zzstring(e[i],&s,&y);
9030 	s = evalx(buf);			/* Evaluate it arithmetically */
9031 	if (s) if (*s)
9032 	  ckstrncpy(buf,s,256);
9033 	if (!chknum(buf)) {		/* Did we get a number? */
9034 	    debug(F110,"boundspair element not numeric",buf,0);
9035 	    makestr(&tmp,NULL);		/* No, fail. */
9036 	    return(-1);
9037 	}
9038 	range[i] = atoi(buf);
9039     }
9040     makestr(&tmp,NULL);                 /* Free temporary poked string */
9041     *lo = range[0];                     /* Return what we got */
9042     *hi = range[1];
9043     *zz = c;
9044     debug(F101,"boundspair lo","",*lo);
9045     debug(F101,"boundspair hi","",*hi);
9046     return(0);
9047 }
9048 
9049 /*  A R R A Y B O U N D S  --  Parse array segment notation \&a[n:m]  */
9050 
9051 /*
9052   Call with s = array reference, plus two pointers to ints.
9053   Returns -1 on error, or array index, with the two ints set as follows:
9054    \&a[]     -1, -1
9055    \&a[3]     3, -1
9056    \&a[3:17]  3, 17
9057   The array need not be declared -- this routine is just for parsing.
9058 */
9059 int
arraybounds(s,lo,hi)9060 arraybounds(s,lo,hi) char * s; int * lo, * hi; {
9061     int i, x, y, range[2];
9062     char zz, buf[256], * p, * q;
9063     char * tmp = NULL;
9064 
9065     *lo = -1;                           /* Default bounds */
9066     *hi = -1;
9067 
9068     if (!s) s = "";                     /* Defense de null args */
9069     if (!*s)
9070       return(-1);
9071 
9072     x = xarray(s);                      /* Check basic structure */
9073     debug(F111,"arraybounds xarray",s,x);
9074     if (x < 0)                          /* Not OK, fail. */
9075       return(-1);
9076     y = boundspair(s,":",lo,hi,&zz);
9077     debug(F111,"arraybounds boundspair",s,y);
9078     debug(F101,"arraybounds lo","",*lo);
9079     debug(F101,"arraybounds hi","",*hi);
9080     if (y < 0)				/* Get bounds */
9081       return(-1);
9082     return(x);
9083 }
9084 
9085 /*  A R R A Y N A M  --  Parse an array name  */
9086 
9087 /*
9088   Call with pointer to string that starts with the array reference.
9089   String may begin with either \& or just &.
9090   On success,
9091     Returns letter ID (always lowercase) in argument c,
9092       which can also be accent grave (` = 96; '@' is converted to grave);
9093     Dimension or subscript in argument n;
9094     IMPORTANT: These arguments must be provided by the caller as addresses
9095     of ints (not chars), for example:
9096       char *s; int x, y;
9097       arraynam(s,&x,&y);
9098   On failure, returns a negative number, with args n and c set to zero.
9099 */
9100 int
arraynam(ss,c,n)9101 arraynam(ss,c,n) char *ss; int *c; int *n; {
9102     int i, y, pp, len;
9103     char x;
9104     char *s, *p, *sx, *vnp;
9105     /* On stack to allow for recursive calls... */
9106     char vnbuf[ARRAYREFLEN+1];          /* Entire array reference */
9107     char ssbuf[ARRAYREFLEN+1];          /* Subscript in "plain text" */
9108     char sxbuf[16];                     /* Evaluated subscript */
9109 
9110     *c = *n = 0;                        /* Initialize return values */
9111     len = strlen(ss);
9112     for (pp = 0,i = 0; i < len; i++) {          /* Check length */
9113         if (ss[i] == '[') {
9114             pp++;
9115         } else if (ss[i] == ']') {
9116             if (--pp == 0)
9117               break;
9118         }
9119     }
9120     if (i > ARRAYREFLEN) {
9121         printf("?Array reference too long - %s\n",ss);
9122         return(-9);
9123     }
9124     ckstrncpy(vnbuf,ss,ARRAYREFLEN);
9125     vnp = vnbuf;
9126     if (vnbuf[0] == CMDQ && vnbuf[1] == '&') vnp++;
9127     if (*vnp != '&') {
9128         printf("?Not an array - %s\n",vnbuf);
9129         return(-9);
9130     }
9131     x = *(vnp + 1);                     /* Fold case of array name */
9132 
9133     /* We don't use isupper & tolower here on purpose because these */
9134     /* would produce undesired effects with accented letters. */
9135     if (x > 63 && x < 91) x  = *(vnp + 1) = (char) (x + 32);
9136     if ((x < ARRAYBASE) || (x > 122) || (*(vnp+2) != '[')) {
9137         if (msgflg) {
9138             printf("?Invalid format for array name - %s\n",vnbuf);
9139             return(-9);
9140         } else
9141           return(-2);
9142     }
9143     *c = x;                             /* Return the array name */
9144     s = vnp+3;                          /* Get dimension */
9145     p = ssbuf;
9146     pp = 1;                             /* Bracket counter */
9147     for (i = 0; i < ARRAYREFLEN && *s != NUL; i++) { /* Copy up to ] */
9148         if (*s == '[') pp++;
9149         if (*s == ']' && --pp == 0) break;
9150         *p++ = *s++;
9151     }
9152     if (*s != ']') {
9153         printf("?No closing bracket on array dimension - %s\n",vnbuf);
9154         return(-9);
9155     }
9156     p--;                                /* Trim whitespace from end */
9157     while (*p == SP || *p == HT)
9158       p--;
9159     p++;
9160     *p = NUL;                           /* Terminate subscript with null */
9161     p = ssbuf;                          /* Point to beginning of subscript */
9162     while (*p == SP || *p == HT)        /* Trim whitespace from beginning */
9163       p++;
9164     sx = sxbuf;                         /* Where to put expanded subscript */
9165     y = 16;
9166     {
9167 	/* Even if VARIABLE-EVALUATION SIMPLE use RECURSIVE for subscripts */
9168 	/* NOTE: This is vulnerable to SIGINT and whatnot... */
9169 	int tmp = vareval;		/* Save VARIABLE-EVALUATION setting */
9170 	vareval = 1;			/* Force it to RECURSIVE */
9171 	zzstring(p,&sx,&y);		/* Convert variables, etc. */
9172 	vareval = tmp;			/* Restore VARIABLE-EVALUATION */
9173     }
9174     sx = sxbuf;
9175     while (*sx == SP) sx++;
9176     /* debug(F110,"arraynam sx","",sx); */
9177     if (!*sx) {                         /* Empty brackets... */
9178         *n = -17;                       /* (Secret code :-) */
9179         return(-2);
9180     }
9181     p = evala(sx);                      /* Run it thru \fneval()... */
9182     if (p) if (*p) ckstrncpy(sxbuf,p,16); /* We know it has to be a number. */
9183 
9184     if (!chknum(sxbuf)) {               /* Make sure it's all digits */
9185         if (msgflg) {
9186             printf("?Array dimension or subscript missing or not numeric\n");
9187             return(-9);
9188         } else
9189           return(-2);
9190     }
9191     if ((y = atoi(sxbuf)) < 0) {
9192         if (cmflgs == 0) printf("\n");
9193         if (msgflg) {
9194             printf("?Array dimension or subscript not positive or zero\n");
9195             return(-9);
9196         } else
9197           return(-2);
9198     }
9199     *n = y;                             /* Return the subscript or dimension */
9200     return(0);
9201 }
9202 
9203 /* chkarray returns 0 or greater if array exists, negative otherwise */
9204 
9205 int
chkarray(a,i)9206 chkarray(a,i) int a, i; {               /* Check if array is declared */
9207     int x;                              /* and if subscript is in range */
9208     if (a == 64) a = 96;                /* Convert atsign to grave accent */
9209     x = a - ARRAYBASE;                  /* Values must be in range 95-122 */
9210 #ifdef COMMENT
9211     if (x == 0 && maclvl < 0)           /* Macro arg vector but no macro */
9212       return(0);
9213 #endif /* COMMENT */
9214     if (x < 0 || x > 'z' - ARRAYBASE)   /* Not in range */
9215       return(-2);
9216     if (a_ptr[x] == NULL) return(-1);   /* Not declared */
9217     if (i > a_dim[x]) return(-2);       /* Declared but out of range. */
9218     return(a_dim[x]);                   /* All ok, return dimension */
9219 }
9220 
9221 #ifdef COMMENT                          /* This isn't used. */
9222 char *
arrayval(a,i)9223 arrayval(a,i) int a, i; {               /* Return value of \&a[i] */
9224     int x; char **p;                    /* (possibly NULL) */
9225     if (a == 64) a = 96;                /* Convert atsign to grave accent */
9226     x = a - ARRAYBASE;                  /* Values must be in range 95-122 */
9227     if (x < 0 || x > 27) return(NULL);  /* Not in range */
9228     if ((x > 0) && (p = a_ptr[x]) == NULL) /* Array not declared */
9229       return(NULL);
9230     if (i > a_dim[x])                   /* Subscript out of range. */
9231       return(NULL);
9232     return(p[i]);                       /* All ok, return pointer to value. */
9233 }
9234 #endif /* COMMENT */
9235 
9236 /*
9237   pusharray() is called when an array name is included in a LOCAL statement.
9238   It moves the pointers from the global definition to the stack, and removes
9239   the global definition.  Later, if the same array is declared in the local
9240   context, it occupies the global definition in the normal way.  But when
9241   popclvl() is called, it replaces the global definition with the one saved
9242   here.  The "secret code" is used to indicate to popclv() that it should
9243   remove the global array when popping through this level -- otherwise if a
9244   local array were declared that had no counterpart at any higher level, it
9245   would never be deleted.  This allows Algol-like inheritance to work both
9246   on the way down and on the way back up.
9247 */
9248 int
pusharray(x,z)9249 pusharray(x,z) int x, z; {
9250     int y;
9251     debug(F000,"pusharray x","",x);
9252     debug(F101,"pusharray z","",z);
9253     y = chkarray(x,z);
9254     debug(F101,"pusharray y","",y);
9255     x -= ARRAYBASE;                     /* Convert name letter to index. */
9256     if (x < 0 || x > 27)
9257       return(-1);
9258     if (y < 0) {
9259         aa_ptr[cmdlvl][x] = (char **) NULL;
9260         aa_dim[cmdlvl][x] = -23;        /* Secret code (see popclvl()) */
9261     } else {
9262         aa_ptr[cmdlvl][x] = a_ptr[x];
9263         aa_dim[cmdlvl][x] = y;
9264     }
9265     a_ptr[x] = (char **) NULL;
9266     a_dim[x] = 0;
9267     return(0);
9268 }
9269 
9270 /*  P A R S E V A R  --  Parse a variable name or array reference.  */
9271 /*
9272  Call with:
9273    s  = pointer to candidate variable name or array reference.
9274    *c = address of integer in which to return variable ID.
9275    *i = address of integer in which to return array subscript.
9276  Returns:
9277    -2:  syntax error in variable name or array reference.
9278     1:  successful parse of a simple variable, with ID in c.
9279     2:  successful parse of an array reference, w/ID in c and subscript in i.
9280 */
9281 int
parsevar(s,c,i)9282 parsevar(s,c,i) char *s; int *c, *i; {
9283     char *p;
9284     int x,y,z;
9285 
9286     p = s;
9287     if (*s == CMDQ) s++;                /* Point after backslash */
9288 
9289     if (*s != '%' && *s != '&') {       /* Make sure it's % or & */
9290         printf("?Not a variable name - %s\n",p);
9291         return(-9);
9292     }
9293     if ((int)strlen(s) < 2) {
9294         printf("?Incomplete variable name - %s\n",p);
9295         return(-9);
9296     }
9297     if (*s == '%' && *(s+2) != '\0') {
9298         printf("?Only one character after '%%' in variable name, please\n");
9299         return(-9);
9300     }
9301     if (*s == '&' && *(s+2) != '[') {
9302         printf("?Array subscript expected - %s\n",p);
9303         return(-9);
9304     }
9305     if (*s == '%') {                    /* Simple variable. */
9306         y = *(s+1);                     /* Get variable ID letter/char */
9307         if (isupper(y)) y -= ('a'-'A'); /* Convert upper to lower case */
9308         *c = y;                         /* Set the return values. */
9309         *i = -1;                        /* No array subscript. */
9310         return(1);                      /* Return 1 = simple variable */
9311     }
9312     if (*s == '&') {                    /* Array reference. */
9313         y = arraynam(s,&x,&z);          /* Go parse it. */
9314         debug(F101,"parsevar arraynam","",y);
9315         if ((y) < 0) {
9316             if (y == -2)
9317               return(pusharray(x,z));
9318             if (y != -9)
9319               printf("?Invalid array reference - %s\n",p);
9320             return(-9);
9321         }
9322         if (chkarray(x,z) < 0) {        /* Check if declared, etc. */
9323             printf("?Array not declared or subscript out of range\n");
9324             return(-9);
9325         }
9326         *c = x;                         /* Return array letter */
9327         *i = z;                         /* and subscript. */
9328         return(2);
9329     }
9330     return(-2);                         /* None of the above. */
9331 }
9332 
9333 
9334 #define VALN 32
9335 
9336 /* Get the numeric value of a variable */
9337 /*
9338   Call with pointer to variable name, pointer to int for return value.
9339   Returns:
9340     0 on success with second arg containing the value.
9341    -1 on failure (bad variable syntax, variable not defined or not numeric).
9342 */
9343 int
varval(s,v)9344 varval(s,v) char *s; CK_OFF_T *v; {
9345     char valbuf[VALN+1];                /* s is pointer to variable name */
9346     char name[256];
9347     char *p;
9348     int y;
9349 
9350     if (*s != CMDQ) {                   /* Handle macro names too */
9351         ckmakmsg(name,256,"\\m(",s,")",NULL);
9352         s = name;
9353     }
9354     p = valbuf;                         /* Expand variable into valbuf. */
9355     y = VALN;
9356     if (zzstring(s,&p,&y) < 0) return(-1);
9357     p = valbuf;                         /* Make sure value is numeric  */
9358     if (!*p) {                          /* Be nice -- let an undefined */
9359         valbuf[0] = '0';                /* variable be treated as 0.   */
9360         valbuf[1] = NUL;
9361     }
9362     if (chknum(p)) {                    /* Convert numeric string to int */
9363         *v = ckatofs(p);		/* OK */
9364     } else {                            /* Not OK */
9365         p = evala(p);                   /* Maybe it's an expression */
9366         if (!chknum(p))                 /* Did it evaluate? */
9367           return(-1);                   /* No, failure. */
9368         else                            /* Yes, */
9369           *v = ckatofs(p);		/* success */
9370     }
9371     return(0);
9372 }
9373 
9374 /* Increment or decrement a variable */
9375 /* Returns -1 on failure, 0 on success */
9376 
9377 int
incvar(s,x,z)9378 incvar(s,x,z) char *s; CK_OFF_T x; int z; {  /* Increment a numeric variable */
9379     CK_OFF_T n;				/* s is pointer to variable name */
9380                                         /* x is amount to increment by */
9381                                         /* z != 0 means add */
9382                                         /* z = 0 means subtract */
9383     if (varval(s,&n) < 0)               /* Convert numeric string to int */
9384       return(-1);
9385     if (z)                              /* Increment it by the given amount */
9386       n += x;
9387     else                                /* or decrement as requested. */
9388       n -= x;
9389     addmac(s,ckfstoa(n));		/* Replace old variable */
9390     return(0);
9391 }
9392 
9393 /* D O D O  --  Do a macro */
9394 
9395 /*
9396   Call with x = macro table index, s = pointer to arguments.
9397   Returns 0 on failure, 1 on success.
9398 */
9399 int
dodo(x,s,flags)9400 dodo(x,s,flags) int x; char *s; int flags; {
9401     int y;
9402     extern int tra_asg, tra_cmd; int tra_tmp; /* For TRACE */
9403 #ifndef NOLOCAL
9404 #ifdef OS2
9405     extern int term_io;
9406     int term_io_sav = term_io;
9407 #endif /* OS2 */
9408 #endif /* NOLOCAL */
9409 
9410     if (x < 0)                          /* It can happen! */
9411       return(-1);
9412 
9413     tra_tmp = tra_asg;
9414 
9415     if (++maclvl >= MACLEVEL) {         /* Make sure we have storage */
9416         debug(F101,"dodo maclvl too deep","",maclvl);
9417         --maclvl;
9418         printf("Macros nested too deeply\n");
9419         return(0);
9420     }
9421     macp[maclvl] = mactab[x].mval;      /* Point to the macro body */
9422     macx[maclvl] = mactab[x].mval;      /* Remember where the beginning is */
9423 
9424 #ifdef COMMENT
9425     makestr(&(m_line[maclvl]),s);       /* Entire arg string for "\%*" */
9426 #endif /* COMMENT */
9427 
9428     cmdlvl++;                           /* Entering a new command level */
9429     if (cmdlvl >= CMDSTKL) {            /* Too many macros + TAKE files? */
9430         debug(F101,"dodo cmdlvl too deep","",cmdlvl);
9431         cmdlvl--;
9432         printf("?TAKE files and DO commands nested too deeply\n");
9433         return(0);
9434     }
9435 #ifdef DEBUG
9436     if (deblog) {
9437         debug(F111,"CMD +M",mactab[x].kwd,cmdlvl);
9438         debug(F010,"CMD ->",s,0);
9439     }
9440 #endif /* DEBUG */
9441 
9442 #ifdef VMS
9443     conres();                           /* So Ctrl-C, etc, will work. */
9444 #endif /* VMS */
9445 #ifndef NOLOCAL
9446 #ifdef OS2
9447     term_io = 0;                        /* Disable terminal emulator I/O */
9448 #endif /* OS2 */
9449 #endif /* NOLOCAL */
9450     ifcmd[cmdlvl] = 0;
9451     iftest[cmdlvl] = 0;
9452     count[cmdlvl] = count[cmdlvl-1];    /* Inherit COUNT from previous level */
9453     intime[cmdlvl] = intime[cmdlvl-1];  /* Inherit previous INPUT TIMEOUT */
9454     inpcas[cmdlvl] = inpcas[cmdlvl-1];  /*   and INPUT CASE */
9455     takerr[cmdlvl] = takerr[cmdlvl-1];  /*   and TAKE ERROR */
9456     merror[cmdlvl] = merror[cmdlvl-1];  /*   and MACRO ERROR */
9457     xquiet[cmdlvl] = quiet;
9458     xvarev[cmdlvl] = vareval;
9459     xcmdsrc = CMD_MD;
9460     cmdstk[cmdlvl].src = CMD_MD;        /* Say we're in a macro */
9461     cmdstk[cmdlvl].lvl = maclvl;        /* and remember the macro level */
9462     cmdstk[cmdlvl].ccflgs = flags & ~CF_IMAC; /* Set flags */
9463 
9464     /* Initialize return value except in FOR, WHILE, IF, and SWITCH macros */
9465 
9466     if (!(flags & CF_IMAC) && mrval[maclvl]) {
9467         free(mrval[maclvl]);
9468         mrval[maclvl] = NULL;
9469     }
9470 
9471     /* Clear old %0..%9 arguments */
9472 
9473     addmac("%0",mactab[x].kwd);         /* Define %0 = name of macro */
9474     makestr(&(m_xarg[maclvl][0]),mactab[x].kwd);
9475     varnam[0] = '%';
9476     varnam[2] = '\0';
9477     tra_asg = 0;
9478     for (y = 1; y < 10; y++) {          /* Clear args %1..%9 */
9479         if (m_arg[maclvl][y]) {         /* Don't call delmac() unless */
9480             varnam[1] = (char) (y + '0'); /* we have to... */
9481             delmac(varnam,0);
9482         }
9483     }
9484     tra_asg = tra_tmp;
9485 
9486 /* Break the big "s" string up into macro arguments */
9487 
9488     xwords(s,MAXARGLIST,NULL,0);
9489 
9490 #ifndef NOLOCAL
9491 #ifdef OS2
9492     term_io = term_io_sav;
9493 #endif /* OS2 */
9494 #endif /* NOLOCAL */
9495     if (tra_cmd)
9496       printf("[%d] +M: \"%s\"\n",cmdlvl,mactab[x].kwd);
9497     return(1);
9498 }
9499 
9500 /* Insert "literal" quote around each comma-separated command to prevent */
9501 /* its premature expansion.  Only do this if object command is surrounded */
9502 /* by braces. */
9503 
9504 static char* flit = "\\flit(";
9505 
9506 int
litcmd(src,dest,n)9507 litcmd(src,dest,n) char **src, **dest; int n; {
9508     int bc = 0, pp = 0;
9509     char c, *s, *lp, *ss;
9510 
9511     s = *src;
9512     lp = *dest;
9513 
9514     debug(F010,"litcmd",s,0);
9515 
9516     while (*s == SP) s++;               /* Strip extra leading spaces */
9517 
9518     if (*s == '{') {                    /* Starts with brace */
9519         pp = 0;                         /* Paren counter */
9520         bc = 1;                         /* Count leading brace */
9521         *lp++ = *s++;                   /* Copy it */
9522         if (--n < 1) return(-1);        /* Check space */
9523         while (*s == SP) s++;           /* Strip interior leading spaces */
9524         ss = flit;                      /* Point to "\flit(" */
9525         while ((*lp++ = *ss++))         /* Copy it */
9526           if (--n < 1)                  /* and check space */
9527             return(-1);
9528         lp--;                           /* Back up over null */
9529 
9530         while (*s) {                    /* Go thru rest of text */
9531             c = *s;
9532             if (c == '{') bc++;         /* Count brackets */
9533             if (c == '(') pp++;         /* and parens */
9534             if (c == ')') {             /* Right parenthesis. */
9535                 pp--;                   /* Count it. */
9536                 if (pp < 0) {           /* An unbalanced right paren... */
9537 #ifdef COMMENT
9538 /*
9539   The problem here is that "\{" appears to be a quoted brace and therefore
9540   isn't counted; then the "}" matches an earlier opening brace, causing
9541   (e.g.) truncation of macros by getncm().
9542 */
9543                     if (n < 5)          /* Out of space in dest buffer? */
9544                       return(-1);       /* If so, give up. */
9545                     *lp++ = CMDQ;       /* Must be quoted to prevent */
9546                     *lp++ = '}';        /* premature termination of */
9547                     *lp++ = '4';        /* \flit(...) */
9548                     *lp++ = '1';
9549                     *lp++ = '}';
9550                     n -= 5;
9551 #else
9552 /* Here we rely on the fact the \nnn never takes more than 3 digits */
9553                     if (n < 4)          /* Out of space in dest buffer? */
9554                       return(-1);       /* If so, give up. */
9555                     *lp++ = CMDQ;       /* Must be quoted to prevent */
9556                     *lp++ = '0';        /* premature termination of */
9557                     *lp++ = '4';        /* \flit(...) */
9558                     *lp++ = '1';
9559                     n -= 4;
9560 #endif /* COMMENT */
9561                     pp++;               /* Uncount it. */
9562                     s++;
9563                     continue;
9564                 }
9565             }
9566             if (c == '}') {             /* Closing brace. */
9567                 if (--bc == 0) {        /* Final one? */
9568                     *lp++ = ')';        /* Add closing paren for "\flit()" */
9569                     if (--n < 1) return(-1);
9570                     *lp++ = c;
9571                     if (--n < 1) return(-1);
9572                     s++;
9573                     break;
9574                 }
9575             }
9576             *lp++ = c;                  /* General case */
9577             if (--n < 1) return(-1);
9578             s++;
9579         }
9580         *lp = NUL;
9581     } else {                            /* No brackets around, */
9582         while ((*lp++ = *s++))          /* just copy. */
9583           if (--n < 1)
9584             return(-1);
9585         lp--;
9586     }
9587     *src = s;                           /* Return updated source */
9588     *dest = lp;                         /* and destination pointers */
9589     if (bc)                             /* Fail if braces unbalanced */
9590       return(-1);
9591     else                                /* Otherwise succeed. */
9592       return(0);
9593 }
9594 #endif /* NOSPL */
9595 
9596 /* Functions moved here from ckuusr.c to even out the module sizes... */
9597 
9598 /*
9599   Breaks up string s -- IN PLACE! -- into a list of up to max words.
9600   Pointers to each word go into the array list[].
9601   max is the maximum number of words (pointers).
9602   If list is NULL, then they are added to the macro table.
9603   flag = 0 means the last field is to be one word, like all the other fields,
9604          so anything after it is discarded.
9605   flag = 1 means the last field extends to the end of the string, even if
9606          there are lots of words left, so the last field contains the
9607          remainder of the string.
9608 */
9609 VOID
xwords(s,max,list,flag)9610 xwords(s,max,list,flag) char *s; int max; char *list[]; int flag; {
9611     char *p;
9612     int b, i, k, q, y, z;
9613     int macro = 0;
9614 
9615     if (!list) {
9616         debug(F100," xwords list is NULL","",0);
9617         macro = 1;
9618     } else {
9619         debug(F100," xwords LIST is defined","",0);
9620     }
9621     debug(F100,"xwords ENTRY","",0);
9622 
9623 #ifndef NOSPL
9624 /*
9625     debug(F110," xwords macro",(char *)m_xarg[maclvl][0],0);
9626 */
9627     debug(F101," xwords maclvl","",maclvl);
9628     debug(F101," xwords max","",max);
9629     debug(F101," xwords flag","",flag);
9630     debug(F110," xwords string",s,0);
9631     debug(F101," xwords macro","",macro);
9632 #endif /* NOSPL */
9633 
9634     p = s;                              /* Pointer to beginning of string */
9635     q = 0;                              /* Flag for doublequote removal */
9636     b = 0;                              /* Flag for outer brace removal */
9637     k = 0;                              /* Flag for in-word */
9638     y = 0;                              /* Brace nesting level */
9639     z = 0;                              /* "Word" counter, 0 thru max */
9640 
9641     if (!s) s = "";                     /* Nothing to do */
9642     if (!*s) return;
9643     if (list)
9644       for (i = 0; i <= max; i++)        /* Initialize pointers */
9645         list[i] = NULL;
9646 
9647     if (flag) max--;
9648 
9649 #ifndef NOSPL
9650     /*
9651       Macro arguments at this point are a single string... must split it up.
9652       As of C-Kermit 9.0.304 Dev.22, 24 April 2017, we use cksplit() for
9653       this instead of tons of messy code in xwords() written decades ago
9654       to do what cksplit() does better.
9655     */
9656     if (macro) {
9657         struct stringarray * q = NULL;
9658         char **pp = NULL;
9659         int n;
9660         if (maclvl < 0) {
9661             debug(F101," xwords maclvl < 0","",maclvl);
9662             newerrmsg("Internal error: maclvl < 0");
9663         }
9664         debug(F101," xwords splitting macro arguments.. maclvl","",maclvl);
9665 
9666         /* Space is the only separator; grouping is with "" or {} */
9667         q = cksplit(1,0,p," ","ALL",1+2,0,0,1);
9668         z = q->a_size;                  /* Number of "words" in string */
9669         if (z <= 0) return;
9670         pp = q->a_head;
9671         if (pp) {
9672 /*
9673   In C-Kermit 9.0.304 Dev.22, April 2017, we have to get the macro arguments
9674   from the previous macro level (prev).  Up to now, the macro arguments were
9675   evaluated when the DO command was parsed, before dodo() or xwords() were
9676   ever called.  Now we're evaluating them after already entering the new macro
9677   stack level: evalmacroarg() is just a front end for zzstring(), which is at
9678   the heart of all variable-substitution operations.  To evaluate a \%1-9
9679   variable, zzstring() looks in the CURRENT macro stack frame.  Rather than
9680   mess with zzstring(), I set maclvl back before calling evalmacroarg() and
9681   restore it immediately afterward.  It's the only safe way to do this,
9682   Because zzstring() has no way of knowing whether (say) \%1 is on the DO
9683   command line or in some other context.
9684 */
9685             debug(F101," xwords macro cksplit items","",z);
9686             if (z > max) z = max;
9687             for (i = 1; i <= z; i++) {  /* Loop through macro arguments. */
9688                 p = pp[i];
9689                 debug(F111," xwords arg i",p,i);
9690                 maclvl--;               /* Get argument from previous level */
9691                 evalmacroarg(&p);       /* Evaluate it */
9692                 maclvl++;               /* Use its value on currentlevel */
9693                 debug(F111," xwords arg i evaluated",p,i);
9694                 makestr(&(m_xarg[maclvl][i]),p);
9695                 if (i < 10) {
9696                     varnam[1] = (char) (i + '0'); /* Assign last arg */
9697                     addmac(varnam,p);
9698                     debug(F111," xwords arg name",varnam,maclvl);
9699                     debug(F111," xwords def def ",p,maclvl);
9700                 }
9701             }
9702             /* Handle argc and the dimension of the \&_[] arg vector array */
9703 
9704             if (maclvl < 0) {           /* (How can this be?) */
9705                 a_dim[0] = z;               /* Array dimension is one less */
9706                 topargc = z + 1;            /* than \v(argc) */
9707                 debug(F111," xwords a_dim[0]","IMPOSSIBLE",a_dim[0]);
9708             } else {
9709                 macargc[maclvl] = z + 1;    /* Set \v(argc) variable */
9710                 n_xarg[maclvl] = z + 1;     /* This is the actual number */
9711                 a_ptr[0] = m_xarg[maclvl];  /* Point \&_[] at the args */
9712                 a_dim[0] = z;               /* And give it this dimension */
9713                 debug(F111," xwords a_dim[0]","E",a_dim[0]);
9714             }
9715         }
9716         return;
9717     }
9718 #endif /* NOSPL */
9719 /*
9720   Not macro args, some other kind of list.
9721   This whole mess could be a cksplit() call...
9722 */
9723     while (1) {                         /* Go thru word list */
9724         if (!s || (*s == '\0')) {       /* No more characters? */
9725             if (k != 0) {               /* Was I in a word? */
9726                 if (z == max) break;    /* Yes, only go up to max. */
9727                 z++;                    /* Count this word. */
9728                 list[z] = p;            /* Assign pointer. */
9729                 debug(F111," xwords list item p z",p,z);
9730             }
9731             break;                      /* And get out. */
9732         }
9733         if (k == 0 && (*s == SP || *s == HT)) { /* Eat leading blanks */
9734             s++;
9735             continue;
9736         } else if (q == 0 && *s == '{') { /* An opening brace */
9737             if (k == 0 && y == 0) {     /* If leading brace */
9738                 p = s+1;                /* point past it */
9739                 b = 1;                  /* and flag that we did this */
9740             }
9741             k = 1;                      /* Flag that we're in a word */
9742             y++;                        /* Count the brace. */
9743         } else if (q == 0 && *s == '}') { /* A closing brace. */
9744             y--;                        /* Count it. */
9745             if (y <= 0 && b != 0) {     /* If it matches the leading brace */
9746                 char c;
9747                 c = *(s+1);
9748                 if (!c || c == SP || c == HT) { /* at EOL or followed by SP */
9749                     *s = SP;            /* change it to a space */
9750                     b = 0;              /* and we're not in braces any more */
9751                 }
9752             }
9753 #ifdef DOUBLEQUOTING
9754         /* Opening doublequote */
9755         } else if (k == 0 && b == 0 && *s == '"' && dblquo) {
9756             y++;
9757             p = s+1;                    /* point past it */
9758             q = 1;                      /* and flag that we did this */
9759             k = 1;                      /* Flag that we're in a word */
9760         /* Closing double quote */
9761         } else if (q > 0 && k > 0 && b == 0 && *s == '"' && dblquo) {
9762             char c;
9763             c = *(s+1);
9764             if (!c || c == SP || c == HT) { /* at EOL or followed by SP */
9765                 y--;
9766                 *s = SP;                /* change it to a space */
9767                 q = 0;                  /* and we're not in quotes any more */
9768             }
9769 #endif /* DOUBLEQUOTING */
9770 
9771         } else if (*s != SP && *s != HT) { /* Nonspace means we're in a word */
9772             if (k == 0) {               /* If we weren't in a word before, */
9773                 p = s;                  /* Mark the beginning */
9774                 if (flag && z == max) { /* Want last word to be remainder? */
9775                     z++;
9776                     list[z] = p;        /* Yes, point to it */
9777                     break;              /* and quit */
9778                 }
9779                 k = 1;                  /* Set in-word flag */
9780             }
9781         }
9782         /* If we're not inside a braced quantity, and we are in a word, and */
9783         /* we have hit whitespace, then we have a word. */
9784         if ((y < 1) && (k != 0) && (*s == SP || *s == HT) && !b) {
9785             if (!flag || z < max)       /* if we don't want to keep rest */
9786               *s = '\0';                /* terminate the arg with null */
9787             k = 0;                      /* say we're not in a word any more */
9788             y = 0;                      /* start braces off clean again */
9789             if (z == max) break;        /* Only go up to max. */
9790             z++;                        /* count this arg */
9791             list[z] = p;
9792             p = s+1;
9793         }
9794         s++;                            /* Point past this character */
9795     }
9796     if ((z == 0) && (y > 1)) {          /* Extra closing brace(s) at end */
9797         z++;
9798         list[z] = p;
9799     }
9800     return;
9801 }
9802 
9803 #ifndef NOSPL
9804 
9805 /*  D O S H I F T  --  Do the SHIFT Command; shift macro args left by n */
9806 
9807 /*  Note: at some point let's consolidate m_arg[][] and m_xarg[][]. */
9808 
9809 int
doshift(n)9810 doshift(n) int n; {                     /* n = shift count */
9811     int i, top, level;
9812     char /* *s, *m, */ buf[6];          /* Buffer to build scalar names */
9813     char * sx = tmpbuf;
9814     int nx = TMPBUFSIZ;
9815 
9816     debug(F101,"SHIFT count","",n);
9817     debug(F101,"SHIFT topargc","",topargc);
9818 
9819     if (n < 1)                          /* Stay in range */
9820       return(n == 0 ? 1 : 0);
9821 
9822     level = maclvl;
9823     top = (level < 0) ? topargc : macargc[level];
9824 
9825     if (n >= top)
9826       n = top - 1;
9827 
9828 #ifdef DEBUG
9829     if (deblog) {
9830         debug(F101,"SHIFT count 2","",n);
9831         debug(F101,"SHIFT level","",level);
9832         if (level > -1)
9833           debug(F101,"SHIFT macargc[level]","",macargc[level]);
9834     }
9835 #endif /* DEBUG */
9836 
9837     buf[0] = '\\';                      /* Initialize name template */
9838     buf[1] = '%';
9839     buf[2] = NUL;
9840     buf[3] = NUL;
9841 
9842     for (i = 1; i <= n; i++) {          /* Free shifted-over args */
9843         if (level < 0) {
9844             makestr(&(toparg[i]),NULL);
9845         } else {
9846             makestr(&(m_xarg[level][i]),NULL);
9847         }
9848         if (i < 10) {                   /* Is this necessary? */
9849             buf[2] = (char)(i+'0');
9850             delmac(buf,0);
9851         }
9852     }
9853     for (i = 1; i <= top-n; i++) {      /* Shift remaining args */
9854         if (level < 0) {
9855 #ifdef COMMENT
9856             toparg[i] = toparg[i+n];    /* Full vector */
9857 #else
9858             makestr(&(toparg[i]),toparg[i+n]); /* Full vector */
9859 #endif /* COMMENT */
9860             if (i < 10)                 /* Scalars... */
9861               makestr(&(g_var[i+'0']),toparg[i+n]);
9862         } else {
9863 #ifdef COMMENT
9864             m_xarg[level][i] = m_xarg[level][i+n];
9865 #else
9866             makestr(&(m_xarg[level][i]),m_xarg[level][i+n]);
9867 #endif /* COMMENT */
9868             if (i < 10) {
9869                 buf[2] = (char)(i+'0');
9870                 debug(F010,"SHIFT buf",buf,0);
9871                 addmac(buf,m_xarg[level][i+n]);
9872             }
9873         }
9874     }
9875     for (i = top-n; i <= top; i++) {    /* Clear n args from the end */
9876         if (level < 0) {
9877 #ifdef COMMENT
9878             toparg[i] = NULL;
9879 #else
9880             makestr(&(toparg[i]),NULL);
9881 #endif /* COMMENt */
9882             if (i < 10)
9883               makestr(&(g_var[i+'0']),NULL);
9884         } else {
9885 #ifdef COMMENT
9886             m_xarg[level][i] = NULL;
9887 #else
9888             makestr(&(m_xarg[level][i]),NULL);
9889 #endif /* COMMENt */
9890             if (i < 10) {
9891                 buf[2] = (char)(i+'0');
9892                 delmac(buf,0);
9893             }
9894         }
9895     }
9896     if (level > -1) {                   /* Macro args */
9897         macargc[level] -= n;            /* Adjust count */
9898         n_xarg[maclvl] = macargc[level]; /* Here too */
9899         a_dim[0] = macargc[level] - 1;  /* Adjust array dimension */
9900 	debug(F111,"a_dim[0]","F",a_dim[0]);
9901         zzstring("\\fjoin(&_[],{ },1)",&sx,&nx); /* Handle \%* */
9902 #ifdef COMMENT
9903         makestr(&(m_line[level]),tmpbuf);
9904 #endif /* COMMENT */
9905     } else {                            /* Ditto for top level */
9906         topargc -= n;
9907         a_dim[0] = topargc - 1;
9908 	debug(F111,"a_dim[0]","G",a_dim[0]);
9909         zzstring("\\fjoin(&_[],{ },1)",&sx,&nx);
9910 #ifdef COMMENT
9911         makestr(&topline,tmpbuf);
9912 #endif /* COMMENT */
9913     }
9914     return(1);
9915 }
9916 #endif /* NOSPL */
9917 
9918 int
docd(cx)9919 docd(cx) int cx; {                      /* Do the CD command */
9920     int x;
9921     extern int server, srvcdmsg, cdactive;
9922     extern char * cdmsgfile[], * ckcdpath;
9923     char *s, *p;
9924 #ifdef MAC
9925     char temp[34];
9926 #endif /* MAC */
9927 #ifdef IKSDCONF
9928 extern int iksdcf;
9929 #endif /* IKSDCONF */
9930 
9931 #ifndef NOFRILLS
9932     if (cx == XXBACK) {
9933         if ((x = cmcfm()) < 0)
9934         cwdf = 1;
9935         if (prevdir) {
9936             s = zgtdir();
9937             if (!zchdir(prevdir)) {
9938                 cwdf = 0;
9939                 perror(s);
9940             } else {
9941                 makestr(&prevdir,s);
9942             }
9943         }
9944         return(cwdf);
9945     }
9946 #endif /* NOFRILLS */
9947 
9948     if (cx == XXCDUP) {
9949 #ifdef VMS
9950         s = "[-]";
9951 #else
9952 #ifdef datageneral
9953         s = "^";
9954 #else
9955         s = "..";
9956 #endif /* datageneral */
9957 #endif /* VMS */
9958         ckstrncpy(line,s,LINBUFSIZ);
9959         goto gocd;
9960     }
9961 #ifndef NOSPL
9962     if (cx == XXKCD) {			/* Symbolic (Kermit) CD */
9963 	char * p;
9964 	int n, k;
9965 	x = cmkey(kcdtab,nkcdtab,"Symbolic directory name","home",xxstring);
9966 	if (x < 0)
9967 	  return(x);
9968 	x = lookup(kcdtab,atmbuf,nkcdtab,&k); /* Get complete keyword */
9969 	if (x < 0) {
9970 	    printf("?Lookup error\n");	/* shouldn't happen */
9971 	    return(-9);
9972 	}
9973         if ((x = cmcfm()) < 0)
9974 	  return(x);
9975 	if (k == VN_HOME) {		/* HOME: allow SET HOME to override */
9976 	    ckstrncpy(line,homepath(),LINBUFSIZ);
9977 	} else {			/* Other symbolic name */
9978 	    /* Convert to variable syntax */
9979 	    ckmakmsg(tmpbuf,TMPBUFSIZ,"\\v(",kcdtab[k].kwd,")",NULL);
9980 	    p = line;			/* Expand the variable */
9981 	    n = LINBUFSIZ;
9982 	    zzstring(tmpbuf,&p,&n);
9983 	    if (!line[0]) {		/* Fail if variable not defined */
9984 		printf("?%s - not defined\n",tmpbuf);
9985 		return(success = 0);
9986 	    }
9987 	}
9988 	s = line;			/* All OK, go try to CD... */
9989 	goto gocd;
9990     }
9991 #endif /* NOSPL */
9992 
9993     cdactive = 1;
9994 #ifdef GEMDOS
9995     if ((x = cmdir("Name of local directory, or carriage return",
9996                    homepath(),
9997                    &s,
9998                    NULL
9999                    )
10000          ) < 0 )
10001       return(x);
10002 #else
10003 #ifdef OS2
10004     if ((x = cmdirp("Name of PC disk and/or directory,\n\
10005        or press the Enter key for the default",
10006                     homepath(),
10007                     &s,
10008                     ckcdpath ? ckcdpath : getenv("CDPATH"),
10009                     xxstring
10010                     )
10011          ) < 0 )
10012       return(x);
10013 #else
10014 #ifdef MAC
10015     x = ckstrncpy(temp,homepath(),32);
10016     if (x > 0) if (temp[x-1] != ':') { temp[x] = ':'; temp[x+1] = NUL; }
10017     if ((x = cmtxt("Name of Macintosh volume and/or folder,\n\
10018  or press the Return key for the desktop on the boot disk",
10019                    temp,&s, xxstring)) < 0 )
10020       return(x);
10021 #else
10022     if ((x = cmdirp("Carriage return for home directory,\n\
10023 or name of directory on this computer",
10024 #ifdef VMS
10025                     "SYS$LOGIN",        /* With no colon */
10026 #else
10027                     homepath(),		/* In VMS this is "SYS$LOGIN:" */
10028 #endif /* VMS */
10029                     &s,
10030                     ckcdpath ? ckcdpath : getenv("CDPATH"),
10031                     xxstring
10032                     )) < 0)
10033       return(x);
10034 #endif /* MAC */
10035 #endif /* OS2 */
10036 #endif /* GEMDOS */
10037     ckstrncpy(line,s,LINBUFSIZ);        /* Make a safe copy */
10038     s = line;
10039 #ifdef VMS
10040     if (ckmatch("*.DIR;1$",s,0,0))
10041       if (cvtdir(s,tmpbuf,TMPBUFSIZ) > 0)
10042         s = tmpbuf;
10043 #endif /* VMS */
10044     debug(F110,"docd",s,0);
10045 #ifndef MAC
10046     if ((x = cmcfm()) < 0)              /* Get confirmation */
10047       return(x);
10048 #endif /* MAC */
10049 
10050   gocd:
10051 
10052 #ifdef datageneral
10053     x = strlen(line);                   /* homdir ends in colon, */
10054     if (x > 1 && line[x-1] == ':')      /* and "dir" doesn't like that... */
10055       line[x-1] = NUL;
10056 #endif /* datageneral */
10057 
10058 #ifdef MAC
10059     cwdf = 1;
10060     if (!zchdir(s)) {
10061         cwdf = 0;
10062         if (*s != ':') {                /* If it failed, */
10063             char *p;                    /* supply leading colon */
10064             int len = (int)strlen(s) + 2;
10065             p = malloc(len);            /* and try again... */
10066             if (p) {
10067                 strcpy(p,":");          /* safe */
10068                 strcat(p,s);            /* safe */
10069                 if (zchdir(p))
10070                   cwdf = 1;
10071                 free(p);
10072                 p = NULL;
10073             }
10074         }
10075     }
10076     if (!cwdf)
10077       perror(s);
10078 #else
10079     p = zgtdir();
10080     if (!zchdir(s)) {
10081         cwdf = 0;
10082 #ifdef CKROOT
10083         if (ckrooterr)
10084           printf("?Off limits: \"%s\"\n",s);
10085         else
10086 #endif /* CKROOT */
10087           perror(s);
10088     } else cwdf = 1;
10089 #endif /* MAC */
10090 
10091     x = 0;
10092     if (cwdf) {
10093         makestr(&prevdir,p);
10094         debug(F111,"docd","srvcdmsg",srvcdmsg);
10095         if (srvcdmsg
10096 #ifdef IKSDCONF
10097             && !(inserver && !iksdcf)
10098 #endif /* IKSDCONF */
10099             ) {
10100             int i;
10101             for (i = 0; i < 8; i++) {
10102                 debug(F111,"docd cdmsgfile[i]",cdmsgfile[i],i);
10103                 if (zchki(cdmsgfile[i]) > -1) {
10104                     x = 1;
10105                     dotype(cdmsgfile[i],xaskmore,0,0,NULL,0,NULL,0,0,NULL,0);
10106                     break;
10107                 }
10108             }
10109         }
10110     }
10111 /* xdocd: */
10112     if (!x && srvcdmsg && !server
10113 #ifdef IKSDCONF
10114         && !(inserver && !iksdcf)
10115 #endif /* IKSDCONF */
10116         && !quiet && !xcmdsrc)
10117       printf("%s\n", zgtdir());
10118 
10119     return(cwdf);
10120 }
10121 
10122 static int on_ctrlc = 0;
10123 
10124 VOID
fixcmd()10125 fixcmd() {                      /* Fix command parser after interruption */
10126 #ifndef NOSPL
10127 #ifndef NOONCTRLC
10128     if (nmac) {                         /* Any macros defined? */
10129         int k;                          /* Yes */
10130         char * s = "on_ctrlc";          /* Name of Ctrl-C handling macro */
10131         k = mlook(mactab,s,nmac);       /* Look it up. */
10132         if (k >= 0) {                   /* If found, */
10133             if (on_ctrlc++ == 0) {      /* if not already executing, */
10134                 if (dodo(k,"",0) > -1)  /* set it up, */
10135                   parser(1);            /* execute it, */
10136             }
10137             delmac(s,1);                /* and undefine it. */
10138         }
10139     }
10140     on_ctrlc = 0;
10141 #endif /* NOONCTRLC */
10142 #endif /* NOSPL */
10143     dostop();                   /* Back to top level (also calls conint()). */
10144     bgchk();                    /* Check background status */
10145     if (*psave) {               /* If old prompt saved, */
10146         cmsetp(psave);          /* restore it. */
10147         *psave = NUL;
10148     }
10149     success = 0;                /* Tell parser last command failed */
10150 }
10151 
10152 #ifndef NOSHOW                          /* SHOW FEATURES */
10153 /*
10154   Note, presently optlist[] index overflow is not checked.
10155   There is plenty of room (less than 360 entries for 1000 slots).
10156   When space starts to get tight, check for noptlist >= NOPTLIST
10157   every time noptlist is incremented.
10158 */
10159 #define NOPTLIST 1024
10160 static int noptlist = 0;
10161 static char * optlist[NOPTLIST+1];
10162 static int hpos = 0;
10163 
10164 int
prtopt(lines,s)10165 prtopt(lines,s) int * lines; char *s; { /* Print an option */
10166     int y, i;                           /* Does word wrap. */
10167     if (!s) s = "";
10168     i = *lines;
10169     if (!*s) {                          /* Empty argument */
10170         if (hpos > 0) {                 /* means to end this line. */
10171             printf("\n");               /* Not needed if already at */
10172             if (++i > (cmd_rows - 3)) { /* beginning of new line. */
10173                 if (!askmore())
10174                   return(0);
10175                 else
10176                   i = 0;
10177             }
10178         }
10179         printf("\n");                   /* And then make a blank line */
10180         if (++i > (cmd_rows - 3)) {
10181             if (!askmore())
10182               return(0);
10183             else
10184               i = 0;
10185         }
10186         hpos = 0;
10187         *lines = i;
10188         return(1);
10189     }
10190     y = (int)strlen(s) + 1;
10191     hpos += y;
10192     debug(F101,"prtopt hpos","",hpos);
10193     debug(F101,"prtopt cmd_cols","",cmd_cols);
10194 
10195     if (
10196 #ifdef OS2
10197         hpos > ((cmd_cols > 40) ? (cmd_cols - 1) : 79)
10198 #else /* OS2 */
10199         hpos > ((tt_cols > 40) ? (tt_cols - 1) : 79)
10200 #endif /* OS2 */
10201         ) {
10202         printf("\n");
10203         if (++i > (cmd_rows - 3)) {
10204             if (!askmore())
10205               return(0);
10206             else
10207               i = 0;
10208         }
10209         printf(" %s",s);
10210         hpos = y;
10211     } else
10212       printf(" %s",s);
10213     *lines = i;
10214     return(1);
10215 }
10216 
10217 static VOID
initoptlist()10218 initoptlist() {
10219     int i;
10220     if (noptlist > 0)
10221       return;
10222     for (i = 0; i < NOPTLIST; i++)
10223       optlist[i] = NULL;
10224 
10225 #ifdef MAC
10226 #ifdef MPW
10227     makestr(&(optlist[noptlist++]),"MPW");
10228 #endif /* MPW */
10229 #endif /* MAC */
10230 
10231 #ifdef MAC
10232 #ifdef THINK_C
10233     makestr(&(optlist[noptlist++]),"THINK_C");
10234 #endif /* THINK_C */
10235 #endif /* MAC */
10236 
10237 #ifdef __386__
10238     makestr(&(optlist[noptlist++]),"__386__");
10239 #endif /* __386__ */
10240 
10241 /* Memory models... */
10242 
10243 #ifdef __FLAT__
10244     makestr(&(optlist[noptlist++]),"__FLAT__");
10245 #endif /* __FLAT__ */
10246 #ifdef __SMALL__
10247     makestr(&(optlist[noptlist++]),"__SMALL__");
10248 #endif /* __SMALL__ */
10249 #ifdef __MEDIUM__
10250     makestr(&(optlist[noptlist++]),"__MEDIUM__");
10251 #endif /* __MEDIUM__ */
10252 #ifdef __COMPACT__
10253     makestr(&(optlist[noptlist++]),"__COMPACT__");
10254 #endif /* __COMPACT__ */
10255 #ifdef __LARGE__
10256     makestr(&(optlist[noptlist++]),"__LARGE__");
10257 #endif /* __LARGE__ */
10258 
10259 #ifdef DEBUG
10260 #ifdef IFDEBUG
10261     makestr(&(optlist[noptlist++]),"IFDEBUG");
10262 #else
10263     makestr(&(optlist[noptlist++]),"DEBUG");
10264 #endif /* IFDEBUG */
10265 #endif /* DEBUG */
10266 #ifdef TLOG
10267     makestr(&(optlist[noptlist++]),"TLOG");
10268 #endif /* TLOG */
10269 #ifdef BIGBUFOK
10270     makestr(&(optlist[noptlist++]),"BIGBUFOK");
10271 #endif /* BIGBUFOK */
10272 #ifdef INPBUFSIZ
10273     sprintf(line,"INPBUFSIZ=%d",INPBUFSIZ); /* SAFE */
10274     makestr(&(optlist[noptlist++]),line);
10275 #endif /* INPBUFSIZE */
10276 #ifdef LINBUFSIZ
10277     sprintf(line,"LINBUFSIZ=%d",LINBUFSIZ); /* SAFE */
10278     makestr(&(optlist[noptlist++]),line);
10279 #endif /* LINBUFSIZE */
10280 #ifdef INBUFSIZE
10281     sprintf(line,"INBUFSIZE=%d",INBUFSIZE); /* SAFE */
10282     makestr(&(optlist[noptlist++]),line);
10283 #endif /* INBUFSIZE */
10284 #ifdef OBUFSIZE
10285     sprintf(line,"OBUFSIZE=%d",OBUFSIZE); /* SAFE */
10286     makestr(&(optlist[noptlist++]),line);
10287 #endif /* OBUFSIZE */
10288 #ifdef FD_SETSIZE
10289     sprintf(line,"FD_SETSIZE=%d",FD_SETSIZE); /* SAFE */
10290     makestr(&(optlist[noptlist++]),line);
10291 #endif /* FD_SETSIZE */
10292 #ifdef XFRCAN
10293     makestr(&(optlist[noptlist++]),"XFRCAN");
10294 #endif /* XFRCAN */
10295 #ifdef XPRINT
10296     makestr(&(optlist[noptlist++]),"XPRINT");
10297 #endif /* XPRINT */
10298 #ifdef PIPESEND
10299     makestr(&(optlist[noptlist++]),"PIPESEND");
10300 #endif /* PIPESEND */
10301 #ifdef CK_SPEED
10302     makestr(&(optlist[noptlist++]),"CK_SPEED");
10303 #endif /* CK_SPEED */
10304 #ifdef CK_FAST
10305     makestr(&(optlist[noptlist++]),"CK_FAST");
10306 #endif /* CK_FAST */
10307 #ifdef CK_APC
10308     makestr(&(optlist[noptlist++]),"CK_APC");
10309 #endif /* CK_APC */
10310 #ifdef CK_AUTODL
10311     makestr(&(optlist[noptlist++]),"CK_AUTODL");
10312 #endif /* CK_AUTODL */
10313 #ifdef CK_MKDIR
10314     makestr(&(optlist[noptlist++]),"CK_MKDIR");
10315 #endif /* CK_MKDIR */
10316 #ifdef HAVE_LOCALE
10317     makestr(&(optlist[noptlist++]),"HAVE_LOCALE");
10318 #endif /* HAVE_LOCALE */
10319 #ifdef HAVE_SNPRINTF
10320     makestr(&(optlist[noptlist++]),"HAVE_SNPRINTF");
10321 #endif /* HAVE_SNPRINTF */
10322 #ifdef NOMKDIR
10323     makestr(&(optlist[noptlist++]),"NOMKDIR");
10324 #endif /* NOMKDIR */
10325 #ifdef CK_LABELED
10326     makestr(&(optlist[noptlist++]),"CK_LABELED");
10327 #endif /* CK_LABELED */
10328 #ifdef NODIAL
10329     makestr(&(optlist[noptlist++]),"NODIAL");
10330 #endif /* NODIAL */
10331 #ifdef MINIDIAL
10332     makestr(&(optlist[noptlist++]),"MINIDIAL");
10333 #endif /* MINIDIAL */
10334 #ifdef WHATAMI
10335     makestr(&(optlist[noptlist++]),"WHATAMI");
10336 #endif /* WHATAMI */
10337 #ifdef DYNAMIC
10338     makestr(&(optlist[noptlist++]),"DYNAMIC");
10339 #endif /* DYNAMIC */
10340 #ifndef NOSPL
10341     sprintf(line,"CMDDEP=%d",CMDDEP);   /* SAFE */
10342     makestr(&(optlist[noptlist++]),line);
10343 #endif /* NOSPL */
10344 
10345 #ifdef MAXPATHLEN
10346     sprintf(line,"MAXPATHLEN=%d",MAXPATHLEN); /* SAFE */
10347     makestr(&(optlist[noptlist++]),line);
10348 #endif /* MAXPATHLEN */
10349 
10350 #ifdef DEVNAMLEN
10351     sprintf(line,"DEVNAMLEN=%d",DEVNAMLEN); /* SAFE */
10352     makestr(&(optlist[noptlist++]),line);
10353 #endif /* DEVNAMLEN */
10354 
10355 #ifdef NO_PARAM_H
10356     makestr(&(optlist[noptlist++]),"NO_PARAM_H");
10357 #endif /* NO_PARAM_H */
10358 
10359 #ifdef INCL_PARAM_H
10360     makestr(&(optlist[noptlist++]),"INCL_PARAM_H");
10361 #endif /* INCL_PARAM_H */
10362 
10363     sprintf(line,"CKMAXPATH=%d",CKMAXPATH); /* SAFE */
10364     makestr(&(optlist[noptlist++]),line);
10365 
10366     sprintf(line,"CKMAXOPEN=%d",CKMAXOPEN); /* SAFE */
10367     makestr(&(optlist[noptlist++]),line);
10368 
10369 #ifndef UNIX
10370     /*
10371       These aren't actually used... In Unix we get maximum number of open
10372       files from sysconf() at runtime.
10373     */
10374     sprintf(line,"Z_MAXCHAN=%d",Z_MAXCHAN); /* SAFE */
10375     makestr(&(optlist[noptlist++]),line);
10376 
10377 #ifdef OPEN_MAX
10378     sprintf(line,"OPEN_MAX=%d",OPEN_MAX); /* SAFE */
10379     makestr(&(optlist[noptlist++]),line);
10380 #endif /* OPEN_MAX */
10381 
10382 #ifdef _POSIX_OPEN_MAX
10383     sprintf(line,"_POSIX_OPEN_MAX=%d",_POSIX_OPEN_MAX); /* SAFE */
10384     makestr(&(optlist[noptlist++]),line);
10385 #endif /* _POSIX_OPEN_MAX */
10386 #endif /* UNIX */
10387 
10388 #ifdef CKCHANNELIO
10389     {
10390         extern int z_maxchan;
10391 #ifdef UNIX
10392         extern int ckmaxfiles;
10393         sprintf(line,"ckmaxfiles=%d",ckmaxfiles); /* SAFE */
10394         makestr(&(optlist[noptlist++]),line);
10395 #endif /* UNIX */
10396         sprintf(line,"z_maxchan=%d",z_maxchan); /* SAFE */
10397         makestr(&(optlist[noptlist++]),line);
10398     }
10399 #endif /* CKCHANNELIO */
10400 
10401 #ifdef FOPEN_MAX
10402     sprintf(line,"FOPEN_MAX=%d",FOPEN_MAX); /* SAFE */
10403     makestr(&(optlist[noptlist++]),line);
10404 #endif /* FOPEN_MAX */
10405 
10406 #ifdef MAXGETPATH
10407     sprintf(line,"MAXGETPATH=%d",MAXGETPATH); /* SAFE */
10408     makestr(&(optlist[noptlist++]),line);
10409 #endif /* MAXGETPATH */
10410 
10411 #ifdef CMDBL
10412     sprintf(line,"CMDBL=%d",CMDBL);     /* SAFE */
10413     makestr(&(optlist[noptlist++]),line);
10414 #endif /* CMDBL */
10415 
10416 #ifdef VNAML
10417     sprintf(line,"VNAML=%d",VNAML);     /* SAFE */
10418     makestr(&(optlist[noptlist++]),line);
10419 #endif /* VNAML */
10420 
10421 #ifdef ARRAYREFLEN
10422     sprintf(line,"ARRAYREFLEN=%d",ARRAYREFLEN); /* SAFE */
10423     makestr(&(optlist[noptlist++]),line);
10424 #endif /* ARRAYREFLEN */
10425 
10426 #ifdef UIDBUFLEN
10427     sprintf(line,"UIDBUFLEN=%d",UIDBUFLEN); /* SAFE */
10428     makestr(&(optlist[noptlist++]),line);
10429 #endif /* UIDBUFLEN */
10430 
10431 #ifdef FORDEPTH
10432     sprintf(line,"FORDEPTH=%d",FORDEPTH); /* SAFE */
10433     makestr(&(optlist[noptlist++]),line);
10434 #endif /* FORDEPTH */
10435 
10436 #ifdef MAXTAKE
10437     sprintf(line,"MAXTAKE=%d",MAXTAKE); /* SAFE */
10438     makestr(&(optlist[noptlist++]),line);
10439 #endif /* MAXTAKE */
10440 
10441 #ifdef MACLEVEL
10442     sprintf(line,"MACLEVEL=%d",MACLEVEL); /* SAFE */
10443     makestr(&(optlist[noptlist++]),line);
10444 #endif /* MACLEVEL */
10445 
10446 #ifdef MAC_MAX
10447     sprintf(line,"MAC_MAX=%d",MAC_MAX); /* SAFE */
10448     makestr(&(optlist[noptlist++]),line);
10449 #endif /* MAC_MAX */
10450 
10451 #ifdef _LARGEFILE_SOURCE
10452     makestr(&(optlist[noptlist++]),"_LARGEFILE_SOURCE");
10453 #endif	/* _LARGEFILE_SOURCE */
10454 
10455 #ifdef _FILE_OFFSET_BITS
10456     sprintf(line,"_FILE_OFFSET_BITS=%d",_FILE_OFFSET_BITS); /* SAFE */
10457     makestr(&(optlist[noptlist++]),line);
10458 #endif	/* _FILE_OFFSET_BITS */
10459 
10460 #ifdef __USE_FILE_OFFSET64
10461     makestr(&(optlist[noptlist++]),"__USE_FILE_OFFSET64");
10462 #endif	/* __USE_FILE_OFFSET64 */
10463 
10464 #ifdef __USE_LARGEFILE64
10465     makestr(&(optlist[noptlist++]),"__USE_LARGEFILE64");
10466 #endif	/* __USE_LARGEFILE64 */
10467 
10468 #ifdef COMMENT
10469 #ifdef CHAR_MAX
10470     sprintf(line,"CHAR_MAX=%llx",CHAR_MAX); /* SAFE */
10471     makestr(&(optlist[noptlist++]),line);
10472 #endif /* CHAR_MAX */
10473 #ifdef UCHAR_MAX
10474     sprintf(line,"UCHAR_MAX=%llx",UCHAR_MAX); /* SAFE */
10475     makestr(&(optlist[noptlist++]),line);
10476 #endif /* UCHAR_MAX */
10477 #ifdef SHRT_MAX
10478     sprintf(line,"SHRT_MAX=%llx",SHRT_MAX); /* SAFE */
10479     makestr(&(optlist[noptlist++]),line);
10480 #endif /* SHRT_MAX */
10481 #ifdef USHRT_MAX
10482     sprintf(line,"USHRT_MAX=%llx",USHRT_MAX); /* SAFE */
10483     makestr(&(optlist[noptlist++]),line);
10484 #endif /* USHRT_MAX */
10485 #ifdef INT_MAX
10486     sprintf(line,"INT_MAX=%llx",INT_MAX); /* SAFE */
10487     makestr(&(optlist[noptlist++]),line);
10488 #endif /* INT_MAX */
10489 #ifdef UINT_MAX
10490     sprintf(line,"UINT_MAX=%llx",UINT_MAX); /* SAFE */
10491     makestr(&(optlist[noptlist++]),line);
10492 #endif /* UINT_MAX */
10493 #ifdef MAX_LONG
10494     sprintf(line,"MAX_LONG=%llx",MAX_LONG); /* SAFE */
10495     makestr(&(optlist[noptlist++]),line);
10496 #endif /* MAX_LONG */
10497 #ifdef LONG_MAX
10498     sprintf(line,"LONG_MAX=%llx",LONG_MAX); /* SAFE */
10499     makestr(&(optlist[noptlist++]),line);
10500 #endif /* LONG_MAX */
10501 #ifdef ULONG_MAX
10502     sprintf(line,"ULONG_MAX=%llx",ULONG_MAX); /* SAFE */
10503     makestr(&(optlist[noptlist++]),line);
10504 #endif /* ULONG_MAX */
10505 #ifdef MAXINT
10506     sprintf(line,"MAXINT=%llx",MAXINT); /* SAFE */
10507     makestr(&(optlist[noptlist++]),line);
10508 #endif /* MAXINT */
10509 #ifdef MAXLONG
10510     sprintf(line,"MAXLONG=%llx",MAXLONG); /* SAFE */
10511     makestr(&(optlist[noptlist++]),line);
10512 #endif /* MAXLONG */
10513 #ifdef NT
10514 #ifdef LLONG_MAX
10515     sprintf(line,"LLONG_MAX=%I64x",LLONG_MAX); /* SAFE */
10516     makestr(&(optlist[noptlist++]),line);
10517 #endif /* LLONG_MAX */
10518 #ifdef ULLONG_MAX
10519     sprintf(line,"ULLONG_MAX=%I64x",ULLONG_MAX); /* SAFE */
10520     makestr(&(optlist[noptlist++]),line);
10521 #endif /* ULLONG_MAX */
10522 #ifdef MAXLONGLONG
10523     sprintf(line,"MAXLONGLONG=%I64x",MAXLONGLONG);  /* SAFE */
10524     makestr(&(optlist[noptlist++]),line);
10525 #endif /* MAXLONGLONG */
10526 #else
10527 #ifdef LLONG_MAX
10528     sprintf(line,"LLONG_MAX=%llx",LLONG_MAX); /* SAFE */
10529     makestr(&(optlist[noptlist++]),line);
10530 #endif /* LLONG_MAX */
10531 #ifdef ULLONG_MAX
10532     sprintf(line,"ULLONG_MAX=%llx",ULLONG_MAX); /* SAFE */
10533     makestr(&(optlist[noptlist++]),line);
10534 #endif /* ULLONG_MAX */
10535 #ifdef MAXLONGLONG
10536     sprintf(line,"MAXLONGLONG=%llx",MAXLONGLONG);  /* SAFE */
10537     makestr(&(optlist[noptlist++]),line);
10538 #endif /* MAXLONGLONG */
10539 #endif
10540 #ifdef _INTEGRAL_MAX_BITS
10541     sprintf(line,"_INTEGRAL_MAX_BITS=%d",_INTEGRAL_MAX_BITS);  /* SAFE */
10542     makestr(&(optlist[noptlist++]),line);
10543 #endif /* _INTEGRAL_MAX_BITS */
10544 #endif	/* COMMENT */
10545 
10546 #ifdef MINPUTMAX
10547     sprintf(line,"MINPUTMAX=%d",MINPUTMAX); /* SAFE */
10548     makestr(&(optlist[noptlist++]),line);
10549 #endif /* MINPUTMAX */
10550 
10551 #ifdef MAXWLD
10552     sprintf(line,"MAXWLD=%d",MAXWLD); /* SAFE */
10553     makestr(&(optlist[noptlist++]),line);
10554 #else
10555 #ifdef OS2
10556     makestr(&(optlist[noptlist++]),"MAXWLD=unlimited");
10557 #endif /* OS2 */
10558 #endif /* MAXWLD */
10559 
10560 #ifdef MSENDMAX
10561     sprintf(line,"MSENDMAX=%d",MSENDMAX); /* SAFE */
10562     makestr(&(optlist[noptlist++]),line);
10563 #endif /* MSENDMAX */
10564 
10565 #ifdef MAXDDIR
10566     sprintf(line,"MAXDDIR=%d",MAXDDIR); /* SAFE */
10567     makestr(&(optlist[noptlist++]),line);
10568 #endif /* MAXDDIR */
10569 
10570 #ifdef MAXDNUMS
10571     sprintf(line,"MAXDNUMS=%d",MAXDNUMS); /* SAFE */
10572     makestr(&(optlist[noptlist++]),line);
10573 #endif /* MAXDNUMS */
10574 
10575 #ifdef UNIX
10576     makestr(&(optlist[noptlist++]),"UNIX");
10577 #endif /* UNIX */
10578 
10579 #ifdef VMS
10580     makestr(&(optlist[noptlist++]),"VMS");
10581 #ifdef __VMS_VER
10582     sprintf(line,"__VMS_VER=%d",__VMS_VER); /* SAFE */
10583     makestr(&(optlist[noptlist++]),line);
10584 #endif /* __VMS_VER */
10585 #ifdef VMSV70
10586     makestr(&(optlist[noptlist++]),"VMSV70");
10587 #endif /* VMSV70 */
10588 #ifdef OLD_VMS
10589     makestr(&(optlist[noptlist++]),"OLD_VMS");
10590 #endif /* OLD_VMS */
10591 #ifdef vms
10592     makestr(&(optlist[noptlist++]),"vms");
10593 #endif /* vms */
10594 #ifdef VMSV60
10595     makestr(&(optlist[noptlist++]),"VMSV60");
10596 #endif /* VMSV60 */
10597 #ifdef VMSV80
10598     makestr(&(optlist[noptlist++]),"VMSV80");
10599 #endif /* VMSV80 */
10600 #ifdef VMSSHARE
10601     makestr(&(optlist[noptlist++]),"VMSSHARE");
10602 #endif /* VMSSHARE */
10603 #ifdef NOVMSSHARE
10604     makestr(&(optlist[noptlist++]),"NOVMSSHARE");
10605 #endif /* NOVMSSHARE */
10606 #endif /* VMS */
10607 
10608 #ifdef datageneral
10609     makestr(&(optlist[noptlist++]),"datageneral");
10610 #endif /* datageneral */
10611 #ifdef apollo
10612     makestr(&(optlist[noptlist++]),"apollo");
10613 #endif /* apollo */
10614 #ifdef aegis
10615     makestr(&(optlist[noptlist++]),"aegis");
10616 #endif /* aegis */
10617 #ifdef A986
10618     makestr(&(optlist[noptlist++]),"A986");
10619 #endif /* A986 */
10620 #ifdef AMIGA
10621     makestr(&(optlist[noptlist++]),"AMIGA");
10622 #endif /* AMIGA */
10623 #ifdef CONVEX9
10624     makestr(&(optlist[noptlist++]),"CONVEX9");
10625 #endif /* CONVEX9 */
10626 #ifdef CONVEX10
10627     makestr(&(optlist[noptlist++]),"CONVEX10");
10628 #endif /* CONVEX9 */
10629 #ifdef MAC
10630     makestr(&(optlist[noptlist++]),"MAC");
10631 #endif /* MAC */
10632 #ifdef AUX
10633     makestr(&(optlist[noptlist++]),"AUX");
10634 #endif /* AUX */
10635 
10636 #ifdef OS2
10637     makestr(&(optlist[noptlist++]),"OS2");
10638 #ifdef NT
10639     makestr(&(optlist[noptlist++]),"NT");
10640 #endif /* NT */
10641 #endif /* OS2 */
10642 
10643 #ifdef OSK
10644     makestr(&(optlist[noptlist++]),"OS9");
10645 #endif /* OSK */
10646 
10647 #ifdef MSDOS
10648     makestr(&(optlist[noptlist++]),"MSDOS");
10649 #endif /* MSDOS */
10650 
10651 #ifdef DIRENT
10652     makestr(&(optlist[noptlist++]),"DIRENT");
10653 #endif /* DIRENT */
10654 
10655 #ifdef SDIRENT
10656     makestr(&(optlist[noptlist++]),"SDIRENT");
10657 #endif /* SDIRENT */
10658 
10659 #ifdef NDIR
10660     makestr(&(optlist[noptlist++]),"NDIR");
10661 #endif /* NDIR */
10662 
10663 #ifdef XNDIR
10664     makestr(&(optlist[noptlist++]),"XNDIR");
10665 #endif /* XNDIR */
10666 
10667 #ifdef SAVEDUID
10668     makestr(&(optlist[noptlist++]),"SAVEDUID");
10669 #endif /* SAVEDUID */
10670 
10671 #ifdef RENAME
10672     makestr(&(optlist[noptlist++]),"RENAME");
10673 #endif /* RENAME */
10674 
10675 #ifdef CK_TMPDIR
10676     makestr(&(optlist[noptlist++]),"CK_TMPDIR");
10677 #endif /* CK_TMPDIR */
10678 
10679 #ifdef NOCCTRAP
10680     makestr(&(optlist[noptlist++]),"NOCCTRAP");
10681 #endif /* NOCCTRAP */
10682 
10683 #ifdef NOCOTFMC
10684     makestr(&(optlist[noptlist++]),"NOCOTFMC");
10685 #endif /* NOCOTFMC */
10686 
10687 #ifdef NOFRILLS
10688     makestr(&(optlist[noptlist++]),"NOFRILLS");
10689 #endif /* NOFRILLS */
10690 
10691 #ifdef PARSENSE
10692     makestr(&(optlist[noptlist++]),"PARSENSE");
10693 #endif /* PARSENSE */
10694 
10695 #ifdef TIMEH
10696     makestr(&(optlist[noptlist++]),"TIMEH");
10697 #endif /* TIMEH */
10698 
10699 #ifdef NOTIMEH
10700     makestr(&(optlist[noptlist++]),"TIMEH");
10701 #endif /* NOTIMEH */
10702 
10703 #ifdef SYSTIMEH
10704     makestr(&(optlist[noptlist++]),"SYSTIMEH");
10705 #endif /* SYSTIMEH */
10706 
10707 #ifdef NOSYSTIMEH
10708     makestr(&(optlist[noptlist++]),"SYSTIMEH");
10709 #endif /* NOSYSTIMEH */
10710 
10711 #ifdef SYSTIMEBH
10712     makestr(&(optlist[noptlist++]),"SYSTIMEBH");
10713 #endif /* SYSTIMEBH */
10714 
10715 #ifdef NOSYSTIMEBH
10716     makestr(&(optlist[noptlist++]),"SYSTIMEBH");
10717 #endif /* NOSYSTIMEBH */
10718 
10719 #ifdef UTIMEH
10720     makestr(&(optlist[noptlist++]),"UTIMEH");
10721 #endif /* UTIMEH */
10722 
10723 #ifdef SYSUTIMEH
10724     makestr(&(optlist[noptlist++]),"SYSUTIMEH");
10725 #endif /* SYSUTIMEH */
10726 
10727 #ifdef CK_NEED_SIG
10728     makestr(&(optlist[noptlist++]),"CK_NEED_SIG");
10729 #endif /* CK_NEED_SIG */
10730 
10731 #ifdef CK_TTYFD
10732     makestr(&(optlist[noptlist++]),"CK_TTYFD");
10733 #endif /* CK_TTYFD */
10734 
10735 #ifdef NETCONN
10736     makestr(&(optlist[noptlist++]),"NETCONN");
10737 #endif /* NETCONN */
10738 
10739 #ifdef TCPSOCKET
10740     makestr(&(optlist[noptlist++]),"TCPSOCKET");
10741 #ifdef NOTCPOPTS
10742     makestr(&(optlist[noptlist++]),"NOTCPOPTS");
10743 #endif /* NOTCPOPTS */
10744 #ifdef CK_DNS_SRV
10745     makestr(&(optlist[noptlist++]),"CK_DNS_SRV");
10746 #endif /* CK_DNS_SRV */
10747 #ifdef NO_DNS_SRV
10748     makestr(&(optlist[noptlist++]),"NO_DNS_SRV");
10749 #endif /* NO_DNS_SRV */
10750 #ifdef CKGHNLHOST
10751     makestr(&(optlist[noptlist++]),"CKGHNLHOST");
10752 #endif /* CKGHNLHOST */
10753 #ifdef NOLISTEN
10754     makestr(&(optlist[noptlist++]),"NOLISTEN");
10755 #endif /* NOLISTEN */
10756 #ifdef SOL_SOCKET
10757     makestr(&(optlist[noptlist++]),"SOL_SOCKET");
10758 #endif /* SOL_SOCKET */
10759 #ifdef SO_OOBINLINE
10760     makestr(&(optlist[noptlist++]),"SO_OOBINLINE");
10761 #endif /* SO_OOBINLNE */
10762 #ifdef SO_DONTROUTE
10763     makestr(&(optlist[noptlist++]),"SO_DONTROUTE");
10764 #endif /* SO_DONTROUTE */
10765 #ifdef SO_KEEPALIVE
10766     makestr(&(optlist[noptlist++]),"SO_KEEPALIVE");
10767 #endif /* SO_KEEPALIVE */
10768 #ifdef SO_LINGER
10769     makestr(&(optlist[noptlist++]),"SO_LINGER");
10770 #endif /* SO_LINGER */
10771 #ifdef TCP_NODELAY
10772     makestr(&(optlist[noptlist++]),"TCP_NODELAY");
10773 #endif /* TCP_NODELAY */
10774 #ifdef SO_SNDBUF
10775     makestr(&(optlist[noptlist++]),"SO_SNDBUF");
10776 #endif /* SO_SNDBUF */
10777 #ifdef SO_RCVBUF
10778     makestr(&(optlist[noptlist++]),"SO_RCVBUF");
10779 #endif /* SO_RCVBUF */
10780 #ifdef h_addr
10781     makestr(&(optlist[noptlist++]),"h_addr");
10782 #endif /* h_addr */
10783 #ifdef HADDRLIST
10784     makestr(&(optlist[noptlist++]),"HADDRLIST");
10785 #endif /* HADDRLIST */
10786 #ifdef CK_SOCKS
10787     makestr(&(optlist[noptlist++]),"CK_SOCKS");
10788 #ifdef CK_SOCKS5
10789     makestr(&(optlist[noptlist++]),"CK_SOCKS5");
10790 #endif /* CK_SOCKS5 */
10791 #ifdef CK_SOCKS_NS
10792     makestr(&(optlist[noptlist++]),"CK_SOCKS_NS");
10793 #endif /* CK_SOCKS_NS */
10794 #endif /* CK_SOCKS */
10795 #ifdef RLOGCODE
10796     makestr(&(optlist[noptlist++]),"RLOGCODE");
10797 #endif /* RLOGCODE */
10798 #ifdef NETCMD
10799     makestr(&(optlist[noptlist++]),"NETCMD");
10800 #endif /* NETCMD */
10801 #ifdef NONETCMD
10802     makestr(&(optlist[noptlist++]),"NONETCMD");
10803 #endif /* NONETCMD */
10804 #ifdef NETPTY
10805     makestr(&(optlist[noptlist++]),"NETPTY");
10806 #endif /* NETPTY */
10807 #ifdef CK_ENVIRONMENT
10808     makestr(&(optlist[noptlist++]),"CK_ENVIRONMENT");
10809 #endif /* CK_ENVIRONMENT */
10810 #endif /* TCPSOCKET */
10811 #ifdef TNCODE
10812     makestr(&(optlist[noptlist++]),"TNCODE");
10813 #endif /* TNCODE */
10814 #ifdef CK_FORWARD_X
10815     makestr(&(optlist[noptlist++]),"CK_FORWARD_X");
10816 #endif /* CK_FORWARD_X */
10817 #ifdef TN_COMPORT
10818     makestr(&(optlist[noptlist++]),"TN_COMPORT");
10819 #endif /* TN_COMPORT */
10820 #ifdef MULTINET
10821     makestr(&(optlist[noptlist++]),"MULTINET");
10822 #endif /* MULTINET */
10823 #ifdef DEC_TCPIP
10824     makestr(&(optlist[noptlist++]),"DEC_TCPIP");
10825 #endif /* DEC_TCPIP */
10826 #ifdef TCPWARE
10827     makestr(&(optlist[noptlist++]),"TCPWARE");
10828 #endif /* TCPWARE */
10829 #ifdef UCX50
10830     makestr(&(optlist[noptlist++]),"UCX50");
10831 #endif /* UCX50 */
10832 #ifdef CMU_TCPIP
10833     makestr(&(optlist[noptlist++]),"CMU_TCPIP");
10834 #endif /* CMU_TCPIP */
10835 #ifdef TTLEBUF
10836     makestr(&(optlist[noptlist++]),"TTLEBUF");
10837 #endif /* TTLEBUF */
10838 #ifdef NETLEBUF
10839     makestr(&(optlist[noptlist++]),"NETLEBUF");
10840 #endif /* NETLEBUF */
10841 #ifdef IKS_OPTION
10842     makestr(&(optlist[noptlist++]),"IKS_OPTION");
10843 #endif /* IKS_OPTION */
10844 #ifdef IKSDB
10845     makestr(&(optlist[noptlist++]),"IKSDB");
10846 #endif /* IKSDB */
10847 #ifdef IKSDCONF
10848     makestr(&(optlist[noptlist++]),"IKSDCONF");
10849 #endif /* IKSDCONF */
10850 #ifdef CK_LOGIN
10851     makestr(&(optlist[noptlist++]),"CK_LOGIN");
10852 #endif /* CK_LOGIN */
10853 #ifdef CK_PAM
10854     makestr(&(optlist[noptlist++]),"CK_PAM");
10855 #endif /* CK_PAM */
10856 #ifdef CK_SHADOW
10857     makestr(&(optlist[noptlist++]),"CK_SHADOW");
10858 #endif /* CK_SHADOW */
10859 #ifdef CONGSPD
10860     makestr(&(optlist[noptlist++]),"CONGSPD");
10861 #endif /* CONGSPD */
10862 #ifdef SUNX25
10863     makestr(&(optlist[noptlist++]),"SUNX25");
10864 #endif /* SUNX25 */
10865 #ifdef IBMX25
10866     makestr(&(optlist[noptlist++]),"IBMX25");
10867 #endif /* IBMX25 */
10868 #ifdef HPX25
10869     makestr(&(optlist[noptlist++]),"HPX25");
10870 #endif /* HPX25 */
10871 #ifdef DECNET
10872     makestr(&(optlist[noptlist++]),"DECNET");
10873 #endif /* DECNET */
10874 #ifdef SUPERLAT
10875     makestr(&(optlist[noptlist++]),"SUPERLAT");
10876 #endif /* SUPERLAT */
10877 #ifdef NPIPE
10878     makestr(&(optlist[noptlist++]),"NPIPE");
10879 #endif /* NPIPE */
10880 #ifdef CK_NETBIOS
10881     makestr(&(optlist[noptlist++]),"CK_NETBIOS");
10882 #endif /* CK_NETBIOS */
10883 #ifdef ATT7300
10884     makestr(&(optlist[noptlist++]),"ATT7300");
10885 #endif /* ATT7300 */
10886 #ifdef ATT6300
10887     makestr(&(optlist[noptlist++]),"ATT6300");
10888 #endif /* ATT6300 */
10889 #ifdef HDBUUCP
10890     makestr(&(optlist[noptlist++]),"HDBUUCP");
10891 #endif /* HDBUUCP */
10892 #ifdef USETTYLOCK
10893     makestr(&(optlist[noptlist++]),"USETTYLOCK");
10894 #endif /* USETTYLOCK */
10895 #ifdef USE_UU_LOCK
10896     makestr(&(optlist[noptlist++]),"USE_UU_LOCK");
10897 #endif /* USE_UU_LOCK */
10898 #ifdef HAVE_LOCKDEV
10899     makestr(&(optlist[noptlist++]),"HAVE_LOCKDEV");
10900 #endif /* HAVE_LOCKDEV */
10901 #ifdef HAVE_BAUDBOY
10902     makestr(&(optlist[noptlist++]),"HAVE_BAUDBOY");
10903 #endif /* HAVE_BAUDBOY */
10904 #ifdef HAVE_OPENPTY
10905     makestr(&(optlist[noptlist++]),"HAVE_OPENPTY");
10906 #endif /* HAVE_OPENPTY */
10907 #ifdef TTPTYCMD
10908     makestr(&(optlist[noptlist++]),"TTPTYCMD");
10909 #endif /* TTPTYCMD */
10910 #ifdef NOUUCP
10911     makestr(&(optlist[noptlist++]),"NOUUCP");
10912 #endif /* NOUUCP */
10913 #ifdef LONGFN
10914     makestr(&(optlist[noptlist++]),"LONGFN");
10915 #endif /* LONGFN */
10916 #ifdef RDCHK
10917     makestr(&(optlist[noptlist++]),"RDCHK");
10918 #endif /* RDCHK */
10919 #ifdef SELECT
10920     makestr(&(optlist[noptlist++]),"SELECT");
10921 #endif /* SELECT */
10922 #ifdef USLEEP
10923     makestr(&(optlist[noptlist++]),"USLEEP");
10924 #endif /* USLEEP */
10925 #ifdef NAP
10926     makestr(&(optlist[noptlist++]),"NAP");
10927 #endif /* NAP */
10928 #ifdef NAPHACK
10929     makestr(&(optlist[noptlist++]),"NAPHACK");
10930 #endif /* NAPHACK */
10931 #ifdef CK_POLL
10932     makestr(&(optlist[noptlist++]),"CK_POLL");
10933 #endif /* CK_POLL */
10934 #ifdef NOIEXTEN
10935     makestr(&(optlist[noptlist++]),"NOIEXTEN");
10936 #endif /* NOIEXTEN */
10937 #ifdef EXCELAN
10938     makestr(&(optlist[noptlist++]),"EXCELAN");
10939 #endif /* EXCELAN */
10940 #ifdef INTERLAN
10941     makestr(&(optlist[noptlist++]),"INTERLAN");
10942 #endif /* INTERLAN */
10943 #ifdef NOFILEH
10944     makestr(&(optlist[noptlist++]),"NOFILEH");
10945 #endif /* NOFILEH */
10946 #ifdef NOSYSIOCTLH
10947     makestr(&(optlist[noptlist++]),"NOSYSIOCTLH");
10948 #endif /* NOSYSIOCTLH */
10949 #ifdef DCLPOPEN
10950     makestr(&(optlist[noptlist++]),"DCLPOPEN");
10951 #endif /* DCLPOPEN */
10952 #ifdef NOSETBUF
10953     makestr(&(optlist[noptlist++]),"NOSETBUF");
10954 #endif /* NOSETBUF */
10955 #ifdef NOXFER
10956     makestr(&(optlist[noptlist++]),"NOXFER");
10957 #endif /* NOXFER */
10958 #ifdef NOCURSES
10959     makestr(&(optlist[noptlist++]),"NOCURSES");
10960 #endif /* NOCURSES */
10961 #ifdef NOSERVER
10962     makestr(&(optlist[noptlist++]),"NOSERVER");
10963 #endif /* NOSERVER */
10964 #ifdef NOPATTERNS
10965     makestr(&(optlist[noptlist++]),"NOPATTERNS");
10966 #else
10967 #ifdef PATTERNS
10968     makestr(&(optlist[noptlist++]),"PATTERNS");
10969 #endif /* PATTERNS */
10970 #endif /* NOPATTERNS */
10971 #ifdef NOCKEXEC
10972     makestr(&(optlist[noptlist++]),"NOCKEXEC");
10973 #else
10974 #ifdef CKEXEC
10975     makestr(&(optlist[noptlist++]),"CKEXEC");
10976 #endif /* CKEXEC */
10977 #endif /* NOCKEXEC */
10978 #ifdef NOAUTODL
10979     makestr(&(optlist[noptlist++]),"NOAUTODL");
10980 #endif /* NOAUTODL */
10981 #ifdef NOMSEND
10982     makestr(&(optlist[noptlist++]),"NOMSEND");
10983 #endif /* NOMSEND */
10984 #ifdef NOFDZERO
10985     makestr(&(optlist[noptlist++]),"NOFDZERO");
10986 #endif /* NOFDZERO */
10987 #ifdef NOPOPEN
10988     makestr(&(optlist[noptlist++]),"NOPOPEN");
10989 #endif /* NOPOPEN */
10990 #ifdef NOPARTIAL
10991     makestr(&(optlist[noptlist++]),"NOPARTIAL");
10992 #endif /* NOPARTIAL */
10993 #ifdef NOKVERBS
10994     makestr(&(optlist[noptlist++]),"NOKVERBS");
10995 #endif /* NOKVERBS */
10996 #ifdef NOSETREU
10997     makestr(&(optlist[noptlist++]),"NOSETREU");
10998 #endif /* NOSETREU */
10999 #ifdef LCKDIR
11000     makestr(&(optlist[noptlist++]),"LCKDIR");
11001 #endif /* LCKDIR */
11002 #ifdef ACUCNTRL
11003     makestr(&(optlist[noptlist++]),"ACUCNTRL");
11004 #endif /* ACUCNTRL */
11005 #ifdef BSD4
11006     makestr(&(optlist[noptlist++]),"BSD4");
11007 #endif /* BSD4 */
11008 #ifdef BSD44
11009     makestr(&(optlist[noptlist++]),"BSD44");
11010 #endif /* BSD44 */
11011 #ifdef BSD41
11012     makestr(&(optlist[noptlist++]),"BSD41");
11013 #endif /* BSD41 */
11014 #ifdef BSD43
11015     makestr(&(optlist[noptlist++]),"BSD43");
11016 #endif /* BSD43 */
11017 #ifdef BSD29
11018     makestr(&(optlist[noptlist++]),"BSD29");
11019 #endif /* BSD29 */
11020 #ifdef BSDI
11021     makestr(&(optlist[noptlist++]),"BSDI");
11022 #endif /* BSDI */
11023 #ifdef __bsdi__
11024     makestr(&(optlist[noptlist++]),"__bsdi__");
11025 #endif /* __bsdi__ */
11026 #ifdef __NetBSD__
11027     makestr(&(optlist[noptlist++]),"__NetBSD__");
11028 #endif /* __NetBSD__ */
11029 #ifdef __OpenBSD__
11030     makestr(&(optlist[noptlist++]),"__OpenBSD__");
11031 #endif /* __OpenBSD__ */
11032 #ifdef __FreeBSD__
11033     makestr(&(optlist[noptlist++]),"__FreeBSD__");
11034 #endif /* __FreeBSD__ */
11035 #ifdef FREEBSD4
11036     makestr(&(optlist[noptlist++]),"FREEBSD4");
11037 #endif /* FREEBSD4 */
11038 #ifdef FREEBSD8
11039     makestr(&(optlist[noptlist++]),"FREEBSD8");
11040 #endif /* FREEBSD8 */
11041 #ifdef FREEBSD9
11042     makestr(&(optlist[noptlist++]),"FREEBSD9");
11043 #endif /* FREEBSD9 */
11044 #ifdef __linux__
11045     makestr(&(optlist[noptlist++]),"__linux__");
11046 #endif /* __linux__ */
11047 #ifdef LINUX_HI_SPD
11048     makestr(&(optlist[noptlist++]),"LINUX_HI_SPD");
11049 #endif /* LINUX_HI_SPD */
11050 #ifdef LYNXOS
11051     makestr(&(optlist[noptlist++]),"LYNXOS");
11052 #endif /* LYNXOS */
11053 #ifdef V7
11054     makestr(&(optlist[noptlist++]),"V7");
11055 #endif /* V7 */
11056 #ifdef AIX370
11057     makestr(&(optlist[noptlist++]),"AIX370");
11058 #endif /* AIX370 */
11059 #ifdef RTAIX
11060     makestr(&(optlist[noptlist++]),"RTAIX");
11061 #endif /* RTAIX */
11062 #ifdef HPUX
11063     makestr(&(optlist[noptlist++]),"HPUX");
11064 #endif /* HPUX */
11065 #ifdef HPUX9
11066     makestr(&(optlist[noptlist++]),"HPUX9");
11067 #endif /* HPUX9 */
11068 #ifdef HPUX10
11069     makestr(&(optlist[noptlist++]),"HPUX10");
11070 #endif /* HPUX10 */
11071 #ifdef HPUX1000
11072     makestr(&(optlist[noptlist++]),"HPUX1000");
11073 #endif /* HPUX1000 */
11074 #ifdef HPUX1100
11075     makestr(&(optlist[noptlist++]),"HPUX1100");
11076 #endif /* HPUX1100 */
11077 #ifdef HPUXPRE65
11078     makestr(&(optlist[noptlist++]),"HPUXPRE65");
11079 #endif /* HPUXPRE65 */
11080 #ifdef DGUX
11081     makestr(&(optlist[noptlist++]),"DGUX");
11082 #endif /* DGUX */
11083 #ifdef DGUX430
11084     makestr(&(optlist[noptlist++]),"DGUX430");
11085 #endif /* DGUX430 */
11086 #ifdef DGUX540
11087     makestr(&(optlist[noptlist++]),"DGUX540");
11088 #endif /* DGUX540 */
11089 #ifdef DGUX543
11090     makestr(&(optlist[noptlist++]),"DGUX543");
11091 #endif /* DGUX543 */
11092 #ifdef DGUX54410
11093     makestr(&(optlist[noptlist++]),"DGUX54410");
11094 #endif /* DGUX54410 */
11095 #ifdef DGUX54411
11096     makestr(&(optlist[noptlist++]),"DGUX54411");
11097 #endif /* DGUX54411 */
11098 #ifdef sony_news
11099     makestr(&(optlist[noptlist++]),"sony_news");
11100 #endif /* sony_news */
11101 #ifdef CIE
11102     makestr(&(optlist[noptlist++]),"CIE");
11103 #endif /* CIE */
11104 #ifdef XENIX
11105     makestr(&(optlist[noptlist++]),"XENIX");
11106 #endif /* XENIX */
11107 #ifdef SCO_XENIX
11108     makestr(&(optlist[noptlist++]),"SCO_XENIX");
11109 #endif /* SCO_XENIX */
11110 #ifdef ISIII
11111     makestr(&(optlist[noptlist++]),"ISIII");
11112 #endif /* ISIII */
11113 #ifdef I386IX
11114     makestr(&(optlist[noptlist++]),"I386IX");
11115 #endif /* I386IX */
11116 #ifdef RTU
11117     makestr(&(optlist[noptlist++]),"RTU");
11118 #endif /* RTU */
11119 #ifdef PROVX1
11120     makestr(&(optlist[noptlist++]),"PROVX1");
11121 #endif /* PROVX1 */
11122 #ifdef PYRAMID
11123     makestr(&(optlist[noptlist++]),"PYRAMID");
11124 #endif /* PYRAMID */
11125 #ifdef TOWER1
11126     makestr(&(optlist[noptlist++]),"TOWER1");
11127 #endif /* TOWER1 */
11128 #ifdef UTEK
11129     makestr(&(optlist[noptlist++]),"UTEK");
11130 #endif /* UTEK */
11131 #ifdef ZILOG
11132     makestr(&(optlist[noptlist++]),"ZILOG");
11133 #endif /* ZILOG */
11134 #ifdef TRS16
11135     makestr(&(optlist[noptlist++]),"TRS16");
11136 #endif /* TRS16 */
11137 #ifdef MINIX
11138     makestr(&(optlist[noptlist++]),"MINIX");
11139 #endif /* MINIX */
11140 #ifdef MINIX2
11141     makestr(&(optlist[noptlist++]),"MINIX2");
11142 #endif /* MINIX2 */
11143 #ifdef MINIX3
11144     makestr(&(optlist[noptlist++]),"MINIX3");
11145 #endif /* MINIX3 */
11146 #ifdef MINIX315
11147     makestr(&(optlist[noptlist++]),"MINIX315");
11148 #endif /* MINIX315 */
11149 #ifdef C70
11150     makestr(&(optlist[noptlist++]),"C70");
11151 #endif /* C70 */
11152 #ifdef AIXPS2
11153     makestr(&(optlist[noptlist++]),"AIXPS2");
11154 #endif /* AIXPS2 */
11155 #ifdef AIXRS
11156     makestr(&(optlist[noptlist++]),"AIXRS");
11157 #endif /* AIXRS */
11158 #ifdef UTSV
11159     makestr(&(optlist[noptlist++]),"UTSV");
11160 #endif /* UTSV */
11161 #ifdef ATTSV
11162     makestr(&(optlist[noptlist++]),"ATTSV");
11163 #endif /* ATTSV */
11164 #ifdef SVR3
11165     makestr(&(optlist[noptlist++]),"SVR3");
11166 #endif /* SVR3 */
11167 #ifdef SVR4
11168     makestr(&(optlist[noptlist++]),"SVR4");
11169 #endif /* SVR4 */
11170 #ifdef DELL_SVR4
11171     makestr(&(optlist[noptlist++]),"DELL_SVR4");
11172 #endif /* DELL_SVR4 */
11173 #ifdef ICL_SVR4
11174     makestr(&(optlist[noptlist++]),"ICL_SVR4");
11175 #endif /* ICL_SVR4 */
11176 #ifdef OSF
11177     makestr(&(optlist[noptlist++]),"OSF");
11178 #endif /* OSF */
11179 #ifdef OSF1
11180     makestr(&(optlist[noptlist++]),"OSF1");
11181 #endif /* OSF1 */
11182 #ifdef __OSF
11183     makestr(&(optlist[noptlist++]),"__OSF");
11184 #endif /* __OSF */
11185 #ifdef __OSF__
11186     makestr(&(optlist[noptlist++]),"__OSF__");
11187 #endif /* __OSF__ */
11188 #ifdef __osf__
11189     makestr(&(optlist[noptlist++]),"__osf__");
11190 #endif /* __osf__ */
11191 #ifdef __OSF1
11192     makestr(&(optlist[noptlist++]),"__OSF1");
11193 #endif /* __OSF1 */
11194 #ifdef __OSF1__
11195     makestr(&(optlist[noptlist++]),"__OSF1__");
11196 #endif /* __OSF1__ */
11197 #ifdef PTX
11198     makestr(&(optlist[noptlist++]),"PTX");
11199 #endif /* PTX */
11200 #ifdef POSIX
11201     makestr(&(optlist[noptlist++]),"POSIX");
11202 #endif /* POSIX */
11203 #ifdef BSD44ORPOSIX
11204     makestr(&(optlist[noptlist++]),"BSD44ORPOSIX");
11205 #endif /* BSD44ORPOSIX */
11206 #ifdef SVORPOSIX
11207     makestr(&(optlist[noptlist++]),"SVORPOSIX");
11208 #endif /* SVORPOSIX */
11209 #ifdef SVR4ORPOSIX
11210     makestr(&(optlist[noptlist++]),"SVR4ORPOSIX");
11211 #endif /* SVR4ORPOSIX */
11212 #ifdef OS2ORVMS
11213     makestr(&(optlist[noptlist++]),"OS2ORVMS");
11214 #endif /* OS2ORVMS */
11215 #ifdef OS2ORUNIX
11216     makestr(&(optlist[noptlist++]),"OS2ORUNIX");
11217 #endif /* OS2ORUNIX */
11218 #ifdef VMSORUNIX
11219     makestr(&(optlist[noptlist++]),"VMSORUNIX");
11220 #endif /* VMSORUNIX */
11221 #ifdef VMS64BIT
11222     makestr(&(optlist[noptlist++]),"VMS64BIT");	/* VMS on Alpha or IA64 */
11223 #endif /* VMS64BIT */
11224 #ifdef VMSI64
11225     makestr(&(optlist[noptlist++]),"VMSI64"); /* VMS on IA64 */
11226 #endif /* VMSI64 */
11227 #ifdef _POSIX_SOURCE
11228     makestr(&(optlist[noptlist++]),"_POSIX_SOURCE");
11229 #endif /* _POSIX_SOURCE */
11230 #ifdef _XOPEN_SOURCE
11231     makestr(&(optlist[noptlist++]),"_XOPEN_SOURCE");
11232 #endif
11233 #ifdef _ALL_SOURCE
11234     makestr(&(optlist[noptlist++]),"_ALL_SOURCE");
11235 #endif
11236 #ifdef _SVID3
11237     makestr(&(optlist[noptlist++]),"_SVID3");
11238 #endif /* _SVID3 */
11239 #ifdef Plan9
11240     makestr(&(optlist[noptlist++]),"Plan9");
11241 #endif /* Plan9 */
11242 #ifdef SOLARIS
11243     makestr(&(optlist[noptlist++]),"SOLARIS");
11244 #ifdef SOLARIS24
11245     makestr(&(optlist[noptlist++]),"SOLARIS24");
11246 #endif /* SOLARIS24 */
11247 #ifdef SOLARIS25
11248     makestr(&(optlist[noptlist++]),"SOLARIS25");
11249 #endif /* SOLARIS25 */
11250 #ifdef SOLARIS26
11251     makestr(&(optlist[noptlist++]),"SOLARIS26");
11252 #endif /* SOLARIS26 */
11253 #ifdef SOLARIS7
11254     makestr(&(optlist[noptlist++]),"SOLARIS7");
11255 #endif /* SOLARIS7 */
11256 #ifdef SOLARIS8
11257     makestr(&(optlist[noptlist++]),"SOLARIS8");
11258 #endif /* SOLARIS8 */
11259 #ifdef SOLARIS9
11260     makestr(&(optlist[noptlist++]),"SOLARIS9");
11261 #endif /* SOLARIS9 */
11262 #ifdef SOLARIS10
11263     makestr(&(optlist[noptlist++]),"SOLARIS10");
11264 #endif /* SOLARIS10 */
11265 #endif /* SOLARIS */
11266 
11267 #ifdef SUNOS4
11268     makestr(&(optlist[noptlist++]),"SUNOS4");
11269 #endif /* SUNOS4 */
11270 #ifdef SUN4S5
11271     makestr(&(optlist[noptlist++]),"SUN4S5");
11272 #endif /* SUN4S5 */
11273 #ifdef IRIX
11274     makestr(&(optlist[noptlist++]),"IRIX");
11275 #endif /* IRIX */
11276 #ifdef ENCORE
11277     makestr(&(optlist[noptlist++]),"ENCORE");
11278 #endif /* ENCORE */
11279 #ifdef ultrix
11280     makestr(&(optlist[noptlist++]),"ultrix");
11281 #endif
11282 #ifdef sxaE50
11283     makestr(&(optlist[noptlist++]),"sxaE50");
11284 #endif
11285 #ifdef mips
11286     makestr(&(optlist[noptlist++]),"mips");
11287 #endif
11288 #ifdef MIPS
11289     makestr(&(optlist[noptlist++]),"MIPS");
11290 #endif
11291 #ifdef vax
11292     makestr(&(optlist[noptlist++]),"vax");
11293 #endif
11294 #ifdef VAX
11295     makestr(&(optlist[noptlist++]),"VAX");
11296 #endif
11297 #ifdef alpha
11298     makestr(&(optlist[noptlist++]),"alpha");
11299 #endif
11300 #ifdef ALPHA
11301     makestr(&(optlist[noptlist++]),"ALPHA");
11302 #endif
11303 #ifdef __ALPHA
11304     makestr(&(optlist[noptlist++]),"__ALPHA");
11305 #endif
11306 #ifdef __alpha
11307     makestr(&(optlist[noptlist++]),"__alpha");
11308 #endif
11309 #ifdef __AXP
11310     makestr(&(optlist[noptlist++]),"__AXP");
11311 #endif
11312 #ifdef AXP
11313     makestr(&(optlist[noptlist++]),"AXP");
11314 #endif
11315 #ifdef axp
11316     makestr(&(optlist[noptlist++]),"axp");
11317 #endif
11318 #ifdef __ALPHA__
11319     makestr(&(optlist[noptlist++]),"__ALPHA__");
11320 #endif
11321 #ifdef __alpha__
11322     makestr(&(optlist[noptlist++]),"__alpha__");
11323 #endif
11324 #ifdef sun
11325     makestr(&(optlist[noptlist++]),"sun");
11326 #endif
11327 #ifdef sun3
11328     makestr(&(optlist[noptlist++]),"sun3");
11329 #endif
11330 #ifdef sun386
11331     makestr(&(optlist[noptlist++]),"sun386");
11332 #endif
11333 #ifdef _SUN
11334     makestr(&(optlist[noptlist++]),"_SUN");
11335 #endif
11336 #ifdef sun4
11337     makestr(&(optlist[noptlist++]),"sun4");
11338 #endif
11339 #ifdef sparc
11340     makestr(&(optlist[noptlist++]),"sparc");
11341 #endif
11342 #ifdef _CRAY
11343     makestr(&(optlist[noptlist++]),"_CRAY");
11344 #endif /* _CRAY */
11345 #ifdef NEXT33
11346     makestr(&(optlist[noptlist++]),"NEXT33");
11347 #endif
11348 #ifdef NEXT
11349     makestr(&(optlist[noptlist++]),"NEXT");
11350 #endif
11351 #ifdef NeXT
11352     makestr(&(optlist[noptlist++]),"NeXT");
11353 #endif
11354 #ifdef MACH
11355     makestr(&(optlist[noptlist++]),"MACH");
11356 #endif
11357 
11358 #ifdef MACOSX
11359     makestr(&(optlist[noptlist++]),"MACOSX");
11360 #endif
11361 #ifdef MACOSX10
11362     makestr(&(optlist[noptlist++]),"MACOSX10");
11363 #endif
11364 #ifdef MACOSX103
11365     makestr(&(optlist[noptlist++]),"MACOSX10e");
11366 #endif
11367 #ifdef COMMENT
11368 /* not used */
11369 #ifdef MACOSX103
11370     makestr(&(optlist[noptlist++]),"MACOSX103");
11371 #endif
11372 #endif	/* COMMENT */
11373 
11374 #ifdef sgi
11375     makestr(&(optlist[noptlist++]),"sgi");
11376 #endif
11377 #ifdef M_SYS5
11378     makestr(&(optlist[noptlist++]),"M_SYS5");
11379 #endif
11380 #ifdef __SYSTEM_FIVE
11381     makestr(&(optlist[noptlist++]),"__SYSTEM_FIVE");
11382 #endif
11383 #ifdef sysV
11384     makestr(&(optlist[noptlist++]),"sysV");
11385 #endif
11386 #ifdef M_XENIX                          /* SCO Xenix V and UNIX/386 */
11387     makestr(&(optlist[noptlist++]),"M_XENIX");
11388 #endif
11389 #ifdef M_UNIX                           /* SCO UNIX */
11390     makestr(&(optlist[noptlist++]),"M_UNIX");
11391 #endif
11392 #ifdef _M_UNIX                          /* SCO UNIX 3.2v4 = ODT 2.0 */
11393     makestr(&(optlist[noptlist++]),"_M_UNIX");
11394 #endif
11395 #ifdef CK_SCOV5
11396     makestr(&(optlist[noptlist++]),"CK_SCOV5");
11397 #endif
11398 #ifdef SCO_OSR504
11399     makestr(&(optlist[noptlist++]),"SCO_OSR504");
11400 #endif
11401 #ifdef M_IA64
11402     makestr(&(optlist[noptlist++]),"M_IA64");
11403 #endif
11404 #ifdef _M_IA64
11405     makestr(&(optlist[noptlist++]),"_M_IA64");
11406 #endif
11407 #ifdef ia64
11408     makestr(&(optlist[noptlist++]),"ia64");
11409 #endif
11410 #ifdef _ia64
11411     makestr(&(optlist[noptlist++]),"_ia64");
11412 #endif
11413 #ifdef _ia64_
11414     makestr(&(optlist[noptlist++]),"_ia64_");
11415 #endif
11416 #ifdef __ia64
11417     makestr(&(optlist[noptlist++]),"__ia64");
11418 #endif
11419 #ifdef M_I686
11420     makestr(&(optlist[noptlist++]),"M_I686");
11421 #endif
11422 #ifdef _M_I686
11423     makestr(&(optlist[noptlist++]),"_M_I686");
11424 #endif
11425 #ifdef i686
11426     makestr(&(optlist[noptlist++]),"i686");
11427 #endif
11428 #ifdef M_I586
11429     makestr(&(optlist[noptlist++]),"M_I586");
11430 #endif
11431 #ifdef _M_I586
11432     makestr(&(optlist[noptlist++]),"_M_I586");
11433 #endif
11434 #ifdef i586
11435     makestr(&(optlist[noptlist++]),"i586");
11436 #endif
11437 #ifdef M_I486
11438     makestr(&(optlist[noptlist++]),"M_I486");
11439 #endif
11440 #ifdef _M_I486
11441     makestr(&(optlist[noptlist++]),"_M_I486");
11442 #endif
11443 #ifdef i486
11444     makestr(&(optlist[noptlist++]),"i486");
11445 #endif
11446 #ifdef M_I386
11447     makestr(&(optlist[noptlist++]),"M_I386");
11448 #endif
11449 #ifdef _M_I386
11450     makestr(&(optlist[noptlist++]),"_M_I386");
11451 #endif
11452 #ifdef i386
11453     makestr(&(optlist[noptlist++]),"i386");
11454 #endif
11455 #ifdef __i386
11456     makestr(&(optlist[noptlist++]),"__i386");
11457 #endif
11458 #ifdef __x86
11459     makestr(&(optlist[noptlist++]),"__x86");
11460 #endif
11461 #ifdef __x86_64
11462     makestr(&(optlist[noptlist++]),"__x86_64");
11463 #endif
11464 #ifdef __amd64
11465     makestr(&(optlist[noptlist++]),"__amd64");
11466 #endif
11467 #ifdef _ILP32
11468     makestr(&(optlist[noptlist++]),"_ILP32");
11469 #endif
11470 #ifdef _ILP64
11471     makestr(&(optlist[noptlist++]),"_ILP64");
11472 #endif
11473 #ifdef _LP32
11474     makestr(&(optlist[noptlist++]),"_LP32");
11475 #endif
11476 #ifdef _LP64
11477     makestr(&(optlist[noptlist++]),"_LP64");
11478 #endif
11479 #ifdef __LP32__
11480     makestr(&(optlist[noptlist++]),"__LP32__");
11481 #endif
11482 #ifdef __LP64__
11483     makestr(&(optlist[noptlist++]),"__LP64__");
11484 #endif
11485 #ifdef _XGP4_2
11486     makestr(&(optlist[noptlist++]),"_XGP4_2");
11487 #endif
11488 #ifdef __ppc__
11489     makestr(&(optlist[noptlist++]),"__ppc__");
11490 #endif
11491 #ifdef __ppc32__
11492     makestr(&(optlist[noptlist++]),"__ppc32__");
11493 #endif
11494 #ifdef __ppc64__
11495     makestr(&(optlist[noptlist++]),"__ppc64__");
11496 #endif
11497 #ifdef CK_64BIT
11498     makestr(&(optlist[noptlist++]),"CK_64BIT");
11499 #endif
11500 #ifdef i286
11501     makestr(&(optlist[noptlist++]),"i286");
11502 #endif
11503 #ifdef M_I286
11504     makestr(&(optlist[noptlist++]),"M_I286");
11505 #endif
11506 #ifdef __sparc
11507     makestr(&(optlist[noptlist++]),"__sparc");
11508 #endif
11509 #ifdef __sparcv8
11510     makestr(&(optlist[noptlist++]),"__sparcv8");
11511 #endif
11512 #ifdef __sparcv9
11513     makestr(&(optlist[noptlist++]),"__sparcv9");
11514 #endif
11515 #ifdef mc68000
11516     makestr(&(optlist[noptlist++]),"mc68000");
11517 #endif
11518 #ifdef mc68010
11519     makestr(&(optlist[noptlist++]),"mc68010");
11520 #endif
11521 #ifdef mc68020
11522     makestr(&(optlist[noptlist++]),"mc68020");
11523 #endif
11524 #ifdef mc68030
11525     makestr(&(optlist[noptlist++]),"mc68030");
11526 #endif
11527 #ifdef mc68040
11528     makestr(&(optlist[noptlist++]),"mc68040");
11529 #endif
11530 #ifdef M_68000
11531     makestr(&(optlist[noptlist++]),"M_68000");
11532 #endif
11533 #ifdef M_68010
11534     makestr(&(optlist[noptlist++]),"M_68010");
11535 #endif
11536 #ifdef M_68020
11537     makestr(&(optlist[noptlist++]),"M_68020");
11538 #endif
11539 #ifdef M_68030
11540     makestr(&(optlist[noptlist++]),"M_68030");
11541 #endif
11542 #ifdef M_68040
11543     makestr(&(optlist[noptlist++]),"M_68040");
11544 #endif
11545 #ifdef m68k
11546     makestr(&(optlist[noptlist++]),"m68k");
11547 #endif
11548 #ifdef m88k
11549     makestr(&(optlist[noptlist++]),"m88k");
11550 #endif
11551 #ifdef pdp11
11552     makestr(&(optlist[noptlist++]),"pdp11");
11553 #endif
11554 #ifdef iAPX
11555     makestr(&(optlist[noptlist++]),"iAPX");
11556 #endif
11557 #ifdef hpux
11558     makestr(&(optlist[noptlist++]),"hpux");
11559 #endif
11560 #ifdef __hpux
11561     makestr(&(optlist[noptlist++]),"__hpux");
11562 #endif
11563 #ifdef __hp9000s800
11564     makestr(&(optlist[noptlist++]),"__hp9000s800");
11565 #endif
11566 #ifdef __hp9000s700
11567     makestr(&(optlist[noptlist++]),"__hp9000s700");
11568 #endif
11569 #ifdef __hp9000s500
11570     makestr(&(optlist[noptlist++]),"__hp9000s500");
11571 #endif
11572 #ifdef __hp9000s300
11573     makestr(&(optlist[noptlist++]),"__hp9000s300");
11574 #endif
11575 #ifdef __hp9000s200
11576     makestr(&(optlist[noptlist++]),"__hp9000s200");
11577 #endif
11578 #ifdef AIX
11579     makestr(&(optlist[noptlist++]),"AIX");
11580 #endif
11581 #ifdef _AIXFS
11582     makestr(&(optlist[noptlist++]),"_AIXFS");
11583 #endif
11584 #ifdef u370
11585     makestr(&(optlist[noptlist++]),"u370");
11586 #endif
11587 #ifdef u3b
11588     makestr(&(optlist[noptlist++]),"u3b");
11589 #endif
11590 #ifdef u3b2
11591     makestr(&(optlist[noptlist++]),"u3b2");
11592 #endif
11593 #ifdef multimax
11594     makestr(&(optlist[noptlist++]),"multimax");
11595 #endif
11596 #ifdef balance
11597     makestr(&(optlist[noptlist++]),"balance");
11598 #endif
11599 #ifdef ibmrt
11600     makestr(&(optlist[noptlist++]),"ibmrt");
11601 #endif
11602 #ifdef _IBMRT
11603     makestr(&(optlist[noptlist++]),"_IBMRT");
11604 #endif
11605 #ifdef ibmrs6000
11606     makestr(&(optlist[noptlist++]),"ibmrs6000");
11607 #endif
11608 #ifdef _AIX
11609     makestr(&(optlist[noptlist++]),"_AIX");
11610 #endif /* _AIX */
11611 #ifdef _IBMR2
11612     makestr(&(optlist[noptlist++]),"_IBMR2");
11613 #endif
11614 #ifdef UNIXWARE
11615     makestr(&(optlist[noptlist++]),"UNIXWARE");
11616 #endif
11617 #ifdef QNX
11618     makestr(&(optlist[noptlist++]),"QNX");
11619 #ifdef __QNX__
11620     makestr(&(optlist[noptlist++]),"__QNX__");
11621 #ifdef __16BIT__
11622     makestr(&(optlist[noptlist++]),"__16BIT__");
11623 #endif
11624 #ifdef CK_QNX16
11625     makestr(&(optlist[noptlist++]),"CK_QNX16");
11626 #endif
11627 #ifdef __32BIT__
11628     makestr(&(optlist[noptlist++]),"__32BIT__");
11629 #endif
11630 #ifdef CK_QNX32
11631     makestr(&(optlist[noptlist++]),"CK_QNX32");
11632 #endif
11633 #endif /* __QNX__ */
11634 #endif /* QNX */
11635 
11636 #ifdef QNX6
11637     makestr(&(optlist[noptlist++]),"QNX6");
11638 #endif /* QNX6 */
11639 
11640 #ifdef NEUTRINO
11641     makestr(&(optlist[noptlist++]),"NEUTRINO");
11642 #endif /* NEUTRINO */
11643 
11644 #ifdef __STRICT_BSD__
11645     makestr(&(optlist[noptlist++]),"__STRICT_BSD__");
11646 #endif
11647 #ifdef __STRICT_ANSI__
11648     makestr(&(optlist[noptlist++]),"__STRICT_ANSI__");
11649 #endif
11650 #ifdef _ANSI_C_SOURCE
11651     makestr(&(optlist[noptlist++]),"_ANSI_C_SOURCE");
11652 #endif
11653 #ifdef __STDC__
11654     makestr(&(optlist[noptlist++]),"__STDC__");
11655 #endif
11656 #ifdef cplusplus
11657     makestr(&(optlist[noptlist++]),"cplusplus");
11658 #endif
11659 #ifdef __DECC
11660     makestr(&(optlist[noptlist++]),"__DECC");
11661 #ifdef __DECC_VER
11662     sprintf(line,"__DECC_VER=%d",__DECC_VER); /* SAFE */
11663     makestr(&(optlist[noptlist++]),line);
11664 #endif /* __DECC_VER */
11665 #endif /* __DECC */
11666 #ifdef __CRTL_VER
11667     sprintf(line,"__CRTL_VER=%d",__CRTL_VER); /* SAFE */
11668     makestr(&(optlist[noptlist++]),line);
11669 #endif /* __CRTL_VER */
11670 #ifdef __GNUC__                         /* gcc in ansi mode */
11671     makestr(&(optlist[noptlist++]),"__GNUC__");
11672 #endif
11673 #ifdef GNUC                             /* gcc in traditional mode */
11674     makestr(&(optlist[noptlist++]),"GNUC");
11675 #endif
11676 #ifdef __EGCS__                         /* egcs in ansi mode */
11677     makestr(&(optlist[noptlist++]),"__EGCS__");
11678 #endif
11679 #ifdef __egcs__                         /* egcs in ansi mode */
11680     makestr(&(optlist[noptlist++]),"__egcs__");
11681 #endif
11682 #ifdef __WATCOMC__
11683     makestr(&(optlist[noptlist++]),"__WATCOMC__");
11684 #endif
11685 #ifdef CK_ANSIC
11686     makestr(&(optlist[noptlist++]),"CK_ANSIC");
11687 #endif
11688 #ifdef CK_ANSILIBS
11689     makestr(&(optlist[noptlist++]),"CK_ANSILIBS");
11690 #endif
11691 #ifdef CKCONINTB4CB
11692     makestr(&(optlist[noptlist++]),"CKCONINTB4CB");
11693 #endif /* CKCONINTB4CB */
11694 #ifdef NOTERMCAP
11695     makestr(&(optlist[noptlist++]),"NOTERMCAP");
11696 #endif /* NOTERMCAP */
11697 #ifdef __GLIBC__
11698     makestr(&(optlist[noptlist++]),"__GLIBC__");
11699 #endif
11700 #ifdef _SC_JOB_CONTROL
11701     makestr(&(optlist[noptlist++]),"_SC_JOB_CONTROL");
11702 #endif
11703 #ifdef _POSIX_JOB_CONTROL
11704     makestr(&(optlist[noptlist++]),"_POSIX_JOB_CONTROL");
11705 #endif
11706 #ifdef SIG_I
11707     makestr(&(optlist[noptlist++]),"SIG_I");
11708 #endif /* SIG_I */
11709 #ifdef SIG_V
11710     makestr(&(optlist[noptlist++]),"SIG_V");
11711 #endif /* SIG_V */
11712 #ifdef CK_POSIX_SIG
11713     makestr(&(optlist[noptlist++]),"CK_POSIX_SIG");
11714 #endif
11715 #ifdef SVR3JC
11716     makestr(&(optlist[noptlist++]),"SVR3JC");
11717 #endif
11718 #ifdef _386BSD
11719     makestr(&(optlist[noptlist++]),"_386BSD");
11720 #endif
11721 #ifdef _BSD
11722     makestr(&(optlist[noptlist++]),"_BSD");
11723 #endif
11724 #ifdef USE_MEMCPY
11725     makestr(&(optlist[noptlist++]),"USE_MEMCPY");
11726 #endif /* USE_MEMCPY */
11727 #ifdef USE_LSTAT
11728     makestr(&(optlist[noptlist++]),"USE_LSTAT");
11729 #endif /* USE_LSTAT */
11730 #ifdef TERMIOX
11731     makestr(&(optlist[noptlist++]),"TERMIOX");
11732 #endif /* TERMIOX */
11733 #ifdef STERMIOX
11734     makestr(&(optlist[noptlist++]),"STERMIOX");
11735 #endif /* STERMIOX */
11736 #ifdef CK_CURSES
11737     makestr(&(optlist[noptlist++]),"CK_CURSES");
11738 #endif /* CK_CURSES */
11739 #ifdef CK_NEWTERM
11740     makestr(&(optlist[noptlist++]),"CK_NEWTERM");
11741 #endif /* CK_NEWTERM */
11742 #ifdef CK_WREFRESH
11743     makestr(&(optlist[noptlist++]),"CK_WREFRESH");
11744 #endif /* CK_WREFRESH */
11745 #ifdef CK_PCT_BAR
11746     makestr(&(optlist[noptlist++]),"CK_PCT_BAR");
11747 #endif /* CK_PCT_BAR */
11748 #ifdef CK_DTRCD
11749     makestr(&(optlist[noptlist++]),"CK_DTRCD");
11750 #endif /* CK_DTRCD */
11751 #ifdef CK_DTRCTS
11752     makestr(&(optlist[noptlist++]),"CK_DTRCTS");
11753 #endif /* CK_DTRCTS */
11754 #ifdef CK_RTSCTS
11755     makestr(&(optlist[noptlist++]),"CK_RTSCTS");
11756 #endif /* CK_RTSCTS */
11757 #ifdef POSIX_CRTSCTS
11758     makestr(&(optlist[noptlist++]),"POSIX_CRTSCTS");
11759 #endif /* POSIX_CRTSCTS */
11760 #ifdef FIXCRTSCTS
11761     makestr(&(optlist[noptlist++]),"FIXCRTSCTS");
11762 #endif /* FIXCRTSCTS */
11763 #ifdef HWPARITY
11764     makestr(&(optlist[noptlist++]),"HWPARITY");
11765 #endif /* HWPARITY */
11766 #ifdef CK_SYSINI
11767 #ifdef CK_INI_A
11768     makestr(&(optlist[noptlist++]),"CK_INI_A");
11769     ckmakmsg(line,LINBUFSIZ,"CK_SYSINI=\"",CK_SYSINI,"\"",NULL);
11770     makestr(&(optlist[noptlist++]),line);
11771 #else
11772 #ifdef CK_INI_B
11773     makestr(&(optlist[noptlist++]),"CK_INI_B");
11774     ckmakmsg(line,LINBUFSIZ,"CK_SYSINI=\"",CK_SYSINI,"\"",NULL);
11775     makestr(&(optlist[noptlist++]),line);
11776 #else
11777     makestr(&(optlist[noptlist++]),"CK_SYSINI");
11778 #endif /* CK_INI_B */
11779 #endif /* CK_INI_A */
11780 #endif /* CK_DSYSINI */
11781 #ifdef CK_DSYSINI
11782     makestr(&(optlist[noptlist++]),"CK_DSYSINI");
11783 #endif /* CK_DSYSINI */
11784 #ifdef CK_TTGWSIZ
11785     makestr(&(optlist[noptlist++]),"CK_TTGWSIZ");
11786 #endif /* CK_TTGWSIZ */
11787 #ifdef CK_NAWS
11788     makestr(&(optlist[noptlist++]),"CK_NAWS");
11789 #endif /* CK_NAWS */
11790 #ifdef MDMHUP
11791     makestr(&(optlist[noptlist++]),"MDMHUP");
11792 #endif /* MDMHUP */
11793 #ifdef HUP_CLOSE_POSIX
11794     makestr(&(optlist[noptlist++]),"HUP_CLOSE_POSIX");
11795 #endif /* HUP_CLOSE_POSIX */
11796 #ifdef NO_HUP_CLOSE_POSIX
11797     makestr(&(optlist[noptlist++]),"NO_HUP_CLOSE_POSIX");
11798 #endif /* NO_HUP_CLOSE_POSIX */
11799 #ifdef DCMDBUF
11800     makestr(&(optlist[noptlist++]),"DCMDBUF");
11801 #endif /* DCMDBUF */
11802 #ifdef CK_RECALL
11803     makestr(&(optlist[noptlist++]),"CK_RECALL");
11804 #endif /* CK_RECALL */
11805 #ifdef BROWSER
11806     makestr(&(optlist[noptlist++]),"BROWSER");
11807 #endif /* BROWSER */
11808 #ifdef CLSOPN
11809     makestr(&(optlist[noptlist++]),"CLSOPN");
11810 #endif /* CLSOPN */
11811 #ifdef STRATUS
11812     makestr(&(optlist[noptlist++]),"STRATUS");
11813 #endif /* STRATUS */
11814 #ifdef __VOS__
11815     makestr(&(optlist[noptlist++]),"__VOS__");
11816 #endif /* __VOS__ */
11817 #ifdef STRATUSX25
11818     makestr(&(optlist[noptlist++]),"STRATUSX25");
11819 #endif /* STRATUSX25 */
11820 #ifdef OS2MOUSE
11821     makestr(&(optlist[noptlist++]),"OS2MOUSE");
11822 #endif /* OS2MOUSE */
11823 #ifdef CK_REXX
11824     makestr(&(optlist[noptlist++]),"CK_REXX");
11825 #endif /* CK_REXX */
11826 #ifdef CK_TIMERS
11827     makestr(&(optlist[noptlist++]),"CK_TIMERS");
11828 #endif /* CK_TIMERS */
11829 #ifdef TTSPDLIST
11830     makestr(&(optlist[noptlist++]),"TTSPDLIST");
11831 #endif /* TTSPDLIST */
11832 #ifdef CK_PERMS
11833     makestr(&(optlist[noptlist++]),"CK_PERMS");
11834 #endif /* CK_PERMS */
11835 #ifdef CKTUNING
11836     makestr(&(optlist[noptlist++]),"CKTUNING");
11837 #endif /* CKTUNING */
11838 #ifdef NEWFTP
11839     makestr(&(optlist[noptlist++]),"NEWFTP");
11840 #endif /* NEWFTP */
11841 #ifdef SYSFTP
11842     makestr(&(optlist[noptlist++]),"SYSFTP");
11843 #endif /* SYSFTP */
11844 #ifdef NOFTP
11845     makestr(&(optlist[noptlist++]),"NOFTP");
11846 #endif /* NOFTP */
11847 #ifdef CKHTTP
11848     makestr(&(optlist[noptlist++]),"CKHTTP");
11849 #endif /* CKHTTP */
11850 #ifdef NOHTTP
11851     makestr(&(optlist[noptlist++]),"NOHTTP");
11852 #endif /* NOHTTP */
11853 #ifdef CKROOT
11854     makestr(&(optlist[noptlist++]),"CKROOT");
11855 #endif /* CKROOT */
11856 #ifdef CKREALPATH
11857     makestr(&(optlist[noptlist++]),"CKREALPATH");
11858 #endif /* CKREALPATH */
11859 #ifdef STREAMING
11860     makestr(&(optlist[noptlist++]),"STREAMING");
11861 #endif /* STREAMING */
11862 #ifdef UNPREFIXZERO
11863     makestr(&(optlist[noptlist++]),"UNPREFIXZERO");
11864 #endif /* UNPREFIXZERO */
11865 #ifdef CKREGEX
11866     makestr(&(optlist[noptlist++]),"CKREGEX");
11867 #endif /* CKREGEX */
11868 #ifdef ZXREWIND
11869     makestr(&(optlist[noptlist++]),"ZXREWIND");
11870 #endif /* ZXREWIND */
11871 #ifdef CKSYSLOG
11872     makestr(&(optlist[noptlist++]),"CKSYSLOG");
11873 #endif /* CKSYSLOG */
11874 #ifdef SYSLOGLEVEL
11875     sprintf(line,"SYSLOGLEVEL=%d",SYSLOGLEVEL); /* SAFE */
11876     makestr(&(optlist[noptlist++]),line);
11877 #endif /* SYSLOGLEVEL */
11878 #ifdef NOSEXP
11879     makestr(&(optlist[noptlist++]),"NOSEXP");
11880 #endif /* NOSEXP */
11881 #ifdef CKLEARN
11882     makestr(&(optlist[noptlist++]),"CKLEARN");
11883 #else
11884 #ifdef NOLOEARN
11885     makestr(&(optlist[noptlist++]),"NOLOEARN");
11886 #endif /* NOLOEARN */
11887 #endif /* CKLEARN */
11888 #ifdef BETATEST
11889     makestr(&(optlist[noptlist++]),"BETATEST");
11890 #endif  /* BETATEST */
11891 
11892 #ifdef NOFLOAT
11893     makestr(&(optlist[noptlist++]),"NOFLOAT");
11894 #else
11895 #ifdef FNFLOAT
11896     makestr(&(optlist[noptlist++]),"FNFLOAT");
11897 #endif /* FNFLOAT */
11898 #ifdef CKFLOAT
11899 #ifdef GFTIMER
11900     makestr(&(optlist[noptlist++]),"GFTIMER");
11901 #endif /* GFTIMER */
11902 #ifdef CKFLOAT_S
11903     ckmakmsg(line,LINBUFSIZ,"CKFLOAT=",CKFLOAT_S,NULL,NULL);
11904     makestr(&(optlist[noptlist++]),line);
11905 #else
11906     makestr(&(optlist[noptlist++]),"CKFLOAT");
11907 #endif /* CKFLOAT_S */
11908 #endif /* CKFLOAT */
11909 #endif /* NOFLOAT */
11910 
11911 #ifdef SSH
11912     makestr(&(optlist[noptlist++]),"SSH");
11913 #endif /* SSH */
11914 #ifdef NETDLL
11915     makestr(&(optlist[noptlist++]),"NETDLL");
11916 #endif /* NETDLL */
11917 #ifdef NETFILE
11918     makestr(&(optlist[noptlist++]),"NETFILE");
11919 #endif /* NETFILE */
11920 #ifdef CK_TAPI
11921     makestr(&(optlist[noptlist++]),"CK_TAPI");
11922 #endif /* CK_TAPI */
11923 #ifdef CK_SSL
11924     makestr(&(optlist[noptlist++]),"CK_SSL");
11925 #ifdef OPENSSL_VERSION_TEXT
11926     ckmakmsg(line,LINBUFSIZ,
11927 	     "OPENSSL_VERSION_TEXT=","\"",OPENSSL_VERSION_TEXT,"\"");
11928     makestr(&(optlist[noptlist++]),line);
11929 #endif	/* OPENSSL_VERSION_TEXT */
11930 #endif /* CK_SSL */
11931     debug(F101,"initoptlist noptlist","",noptlist);
11932     sh_sort(optlist,NULL,noptlist,0,0,0);
11933 }
11934 
11935 int
shofea()11936 shofea() {
11937     int i;
11938     int flag = 0;
11939     int lines = 1;
11940 #ifdef FNFLOAT
11941     extern int fp_digits, fp_rounding;
11942 #endif /* FNFLOAT */
11943     extern int byteorder;
11944     printf("%s\n",versio);
11945     if (inserver)
11946       return(1);
11947 
11948     debug(F101,"shofea NOPTLIST","",NOPTLIST);
11949     initoptlist();
11950     debug(F101,"shofea noptlist","",noptlist);
11951 #ifdef OS2
11952 #ifdef NT
11953 #ifdef _M_ALPHA
11954     printf("Microsoft Windows Operating Systems for Alpha CPUs.\n");
11955 #else /* _M_ALPHA */
11956 #ifdef _M_PPC
11957     printf("Microsoft Windows Operating Systems for PowerPC CPUs.\n");
11958 #else /* _M_PPC */
11959 #ifdef _M_MRX000
11960     printf("Microsoft Windows Operating Systems for MIPS CPUs.\n");
11961 #else /* _M_MRX000 */
11962 #ifdef _M_IX86
11963     printf("Microsoft Windows Operating Systems for 32-bit Intel CPUs.\n");
11964 #else /* _M_IX86 */
11965     UNKNOWN WINDOWS PLATFORM
11966 #endif /* _M_IX86 */
11967 #endif /* _M_MRX000 */
11968 #endif /* _M_PPC */
11969 #endif /* _M_ALPHA */
11970 #else /* NT */
11971 #ifdef M_I286
11972     printf("IBM OS/2 16-bit.\n");
11973 #else
11974     printf("IBM OS/2 32-bit.\n");
11975 #endif /* M_I286 */
11976 #endif /* NT */
11977     lines++;
11978 #endif /* OS2 */
11979     printf("\n");
11980     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11981     printf("Major optional features included:\n");
11982     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11983 
11984     if (sizeof(CK_OFF_T) == 8) {
11985 	printf(" Large files and large integers (64 bits)\n");
11986         if (++lines > cmd_rows - 3) {
11987 	    if (!askmore()) return(1); else lines = 0;
11988 	}
11989     }
11990 #ifdef NETCONN
11991     printf(" Network support (type SHOW NET for further info)\n");
11992     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11993 #ifdef IKS_OPTION
11994     printf(" Telnet Kermit Option\n");
11995     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
11996 #endif /* IKS_OPTION */
11997 #ifdef CK_AUTHENTICATION
11998     printf(" Telnet Authentication Option\n");
11999     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12000 #ifdef CK_KERBEROS
12001 #ifdef KRB4
12002 #ifdef KRB5
12003     printf(" Kerberos(TM) IV and Kerberos V authentication\n");
12004     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12005 #else /* KRB5 */
12006     printf(" Kerberos(TM) IV authentication\n");
12007     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12008 #endif /* KRB5 */
12009 #else /* KRB4 */
12010 #ifdef KRB5
12011     printf(" Kerberos(TM) V authentication\n");
12012     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12013 #endif /* KRB5 */
12014 #endif /* KRB4 */
12015 #endif /* CK_KERBEROS */
12016 #ifdef CK_SRP
12017     printf(" SRP(TM) (Secure Remote Password) authentication\n");
12018     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12019 #endif /* CK_SRP */
12020 #ifdef CK_SSL
12021     printf(" Secure Sockets Layer (SSL)\n");
12022     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12023     printf(" Transport Layer Security (TLS)\n");
12024     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12025 #endif /* CK_SSL */
12026 #ifdef SSHBUILTIN
12027     printf(" Secure Shell (SSH) [internal]\n");
12028     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12029 #endif /* SSHBUILTIN */
12030 #ifdef SSHCMD
12031     printf(" Secure Shell (SSH) [external]\n");
12032     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12033 #endif /* SSHCMD */
12034 #ifdef CK_ENCRYPTION
12035     printf(" Telnet Encryption Option\n");
12036     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12037 #ifdef CK_DES
12038     printf(" Telnet DES Encryption\n");
12039     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12040 #endif /* CK_DES */
12041 #ifdef CK_CAST
12042     printf(" Telnet CAST Encryption\n");
12043     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12044 #endif /* CK_CAST */
12045 
12046 #ifdef CK_KERBEROS
12047 #ifdef KRB5
12048 #ifdef ALLOW_KRB_3DES_ENCRYPT
12049     printf(" Kerberos 3DES/AES Telnet Encryption\n");
12050     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12051 #endif /* ALLOW_KRB_3DES_ENCRYPT */
12052 #endif /* KRB5 */
12053 #endif /* CK_KERBEROS */
12054 
12055 #endif /* CK_ENCRYPTION */
12056 #endif /* CK_AUTHENTICATION */
12057 #ifdef CK_FORWARD_X
12058     printf(" X Windows forwarding\n");
12059     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12060 #endif /* CK_FORWARD_X */
12061 #ifdef TN_COMPORT
12062     printf(" Telnet Remote Com Port Control Option\n");
12063     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12064 #endif /* TN_COMPORT */
12065 #ifdef CK_SOCKS
12066 #ifdef CK_SOCKS5
12067     printf(" SOCKS 5\n");
12068     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12069 #else /* CK_SOCKS5 */
12070     printf(" SOCKS 4\n");
12071     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12072 #endif /* CK_SOCKS5 */
12073 #endif /* CK_SOCKS */
12074 #ifdef NEWFTP
12075     printf(" Built-in FTP client\n");
12076     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12077 #endif /* NEWFTP */
12078 #ifdef CKHTTP
12079     printf(" Built-in HTTP client\n");
12080     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12081 #endif /* CKHTTP */
12082 #endif /* NETCONN */
12083 
12084 #ifdef CK_RTSCTS
12085     printf(" Hardware flow control\n");
12086     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12087 #endif /* CK_RTSCTS */
12088 
12089 #ifdef CK_XYZ
12090 #ifdef XYZ_INTERNAL
12091     printf(" Built-in XYZMODEM protocols\n");
12092 #else
12093     printf(" External XYZMODEM protocol support\n");
12094 #endif /* XYZ_INTERNAL */
12095     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12096 #endif /* CK_XYZ */
12097 
12098 #ifndef NOCSETS
12099     printf(" Latin-1 (West European) character-set translation\n");
12100     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12101 #ifdef LATIN2
12102     printf(" Latin-2 (East European) character-set translation\n");
12103     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12104 #endif /* LATIN2 */
12105 #ifdef CYRILLIC
12106     printf(" Cyrillic (Russian, Ukrainian, etc) character-set translation\n");
12107     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12108 #endif /* CYRILLIC */
12109 #ifdef GREEK
12110     printf(" Greek character-set translation\n");
12111     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12112 #endif /* GREEK */
12113 #ifdef HEBREW
12114     printf(" Hebrew character-set translation\n");
12115     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12116 #endif /* HEBREW */
12117 #ifdef KANJI
12118     printf(" Japanese character-set translation\n");
12119     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12120 #endif /* KANJI */
12121 #ifdef UNICODE
12122     printf(" Unicode character-set translation\n");
12123     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12124 #endif /* UNICODE */
12125 #ifdef CKOUNI
12126     if (isunicode())
12127       printf(" Unicode support for ISO-2022 Terminal Emulation\n");
12128     else
12129       printf(" Unicode translation for Terminal Character-Sets\n");
12130     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12131 #endif /* CKOUNI */
12132 #endif /* NOCSETS */
12133 
12134 #ifdef NETPTY
12135     printf(" Pseudoterminal control\n");
12136     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12137 #endif /* NETPTY */
12138 
12139 #ifdef CK_REDIR
12140     printf(" REDIRECT command\n");
12141     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12142 #endif /* CK_REDIR */
12143 
12144 #ifdef CK_RESEND
12145     printf(" RESEND command\n");
12146     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12147 #endif /* CK_RESEND */
12148 
12149 #ifndef NOXFER
12150 #ifdef CK_CURSES
12151     printf(" Fullscreen file transfer display\n");
12152     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12153 #endif /* CK_CURSES */
12154 #endif /* NOXFER */
12155 
12156 #ifdef CK_SPEED
12157     printf(" Control-character unprefixing\n");
12158     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12159 #endif /* CK_SPEED */
12160 
12161 #ifdef STREAMING
12162     printf(" Streaming\n");
12163     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12164 #endif /* STREAMING */
12165 
12166 #ifdef CK_AUTODL
12167     printf(" Autodownload\n");
12168     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12169 #endif /* CK_AUTODL */
12170 
12171 #ifdef OS2MOUSE
12172     printf(" Mouse support\n");
12173     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12174 #endif /* OS2MOUSE */
12175 
12176 #ifdef CK_REXX
12177     printf(" REXX script language interface\n");
12178     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12179 #endif /* CK_REXX */
12180 
12181 #ifdef IKSD
12182 #ifdef CK_LOGIN
12183     printf(" Internet Kermit Service with user login support\n");
12184 #else /* CK_LOGIN */
12185     printf(" Internet Kermit Service without user login support\n");
12186 #endif /* CK_LOGIN */
12187     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12188 #endif /* IKSD */
12189 
12190     printf("\n");
12191     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12192     printf("Major optional features not included:\n");
12193     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12194 
12195     if (sizeof(CK_OFF_T) <= 4) {
12196 	printf(" No large files or large integers\n");
12197         if (++lines > cmd_rows - 3) {
12198 	    if (!askmore()) return(1); else lines = 0;
12199 	}
12200     }
12201 
12202 #ifdef NOXFER
12203     printf(" No file-transfer protocols\n");
12204     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12205     flag = 1;
12206 #else
12207 #ifndef CK_CURSES
12208 #ifndef MAC
12209     printf(" No fullscreen file transfer display\n");
12210     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12211     flag = 1;
12212 #endif /* MAC */
12213 #endif /* CK_CURSES */
12214 
12215 #ifdef NOSERVER
12216     printf(" No server mode\n");
12217     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12218     flag = 1;
12219 #endif /* NOSERVER */
12220 
12221 #ifndef CK_SPEED
12222     printf(" No control-character unprefixing\n");
12223     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12224     flag = 1;
12225 #endif /* CK_SPEED */
12226 
12227 #ifndef STREAMING
12228     printf(" No streaming\n");
12229     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12230     flag = 1;
12231 #endif /* STREAMING */
12232 
12233 #ifndef CK_AUTODL
12234     printf(" No autodownload\n");
12235     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12236     flag = 1;
12237 #endif /* CK_AUTODL */
12238 
12239 #ifndef CK_XYZ
12240     printf(" No built-in XYZMODEM protocols\n");
12241     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12242     flag = 1;
12243 #endif /* CK_XYZ */
12244 
12245 #ifdef NOFLOAT
12246     printf(" No floating-point arithmetic\n");
12247     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12248     flag = 1;
12249     printf(" No S-Expressions (LISP interpreter)\n");
12250     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12251     flag = 1;
12252 #else
12253 #ifdef NOSEXP
12254     printf(" No S-Expressions (LISP interpreter)\n");
12255     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12256     flag = 1;
12257 #endif	/* NOSEXP */
12258 #endif	/* NOFLOAT */
12259 
12260 #ifdef NOTLOG
12261     printf(" No transaction log\n");
12262     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12263     flag = 1;
12264 #endif /* NOTLOG */
12265 #endif /* NOXFER */
12266 
12267 #ifdef NODEBUG
12268     printf(" No debugging\n");
12269     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12270     flag = 1;
12271 #endif /* NODEBUG */
12272 
12273 #ifdef NOHELP
12274     printf(" No built-in help\n");
12275     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12276     flag = 1;
12277 #endif /* NOHELP */
12278 
12279 #ifdef NOLOCAL
12280     printf(" No making connections\n");
12281     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12282     flag = 1;
12283 #else
12284 #ifndef NETCONN
12285     printf(" No network support\n");
12286     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12287     flag = 1;
12288 #else /* NETCONN */
12289 #ifndef IKS_OPTION
12290     printf(" No Telnet Kermit Option\n");
12291     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12292     flag = 1;
12293 #endif /* IKS_OPTION */
12294 #endif /* NETCONN */
12295 
12296 #ifdef NOSSH
12297     printf(" No Secure Shell (SSH)\n");
12298     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12299 #endif /* NOSSH */
12300 #ifndef CK_AUTHENTICATION
12301     printf(" No Kerberos(TM) authentication\n");
12302     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12303     printf(" No SRP(TM) (Secure Remote Password) protocol\n");
12304     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12305     printf(" No Secure Sockets Layer (SSL) protocol\n");
12306     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12307     printf(" No Transport Layer Security (TLS) protocol\n");
12308     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12309     printf(" No encryption\n");
12310     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12311     flag = 1;
12312 #else /* CK_AUTHENTICATION */
12313 #ifndef CK_KERBEROS
12314     printf(" No Kerberos(TM) authentication\n");
12315     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12316     flag = 1;
12317 #else /* CK_KERBEROS */
12318 #ifndef KRB4
12319     printf(" No Kerberos(TM) IV authentication\n");
12320     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12321     flag = 1;
12322 #endif /* KRB4 */
12323 #ifndef KRB5
12324     printf(" No Kerberos(TM) V authentication\n");
12325     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12326     flag = 1;
12327 #endif /* KRB5 */
12328 #endif /* CK_KERBEROS */
12329 #ifndef CK_SRP
12330     printf(" No SRP(TM) (Secure Remote Password) authentication\n");
12331     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12332     flag = 1;
12333 #endif /* CK_SRP */
12334 #ifndef CK_SSL
12335     printf(" No Secure Sockets Layer (SSL) protocol\n");
12336     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12337     printf(" No Transport Layer Security (TLS) protocol\n");
12338     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12339     flag = 1;
12340 #endif /* CK_SSL */
12341 #ifndef CK_ENCRYPTION
12342     printf(" No Telnet Encryption Option\n");
12343     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12344     flag = 1;
12345 #else /* CK_ENCRYPTION */
12346 #ifndef OS2
12347 #ifndef CK_DES
12348     printf(" No Telnet DES encryption\n");
12349     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12350     flag = 1;
12351 #endif /* CK_DES */
12352 #ifndef CK_CAST
12353     printf(" No Telnet CAST encryption\n");
12354     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12355     flag = 1;
12356 #endif /* CK_CAST */
12357 
12358 #ifdef COMMENT
12359 #ifdef CK_KERBEROS
12360 #ifdef KRB5
12361 #ifndef ALLOW_KRB_3DES_ENCRYPT
12362     printf(" No Kerberos 3DES/AES Telnet Encryption\n");
12363     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12364 #endif /* ALLOW_KRB_3DES_ENCRYPT */
12365 #endif /* KRB5 */
12366 #endif /* CK_KERBEROS */
12367 #endif /* COMMENT */
12368 
12369 #endif /* OS2 */
12370 #endif /* CK_ENCRYPTION */
12371 #endif /* CK_AUTHENTICATION */
12372 #ifndef CK_FORWARD_X
12373     printf(" No X Windows forwarding\n");
12374     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12375 #endif /* CK_FORWARD_X */
12376 #ifndef TN_COMPORT
12377     printf(" No Telnet Remote Com Port Control Option\n");
12378     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12379 #endif /* TN_COMPORT */
12380 #ifndef CK_SOCKS
12381     printf(" No SOCKS\n");
12382     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12383 #endif /* CK_SOCKS */
12384 #ifndef NEWFTP
12385     printf(" No built-in FTP client\n");
12386     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12387 #endif /* NEWFTP */
12388 #ifdef NOHTTP
12389     printf(" No built-in HTTP client\n");
12390     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12391 #endif /* NOHTTP */
12392 
12393 #ifdef NODIAL
12394     printf(" No DIAL command\n");
12395     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12396     flag = 1;
12397 #else
12398 #ifdef MINIDIAL
12399     printf(" Support for most modem types excluded\n");
12400     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12401     flag = 1;
12402 #endif /* MINIDIAL */
12403 #endif /* NODIAL */
12404 #endif /* NOLOCAL */
12405 
12406 #ifndef CK_RTSCTS
12407 #ifndef MAC
12408     printf(" No hardware flow control\n");
12409     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12410     flag = 1;
12411 #endif /* MAC */
12412 #endif /* CK_RTSCTS */
12413 
12414 #ifdef NOXMIT
12415     printf(" No TRANSMIT command\n");
12416     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12417     flag = 1;
12418 #endif /* NOXMIT */
12419 
12420 #ifdef NOSCRIPT
12421     printf(" No SCRIPT command\n");
12422     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12423     flag = 1;
12424 #endif /* NOSCRIPT */
12425 
12426 #ifdef NOSPL
12427     printf(" No script programming features\n");
12428     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12429     flag = 1;
12430 #endif /* NOSPL */
12431 
12432 #ifdef NOCSETS
12433     printf(" No character-set translation\n");
12434     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12435     flag = 1;
12436 #else
12437 
12438 #ifndef LATIN2
12439     printf(" No Latin-2 character-set translation\n");
12440     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12441     flag = 1;
12442 #endif /* LATIN2 */
12443 
12444 #ifdef NOGREEK
12445     printf(" No Greek character-set translation\n");
12446     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12447     flag = 1;
12448 #endif /* NOGREEK */
12449 
12450 #ifdef NOHEBREW
12451     printf(" No Hebrew character-set translation\n");
12452     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12453     flag = 1;
12454 #endif /* NOHEBREW */
12455 
12456 #ifdef NOUNICODE
12457     printf(" No Unicode character-set translation\n");
12458     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12459     flag = 1;
12460 #endif /* NOUNICODE */
12461 
12462 #ifdef NOCYRIL
12463     printf(" No Cyrillic character-set translation\n");
12464     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12465     flag = 1;
12466 #endif /* NOCYRIL */
12467 
12468 #ifndef KANJI
12469     printf(" No Kanji character-set translation\n");
12470     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12471     flag = 1;
12472 #endif /* KANJI */
12473 #endif /* NOCSETS */
12474 
12475 #ifdef NOCMDL
12476     printf(" No command-line arguments\n");
12477     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12478     flag = 1;
12479 #endif /* NOCMDL */
12480 
12481 #ifdef NOPUSH
12482     printf(" No escape to system\n");
12483     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12484     flag = 1;
12485 #endif /* NOPUSH */
12486 
12487 #ifdef NOJC
12488 #ifdef UNIX
12489     printf(" No UNIX job control\n");
12490     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12491     flag = 1;
12492 #endif /* UNIX */
12493 #endif /* NOJC */
12494 
12495 #ifdef NOSETKEY
12496     printf(" No SET KEY command\n");
12497     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12498     flag = 1;
12499 #endif /* NOSETKEY */
12500 
12501 #ifndef CK_REDIR
12502     printf(" No REDIRECT or PIPE command\n");
12503     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12504     flag = 1;
12505 #endif /* CK_REDIR */
12506 
12507 #ifdef UNIX
12508 #ifndef NETPTY
12509     printf(" No pseudoterminal control\n");
12510     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12511     flag = 1;
12512 #endif /* NETPTY */
12513 #endif /* UNIX */
12514 
12515 #ifndef CK_RESEND
12516     printf(" No RESEND command\n");
12517     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12518     flag = 1;
12519 #endif /* CK_RESEND */
12520 
12521 #ifdef OS2
12522 #ifdef __32BIT__
12523 #ifndef OS2MOUSE
12524     printf(" No Mouse support\n");
12525     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12526     flag = 1;
12527 #endif /* __32BIT__ */
12528 #endif /* OS2 */
12529 #endif /* OS2MOUSE */
12530 
12531 #ifdef OS2
12532 #ifndef NT
12533 #ifndef CK_REXX
12534     printf(" No REXX script language interface\n");
12535     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12536     flag = 1;
12537 #endif /* CK_REXX */
12538 #endif /* NT */
12539 #endif /* OS2 */
12540 
12541 #ifndef IKSD
12542     printf(" No Internet Kermit Service\n");
12543     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12544     flag = 1;
12545 #endif /* IKSD */
12546 
12547     if (flag == 0) {
12548         printf(" None\n");
12549         if (++lines > cmd_rows - 3)
12550           { if (!askmore()) return(1); else lines = 0; }
12551     }
12552     printf("\n");
12553     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12554 
12555 #ifdef CK_UTSNAME
12556     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12557     printf("Host info:\n");
12558     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12559     printf(" Machine:    %s\n",unm_mch[0] ? unm_mch : "(unknown)");
12560     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12561     printf(" Model:      %s\n",unm_mod[0] ? unm_mod : "(unknown)");
12562     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12563     printf(" OS:         %s\n",unm_nam[0] ? unm_nam : "(unknown)");
12564     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12565     printf(" OS Release: %s\n",unm_rel[0] ? unm_rel : "(unknown)");
12566     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12567     printf(" OS Version: %s\n",unm_ver[0] ? unm_ver : "(unknown)");
12568     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12569     printf("\n");
12570     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12571 #endif /* CK_UTSNAME */
12572 
12573 /*
12574   Print compile-time (-D) options, as well as C preprocessor
12575   predefined symbols that might affect us...
12576 */
12577 #ifdef KTARGET
12578     {
12579         char * s;                       /* Makefile target */
12580         s = KTARGET;
12581         if (!s) s = "";
12582         if (!*s) s = "(unknown)";
12583         printf("\n");
12584         if (++lines > cmd_rows - 3) {
12585             if (!askmore()) return(1); else lines = 0;
12586         }
12587         printf("Target: %s\n", s);
12588         if (++lines > cmd_rows - 3) {
12589             if (!askmore()) return(1); else lines = 0;
12590         }
12591     }
12592 #endif /* KTARGET */
12593 
12594 #ifdef __VERSION__
12595 #ifdef __GNUC__
12596     printf("GCC version: %s\n", __VERSION__);
12597 #else
12598     printf("Compiler version: %s\n", __VERSION__);
12599 #endif /* __GNUC__ */
12600     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12601 #endif /* __VERSION__ */
12602 
12603 #ifdef __DATE__                         /* GNU and other ANSI */
12604 #ifdef __TIME__
12605     printf("Compiled %s %s, options:\n", __DATE__, __TIME__);
12606 #else
12607     printf("Compiled %s, options:\n", __DATE__);
12608 #endif /* __TIME__ */
12609 #else /* !__DATE__ */
12610     printf("Compiler options:\n");
12611 #endif /* __DATE__ */
12612     if (++lines > cmd_rows - 3) { if (!askmore()) return(1); else lines = 0; }
12613 
12614     for (i = 0; i < noptlist; i++)      /* Print sorted option list */
12615       if (!prtopt(&lines,optlist[i]))
12616         return(0);
12617 
12618     if (!prtopt(&lines,"")) return(0);  /* Start a new section */
12619 
12620 /* Sizes of data types */
12621 
12622     ckmakmsg(line,
12623              LINBUFSIZ,
12624              "byte order: ",
12625              byteorder ? "little" : "big",
12626              " endian",
12627              NULL
12628              );
12629     {
12630 /* Whether to use %d or %ld with sizeof is a portability issue, so... */
12631 	int size = 0;
12632 
12633 	if (!prtopt(&lines,line)) return(0);
12634 	if (!prtopt(&lines,"")) return(0);  /* Start a new section */
12635 
12636 	size = (int)sizeof(int);
12637 	sprintf(line,"sizeofs: int=%d",size); /* SAFE */
12638 	if (!prtopt(&lines,line)) return(0);
12639 
12640 	size = (int)sizeof(long);
12641 	sprintf(line,"long=%d",size); /* SAFE */
12642 	if (!prtopt(&lines,line)) return(0);
12643 
12644 #ifndef OS2
12645 	/* Windows doesn't have off_t */
12646 	size = (int)sizeof(off_t);
12647 	sprintf(line,"off_t=%d",size); /* SAFE */
12648 	if (!prtopt(&lines,line)) return(0);
12649 #endif /* OS2 */
12650 
12651 	size = (int)sizeof(CK_OFF_T);
12652 	sprintf(line,"CK_OFF_T=%d",size); /* SAFE */
12653 	if (!prtopt(&lines,line)) return(0);
12654 
12655 #ifdef BIGBUFOK
12656 	size = (int)sizeof(size_t);
12657 	sprintf(line,"size_t=%d",size); /* SAFE */
12658 	if (!prtopt(&lines,line)) return(0);
12659 #endif /* BIGBUFOK */
12660 
12661 	size = (int)sizeof(short);
12662 	sprintf(line,"short=%d",size); /* SAFE */
12663 	if (!prtopt(&lines,line)) return(0);
12664 
12665 	size = (int)sizeof(char);
12666 	sprintf(line,"char=%d",size); /* SAFE */
12667 	if (!prtopt(&lines,line)) return(0);
12668 
12669 	size = (int)sizeof(char *);
12670 	sprintf(line,"char*=%d",size); /* SAFE */
12671 	if (!prtopt(&lines,line)) return(0);
12672 
12673 	size = (int)sizeof(float);
12674 	sprintf(line,"float=%d",size); /* SAFE */
12675 	if (!prtopt(&lines,line)) return(0);
12676 
12677 	size = (int)sizeof(double);
12678 	sprintf(line,"double=%d",size); /* SAFE */
12679 	if (!prtopt(&lines,line)) return(0);
12680     }
12681 
12682 #ifdef FNFLOAT
12683     if (!prtopt(&lines,"")) return(0);  /* Start a new section */
12684     if (!prtopt(&lines,"floating-point:")) return(0);
12685     sprintf(line,"precision=%d",fp_digits); /* SAFE */
12686     if (!prtopt(&lines,line)) return(0);
12687     sprintf(line,"rounding=%d",fp_rounding); /* SAFE */
12688     if (!prtopt(&lines,line)) return(0);
12689 #endif /* FNFLOAT */
12690 
12691     prtopt(&lines,"");
12692     return(0);
12693 }
12694 #endif /* NOSHOW */
12695 #endif /* NOICP */
12696