|
|
1.1 root 1: #ifndef NOICP
2:
3: /* C K U U S 5 -- "User Interface" for Unix Kermit, part 5 */
4:
5: /*
6: Author: Frank da Cruz ([email protected], [email protected]),
7: Columbia University Center for Computing Activities.
8: First released January 1985.
9: Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
10: York. Permission is granted to any individual or institution to use this
11: software as long as it is not sold for profit. This copyright notice must be
12: retained. This software may not be included in commercial products without
13: written permission of Columbia University.
14: */
15:
16: /* Includes */
17:
18: #include "ckcdeb.h"
19: #include "ckcasc.h"
20: #include "ckcker.h"
21: #include "ckuusr.h"
22: #include "ckcnet.h"
23: #ifndef NOCSETS
24: #include "ckcxla.h"
25: #endif /* NOCSETS */
26: #ifdef MAC
27: #include "ckmasm.h"
28: #endif /* MAC */
29:
30: /* For formatted screens, "more?" prompting, etc. */
31:
32: #define SCRNLEN 21 /* Screen length */
33: #define SCRNWID 79 /* Screen width */
34:
35: #ifdef FT18
36: #define isxdigit(c) isdigit(c)
37: #endif /* FT18 */
38:
39: #ifdef MAC /* Internal MAC file routines */
40: #define feof mac_feof
41: #define rewind mac_rewind
42: #define fgets mac_fgets
43: #define fopen mac_fopen
44: #define fclose mac_fclose
45:
46: int mac_feof();
47: void mac_rewind();
48: char *mac_fgets();
49: FILE *mac_fopen();
50: int mac_fclose();
51: #endif /* MAC */
52:
53: /* External variables */
54:
55: extern int carrier, cdtimo, local, backgrd, bgset, sosi, suspend,
56: displa, binary, deblog, escape, xargs, flow, cmdmsk,
57: duplex, ckxech, pktlog, seslog, tralog, what,
58: keep, warn, tlevel, cwdf, nfuncs, unkcs, msgflg,
59: mdmtyp, zincnt, cmask, rcflag, success, xitsta, pflag, lf_opts, tnlm, tn_nlm;
60:
61: extern char *ccntab[];
62:
63: #ifndef NOFRILLS
64: extern int en_cwd, en_del, en_dir, en_fin, en_bye,
65: en_get, en_hos, en_sen, en_set, en_spa, en_typ, en_who;
66: #endif /* NOFRILLS */
67: extern long vernum;
68: extern int srvtim, srvdis, incase, inecho, intime, insilence, nvars, verwho;
69: extern char *protv, *fnsv, *cmdv, *userv, *ckxv, *ckzv, *ckzsys, *xlav,
70: *cknetv, *clcmds;
71: extern char *connv, *dialv, *loginv, *nvlook();
72:
73: #ifndef NOSCRIPT
74: extern int secho;
75: #endif /* NOSCRIPT */
76:
77: #ifndef NODIAL
78: extern int nmdm;
79: extern struct keytab mdmtab[];
80: #endif /* NODIAL */
81:
82: #ifdef NETCONN
83: extern int tn_init, network, ttnproto;
84: #endif /* NETCONN */
85:
86: #ifdef OS2
87: extern int tt_type, tt_arrow, tt_keypad, tt_wrap;
88: #endif /* OS2 */
89: extern int tt_crd;
90:
91: #ifndef NOCSETS
92: extern int language, nfilc, tcsr, tcsl;
93: extern struct keytab fcstab[];
94: #ifndef MAC
95: extern struct keytab ttcstab[];
96: #endif /* MAC */
97: #endif /* NOCSETS */
98:
99: extern int atcapr,
100: atenci, atenco, atdati, atdato, atleni, atleno, atblki, atblko,
101: attypi, attypo, atsidi, atsido, atsysi, atsyso, atdisi, atdiso;
102:
103: extern long speed;
104:
105: extern char *DIRCMD, *PWDCMD, *DELCMD;
106: #ifndef NOXMIT
107: extern int xmitf, xmitl, xmitp, xmitx, xmits, xmitw;
108: extern char xmitbuf[];
109: #endif /* NOXMIT */
110:
111: extern char **xargv, *versio, *ckxsys, *dftty, *cmarg, *lp;
112:
113: #ifdef DCMDBUF
114: extern char *cmdbuf, *atmbuf; /* Command buffers */
115: #ifndef NOSPL
116: extern char *savbuf; /* Command buffers */
117: #endif /* NOSPL */
118: #else
119: extern char cmdbuf[], atmbuf[]; /* Command buffers */
120: #ifndef NOSPL
121: extern char savbuf[]; /* Command buffers */
122: #endif /* NOSPL */
123: #endif /* DCMDBUF */
124:
125: extern char toktab[], ttname[], psave[];
126: extern CHAR sstate;
127: extern int cmflgs, techo, terror, repars, ncmd;
128: extern struct keytab cmdtab[];
129:
130: #ifndef MAC
131: #ifndef NOSETKEY
132: KEY *keymap;
133: MACRO *macrotab;
134: #endif /* NOSETKEY */
135: #endif /* MAC */
136:
137: #ifndef NOSPL
138: extern struct mtab *mactab;
139: extern struct keytab vartab[], fnctab[];
140: extern int cmdlvl, maclvl, nmac, mecho, merror;
141: #endif /* NOSPL */
142:
143: FILE *tfile[MAXTAKE]; /* TAKE file stack */
144: char *tfnam[MAXTAKE];
145:
146: #ifndef NOSPL
147: /* Local declarations */
148:
149: int nulcmd = 0; /* Flag for next cmd to be ignored */
150:
151: /* Definitions for built-in macros */
152:
153: /* First, the single line macros, installed with addmac()... */
154:
155: /* IBM-LINEMODE macro */
156: char *m_ibm = "set parity mark, set dupl half, set handsh xon, set flow none";
157:
158: /* FATAL macro */
159: char *m_fat = "if def \\%1 echo \\%1, if not = \\v(local) 0 hangup, stop 1";
160:
161: #ifdef COMMENT
162: /*
163: Long macro definitions were formerly done like this. But some compilers
164: cannot handle continued string constants, others cannot handle string
165: constants that are this long. So these definitions have been broken up
166: into pieces and put into arrays, see below.
167: */
168: char *m_forx = "if def _floop ass \\%9 \\fdef(_floop),else def \\%9,\
169: ass _floop { _getargs,\
170: define \\\\\\%1 \\%2,:top,if \\%5 \\\\\\%1 \\%3 goto bot,\
171: \\%6,:inc, incr \\\\\\%1 \\%4,goto top,:bot,_putargs,return},\
172: def break goto bot, def continue goto inc,\
173: do _floop \\%1 \\%2 \\%3 \\%4 { \\%5 },assign _floop \\fcont(\\%9)";
174:
175: char *m_while = "if def _wloop ass \\%9 \\fdef(_wloop),\
176: ass _wloop {_getargs,:wtest,\\%1,\\%2,goto wtest,:wbot,_putargs,return},\
177: def break goto wbot, def continue goto wtest,\
178: do _wloop,assign _wloop \\fcont(\\%9)";
179:
180: char *m_xif = "ass \\%9 \\fdef(_ify),ass _ify {_getargs, \\%1, _putargs},\
181: do _ify,ass _ify \\fcont(\\%9)";
182: #endif /* COMMENT */
183:
184: /* Now the multiline macros, defined with addmmac()... */
185:
186: /* FOR macro */
187: char *for_def[] = { "_assign _for\\v(cmdlevel) { _getargs,",
188: "define \\\\\\%1 \\%2,:top,if \\%5 \\\\\\%1 \\%3 goto bot,",
189: "\\%6,:inc,incr \\\\\\%1 \\%4,goto top,:bot,_putargs},",
190: "def break goto bot, def continue goto inc,",
191: "do _for\\v(cmdlevel) \\%1 \\%2 \\%3 \\%4 { \\%5 },_assign _for\\v(cmdlevel)",
192: ""};
193: #ifdef COMMENT
194: /*
195: This one didn't work right. When an interior loop finished executing,
196: the definition of the enclosing loop was restored, but the new definition
197: could be in a different location in memory, so its macro execution pointer
198: could (and usually was) pointing at garbage.
199: */
200: char *old_for_def[] = { "if def _floop ass \\%9 \\fdef(_floop),else def \\%9,",
201: "ass _floop { _getargs,",
202: "define \\\\\\%1 \\%2,:top,if \\%5 \\\\\\%1 \\%3 goto bot,",
203: "\\%6,:inc, incr \\\\\\%1 \\%4,goto top,:bot,_putargs,return},",
204: "def break goto bot, def continue goto inc,",
205: "do _floop \\%1 \\%2 \\%3 \\%4 { \\%5 },assign _floop \\fcont(\\%9)",
206: ""};
207: #endif /* COMMENT */
208:
209: /* WHILE macro */
210: char *whil_def[] = { "_assign _whi\\v(cmdlevel) {_getargs,",
211: ":wtest,\\%1,\\%2,goto wtest,:wbot,_putargs},",
212: "def break goto wbot, def continue goto wtest,",
213: "do _whi\\v(cmdlevel),_assign _whi\\v(cmdlevel)",
214: ""};
215: #ifdef COMMENT
216: /*
217: Same deal as FOR loop...
218: */
219: char *old_whil_def[] = { "if def _wloop asg \\%9 \\fdef(_wloop),",
220: "asg _wloop {_getargs,:wtest,\\%1,\\%2,goto wtest,:wbot,_putargs,return},",
221: "def break goto wbot, def continue goto wtest,",
222: "do _wloop,assign _wloop \\fcont(\\%9)",
223: ""};
224: #endif /* COMMENT */
225:
226: /* XIF macro */
227: char *xif_def[] = {
228: "_assign _if\\v(cmdlevel) {_getargs,\\%1,_putargs},",
229: "do _if\\v(cmdlevel),_assign _if\\v(cmdlevel)",
230: ""};
231: #ifdef COMMENT
232: /* Same deal */
233: char *old_xif_def[] = {
234: "asg \\%9 \\fdef(_ify),ass _ify {_getargs, \\%1, _putargs},",
235: "do _ify,ass _ify \\fcont(\\%9)",
236: ""};
237: #endif /* COMMENT */
238:
239: /* Variables declared here for use by other ckuus*.c modules */
240: /* Space is allocated here to save room in ckuusr.c */
241:
242: #ifdef DCMDBUF
243: struct cmdptr *cmdstk;
244: int *ifcmd, *count, *iftest;
245: #else
246: struct cmdptr cmdstk[CMDSTKL];
247: int ifcmd[CMDSTKL], count[CMDSTKL], iftest[CMDSTKL];
248: #endif /* DCMDBUF */
249:
250: char *m_arg[MACLEVEL][NARGS];
251: char *g_var[GVARS], *macp[MACLEVEL], *mrval[MACLEVEL];
252: int macargc[MACLEVEL];
253: char *macx[MACLEVEL];
254: extern char varnam[];
255:
256: char **a_ptr[27]; /* Array pointers, for arrays a-z */
257: int a_dim[27]; /* Dimensions for each array */
258:
259: char inpbuf[INPBUFSIZ] = { NUL }; /* Buffer for INPUT and REINPUT */
260: char inpbufa[2] = { NUL, NUL }; /* Null terminators for INPUT buffer */
261: char inchar[2] = { NUL, NUL }; /* Last character that was INPUT */
262: int incount = 0; /* INPUT character count */
263:
264: char lblbuf[50]; /* Buffer for labels */
265: #endif /* NOSPL */
266:
267: #ifdef DCMDBUF
268: char *line; /* Character buffer for anything */
269: #else
270: char line[LINBUFSIZ];
271: #endif /* DCMDBUF */
272:
273: #ifdef CK_CURSES
274: #ifndef TRMBUFL
275: #define TRMBUFL 1024
276: #endif /* TRMBUFL */
277: #ifdef DCMDBUF
278: char *trmbuf; /* Character buffer for termcap */
279: #else
280: char trmbuf[TRMBUFL];
281: #endif /* DCMDBUF */
282: #endif /* CK_CURSES */
283:
284: extern char pktfil[],
285: #ifdef DEBUG
286: debfil[],
287: #endif /* DEBUG */
288: #ifdef TLOG
289: trafil[],
290: #endif /* TLOG */
291: sesfil[],
292: cmdstr[];
293: #ifndef NOFRILLS
294: extern int rmailf, rprintf; /* REMOTE MAIL & PRINT items */
295: extern char optbuf[];
296: #endif /* NOFRILLS */
297:
298: char *homdir = ""; /* Pointer to home directory string */
299:
300: char tmpbuf[50], *tp; /* Temporary buffer */
301: char numbuf[20]; /* Buffer for numeric strings. */
302: char kermrc[100]; /* Name of initialization file */
303: int noinit = 0; /* Flag for skipping init file */
304:
305: #ifndef NOSPL
306: _PROTOTYP( static long expon, (long, long) );
307: _PROTOTYP( static long gcd, (long, long) );
308: _PROTOTYP( static long fact, (long) );
309: int /* Initialize macro data structures. */
310: macini() { /* Allocate mactab and preset the first element. */
311: if (!(mactab = (struct mtab *) malloc(sizeof(struct mtab) * MAC_MAX)))
312: return(-1);
313: mactab[0].kwd = NULL;
314: mactab[0].mval = NULL;
315: mactab[0].flgs = 0;
316: return(0);
317: }
318: #endif /* NOSPL */
319:
320: /* C M D I N I -- Initialize the interactive command parser */
321:
322: VOID
323: cmdini() {
324: int i, x, y, z;
325: #ifndef NOSPL
326: /*
327: On stack in case of recursion!
328: */
329: char vnambuf[VNAML]; /* Buffer for variable names */
330: #endif /* NOSPL */
331:
332: #ifndef MAC
333: #ifndef NOSETKEY /* Allocate & initialize the keymap */
334: if (!(keymap = (KEY *) malloc(sizeof(KEY)*KMSIZE)))
335: fatal("cmdini: no memory for keymap");
336: if (!(macrotab = (MACRO *) malloc(sizeof(MACRO)*KMSIZE)))
337: fatal("cmdini: no memory for macrotab");
338: for ( i = 0; i < KMSIZE; i++ ) {
339: keymap[i] = i;
340: macrotab[i] = NULL;
341: }
342: #ifdef OS2
343: keymapinit();
344: #endif /* OS2 */
345: #endif /* NOSETKEY */
346: #endif /* MAC */
347:
348: #ifdef DCMDBUF
349: if (cmsetup() < 0) fatal("Can't allocate command buffers!");
350: #ifndef NOSPL
351: if (!(cmdstk = (struct cmdptr *) malloc(sizeof(struct cmdptr)*CMDSTKL)))
352: fatal("cmdini: no memory for cmdstk");
353: if (!(ifcmd = (int *) malloc(sizeof(int)*CMDSTKL)))
354: fatal("cmdini: no memory for ifcmd");
355: if (!(count = (int *) malloc(sizeof(int)*CMDSTKL)))
356: fatal("cmdini: no memory for count");
357: if (!(iftest = (int *) malloc(sizeof(int)*CMDSTKL)))
358: fatal("cmdini: no memory for iftest");
359: #endif /* NOSPL */
360: #ifdef CK_CURSES
361: /*
362: Termcap buffer for fullscreen display, UNIX only. VMS does it another way.
363: The fullscreen display is not supported on AOS/VS or OS-9, etc, yet, and
364: the Mac has its own built-in fullscreen display.
365: */
366: #ifdef UNIX
367: if (!(trmbuf = malloc(TRMBUFL+1)))
368: fatal("cmdini: no memory for termcap buffer");
369: #endif /* UNIX */
370: #endif /* CK_CURSES */
371: if (!(line = malloc(LINBUFSIZ)))
372: fatal("cmdini: no memory for line");
373: #endif /* DCMDBUF */
374:
375: #ifndef NOSPL
376: if (macini() < 0) fatal("Can't allocate macro buffers!");
377: #endif /* NOSPL */
378:
379: #ifdef AMIGA
380: if (tlevel < 0)
381: concb(escape);
382: #endif /* AMIGA */
383:
384: #ifndef NOSPL
385: cmdlvl = 0; /* Start at command level 0 */
386: cmdstk[cmdlvl].src = CMD_KB;
387: cmdstk[cmdlvl].lvl = 0;
388: #endif /* NOSPL */
389:
390: tlevel = -1; /* Take file level = keyboard */
391: for (i = 0; i < MAXTAKE; i++) /* Initialize command file names */
392: tfnam[i] = NULL;
393:
394: #ifdef MAC
395: cmsetp("Mac-Kermit>"); /* Set default prompt */
396: #else
397: cmsetp("C-Kermit>"); /* Set default prompt */
398: #endif /* MAC */
399:
400: #ifndef NOSPL
401: initmac(); /* Initialize macro table */
402: /* Add one-line macros */
403: addmac("ibm-linemode",m_ibm); /* Add built-in macros. */
404: addmac("fatal",m_fat); /* FATAL macro. */
405: /* Add multiline macros */
406: addmmac("_forx",for_def); /* FOR macro. */
407: addmmac("_xif",xif_def); /* XIF macro. */
408: addmmac("_while",whil_def); /* WHILE macro. */
409: /* Fill in command line argument vector */
410: sprintf(vnambuf,"\\&@[%d]",xargs); /* Command line argument vector */
411: y = arraynam(vnambuf,&x,&z); /* goes in array \&@[] */
412: if (y > -1) {
413: dclarray((char)x,z); /* Declare the array */
414: for (i = 0; i < xargs; i++) { /* Fill it */
415: sprintf(vnambuf,"\\&@[%d]",i);
416: addmac(vnambuf,xargv[i]);
417: }
418: }
419: *vnambuf = NUL;
420: #endif /* NOSPL */
421:
422: /* Get our home directory now. This needed in lots of places. */
423:
424: homdir = zhome();
425:
426: /* If skipping init file ('-Y' on Kermit command line), return now. */
427:
428: if (noinit) return;
429:
430: #ifdef OS2
431: /*
432: The -y init file must be fully specified or in the current directory.
433: KERMRC is looked for via INIT, PATH and DPATH in that order. Finally, our
434: own executable file path is taken and the .EXE suffix is replaced by .INI
435: and this is tried as initialization file.
436: */
437: if (rcflag) {
438: strcpy(line, kermrc);
439: } else {
440: _searchenv(kermrc,"INIT",line);
441: if (line[0] == 0)
442: _searchenv(kermrc,"PATH",line);
443: if (line[0] == 0)
444: _searchenv(kermrc,"DPATH",line);
445: if (line[0] == 0) {
446: char *pgmptr = GetLoadPath();
447: if (pgmptr) {
448: lp = strrchr(pgmptr, '.');
449: strncpy(line, pgmptr, lp - pgmptr);
450: strcpy(line + (lp - pgmptr), ".ini");
451: }
452: }
453: }
454: if ((tfile[0] = fopen(line,"r")) != NULL) {
455: tlevel = 0;
456: if (tfnam[tlevel] = malloc(strlen(line)+1))
457: strcpy(tfnam[tlevel],line);
458: #ifndef NOSPL
459: cmdlvl++;
460: cmdstk[cmdlvl].src = CMD_TF;
461: cmdstk[cmdlvl].lvl = tlevel;
462: ifcmd[cmdlvl] = 0;
463: iftest[cmdlvl] = 0;
464: count[cmdlvl] = 0;
465: #endif /* NOSPL */
466: debug(F110,"init file",line,0);
467: } else {
468: debug(F100,"no init file","",0);
469: }
470: #else /* not OS2 */
471: lp = line;
472: lp[0] = '\0';
473: #ifdef GEMDOS
474: zkermini(line,rcflag, kermrc);
475: #else
476: #ifdef VMS
477: zkermini(line,LINBUFSIZ,kermrc);
478: #else /* not VMS */
479: if (rcflag) { /* If init file name from cmd line */
480: strcpy(lp,kermrc); /* use it */
481: } else { /* otherwise */
482: if (homdir) { /* look in home directory for it */
483: strcpy(lp,homdir);
484: if (lp[0] == '/') strcat(lp,"/");
485: }
486: strcat(lp,kermrc); /* and use the default name */
487: }
488: #endif /* VMS */
489: #endif /* GEMDOS */
490:
491: #ifdef AMIGA
492: reqoff(); /* disable requestors */
493: #endif /* AMIGA */
494:
495: debug(F110,"ini file is",line,0);
496: if ((tfile[0] = fopen(line,"r")) != NULL) {
497: tlevel = 0;
498: if (tfnam[tlevel] = malloc(strlen(line)+1))
499: strcpy(tfnam[tlevel],line);
500: #ifndef NOSPL
501: cmdlvl++;
502: ifcmd[cmdlvl] = 0;
503: iftest[cmdlvl] = 0;
504: count[cmdlvl] = 0;
505: debug(F101,"open ok","",cmdlvl);
506: cmdstk[cmdlvl].src = CMD_TF;
507: cmdstk[cmdlvl].lvl = tlevel;
508: #endif /* NOSPL */
509: debug(F110,"init file",line,0);
510: }
511: if (homdir && (tlevel < 0)) {
512: strcpy(lp,kermrc);
513: if ((tfile[0] = fopen(line,"r")) != NULL) {
514: tlevel = 0;
515: if (tfnam[tlevel] = malloc(strlen(line)+1))
516: strcpy(tfnam[tlevel],line);
517: #ifndef NOSPL
518: cmdlvl++;
519: cmdstk[cmdlvl].src = CMD_TF;
520: cmdstk[cmdlvl].lvl = tlevel;
521: ifcmd[cmdlvl] = 0;
522: iftest[cmdlvl] = 0;
523: count[cmdlvl] = 0;
524: #endif /* NOSPL */
525: }
526: }
527: #endif /* OS2 */
528: #ifdef AMIGA
529: reqpop(); /* Restore requestors */
530: #endif /* AMIGA */
531: }
532:
533: #ifndef NOSPL
534: /*
535: G E T N C M
536:
537: Get next command from current macro definition.
538:
539: Moved to a separate routine in edit 181 to allow multiline GET
540: to work when issued in a macro.
541:
542: Command is copied into string pointed to by argument s, max length n.
543: Returns:
544: 0 if a string was copied, -1 if there was no string to copy.
545: */
546: int
547: getncm(s,n) char *s; int n; {
548: int y, kp = 0, pp = 0;
549: char *s2;
550:
551: s2 = s;
552: *s = NUL; /* Copy next cmd to command buffer. */
553:
554: debug(F111,"getncm",s,n);
555:
556: for (y = 0;
557: macp[maclvl] && *macp[maclvl] && y < n;
558: y++, s++, macp[maclvl]++) {
559:
560: *s = *macp[maclvl]; /* Get next character */
561: debug(F000,"char","",*s);
562: /*
563: Allow braces around macro definition to prevent commas from being turned to
564: end-of-lines and also treat any commas within parens as text so that
565: multiple-argument functions won't cause the command to break prematurely.
566: */
567: if (*s == '{') kp++; /* Count braces */
568: if (*s == '}') kp--;
569: if (*s == '(') pp++; /* Count parentheses. */
570: if (*s == ')') pp--;
571: if (*s == ',' && pp <= 0 && kp <= 0) {
572: macp[maclvl]++;
573: debug(F110,"next cmd",s,0);
574: kp = pp = 0;
575: break;
576: }
577: } /* Reached end. */
578: if (*s2 == NUL) { /* If nothing was copied, */
579: debug(F100,"getncm eom","",0);
580: popclvl(); /* pop command level. */
581: return(-1);
582: } else { /* otherwise, tack CR onto end */
583: *s++ = CR;
584: *s = '\0';
585: if (mecho && pflag)
586: printf("%s\n",s2);
587: debug(F101,"getncm returns ptr to",s2,0);
588: }
589: return(0);
590: }
591: #endif /* NOSPL */
592:
593: /*
594: G E T N C T
595:
596: Get next command from current TAKE file.
597:
598: Moved to a separate routine in edit 181 to allow multiline GET
599: to work when issued in a macro.
600:
601: Command is copied into string pointed to by argument s, max length n.
602: Returns:
603: 0 if a string was copied,
604: -1 on EOF,
605: -2 on malloc failure
606: -3 if line not properly terminated
607: */
608: int
609: getnct(s,n) char *s; int n; {
610: int i, j;
611: char c, *s2, *lp, *lp2;
612:
613: s2 = s; /* Remember original pointer */
614:
615: debug(F101,"getnct","",n);
616: if (!(lp2 = (char *) malloc(n+1))) { /* Get a temporary buffer */
617: debug(F101,"getnct malloc failure","",0);
618: return(-2);
619: }
620: lp = lp2; /* Make a working pointer */
621: /* (lp2 must not change!) */
622:
623: while (1) { /* Loop to read lines from file */
624:
625: if (fgets(lp2,n,tfile[tlevel]) == NULL) { /* EOF */
626: free(lp2); /* Free temporary storage */
627: *s = NUL; /* Make destination be empty */
628: return(-1); /* Return failure code */
629: }
630: debug(F110,"Line from TAKE file",lp2,0); /* Got a line */
631: if (techo && pflag) /* If TAKE ECHO ON, */
632: printf("%s",lp2); /* echo it. */
633:
634: lp = lp2; /* Make a working pointer */
635:
636: /* Trim trailing whitespace */
637:
638: j = strlen(lp2) - 1; /* Position of line terminator */
639: if (j < 0) j = 0;
640: c = lp2[j]; /* Value of line terminator */
641: if (c < LF || c > CR) { /* It's not a terminator */
642: debug(F111,"getnct bad line",lp2,c);
643: if (feof(tfile[tlevel]) && j > 0 && j < n) {
644: printf("Warning: Last line of TAKE file lacks terminator\n");
645: c = lp2[++j] = '\n';
646: } else return(-3);
647: }
648: for (i = j - 1; i > -1; i--) /* Back up over spaces and tabs */
649: if (lp2[i] != SP && lp2[i] != HT && lp2[i] != NUL)
650: break;
651: lp2[i+1] = c; /* Move after last nonblank char */
652: lp2[i+2] = NUL; /* Terminate the string */
653: while (*s++ = *lp++) { /* Copy result to target buffer */
654: if (--n < 2) {
655: printf("?Command too long, maximum length: %d.\n",CMDBL);
656: free(lp2);
657: return(dostop());
658: }
659:
660: /* Check for trailing comment, " ;" or " #" */
661:
662: if ((s > s2 + 1) &&
663: (*(s-1) == ';' || *(s-1) == '#') &&
664: (*(s-2) == SP || *(s-2) == HT)) {
665: debug(F100,"Trailing comment","",0);
666: s -= 2; /* Got one, back up buffer pointer */
667: n += 2; /* and adjust free space count. */
668: while ((s >= s2) /* Trim whitespace again. */
669: && (*s == SP || *s == HT))
670: s--, n++;
671: s++; /* Point after last character */
672: *s++ = c; /* Put back line terminator */
673: *s++ = NUL; /* and string terminator */
674: n -= 3; /* Adjust free count */
675: debug(F110,"Comment trimmed & terminated",s2,0);
676: break;
677: }
678: }
679:
680: /* Check whether this line is continued */
681:
682: debug(F000,"Last char in line","",*(s-3));
683: if (*(s - 3) != CMDQ && *(s - 3) != '-') /* Line continued? */
684: break; /* No, done. */
685: s -= 3; /* No, back up pointer */
686: debug(F100,"Got continue char","",0); /* and continue */
687: }
688: untab(s2); /* Done, convert tabs to spaces */
689: free(lp2); /* Free temporary storage */
690: return(0); /* Return success */
691: }
692:
693: /* P A R S E R -- Top-level interactive command parser. */
694:
695: /*
696: Call with:
697: m = 0 for normal behavior: keep parsing and executing commands
698: until an action command is parsed, then return with a
699: Kermit start-state as the value of this function.
700: m = 1 to parse only one command, can also be used to call parser()
701: recursively.
702: m = 2 to read but do not execute one command.
703: In all cases, parser() returns:
704: 0 if no Kermit protocol action required
705: > 0 with a Kermit protocol start-state.
706: < 0 upon error.
707: */
708: int
709: parser(m) int m; {
710: int tfcode, xx, yy, zz; /* Workers */
711:
712: #ifndef NOSPL
713: int inlevel; /* Level we were called at */
714: #endif /* NOSPL */
715: char *cbp; /* Command buffer pointer */
716: #ifdef MAC
717: extern char *lfiles; /* Fake extern cast */
718: #endif /* MAC */
719:
720: #ifdef AMIGA
721: reqres(); /* restore AmigaDOS requestors */
722: #endif /* AMIGA */
723:
724: what = W_COMMAND; /* Now we're parsing commands. */
725: #ifndef NOSPL
726: if (cmdlvl == 0) /* If at top (interactive) level, */
727: #else
728: if (tlevel < 0)
729: #endif /* NOSPL */
730: concb((char)escape); /* put console in cbreak mode. */
731:
732: #ifndef NOSPL
733: ifcmd[0] = 0; /* Command-level related variables */
734: iftest[0] = 0; /* initialize variables at top level */
735: count[0] = 0; /* of stack... */
736: inlevel = cmdlvl; /* Current macro level */
737: debug(F101,"&parser entry maclvl","",maclvl);
738: debug(F101,"&parser entry inlevel","",inlevel);
739: debug(F101,"&parser entry tlevel","",tlevel);
740: debug(F101,"&parser entry cmdlvl","",cmdlvl);
741: debug(F101,"&parser entry m","",m);
742: #endif /* NOSPL */
743:
744: /*
745: sstate becomes nonzero when a command has been parsed that requires some
746: action from the protocol module. Any non-protocol actions, such as local
747: directory listing or terminal emulation, are invoked directly from below.
748: */
749: #ifdef COMMENT
750: if (local && pflag) /* Just returned from connect? */
751: printf("\n");
752: #endif /* COMMENT */
753: sstate = 0; /* Start with no start state. */
754: #ifndef NOFRILLS
755: rmailf = rprintf = 0; /* MAIL and PRINT modifiers for SEND */
756: *optbuf = NUL; /* MAIL and PRINT options */
757: #endif /* NOFRILLS */
758: while (sstate == 0) { /* Parse cmds until action requested */
759: debug(F100,"top of parse loop","",0);
760:
761: /* Take requested action if there was an error in the previous command */
762:
763: #ifndef MAC
764: conint(trap,stptrap); /* In case we were just fg'd */
765: bgchk(); /* Check background status */
766: #endif /* MAC */
767:
768: debug(F101,"tlevel","",tlevel);
769: #ifndef NOSPL /* In case we just reached top level */
770: debug(F101,"cmdlvl","",cmdlvl);
771: if (cmdlvl == 0) concb((char)escape);
772: #else
773: if (tlevel < 0) concb((char)escape);
774: #endif /* NOSPL */
775:
776: #ifndef NOSPL
777: if (success == 0) {
778: if (cmdstk[cmdlvl].src == CMD_TF && terror) {
779: printf("Command error: take file terminated.\n");
780: popclvl();
781: if (cmdlvl == 0) return(0);
782: }
783: if (cmdstk[cmdlvl].src == CMD_MD && merror) {
784: printf("Command error: macro terminated.\n");
785: popclvl();
786: if (m && (cmdlvl < inlevel))
787: return((int) sstate);
788: }
789: }
790:
791: nulcmd = (m == 2);
792: #else
793: if (success == 0 && tlevel > -1 && terror) {
794: printf("Command error: take file terminated.\n");
795: popclvl();
796: cmini(ckxech); /* Clear the cmd buffer. */
797: if (tlevel < 0) /* Just popped out of cmd files? */
798: return(0); /* End of init file or whatever. */
799: }
800: #endif /* NOSPL */
801:
802: #ifdef MAC
803: /* Check for TAKE initiated by menu. */
804: if ((tlevel == -1) && lfiles)
805: startlfile();
806: #endif /* MAC */
807:
808: /* If in TAKE file, check for EOF */
809: #ifndef NOSPL
810: #ifdef MAC
811: if
812: #else
813: while
814: #endif /* MAC */
815: ((cmdstk[cmdlvl].src == CMD_TF) /* If end of take file */
816: && (tlevel > -1)
817: && feof(tfile[tlevel])) {
818: popclvl(); /* pop command level */
819: cmini(ckxech); /* and clear the cmd buffer. */
820: if (cmdlvl == 0) /* Just popped out of all cmd files? */
821: return(0); /* End of init file or whatever. */
822: }
823: #ifdef MAC
824: miniparser(1);
825: if (sstate == 'a') { /* if cmd-. cancel */
826: debug(F100, "parser: cancel take due to sstate", "", sstate);
827: sstate = '\0';
828: dostop();
829: return(0); /* End of init file or whatever. */
830: }
831: #endif /* MAC */
832:
833: #else /* NOSPL */
834: if ((tlevel > -1) && feof(tfile[tlevel])) { /* If end of take */
835: popclvl(); /* Pop up one level. */
836: cmini(ckxech); /* and clear the cmd buffer. */
837: if (tlevel < 0) /* Just popped out of cmd files? */
838: return(0); /* End of init file or whatever. */
839: }
840: #endif /* NOSPL */
841:
842: #ifndef NOSPL
843: if (cmdstk[cmdlvl].src == CMD_MD) { /* Executing a macro? */
844: debug(F100,"parser macro","",0);
845: maclvl = cmdstk[cmdlvl].lvl; /* Get current level */
846: debug(F101,"parser maclvl","",maclvl);
847: cbp = cmdbuf; /* Copy next cmd to command buffer. */
848: *cbp = NUL;
849: if (*savbuf) { /* In case then-part of 'if' command */
850: strcpy(cbp,savbuf); /* was saved, restore it. */
851: *savbuf = '\0';
852: } else { /* Else get next cmd from macro def */
853: if (getncm(cbp,CMDBL) < 0) {
854: if (m && (cmdlvl < inlevel))
855: return((int) sstate);
856: else /* if (!m) */ continue;
857: }
858: }
859: debug(F110,"cmdbuf from macro",cmdbuf,0);
860:
861: } else if (cmdstk[cmdlvl].src == CMD_TF)
862: #else
863: if (tlevel > -1)
864: #endif /* NOSPL */
865: {
866: #ifndef NOSPL
867: if (*savbuf) { /* In case THEN-part of IF command */
868: strcpy(cmdbuf,savbuf); /* was saved, restore it. */
869: *savbuf = '\0';
870: } else
871: #endif /* NOSPL */
872:
873: /* Get next line from TAKE file */
874:
875: if ((tfcode = getnct(cmdbuf,CMDBL)) < 0) {
876: if (tfcode < -1) { /* Error */
877: printf("?Error in TAKE command file: %s\n",
878: (tfcode == -2) ? "Memory allocation failure" :
879: "Line too long or contains NUL characters"
880: );
881: popclvl();
882: }
883: continue; /* -1 means EOF */
884: }
885:
886: /* If interactive, get next command from user. */
887:
888: } else { /* User types it in. */
889: if (pflag) prompt(xxstring);
890: cmini(ckxech);
891: }
892:
893: /* Now know where next command is coming from. Parse and execute it. */
894:
895: repars = 1; /* 1 = command needs parsing */
896: displa = 0; /* Assume no file transfer display */
897:
898: while (repars) { /* Parse this cmd until entered. */
899: debug(F101,"parser top of while loop","",0);
900: cmres(); /* Reset buffer pointers. */
901: xx = cmkey2(cmdtab,ncmd,"Command","",toktab,xxstring);
902: debug(F101,"top-level cmkey2","",xx);
903: if (xx == -5) {
904: yy = chktok(toktab);
905: debug(F101,"top-level cmkey token","",yy);
906: ungword();
907: switch (yy) {
908: #ifndef NOPUSH
909: case '!': xx = XXSHE; break; /* Shell escape */
910: #endif /* NOPUSH */
911: case '#': xx = XXCOM; break; /* Comment */
912: case ';': xx = XXCOM; break; /* Comment */
913: #ifndef NOSPL
914: case ':': xx = XXLBL; break; /* GOTO label */
915: #endif /* NOSPL */
916: #ifndef NOPUSH
917: case '@': xx = XXSHE; break; /* Shell (DCL) escape */
918: #endif /* NOPUSH */
919: default:
920: printf("\n?Invalid - %s\n",cmdbuf);
921: xx = -2;
922: }
923: }
924:
925: #ifndef NOSPL
926: /* Special handling for IF..ELSE */
927:
928: if (ifcmd[cmdlvl]) /* Count stmts after IF */
929: ifcmd[cmdlvl]++;
930: if (ifcmd[cmdlvl] > 2 && xx != XXELS && xx != XXCOM)
931: ifcmd[cmdlvl] = 0;
932:
933: /* Execute the command and take action based on return code. */
934:
935: if (nulcmd) { /* Ignoring this command? */
936: xx = XXCOM; /* Make this command a comment. */
937: }
938: #endif /* NOSPL */
939:
940: zz = docmd(xx); /* Parse rest of command & execute. */
941: debug(F101,"docmd returns","",zz);
942: #ifdef MAC
943: if (tlevel > -1) {
944: if (sstate == 'a') { /* if cmd-. cancel */
945: debug(F110, "parser: cancel take, sstate:", "a", 0);
946: sstate = '\0';
947: dostop();
948: return(0); /* End of init file or whatever. */
949: }
950: }
951: #endif /* MAC */
952: switch (zz) {
953: case -4: /* EOF (e.g. on redirected stdin) */
954: doexit(GOOD_EXIT,xitsta); /* ...exit successfully */
955: case -1: /* Reparse needed */
956: repars = 1; /* Just set reparse flag and */
957: continue;
958: case -6: /* Invalid command given w/no args */
959: case -2: /* Invalid command given w/args */
960: #ifdef COMMENT
961: #ifndef NOSPL
962: /* This is going to be really ugly... */
963: yy = mlook(mactab,atmbuf,nmac); /* Look in macro table */
964: if (yy > -1) { /* If it's there */
965: if (zz == -2) { /* insert "do" */
966: char *mp;
967: mp = malloc((int)strlen(cmdbuf) + 5);
968: if (!mp) {
969: printf("?malloc error 1\n");
970: return(-2);
971: }
972: sprintf(mp,"do %s ",cmdbuf);
973: strcpy(cmdbuf,mp);
974: free(mp);
975: } else sprintf(cmdbuf,"do %s %c",atmbuf, CR);
976: if (ifcmd[cmdlvl] == 2) /* This one doesn't count! */
977: ifcmd[cmdlvl]--;
978: debug(F111,"stuff cmdbuf",cmdbuf,zz);
979: repars = 1; /* go for reparse */
980: continue;
981: } else {
982: char *p;
983: int n;
984: p = cmdbuf;
985: lp = line;
986: n = LINBUFSIZ;
987: if (cmflgs == 0) printf("\n");
988: if (xxstring(p,&lp,&n) > -1)
989: printf("?Invalid: %s\n",line);
990: else
991: printf("?Invalid: %s\n",cmdbuf);
992: } /* (fall thru...) */
993: #else
994: printf("?Invalid: %s\n",cmdbuf);
995: #endif /* NOSPL */
996: #else
997: printf("?Invalid: %s\n",cmdbuf);
998: #endif /* COMMENT */
999:
1000: case -9: /* Bad, error message already done */
1001: success = 0;
1002: debug(F110,"top-level cmkey failed",cmdbuf,0);
1003: if (pflag == 0) /* if background, terminate */
1004: fatal("Kermit command error in background execution");
1005: cmini(ckxech); /* (fall thru) */
1006:
1007: case -3: /* Empty command OK at top level */
1008: repars = 0; /* Don't need to reparse. */
1009: continue; /* Go back and get another command. */
1010:
1011: default: /* Command was successful. */
1012: #ifndef NOSPL
1013: debug(F101,"parser preparing to continue","",maclvl);
1014: #endif /* NOSPL */
1015: repars = 0; /* Don't need to reparse. */
1016: continue; /* Go back and get another command. */
1017: }
1018: }
1019: #ifndef NOSPL
1020: debug(F101,"parser breaks out of while loop","",maclvl);
1021: if (m && (cmdlvl < inlevel)) return((int) sstate);
1022: #endif /* NOSPL */
1023: }
1024:
1025: /* Got an action command, return start state. */
1026:
1027: #ifdef COMMENT
1028: /* This is done in ckcpro.w instead, no need to do it twice. */
1029: /* Interrupts off only if remote */
1030: if (!local) connoi();
1031: #endif /* COMMENT */
1032: return((int) sstate);
1033: }
1034:
1035: #ifndef NOSPL
1036: /* OUTPUT command */
1037:
1038: int /* This could easily become a macro */
1039: #ifdef CK_ANSIC
1040: xxout(char c)
1041: #else
1042: xxout(c) char c;
1043: #endif /* CK_ANSIC */
1044: /* xxout */ { /* Function to output a character. */
1045: debug(F101,"xxout","",c);
1046: if (local) /* If in local mode */
1047: return(ttoc(c)); /* then to the external line */
1048: else return(conoc(c)); /* otherwise to the console. */
1049: }
1050:
1051: /* Returns 0 on failure, 1 on success */
1052:
1053: int
1054: dooutput(s) char *s; {
1055: int x, y, quote;
1056:
1057: if (local) { /* Condition external line */
1058: y = ttvt(speed,flow);
1059: if (y < 0) return(0);
1060: }
1061: quote = 0; /* Initialize backslash (\) quote */
1062:
1063: #ifdef COMMENT
1064: /* This is done automatically in ttopen() now... */
1065: #ifdef TNCODE
1066: if (network && ttnproto == NP_TELNET) /* If telnet connection, */
1067: if (!tn_init++) tn_ini(); /* initialize it if necessary */
1068: #endif /* TNCODE */
1069: #endif /* COMMENT */
1070: while (x = *s++) { /* Loop through the string */
1071: y = 0; /* Error code, 0 = no error. */
1072: if (x == CMDQ) { /* Look for \b or \B in string */
1073: quote++; /* Got \ */
1074: continue; /* Get next character */
1075: } else if (quote) { /* This character is quoted */
1076: if (quote == 1 && (x == 'b' || x == 'B')) { /* If \b or \B */
1077: debug(F100,"OUTPUT BREAK","",0);
1078: ttsndb(); /* send BREAK signal */
1079: quote = 0; /* Turn off quote flag */
1080: continue; /* and not the b or B */
1081: #ifdef CK_LBRK
1082: } else if (quote == 1 && (x == 'l' || x == 'L')) { /* \l or \L */
1083: debug(F100,"OUTPUT Long BREAK","",0);
1084: ttsndlb(); /* send Long BREAK signal */
1085: quote = 0; /* Turn off quote flag */
1086: continue; /* and not the l or L */
1087: #endif /* CK_LBRK */
1088: } else { /* if \ not followed by b or B */
1089: y = xxout(dopar(CMDQ)); /* output the backslash. */
1090: quote = 0; /* Turn off quote flag */
1091: }
1092: } else quote = 0; /* Turn off quote flag */
1093: y = xxout(dopar((char)x)); /* Output this character */
1094: if (y < 0) {
1095: printf("output error.\n");
1096: return(0);
1097: }
1098: if (x == '\015') { /* User typed carriage return */
1099: if (tnlm /* If TERMINAL NEWLINE-MODE is ON */
1100: #ifdef TNCODE
1101: || (network && /* Or we have a network connection */
1102: ttnproto == NP_TELNET && /* using TELNET protocol */
1103: tn_nlm /* and TELNET NEWLINE-MODE is ON */
1104: )
1105: #endif /* TNCODE */
1106: )
1107: xxout(dopar('\012')); /* Send LF too (CR => CRLF) */
1108: }
1109: if (seslog && duplex)
1110: if (zchout(ZSFILE,(char)x) < 0) seslog = 0;
1111: }
1112: return(1);
1113: }
1114: #endif /* NOSPL */
1115:
1116:
1117: /* Display version herald and initial prompt */
1118:
1119: VOID
1120: herald() {
1121: int x = 0;
1122: if (bgset > 0 || (bgset != 0 && backgrd != 0)) x = 1;
1123: debug(F101,"herald","",backgrd);
1124: if (x == 0)
1125: #ifdef datageneral
1126: printf("%s,%s\nType ? or HELP for help\n",versio,ckxsys);
1127: #else
1128: printf("%s,%s\n\rType ? or HELP for help\n",versio,ckxsys);
1129: #endif /* datageneral */
1130: }
1131: #ifndef NOSPL
1132: /* M L O O K -- Lookup the macro name in the macro table */
1133:
1134: /*
1135: Call this way: v = mlook(table,word,n);
1136:
1137: table - a 'struct mtab' table.
1138: word - the target string to look up in the table.
1139: n - the number of elements in the table.
1140:
1141: The keyword table must be arranged in ascending alphabetical order, and
1142: all letters must be lowercase.
1143:
1144: Returns the table index, 0 or greater, if the name was found, or:
1145:
1146: -3 if nothing to look up (target was null),
1147: -2 if ambiguous,
1148: -1 if not found.
1149:
1150: A match is successful if the target matches a keyword exactly, or if
1151: the target is a prefix of exactly one keyword. It is ambiguous if the
1152: target matches two or more keywords from the table.
1153: */
1154: int
1155: mlook(table,cmd,n) struct mtab table[]; char *cmd; int n; {
1156:
1157: int i, v, cmdlen;
1158:
1159: /* Lowercase & get length of target, if it's null return code -3. */
1160:
1161: if ((((cmdlen = lower(cmd))) == 0) || (n < 1)) return(-3);
1162:
1163: /* Not null, look it up */
1164:
1165: for (i = 0; i < n-1; i++) {
1166: if (!strcmp(table[i].kwd,cmd) ||
1167: ((v = !strncmp(table[i].kwd,cmd,cmdlen)) &&
1168: strncmp(table[i+1].kwd,cmd,cmdlen))) {
1169: return(i);
1170: }
1171: if (v) return(-2);
1172: }
1173:
1174: /* Last (or only) element */
1175:
1176: if (!strncmp(table[n-1].kwd,cmd,cmdlen)) {
1177: return(n-1);
1178: } else return(-1);
1179: }
1180:
1181: /* mxlook is like mlook, but an exact full-length match is required */
1182:
1183: int
1184: mxlook(table,cmd,n) char *cmd; struct mtab table[]; int n; {
1185: int i, cmdlen;
1186: if ((((cmdlen = lower(cmd))) == 0) || (n < 1)) return(-3);
1187: for (i = 0; i < n; i++)
1188: if (((int)strlen(table[i].kwd) == cmdlen) &&
1189: (!strncmp(table[i].kwd,cmd,cmdlen))) return(i);
1190: return(-1);
1191: }
1192:
1193: /*
1194: This routine is for the benefit of those compilers that can't handle
1195: long string constants or continued lines within them. Long predefined
1196: macros like FOR, WHILE, and XIF have their contents broken up into
1197: arrays of string pointers. This routine concatenates them back into a
1198: single string again, and then calls the real addmac() routine to enter
1199: the definition into the macro table.
1200: */
1201: int
1202: addmmac(nam,s) char *nam, *s[]; { /* Add a multiline macro definition */
1203: int i, x, y; char *p;
1204: x = 0; /* Length counter */
1205: for (i = 0; (y = (int)strlen(s[i])) > 0; i++) { /* Add up total length */
1206: debug(F111,"addmmac line",s[i],y);
1207: x += y;
1208: }
1209: debug(F101,"addmmac lines","",i);
1210: debug(F101,"addmmac loop exit","",y);
1211: debug(F111,"addmmac length",nam,x);
1212: if (x < 0) return(-1);
1213:
1214: p = malloc(x+1); /* Allocate space for all of it. */
1215: if (!p) {
1216: printf("?addmmac malloc error: %s\n",nam);
1217: debug(F110,"addmmac malloc error",nam,0);
1218: return(-1);
1219: }
1220: *p = '\0'; /* Start off with null string. */
1221: for (i = 0; *s[i]; i++) /* Concatenate them all together. */
1222: strcat(p,s[i]);
1223: y = (int)strlen(p); /* Final precaution. */
1224: debug(F111,"addmmac constructed string",p,y);
1225: if (y == x) {
1226: y = addmac(nam,p); /* Add result to the macro table. */
1227: } else {
1228: debug(F100,"addmmac length mismatch","",0);
1229: printf("\n!addmmac internal error!\n");
1230: y = -1;
1231: }
1232: free(p); /* Free the temporary copy. */
1233: return(y);
1234: }
1235:
1236: /* Here is the real addmac routine. */
1237:
1238: int
1239: addmac(nam,def) char *nam, *def; { /* Add a macro to the macro table */
1240: int i, x, y, z, namlen, deflen;
1241: char *p, c;
1242:
1243: if (!nam) return(-1);
1244: namlen = (int)strlen(nam); /* Get argument lengths */
1245: debug(F111,"addmac nam",nam,namlen);
1246: if (!def) { /* Watch out for null pointer */
1247: deflen = 0;
1248: debug(F111,"addmac def","(null pointer)",deflen);
1249: } else {
1250: deflen = (int)strlen(def);
1251: debug(F111,"addmac def",def,deflen);
1252: }
1253: if (deflen < 0) return(-1); /* strlen() failure, fail. */
1254: if (namlen < 1) return(-1); /* No name given, fail. */
1255:
1256: if (*nam == CMDQ) nam++; /* Backslash quote? */
1257: if (*nam == '%') { /* Yes, if it's a variable name, */
1258: delmac(nam); /* Delete any old value. */
1259: if (!(c = *(nam + 1))) return(-1); /* Variable name letter or digit */
1260: if (deflen < 1) { /* Null definition */
1261: p = NULL; /* Better not malloc or strcpy! */
1262: } else { /* A substantial definition */
1263: p = malloc(deflen + 1); /* Allocate space for it */
1264: if (!p) {
1265: printf("?addmac malloc error 2\n");
1266: return(-1);
1267: } else strcpy(p,def); /* Copy definition into new space */
1268: }
1269:
1270: /* Now p points to the definition, or is a null pointer */
1271:
1272: if (p)
1273: debug(F110,"addmac p",p,0);
1274: else
1275: debug(F110,"addmac p","(null pointer)",0);
1276:
1277: if (c >= '0' && c <= '9') { /* Digit variable */
1278: if (maclvl < 0) { /* Are we calling or in a macro? */
1279: g_var[c] = p; /* No, it's a global "top level" one */
1280: debug(F101,"addmac numeric global maclvl","",maclvl);
1281: } else { /* Yes, it's a macro argument */
1282: m_arg[maclvl][c - '0'] = p;
1283: debug(F101,"addmac macro arg maclvl","",maclvl);
1284: }
1285: } else { /* It's a global variable */
1286: if (c < 33 || c > GVARS) return(-1);
1287: if (isupper(c)) c = tolower(c);
1288: g_var[c] = p; /* Put pointer in global-var table */
1289: debug(F100,"addmac global","",0);
1290: }
1291: return(0);
1292: } else if (*nam == '&') { /* An array reference? */
1293: char **q;
1294: if ((y = arraynam(nam,&x,&z)) < 0) /* If syntax is bad */
1295: return(-1); /* return -1. */
1296: if (chkarray(x,z) < 0) /* If array not declared or */
1297: return(-2); /* subscript out of range, ret -2 */
1298: delmac(nam); /* Delete any current definition. */
1299: x -= 96; /* Convert name letter to index. */
1300: if ((q = a_ptr[x]) == NULL) /* If array not declared, */
1301: return(-3); /* return -3. */
1302: if (deflen > 0) {
1303: if ((p = malloc(deflen+1)) == NULL) { /* Allocate space */
1304: printf("addmac macro error 7: %s\n",nam);
1305: return(-4); /* for new def, return -4 on fail. */
1306: }
1307: strcpy(p,def); /* Copy definition into new space. */
1308: } else p = NULL;
1309: q[z] = p; /* Store pointer to it. */
1310: return(0); /* Done. */
1311: } else debug(F110,"addmac macro def",nam,0);
1312:
1313: /* Not a macro argument or a variable, so it's a macro definition */
1314:
1315: lower(nam); /* Lowercase the name */
1316: if (mxlook(mactab,nam,nmac) > -1) /* Look up, requiring exact match */
1317: delmac(nam); /* if it's there, delete it. */
1318: debug(F111,"addmac table size",nam,nmac);
1319: for (y = 0; /* Find the alphabetical slot */
1320: y < MAC_MAX && mactab[y].kwd != NULL && strcmp(nam,mactab[y].kwd) > 0;
1321: y++) ;
1322: if (y == MAC_MAX) { /* No more room. */
1323: debug(F101,"addmac table overflow","",y);
1324: return(-1);
1325: } else debug(F111,"addmac position",nam,y);
1326: if (mactab[y].kwd != NULL) { /* Must insert */
1327: for (i = nmac; i > y; i--) { /* Move the rest down one slot */
1328: mactab[i].kwd = mactab[i-1].kwd;
1329: mactab[i].mval = mactab[i-1].mval;
1330: mactab[i].flgs = mactab[i-1].flgs;
1331: }
1332: }
1333: p = malloc(namlen + 1); /* Allocate space for name */
1334: if (!p) {
1335: printf("?addmac malloc error 3: %s\n",nam);
1336: return(-1);
1337: }
1338: strcpy(p,nam); /* Copy name into new space */
1339: mactab[y].kwd = p; /* Add pointer to table */
1340:
1341: if (deflen > 0) { /* Same deal for definition */
1342: p = malloc(deflen + 1); /* but watch out for null pointer */
1343: if (p == NULL) {
1344: printf("?addmac malloc error 5: %s\n", nam);
1345: free(mactab[y].kwd);
1346: mactab[y].kwd = NULL;
1347: return(-1);
1348: } else strcpy(p,def); /* Copy the definition */
1349: } else p = NULL;
1350: mactab[y].mval = p;
1351: mactab[y].flgs = 0;
1352: nmac++; /* Count this macro */
1353: return(y);
1354: }
1355:
1356: int
1357: delmac(nam) char *nam; { /* Delete the named macro */
1358: int i, x, z;
1359: char *p, c;
1360:
1361: if (!nam) return(0); /* Watch out for null pointer */
1362: debug(F110,"delmac nam",nam,0);
1363: if (*nam == CMDQ) nam++;
1364: if (*nam == '%') { /* If it's a variable name */
1365: if (!(c = *(nam+1))) return(0); /* Get variable name letter or digit */
1366: p = (char *)0; /* Initialize value pointer */
1367: if (maclvl > -1 && c >= '0' && c <= '9') { /* Digit? */
1368: p = m_arg[maclvl][c - '0']; /* Get pointer from macro-arg table */
1369: m_arg[maclvl][c - '0'] = NULL; /* Zero the table pointer */
1370: } else { /* It's a global variable */
1371: if (c < 33 || c > GVARS) return(0);
1372: p = g_var[c]; /* Get pointer from global-var table */
1373: g_var[c] = NULL; /* Zero the table entry */
1374: }
1375: if (p) {
1376: debug(F110,"delmac def",p,0);
1377: free(p); /* Free the storage */
1378: } else debug(F110,"delmac def","(null pointer)",0);
1379: return(0);
1380: }
1381:
1382: if (*nam == '&') { /* An array reference? */
1383: char **q;
1384: if (arraynam(nam,&x,&z) < 0) /* If syntax is bad */
1385: return(-1); /* return -1. */
1386: x -= 96; /* Convert name to number. */
1387: if ((q = a_ptr[x]) == NULL) /* If array not declared, */
1388: return(-2); /* return -2. */
1389: if (z > a_dim[x]) /* If subscript out of range, */
1390: return(-3); /* return -3. */
1391: if (q[z]) { /* If there is an old value, */
1392: debug(F110,"delman def",q[z],0);
1393: free(q[z]); /* delete it. */
1394: q[z] = NULL;
1395: } else debug(F110,"delmac def","(null pointer)",0);
1396: }
1397:
1398: /* Not a variable or an array, so it must be a macro. */
1399:
1400: if ((x = mlook(mactab,nam,nmac)) < 0) { /* Look it up */
1401: debug(F111,"delmac mlook",nam,x);
1402: return(x);
1403: }
1404: if (mactab[x].kwd) /* Free the storage for the name */
1405: free(mactab[x].kwd);
1406: if (mactab[x].mval) /* and for the definition */
1407: free(mactab[x].mval);
1408:
1409: for (i = x; i < nmac; i++) { /* Now move up the others. */
1410: mactab[i].kwd = mactab[i+1].kwd;
1411: mactab[i].mval = mactab[i+1].mval;
1412: mactab[i].flgs = mactab[i+1].flgs;
1413: }
1414: nmac--; /* One less macro */
1415: mactab[nmac].kwd = NULL; /* Delete last item from table */
1416: mactab[nmac].mval = NULL;
1417: mactab[nmac].flgs = 0;
1418: return(0);
1419: }
1420:
1421: VOID
1422: initmac() { /* Init macro & variable tables */
1423: int i, j;
1424:
1425: nmac = 0; /* No macros */
1426: for (i = 0; i < MAC_MAX; i++) { /* Initialize the macro table */
1427: mactab[i].kwd = NULL;
1428: mactab[i].mval = NULL;
1429: mactab[i].flgs = 0;
1430: }
1431: for (i = 0; i < MACLEVEL; i++) { /* Init the macro argument tables */
1432: mrval[i] = NULL;
1433: for (j = 0; j < 10; j++) {
1434: m_arg[i][j] = NULL;
1435: }
1436: }
1437: for (i = 0; i < GVARS; i++) { /* And the global variables table */
1438: g_var[i] = NULL;
1439: }
1440: for (i = 0; i < 26; i++) { /* And the table of arrays */
1441: a_ptr[i] = (char **) NULL; /* Null pointer for each */
1442: a_dim[i] = 0; /* and a dimension of zero */
1443: }
1444: }
1445:
1446: int
1447: popclvl() { /* Pop command level, return cmdlvl */
1448: if (cmdlvl < 1) { /* If we're already at top level */
1449: cmdlvl = 0; /* just make sure all the */
1450: tlevel = -1; /* stack pointers are set right */
1451: maclvl = -1; /* and return */
1452: } else if (cmdstk[cmdlvl].src == CMD_TF) { /* Reading from TAKE file? */
1453: if (tlevel > -1) { /* Yes, */
1454: if (tfnam[tlevel]) {
1455: free(tfnam[tlevel]);
1456: tfnam[tlevel] = NULL;
1457: }
1458: fclose(tfile[tlevel--]); /* close it and pop take level */
1459: cmdlvl--; /* pop command level */
1460: } else tlevel = -1;
1461: } else if (cmdstk[cmdlvl].src == CMD_MD) { /* In a macro? */
1462: if (maclvl > -1) { /* Yes, */
1463: debug(F111,"popclvl before",macx[maclvl],maclvl);
1464: macp[maclvl] = ""; /* set macro pointer to null string */
1465: *cmdbuf = '\0'; /* clear the command buffer */
1466: if (mrval[maclvl+1]) { /* Free any deeper return values. */
1467: free(mrval[maclvl+1]);
1468: mrval[maclvl+1] = NULL;
1469: }
1470: maclvl--; /* pop macro level */
1471: cmdlvl--; /* and command level */
1472: debug(F111,"popclvl after ",
1473: macx[maclvl] ? macx[maclvl] : "",maclvl);
1474: } else maclvl = -1;
1475: }
1476: #ifndef MAC
1477: if (cmdlvl < 1) { /* If back at top level */
1478: conint(trap,stptrap); /* Fix interrupts */
1479: bgchk(); /* Check background status */
1480: concb((char)escape); /* Go into cbreak mode */
1481: }
1482: #endif /* MAC */
1483: return(cmdlvl < 1 ? 0 : cmdlvl); /* Return command level */
1484: }
1485: #else /* No script programming language */
1486: int popclvl() { /* Just close current take file. */
1487: if (tlevel > -1) { /* if any... */
1488: if (tfnam[tlevel]) {
1489: free(tfnam[tlevel]);
1490: tfnam[tlevel] = NULL;
1491: }
1492: fclose(tfile[tlevel--]);
1493: }
1494: if (tlevel == -1) { /* And if back at top level */
1495: conint(trap,stptrap); /* check and set interrupts */
1496: bgchk(); /* and background status */
1497: concb((char)escape); /* and go back into cbreak mode. */
1498: }
1499: return(tlevel + 1);
1500: }
1501: #endif /* NOSPL */
1502:
1503: /* STOP - get back to C-Kermit prompt, no matter where from. */
1504:
1505: int
1506: dostop() {
1507: while ( popclvl() ) ; /* Pop all macros & take files */
1508: #ifndef NOSPL
1509: while (cmpop() > -1) ; /* And all recursive cmd pkg invocations */
1510: #endif /* NOSPL */
1511: cmini(ckxech); /* Clear the command buffer. */
1512: return(0);
1513: }
1514:
1515:
1516: /* Close the given log */
1517:
1518: int
1519: doclslog(x) int x; {
1520: int y;
1521: switch (x) {
1522: #ifdef DEBUG
1523: case LOGD:
1524: if (deblog == 0) {
1525: printf("?Debugging log wasn't open\n");
1526: return(0);
1527: }
1528: *debfil = '\0';
1529: deblog = 0;
1530: return(zclose(ZDFILE));
1531: #endif /* DEBUG */
1532:
1533: case LOGP:
1534: if (pktlog == 0) {
1535: printf("?Packet log wasn't open\n");
1536: return(0);
1537: }
1538: *pktfil = '\0';
1539: pktlog = 0;
1540: return(zclose(ZPFILE));
1541:
1542: case LOGS:
1543: if (seslog == 0) {
1544: printf("?Session log wasn't open\n");
1545: return(0);
1546: }
1547: *sesfil = '\0';
1548: seslog = 0;
1549: return(zclose(ZSFILE));
1550:
1551: #ifdef TLOG
1552: case LOGT:
1553: if (tralog == 0) {
1554: printf("?Transaction log wasn't open\n");
1555: return(0);
1556: }
1557: *trafil = '\0';
1558: tralog = 0;
1559: return(zclose(ZTFILE));
1560: #endif /* TLOG */
1561:
1562: #ifndef NOSPL
1563: case LOGW: /* WRITE file */
1564: case LOGR: /* READ file */
1565: y = (x == LOGR) ? ZRFILE : ZWFILE;
1566: if (chkfn(y) < 1) /* If no file to close */
1567: return(1); /* succeed silently. */
1568: return(zclose(y)); /* Otherwise, close the file. */
1569: #endif /* NOSPL */
1570:
1571: default:
1572: printf("\n?Unexpected log designator - %ld\n", x);
1573: return(0);
1574: }
1575: }
1576:
1577: #ifndef NOSERVER
1578: #ifndef NOFRILLS
1579: static char *nm[] = { "disabled", "enabled" };
1580: #endif /* NOFRILLS */
1581: #endif /* NOSERVER */
1582:
1583: static int slc = 0; /* Screen line count */
1584:
1585: #ifndef NOSHOW
1586: #ifndef NOFRILLS
1587: #define xxdiff(v,sys) strncmp(v,sys,strlen(sys))
1588: VOID
1589: shover() {
1590: printf("\nVersions:\n %s\n Numeric: %ld",versio,vernum);
1591: if (verwho) printf("-%d",verwho);
1592: printf(xxdiff(ckxv,ckxsys) ? "\n %s for%s\n" : "\n %s\n",ckxv,ckxsys);
1593: printf(xxdiff(ckzv,ckzsys) ? " %s for%s\n" : " %s\n",ckzv,ckzsys);
1594: printf(" %s\n",protv);
1595: printf(" %s\n",fnsv);
1596: printf(" %s\n %s\n",cmdv,userv);
1597: #ifndef NOCSETS
1598: printf(" %s\n",xlav);
1599: #endif /* NOCSETS */
1600: #ifndef MAC
1601: printf(" %s\n",connv);
1602: #endif /* MAC */
1603: #ifndef NODIAL
1604: printf(" %s\n",dialv);
1605: #endif /* NODIAL */
1606: #ifndef NOSCRIPT
1607: printf(" %s\n",loginv);
1608: #endif /* NOSCRIPT */
1609: #ifdef NETCONN
1610: printf(" %s\n",cknetv);
1611: #endif /* NETCONN */
1612: printf("\n");
1613: }
1614:
1615: VOID
1616: shofea() {
1617: #ifdef OS2
1618: #ifdef M_I286
1619: printf("\nOS/2 16-bit.\n");
1620: #else
1621: printf("\nOS/2 32-bit.\n");
1622: #endif /* M_I286 */
1623: #endif /* OS2 */
1624: printf("\nSpecial features:\n");
1625: #ifdef NETCONN
1626: printf(" Network support (type SHOW NET for further info)\n");
1627: #endif /* NETCONN */
1628: #ifndef NOCSETS
1629: printf(" Latin-1 (West European) character-set translation\n");
1630: #ifdef LATIN2
1631: printf(" Latin-2 (East European) character-set translation\n");
1632: #endif /* LATIN2 */
1633: #ifdef CYRILLIC
1634: printf(" Cyrillic (Russian, Ukrainian, etc) character-set translation\n");
1635: #endif /* CYRILLIC */
1636: #ifdef KANJI
1637: printf(" Kanji (Japanese) character-set translation\n");
1638: #endif /* KANJI */
1639: #endif /* NOCSETS */
1640:
1641: #ifdef CK_CURSES
1642: printf(" Fullscreen file transfer display\n");
1643: #endif /* CK_CURSES */
1644:
1645: printf("\nFeatures not included:\n");
1646: #ifndef CK_CURSES
1647: #ifndef MAC
1648: printf(" No fullscreen file transfer display\n");
1649: #endif /* MAC */
1650: #endif /* CK_CURSES */
1651: #ifdef NOSERVER
1652: printf(" No server mode\n");
1653: #endif /* NOSERVER */
1654: #ifdef NODEBUG
1655: printf(" No debugging\n");
1656: #endif /* NODEBUG */
1657: #ifdef NOTLOG
1658: printf(" No transaction log\n");
1659: #endif /* NOTLOG */
1660: #ifdef NOHELP
1661: printf(" No built-in help\n");
1662: #endif /* NOHELP */
1663: #ifndef NETCONN
1664: printf(" No network support\n");
1665: #endif /* NETCONN */
1666: #ifdef NOMSEND
1667: printf(" No MSEND command\n");
1668: #endif /* NOMSEND */
1669: #ifdef NODIAL
1670: printf(" No DIAL command\n");
1671: #else
1672: #ifdef MINIDIAL
1673: printf(" DIAL command for modems other than Hayes, CCITT, and Unknown\n");
1674: #endif /* MINIDIAL */
1675: #endif /* NODIAL */
1676: #ifdef NOXMIT
1677: printf(" No TRANSMIT command\n");
1678: #endif /* NOXMIT */
1679: #ifdef NOSCRIPT
1680: printf(" No SCRIPT command\n");
1681: #endif /* NOSCRIPT */
1682: #ifdef NOSPL
1683: printf(" No script programming features\n");
1684: #endif /* NOSPL */
1685: #ifdef NOCSETS
1686: printf(" No character-set translation\n");
1687: #else
1688: #ifndef LATIN2
1689: printf(" No Latin-2 character-set translation\n");
1690: #endif /* LATIN2 */
1691: #ifdef NOCYRIL
1692: printf(" No Cyrillic character-set translation\n");
1693: #endif /* NOCYRIL */
1694: #ifndef KANJI
1695: printf(" No Kanji character-set translation\n");
1696: #endif /* KANJI */
1697: #endif /* NOCSETS */
1698: #ifdef NOCMDL
1699: printf(" No command-line arguments\n");
1700: #endif /* NOCMDL */
1701: #ifdef NOFRILLS
1702: printf(" No frills\n");
1703: #endif /* NOFRILLS */
1704: #ifdef NOPUSH
1705: printf(" No escape to system\n");
1706: #endif /* NOPUSH */
1707: #ifdef NOJC
1708: #ifdef UNIX
1709: printf(" No UNIX job control\n");
1710: #endif /* UNIX */
1711: #endif /* NOJC */
1712: #ifdef NOSETKEY
1713: printf(" No SET KEY command\n");
1714: #endif /* NOSETKEY */
1715: #ifdef NOESCSEQ
1716: printf(" No ANSI escape sequence recognition\n");
1717: #endif /* NOESCSEQ */
1718: #ifndef PARSENSE
1719: printf(" No automatic parity detection\n");
1720: #endif /* PARSENSE */
1721: /*
1722: Print all of Kermit's compile-time options, as well as C preprocessor
1723: predefined symbols that might affect us...
1724: */
1725: printf("\nCompiler options:\n");
1726: #ifdef DEBUG
1727: #ifdef IFDEBUG
1728: prtopt(" IFDEBUG");
1729: #else
1730: prtopt(" DEBUG");
1731: #endif /* IFDEBUG */
1732: #endif /* DEBUG */
1733: #ifdef TLOG
1734: prtopt(" TLOG");
1735: #endif /* TLOG */
1736: #ifdef NODIAL
1737: prtopt(" NODIAL");
1738: #endif /* NODIAL */
1739: #ifdef MINIDIAL
1740: prtopt(" MINIDIAL");
1741: #endif /* MINIDIAL */
1742: #ifdef DYNAMIC
1743: prtopt(" DYNAMIC");
1744: #endif /* IFDEBUG */
1745: #ifndef NOSPL
1746: sprintf(line," CMDDEP=%d",CMDDEP);
1747: prtopt(line);
1748: #endif /* NOSPL */
1749: #ifdef UNIX
1750: prtopt(" UNIX");
1751: #endif /* UNIX */
1752: #ifdef VMS
1753: prtopt(" VMS");
1754: #endif /* VMS */
1755: #ifdef vms
1756: prtopt(" vms");
1757: #endif /* vms */
1758: #ifdef VMSSHARE
1759: prtopt(" VMSSHARE");
1760: #endif /* VMSSHARE */
1761: #ifdef datageneral
1762: prtopt(" datageneral");
1763: #endif /* datageneral */
1764: #ifdef apollo
1765: prtopt(" apollo");
1766: #endif /* apollo */
1767: #ifdef aegis
1768: prtopt(" aegis");
1769: #endif /* aegis */
1770: #ifdef A986
1771: prtopt(" A986");
1772: #endif /* A986 */
1773: #ifdef AMIGA
1774: prtopt(" AMIGA");
1775: #endif /* AMIGA */
1776: #ifdef CONVEX9
1777: prtopt(" CONVEX9");
1778: #endif /* CONVEX9 */
1779: #ifdef MAC
1780: prtopt(" MAC");
1781: #endif /* MAC */
1782: #ifdef AUX
1783: prtopt(" AUX");
1784: #endif /* AUX */
1785: #ifdef OS2
1786: prtopt(" OS2");
1787: #endif /* OS2 */
1788: #ifdef OS9
1789: prtopt(" OS9");
1790: #endif /* OS9 */
1791: #ifdef MSDOS
1792: prtopt(" MSDOS");
1793: #endif /* MSDOS */
1794: #ifdef DIRENT
1795: prtopt(" DIRENT");
1796: #endif /* DIRENT */
1797: #ifdef SDIRENT
1798: prtopt(" SDIRENT");
1799: #endif /* SDIRENT */
1800: #ifdef NDIR
1801: prtopt(" NDIR");
1802: #endif /* NDIR */
1803: #ifdef XNDIR
1804: prtopt(" XNDIR");
1805: #endif /* XNDIR */
1806: #ifdef MATCHDOT
1807: prtopt(" MATCHDOT");
1808: #endif /* MATCHDOT */
1809: #ifdef SAVEDUID
1810: prtopt(" SAVEDUID");
1811: #endif /* SAVEDUID */
1812: #ifdef NOCCTRAP
1813: prtopt(" NOCCTRAP");
1814: #endif /* NOCCTRAP */
1815: #ifdef SUNX25
1816: prtopt(" SUNX25");
1817: #endif /* SUNX25 */
1818: #ifdef DECNET
1819: prtopt(" DECNET");
1820: #endif /* DECNET */
1821: #ifdef ATT7300
1822: prtopt(" ATT7300");
1823: #endif /* ATT7300 */
1824: #ifdef ATT6300
1825: prtopt(" ATT6300");
1826: #endif /* ATT6300 */
1827: #ifdef HDBUUCP
1828: prtopt(" HDBUUCP");
1829: #endif /* HDBUUCP */
1830: #ifdef NOUUCP
1831: prtopt(" NOUUCP");
1832: #endif /* NOUUCP */
1833: #ifdef LONGFN
1834: prtopt(" LONGFN");
1835: #endif /* LONGFN */
1836: #ifdef RDCHK
1837: prtopt(" RDCHK");
1838: #endif /* RDCHK */
1839: #ifdef NAP
1840: prtopt(" NAP");
1841: #endif /* NAP */
1842: #ifdef NAPHACK
1843: prtopt(" NAPHACK");
1844: #endif /* NAPHACK */
1845: #ifdef NOIEXTEN
1846: prtopt(" NOIEXTEN");
1847: #endif /* NOIEXTEN */
1848: #ifdef EXCELAN
1849: prtopt(" EXCELAN");
1850: #endif /* EXCELAN */
1851: #ifdef PARAMH
1852: prtopt(" PARAMH");
1853: #endif /* PARAMH */
1854: #ifdef INTERLAN
1855: prtopt(" INTERLAN");
1856: #endif /* INTERLAN */
1857: #ifdef NOFILEH
1858: prtopt(" NOFILEH");
1859: #endif /* NOFILEH */
1860: #ifdef NOSYSIOCTLH
1861: prtopt(" NOSYSIOCTLH");
1862: #endif /* NOSYSIOCTLH */
1863: #ifdef DCLPOPEN
1864: prtopt(" DCLPOPEN");
1865: #endif /* DCLPOPEN */
1866: #ifdef NOSETBUF
1867: prtopt(" NOSETBUF");
1868: #endif /* NOSETBUF */
1869: #ifdef NOFDZERO
1870: prtopt(" NOFDZERO");
1871: #endif /* NOFDZERO */
1872: #ifdef NOPOPEN
1873: prtopt(" NOPOPEN");
1874: #endif /* NOPOPEN */
1875: #ifdef NOPARTIAL
1876: prtopt(" NOPARTIAL");
1877: #endif /* NOPARTIAL */
1878: #ifdef NOSETREU
1879: prtopt(" NOSETREU");
1880: #endif /* NOSETREU */
1881: #ifdef _POSIX_SOURCE
1882: prtopt(" _POSIX_SOURCE");
1883: #endif /* _POSIX_SOURCE */
1884: #ifdef LCKDIR
1885: prtopt(" LCKDIR");
1886: #endif /* LCKDIR */
1887: #ifdef ACUCNTRL
1888: prtopt(" ACUCNTRL");
1889: #endif /* ACUCNTRL */
1890: #ifdef BSD4
1891: prtopt(" BSD4");
1892: #endif /* BSD4 */
1893: #ifdef BSD44
1894: prtopt(" BSD44");
1895: #endif /* BSD44 */
1896: #ifdef BSD41
1897: prtopt(" BSD41");
1898: #endif /* BSD41 */
1899: #ifdef BSD43
1900: prtopt(" BSD43");
1901: #endif /* BSD43 */
1902: #ifdef BSD29
1903: prtopt(" BSD29");
1904: #endif /* BSD29 */
1905: #ifdef V7
1906: prtopt(" V7");
1907: #endif /* V7 */
1908: #ifdef AIX370
1909: prtopt(" AIX370");
1910: #endif /* AIX370 */
1911: #ifdef RTAIX
1912: prtopt(" RTAIX");
1913: #endif /* RTAIX */
1914: #ifdef HPUX
1915: prtopt(" HPUX");
1916: #endif /* HPUX */
1917: #ifdef HPUXPRE65
1918: prtopt(" HPUXPRE65");
1919: #endif /* HPUXPRE65 */
1920: #ifdef DGUX
1921: prtopt(" DGUX");
1922: #endif /* DGUX */
1923: #ifdef DGUX430
1924: prtopt(" DGUX430");
1925: #endif /* DGUX430 */
1926: #ifdef DGUX540
1927: prtopt(" DGUX540");
1928: #endif /* DGUX540 */
1929: #ifdef sony_news
1930: prtopt(" sony_news");
1931: #endif /* sony_news */
1932: #ifdef CIE
1933: prtopt(" CIE");
1934: #endif /* CIE */
1935: #ifdef XENIX
1936: prtopt(" XENIX");
1937: #endif /* XENIX */
1938: #ifdef SCO_XENIX
1939: prtopt(" SCO_XENIX");
1940: #endif /* SCO_XENIX */
1941: #ifdef ISIII
1942: prtopt(" ISIII");
1943: #endif /* ISIII */
1944: #ifdef I386IX
1945: prtopt(" I386IX");
1946: #endif /* I386IX */
1947: #ifdef RTU
1948: prtopt(" RTU");
1949: #endif /* RTU */
1950: #ifdef PROVX1
1951: prtopt(" PROVX1");
1952: #endif /* PROVX1 */
1953: #ifdef TOWER1
1954: prtopt(" TOWER1");
1955: #endif /* TOWER1 */
1956: #ifdef UTEK
1957: prtopt(" UTEK");
1958: #endif /* UTEK */
1959: #ifdef ZILOG
1960: prtopt(" ZILOG");
1961: #endif /* ZILOG */
1962: #ifdef TRS16
1963: prtopt(" TRS16");
1964: #endif /* TRS16 */
1965: #ifdef MINIX
1966: prtopt(" MINIX");
1967: #endif /* MINIX */
1968: #ifdef C70
1969: prtopt(" C70");
1970: #endif /* C70 */
1971: #ifdef AIXPS2
1972: prtopt(" AIXPS2");
1973: #endif /* AIXPS2 */
1974: #ifdef AIXRS
1975: prtopt(" AIXRS");
1976: #endif /* AIXRS */
1977: #ifdef UTSV
1978: prtopt(" UTSV");
1979: #endif /* UTSV */
1980: #ifdef ATTSV
1981: prtopt(" ATTSV");
1982: #endif /* ATTSV */
1983: #ifdef SVR3
1984: prtopt(" SVR3");
1985: #endif /* SVR3 */
1986: #ifdef SVR4
1987: prtopt(" SVR4");
1988: #endif /* SVR4 */
1989: #ifdef DELL_SVR4
1990: prtopt(" DELL_SVR4");
1991: #endif /* DELL_SVR4 */
1992: #ifdef ICL_SVR4
1993: prtopt(" ICL_SVR4");
1994: #endif /* ICL_SVR4 */
1995: #ifdef OSF
1996: prtopt(" OSF");
1997: #endif /* OSF */
1998: #ifdef PTX
1999: prtopt(" PTX");
2000: #endif /* PTX */
2001: #ifdef POSIX
2002: prtopt(" POSIX");
2003: #endif /* POSIX */
2004: #ifdef SOLARIS
2005: prtopt(" SOLARIS");
2006: #endif /* SOLARIS */
2007: #ifdef SUNOS4
2008: prtopt(" SUNOS4");
2009: #endif /* SUNOS4 */
2010: #ifdef SUN4S5
2011: prtopt(" SUN4S5");
2012: #endif /* SUN4S5 */
2013: #ifdef ENCORE
2014: prtopt(" ENCORE");
2015: #endif /* ENCORE */
2016: #ifdef ultrix
2017: prtopt(" ultrix");
2018: #endif
2019: #ifdef sxaE50
2020: prtopt(" sxaE50");
2021: #endif
2022: #ifdef mips
2023: prtopt(" mips");
2024: #endif
2025: #ifdef MIPS
2026: prtopt(" MIPS");
2027: #endif
2028: #ifdef vax
2029: prtopt(" vax");
2030: #endif
2031: #ifdef VAX
2032: prtopt(" VAX");
2033: #endif
2034: #ifdef sun
2035: prtopt(" sun");
2036: #endif
2037: #ifdef sun3
2038: prtopt(" sun3");
2039: #endif
2040: #ifdef sun386
2041: prtopt(" sun386");
2042: #endif
2043: #ifdef _SUN
2044: prtopt(" _SUN");
2045: #endif
2046: #ifdef sun4
2047: prtopt(" sun4");
2048: #endif
2049: #ifdef sparc
2050: prtopt(" sparc");
2051: #endif
2052: #ifdef NEXT
2053: prtopt(" NEXT");
2054: #endif
2055: #ifdef NeXT
2056: prtopt(" NeXT");
2057: #endif
2058: #ifdef sgi
2059: prtopt(" sgi");
2060: #endif
2061: #ifdef M_SYS5
2062: prtopt(" M_SYS5");
2063: #endif
2064: #ifdef __SYSTEM_FIVE
2065: prtopt(" __SYSTEM_FIVE");
2066: #endif
2067: #ifdef sysV
2068: prtopt(" sysV");
2069: #endif
2070: #ifdef M_XENIX /* SCO Xenix V and UNIX/386 */
2071: prtopt(" M_XENIX");
2072: #endif
2073: #ifdef M_UNIX
2074: prtopt(" M_UNIX");
2075: #endif
2076: #ifdef M_I386
2077: prtopt(" M_I386");
2078: #endif
2079: #ifdef _M_I386
2080: prtopt(" _M_I386");
2081: #endif
2082: #ifdef i386
2083: prtopt(" i386");
2084: #endif
2085: #ifdef i286
2086: prtopt(" i286");
2087: #endif
2088: #ifdef M_I286
2089: prtopt(" M_I286");
2090: #endif
2091: #ifdef mc68000
2092: prtopt(" mc68000");
2093: #endif
2094: #ifdef mc68010
2095: prtopt(" mc68010");
2096: #endif
2097: #ifdef mc68020
2098: prtopt(" mc68020");
2099: #endif
2100: #ifdef mc68030
2101: prtopt(" mc68030");
2102: #endif
2103: #ifdef mc68040
2104: prtopt(" mc68040");
2105: #endif
2106: #ifdef M_68000
2107: prtopt(" M_68000");
2108: #endif
2109: #ifdef M_68010
2110: prtopt(" M_68010");
2111: #endif
2112: #ifdef M_68020
2113: prtopt(" M_68020");
2114: #endif
2115: #ifdef M_68030
2116: prtopt(" M_68030");
2117: #endif
2118: #ifdef M_68040
2119: prtopt(" M_68040");
2120: #endif
2121: #ifdef m68k
2122: prtopt(" m68k");
2123: #endif
2124: #ifdef m88k
2125: prtopt(" m88k");
2126: #endif
2127: #ifdef pdp11
2128: prtopt(" pdp11");
2129: #endif
2130: #ifdef iAPX
2131: prtopt(" iAPX");
2132: #endif
2133: #ifdef __hp9000s800
2134: prtopt(" __hp9000s800");
2135: #endif
2136: #ifdef __hp9000s500
2137: prtopt(" __hp9000s500");
2138: #endif
2139: #ifdef __hp9000s300
2140: prtopt(" __hp9000s300");
2141: #endif
2142: #ifdef __hp9000s200
2143: prtopt(" __hp9000s200");
2144: #endif
2145: #ifdef AIX
2146: prtopt(" AIX");
2147: #endif
2148: #ifdef _AIXFS
2149: prtopt(" _AIXFS");
2150: #endif
2151: #ifdef u370
2152: prtopt(" u370");
2153: #endif
2154: #ifdef u3b
2155: prtopt(" u3b");
2156: #endif
2157: #ifdef u3b2
2158: prtopt(" u3b2");
2159: #endif
2160: #ifdef multimax
2161: prtopt(" multimax");
2162: #endif
2163: #ifdef balance
2164: prtopt(" balance");
2165: #endif
2166: #ifdef ibmrt
2167: prtopt(" ibmrt");
2168: #endif
2169: #ifdef _IBMRT
2170: prtopt(" _IBMRT");
2171: #endif
2172: #ifdef ibmrs6000
2173: prtopt(" ibmrs6000");
2174: #endif
2175: #ifdef _AIX
2176: prtopt(" _AIX");
2177: #endif /* _AIX */
2178: #ifdef _IBMR2
2179: prtopt(" _IBMR2");
2180: #endif
2181: #ifdef __STRICT_BSD__
2182: prtopt(" __STRICT_BSD__");
2183: #endif
2184: #ifdef __STRICT_ANSI__
2185: prtopt(" __STRICT_ANSI__");
2186: #endif
2187: #ifdef _ANSI_C_SOURCE
2188: prtopt(" _ANSI_C_SOURCE");
2189: #endif
2190: #ifdef __STDC__
2191: prtopt(" __STDC__");
2192: #endif
2193: #ifdef __GNUC__ /* gcc in ansi mode */
2194: prtopt(" __GNUC__");
2195: #endif
2196: #ifdef GNUC /* gcc in traditional mode */
2197: prtopt(" GNUC");
2198: #endif
2199: #ifdef CK_ANSIC
2200: prtopt(" CK_ANSIC");
2201: #endif
2202: #ifdef CK_ANSILIBS
2203: prtopt(" CK_ANSILIBS");
2204: #endif
2205: #ifdef _XOPEN_SOURCE
2206: prtopt(" _XOPEN_SOURCE");
2207: #endif
2208: #ifdef _ALL_SOURCE
2209: prtopt(" _ALL_SOURCE");
2210: #endif
2211: #ifdef _SC_JOB_CONTROL
2212: prtopt(" _SC_JOB_CONTROL");
2213: #endif
2214: #ifdef _POSIX_JOB_CONTROL
2215: prtopt(" _POSIX_JOB_CONTROL");
2216: #endif
2217: #ifdef SVR3JC
2218: prtopt(" SVR3JC");
2219: #endif
2220: #ifdef _386BSD
2221: prtopt(" _386BSD");
2222: #endif
2223: #ifdef _BSD
2224: prtopt(" _BSD");
2225: #endif
2226: #ifdef TERMIOX
2227: prtopt(" TERMIOX");
2228: #endif /* TERMIOX */
2229: #ifdef STERMIOX
2230: prtopt(" STERMIOX");
2231: #endif /* STERMIOX */
2232: #ifdef CK_CURSES
2233: prtopt(" CK_CURSES");
2234: #endif /* CK_CURSES */
2235: #ifdef CK_DTRCD
2236: prtopt(" CK_DTRCD");
2237: #endif /* CK_DTRCD */
2238: #ifdef CK_DTRCTS
2239: prtopt(" CK_DTRCTS");
2240: #endif /* CK_DTRCTS */
2241: #ifdef CK_RTSCTS
2242: prtopt(" CK_RTSCTS");
2243: #endif /* CK_RTSCTS */
2244: prtopt((char *)0);
2245: printf("\n\n");
2246: }
2247: #endif /* NOFRILLS */
2248: #endif /* NOSHOW */
2249:
2250: #ifdef VMS
2251: int
2252: sholbl() {
2253: printf("VMS Labeled File Features:\n");
2254: printf(" acl %s (ACL info %s)\n",
2255: lf_opts & LBL_ACL ? "on " : "off",
2256: lf_opts & LBL_ACL ? "preserved" : "discarded");
2257: printf(" backup-date %s (backup date/time %s)\n",
2258: lf_opts & LBL_BCK ? "on " : "off",
2259: lf_opts & LBL_BCK ? "preserved" : "discarded");
2260: printf(" name %s (original filename %s)\n",
2261: lf_opts & LBL_NAM ? "on " : "off",
2262: lf_opts & LBL_NAM ? "preserved" : "discarded");
2263: printf(" owner %s (original file owner id %s)\n",
2264: lf_opts & LBL_OWN ? "on " : "off",
2265: lf_opts & LBL_OWN ? "preserved" : "discarded");
2266: printf(" path %s (original file's disk:[directory] %s)\n",
2267: lf_opts & LBL_PTH ? "on " : "off",
2268: lf_opts & LBL_PTH ? "preserved" : "discarded");
2269: }
2270: #endif /* VMS */
2271:
2272: #ifndef NOSHOW
2273: VOID
2274: shotcs(cs1,cs2) int cs1, cs2; { /* Show terminal character set */
2275: #ifndef NOCSETS
2276: #ifndef MAC
2277: int y;
2278: char *s;
2279: #ifdef CK_ANSIC
2280: int gettcs(int, int);
2281: #else
2282: int gettcs();
2283: #endif /* CK_ANSIC */
2284:
2285: printf(" Terminal character-set");
2286: if (cs1 == cs2) {
2287: printf(": transparent\n");
2288: } else {
2289: s = "unknown";
2290: for (y = 0; y <= nfilc; y++) /* Look up name in keyword table */
2291: if (ttcstab[y].kwval == cs2) {
2292: if (ttcstab[y].flgs & CM_INV) /* Skip synonyms */
2293: continue;
2294: s = ttcstab[y].kwd;
2295: break;
2296: }
2297: printf("s:\n Remote: %s\n Local: ",s);
2298: s = "unknown";
2299: for (y = 0; y <= nfilc; y++)
2300: if (ttcstab[y].kwval == cs1) {
2301: if (ttcstab[y].flgs & CM_INV) /* Skip synonyms */
2302: continue;
2303: s = ttcstab[y].kwd;
2304: break;
2305: }
2306: printf("%s",s);
2307: if (cs2 != cs1) {
2308: switch(gettcs(cs2,cs1)) {
2309: case TC_USASCII: s = "ascii"; break;
2310: case TC_1LATIN: s = "latin1-iso"; break;
2311: case TC_2LATIN: s = "latin2-iso"; break;
2312: case TC_CYRILL: s = "cyrillic-iso"; break;
2313: case TC_JEUC: s = "japanese-euc"; break;
2314: default: s = "transparent"; break;
2315: }
2316: printf("\n Via: %s\n",s);
2317: }
2318: }
2319: #endif /* MAC */
2320: #endif /* NOCSETS */
2321: }
2322: #endif /* NOSHOW */
2323:
2324: #ifndef NOSHOW
2325: int
2326: doshow(x) int x; {
2327: int y, i; long zz;
2328: char *s;
2329:
2330: #ifndef NOSETKEY
2331: if (x == SHKEY) { /* SHOW KEY */
2332: int c;
2333: KEY ch;
2334: CHAR *s;
2335:
2336: if ((y = cmcfm()) < 0) return(y);
2337: #ifdef MAC
2338: printf("Not implemented\n");
2339: return(0);
2340: #else /* Not MAC */
2341: printf(" Press key: ");
2342: #ifdef UNIX
2343: #ifdef NOSETBUF
2344: fflush(stdout);
2345: #endif /* NOSETBUF */
2346: #endif /* UNIX */
2347: conbin((char)escape); /* Put terminal in binary mode */
2348: c = congks(0); /* Get character or scan code */
2349: concb((char)escape); /* Restore terminal to cbreak mode */
2350: if (c < 0) { /* Check for error */
2351: printf("?Error reading key\n");
2352: return(0);
2353: }
2354: #ifndef OS2
2355: /*
2356: Do NOT mask when it can be a raw scan code, perhaps > 255
2357: */
2358: c &= cmdmsk; /* Apply command mask */
2359: #endif /* OS2 */
2360: printf("\n Key code \\%d => ",c);
2361: if (macrotab[c]) { /* See if there's a macro */
2362: printf("String: "); /* If so, display its definition */
2363: s = macrotab[c];
2364: while (ch = *s++)
2365: if (ch < 32 || ch == 127
2366: /*
2367: Systems whose native character sets have graphic characters in C1...
2368: */
2369: #ifndef NEXT /* NeXT */
2370: #ifndef AUX /* Macintosh */
2371: #ifndef XENIX /* IBM PC */
2372: #ifndef OS2 /* IBM PC */
2373: || (ch > 127 && ch < 160)
2374: #endif /* OS2 */
2375: #endif /* XENIX */
2376: #endif /* AUX */
2377: #endif /* NEXT */
2378: )
2379: printf("\\{%d}",ch); /* Display control characters */
2380: else putchar((char) ch); /* in backslash notation */
2381: printf("\n");
2382: } else { /* No macro, show single character */
2383: printf("Character: ");
2384: ch = keymap[c];
2385: if (ch < 32 || ch == 127 || ch > 255
2386: #ifndef NEXT
2387: #ifndef AUX
2388: #ifndef XENIX
2389: #ifndef OS2
2390: || (ch > 127 && ch < 160)
2391: #endif /* OS2 */
2392: #endif /* XENIX */
2393: #endif /* AUX */
2394: #endif /* NEXT */
2395: )
2396: printf("\\%d",(unsigned int) ch);
2397: else printf("%c \\%d",ch,(unsigned int) ch);
2398: }
2399: if (ch == (KEY) c)
2400: printf(" (self, no translation)\n");
2401: else printf("\n");
2402: return(1);
2403: #endif /* MAC */
2404: }
2405: #endif /* NOSETKEY */
2406:
2407: #ifndef NOSPL
2408: if (x == SHMAC) { /* SHOW MACRO */
2409: x = cmfld("Macro name, or carriage return to see them all","",&s,
2410: NULL);
2411: if (x == -3) /* This means they want see all */
2412: *line = '\0';
2413: else if (x < 0) /* Otherwise negative = parse error */
2414: return(x);
2415: else /* 0 or greater */
2416: strcpy(line,s); /* means they typed something */
2417: if ((y = cmcfm()) < 0) return(y); /* Get confirmation */
2418: if (*line) {
2419: slc = 0; /* Initial SHO MAC line number */
2420: x = mlook(mactab,s,nmac); /* Look up what they typed */
2421: switch (x) {
2422: case -3: /* Nothing to look up */
2423: return(0);
2424: case -1: /* Not found */
2425: printf("%s - not found\n",s);
2426: return(0);
2427: case -2: /* Ambiguous, matches more than one */
2428: y = (int)strlen(line);
2429: slc = 1;
2430: for (x = 0; x < nmac; x++)
2431: if (!strncmp(mactab[x].kwd,line,y))
2432: if (shomac(mactab[x].kwd,mactab[x].mval) < 0) break;
2433: return(1);
2434: default: /* Matches one exactly */
2435: shomac(mactab[x].kwd,mactab[x].mval);
2436: return(1);
2437: }
2438: } else { /* They want to see them all */
2439: printf("Macros:\n");
2440: slc = 1;
2441: for (y = 0; y < nmac; y++)
2442: if (shomac(mactab[y].kwd,mactab[y].mval) < 0) break;
2443: return(1);
2444: }
2445: }
2446: #endif /* NOSPL */
2447:
2448: /*
2449: Other SHOW commands only have two fields. Get command confirmation here,
2450: then handle with big switch() statement.
2451: */
2452: if ((y = cmcfm()) < 0) return(y);
2453: switch (x) {
2454:
2455: #ifdef SUNX25
2456: case SHPAD:
2457: shopad();
2458: break;
2459: #endif /* SUNX25 */
2460:
2461: #ifdef NETCONN
2462: case SHNET:
2463: shonet();
2464: break;
2465: #endif /* NETCONN */
2466:
2467: case SHPAR:
2468: shopar();
2469: break;
2470:
2471: case SHATT:
2472: shoatt();
2473: break;
2474:
2475: #ifndef NOSPL
2476: case SHCOU:
2477: printf(" %d\n",count[cmdlvl]);
2478: break;
2479: #endif /* NOSPL */
2480:
2481: #ifndef NOSERVER
2482: case SHSER: /* Show Server */
2483: #ifndef NOFRILLS
2484: printf("Function Status:\n");
2485: printf(" GET %s\n",nm[en_get]);
2486: printf(" SEND %s\n",nm[en_sen]);
2487: printf(" REMOTE CD/CWD %s\n",nm[en_cwd]);
2488: printf(" REMOTE DELETE %s\n",nm[en_del]);
2489: printf(" REMOTE DIRECTORY %s\n",nm[en_dir]);
2490: printf(" REMOTE HOST %s\n",nm[en_hos]);
2491: printf(" REMOTE SET %s\n",nm[en_set]);
2492: printf(" REMOTE SPACE %s\n",nm[en_spa]);
2493: printf(" REMOTE TYPE %s\n",nm[en_typ]);
2494: printf(" REMOTE WHO %s\n",nm[en_who]);
2495: printf(" BYE %s\n",nm[en_bye]);
2496: printf(" FINISH %s\n",nm[en_fin]);
2497: #endif /* NOFRILLS */
2498: printf("Server timeout: %d\n",srvtim);
2499: printf("Server display: %s\n\n", srvdis ? "on" : "off");
2500: break;
2501: #endif /* NOSERVER */
2502:
2503: case SHSTA: /* Status of last command */
2504: printf( " %s\n", success ? "SUCCESS" : "FAILURE" );
2505: return(0); /* Don't change it */
2506:
2507: #ifdef MAC
2508: case SHSTK: { /* Stack for MAC debugging */
2509: long sp;
2510:
2511: sp = -1;
2512: loadA0 ((char *)&sp); /* set destination address */
2513: SPtoaA0(); /* move SP to destination */
2514: printf("Stack at 0x%x\n", sp);
2515: show_queue(); /* more debugging */
2516: break;
2517: }
2518: #endif /* MAC */
2519:
2520: case SHTER:
2521: printf(" Command bytesize: %d bits\n",
2522: (cmdmsk == 0377) ? 8 : 7);
2523: printf(" Terminal bytesize: %d bits\n",
2524: (cmask == 0377) ? 8 : 7);
2525: #ifdef OS2
2526: printf(" Terminal type: %s\n",
2527: (tt_type == TT_VT102) ? "VT102" : "VT52");
2528:
2529: #endif /* OS2 */
2530: printf(" Terminal echo: %s\n", duplex ? "local" : "remote");
2531: printf(" Terminal locking-shift: %s\n", sosi ? "on" : "off");
2532: printf(" Terminal newline-mode: %s\n", tnlm ? "on" : "off");
2533: printf(" Terminal cr-display: %s\n",
2534: tt_crd ? "crlf" : "normal");
2535: #ifdef OS2
2536: /* Should show cursor and colors here too... */
2537: printf(" Terminal arrow-keys: %s\n",
2538: tt_arrow ? "cursor" : "application");
2539: printf(" Terminal keypad-mode: %s\n",
2540: tt_keypad ? "numeric" : "application");
2541: printf(" Terminal wrap: %s\n", tt_wrap ? "on" : "off");
2542: #endif /* OS2 */
2543:
2544: #ifndef NOCSETS
2545: shotcs(tcsl,tcsr);
2546: #endif /* NOCSETS */
2547: printf(" CONNECT-mode escape character: %d (Ctrl-%c, %s)\n",
2548: escape,ctl(escape),(escape == 127 ? "DEL" : ccntab[escape]));
2549: #ifdef UNIX
2550: printf(" Suspend: %s\n", suspend ? "on" : "off");
2551: #endif /* UNIX */
2552: break;
2553:
2554: #ifndef NOFRILLS
2555: case SHVER:
2556: shover();
2557: break;
2558: #endif /* NOFRILLS */
2559:
2560: #ifndef NOSPL
2561: case SHBUI: /* Built-in variables */
2562: i = 0;
2563: for (y = 0; y < nvars; y++) {
2564: printf(" \\v(%s) = %s\n",vartab[y].kwd,nvlook(vartab[y].kwd));
2565: if (++i > SCRNLEN) { /* More than a screenful... */
2566: if (!askmore())
2567: break;
2568: else
2569: i = 0;
2570: }
2571: }
2572: break;
2573:
2574: case SHFUN: /* Functions */
2575: for (y = 0; y < nfuncs; y++)
2576: printf(" \\f%s()\n",fnctab[y].kwd);
2577: break;
2578:
2579: case SHVAR: /* Global variables */
2580: x = 0; /* Variable count */
2581: slc = 1; /* Screen line count for "more?" */
2582: for (y = 33; y < GVARS; y++)
2583: if (g_var[y]) {
2584: if (x++ == 0) printf("Global variables:\n");
2585: sprintf(line," \\%%%c",y);
2586: if (shomac(line,g_var[y]) < 0) break;
2587: }
2588: if (!x) printf(" No variables defined\n");
2589: break;
2590:
2591: case SHARG: /* Args */
2592: if (maclvl > -1) {
2593: printf("Macro arguments at level %d\n",maclvl);
2594: for (y = 0; y < 10; y++)
2595: if (m_arg[maclvl][y])
2596: printf(" \\%%%d = %s\n",y,m_arg[maclvl][y]);
2597: } else {
2598: printf(" No macro arguments at top level\n");
2599: }
2600: break;
2601:
2602: case SHARR: /* Arrays */
2603: x = 0;
2604: for (y = 0; y < 27; y++)
2605: if (a_ptr[y]) {
2606: if (x == 0) printf("Declared arrays:\n");
2607: x = 1;
2608: printf(" \\&%c[%d]\n",(y == 0) ? 64 : y + 96, a_dim[y]);
2609: }
2610: if (!x) printf(" No arrays declared\n");
2611: break;
2612: #endif /* NOSPL */
2613:
2614: case SHPRO: /* Protocol parameters */
2615: shoparp();
2616: printf("\n");
2617: break;
2618:
2619: case SHCOM: /* Communication parameters */
2620: printf("\n");
2621: shoparc();
2622: #ifndef NODIAL
2623: printf("\n");
2624: #ifdef NETCONN
2625: if (!network)
2626: #endif /* NETCONN */
2627: shodial();
2628: #endif /* NODIAL */
2629: printf("\n");
2630: shomdm();
2631: printf("\n");
2632: break;
2633:
2634: case SHFIL: /* File parameters */
2635: shoparf();
2636: printf("\n");
2637: break;
2638:
2639: #ifndef NOCSETS
2640: case SHLNG: /* Languages */
2641: shoparl();
2642: break;
2643: #endif /* NOCSETS */
2644:
2645: #ifndef NOSPL
2646: case SHSCR: /* Scripts */
2647: printf(" Take Echo: %s\n", techo ? "On" : "Off");
2648: printf(" Take Error: %s\n", terror ? "On" : "Off");
2649: printf(" Macro Echo: %s\n", mecho ? "On" : "Off");
2650: printf(" Macro Error: %s\n", merror ? "On" : "Off");
2651: printf(" Input Case: %s\n", incase ? "Observe" : "Ignore");
2652: printf(" Input Echo: %s\n", inecho ? "On" : "Off");
2653: printf(" Input Silence: %d\n", insilence);
2654: printf(" Input Timeout: %s\n", intime ? "Quit" : "Proceed");
2655: #ifndef NOSCRIPT
2656: printf(" Script Echo: %s\n", secho ? "On" : "Off");
2657: #endif /* NOSCRIPT */
2658: break;
2659: #endif /* NOSPL */
2660:
2661: #ifndef NOXMIT
2662: case SHXMI:
2663: printf(" File type: %s\n", binary ? "binary" : "text");
2664: #ifndef NOCSETS
2665: shotcs(tcsl,tcsr);
2666: #endif /* NOCSETS */
2667: printf(" Terminal echo: %s\n", duplex ? "local" : "remote");
2668: printf(" Transmit EOF: ");
2669: if (*xmitbuf == NUL) {
2670: printf("none\n");
2671: } else {
2672: char *p;
2673: p = xmitbuf;
2674: while (*p) {
2675: if (*p < SP)
2676: printf("^%c",ctl(*p));
2677: else
2678: printf("%c",*p);
2679: p++;
2680: }
2681: printf("\n");
2682: }
2683: if (xmitf)
2684: printf(" Transmit Fill: %d (fill character for blank lines)\n",
2685: xmitf);
2686: else printf(" Transmit Fill: none\n");
2687: printf(" Transmit Linefeed: %s\n",
2688: xmitl ? "on (send linefeeds too)" : "off");
2689: if (xmitp)
2690: printf(" Transmit Prompt: %d (host line end character)\n",xmitp);
2691: else printf(" Transmit Prompt: none\n");
2692: printf(" Transmit Echo: %s\n",
2693: xmitx ? "on" : "off");
2694: printf(" Transmit Locking-Shift: %s\n",xmits ? "on" : "off");
2695: printf(" Transmit Pause: %d milliseconds\n", xmitw);
2696: break;
2697: #endif /* NOXMIT */
2698:
2699: case SHMOD: /* SHOW MODEM */
2700: shmdmlin();
2701: printf("\n");
2702: shomdm();
2703: break;
2704:
2705: #ifndef MAC
2706: case SHDFLT:
2707: zsyscmd(PWDCMD);
2708: break;
2709: #endif /* MAC */
2710:
2711: case SHESC:
2712: printf(" Escape character: Ctrl-%c (ASCII %d, %s)\r\n",
2713: ctl(escape), escape, (escape == 127 ? "DEL" : ccntab[escape]));
2714: break;
2715:
2716: #ifndef NODIAL
2717: case SHDIA:
2718: shmdmlin();
2719: printf(", speed: ");
2720: if ((zz = ttgspd()) < 0) {
2721: printf("unknown\n");
2722: } else {
2723: if (zz == 8880) printf("75/1200\n"); else printf("%ld\n",zz);
2724: }
2725: doshodial();
2726: if (carrier == CAR_OFF) s = "off";
2727: else if (carrier == CAR_ON) s = "on";
2728: else if (carrier == CAR_AUT) s = "auto";
2729: else s = "unknown";
2730: printf(" Carrier: %s", s);
2731: if (carrier == CAR_ON) {
2732: if (cdtimo) printf(", timeout: %d sec", cdtimo);
2733: else printf(", timeout: none");
2734: }
2735: if (local
2736: #ifdef NETCONN
2737: && !network
2738: #endif /* NETCONN */
2739: ) {
2740: printf("\n%s modem signals:\n",ttname);
2741: shomdm();
2742: } else printf("\n");
2743: break;
2744: #endif /* NODIAL */
2745:
2746: #ifdef VMS
2747: case SHLBL: /* Labeled file info */
2748: sholbl();
2749: break;
2750: #endif /* VMS */
2751:
2752: case SHCSE: /* Character sets */
2753: #ifdef NOCSETS
2754: printf(
2755: " Character set translation is not supported in this version of C-Kermit\n");
2756: #else
2757: shocharset();
2758: printf("\n Unknown-Char-Set: %s\n",
2759: unkcs ? "Keep" : "Discard");
2760: shotcs(tcsl,tcsr);
2761: printf("\n");
2762: #endif /* NOCSETS */
2763: break;
2764:
2765: #ifndef NOFRILLS
2766: case SHFEA: /* Features */
2767: shofea();
2768: break;
2769: #endif /* NOFRILLS */
2770:
2771: default:
2772: printf("\nNothing to show...\n");
2773: return(-2);
2774: }
2775: return(success = 1);
2776: }
2777:
2778: VOID
2779: shmdmlin() { /* Briefly show modem & line */
2780: int i;
2781: #ifndef NODIAL
2782: #ifndef MINIDIAL
2783: extern int tbmodel;
2784: _PROTOTYP( char * gtbmodel, (void) );
2785: #endif /* MINIDIAL */
2786: #endif /* NODIAL */
2787: if (local)
2788: printf(" Line: %s, Modem: ",ttname);
2789: else
2790: printf(" Communication device not yet selected with SET LINE\n Modem: ");
2791: #ifndef NODIAL
2792: for (i = 0; i < nmdm; i++) {
2793: if (mdmtab[i].kwval == mdmtyp) {
2794: printf("%s",mdmtab[i].kwd);
2795: break;
2796: }
2797: }
2798: #ifndef MINIDIAL
2799: if (tbmodel) printf(" (%s)",gtbmodel()); /* Telebit model info */
2800: #endif /* MINIDIAL */
2801: #else
2802: printf("(disabled)");
2803: #endif /* NODIAL */
2804: }
2805: #endif /* NOSHOW */
2806:
2807: #ifdef GEMDOS
2808: isxdigit(c) int c; {
2809: return(isdigit(c) ||
2810: (c >= 'a' && c <= 'f') ||
2811: (c >= 'A' && c <= 'F'));
2812: }
2813: #endif /* GEMDOS */
2814:
2815: #ifndef NOSHOW
2816: #ifndef NOSPL
2817: int /* SHO MACROS */
2818: shomac(s1, s2) char *s1, *s2; {
2819: int x, n, pp;
2820: pp = 0; /* Parenthesis counter */
2821:
2822: if (!s1)
2823: return(0);
2824: else
2825: printf("\n%s = ",s1); /* Print blank line and macro name */
2826: slc++; /* Count the line */
2827: n = (int)strlen(s1) + 4; /* Width of current line */
2828: if (!s2) s2 = "(null definition)";
2829:
2830: while (x = *s2++) { /* Loop thru definition */
2831: if (x == '(') pp++; /* Treat commas within parens */
2832: if (x == ')') pp--; /* as ordinary text */
2833: if (pp < 0) pp = 0; /* Outside parens, */
2834: if (x == ',' && pp == 0) { /* comma becomes comma-dash-NL. */
2835: putchar(',');
2836: putchar('-');
2837: x = '\n';
2838: }
2839: putchar(x); /* Output the character */
2840: if (x == '\n') { /* If it was a newline */
2841: #ifdef UNIX
2842: #ifdef NOSETBUF
2843: fflush(stdout);
2844: #endif /* NOSETBUF */
2845: #endif /* UNIX */
2846: putchar(' '); /* Indent the next line 1 space */
2847: while(*s2 == ' ') s2++; /* skip past leading blanks */
2848: n = 2; /* restart the character counter */
2849: slc++; /* and increment the line counter. */
2850: } else if (++n > SCRNWID) { /* If line is too wide */
2851: putchar('-'); /* output a dash */
2852: putchar(NL); /* and a newline */
2853: #ifdef UNIX
2854: #ifdef NOSETBUF
2855: fflush(stdout);
2856: #endif /* NOSETBUF */
2857: #endif /* UNIX */
2858: n = 1; /* and restart the char counter */
2859: slc++; /* and increment the line counter */
2860: }
2861: if (n < 3 && slc > SCRNLEN) { /* If new line and screen is full */
2862: if (!askmore()) return(-1); /* ask if they want more. */
2863: n = 1; /* They do, start a new line */
2864: slc = 0; /* and restart line counter */
2865: }
2866: }
2867: putchar(NL); /* End of definition */
2868: if (++slc > SCRNLEN) {
2869: if (!askmore()) return(-1);
2870: slc = 0;
2871: }
2872: return(0);
2873: }
2874: #endif /* NOSPL */
2875: #endif /* NOSHOW */
2876:
2877: #ifndef NOSHOW
2878: int
2879: shoatt() {
2880: printf("Attributes: %s\n", atcapr ? "On" : "Off");
2881: if (!atcapr) return(0);
2882: printf(" Blocksize: %s\n", atblki ? "On" : "Off");
2883: printf(" Date: %s\n", atdati ? "On" : "Off");
2884: printf(" Disposition: %s\n", atdisi ? "On" : "Off");
2885: printf(" Encoding (Character Set): %s\n", atenci ? "On" : "Off");
2886: printf(" Length: %s\n", atleni ? "On" : "Off");
2887: printf(" Type (text/binary): %s\n", attypi ? "On" : "Off");
2888: printf(" System ID: %s\n", atsidi ? "On" : "Off");
2889: printf(" System Info: %s\n", atsysi ? "On" : "Off");
2890: return(0);
2891: }
2892: #endif /* NOSHOW */
2893:
2894: #ifndef NOSPL
2895: /* Evaluate an arithmetic expression. */
2896: /* Code adapted from ev, by Howie Kaye of Columbia U & others. */
2897:
2898: static int xerror;
2899: static char *cp;
2900: static long tokval;
2901: static char curtok;
2902: static long expval;
2903:
2904: #define LONGBITS (8*sizeof (long))
2905: #define NUMBER 'N'
2906: #define EOT 'E'
2907:
2908: /*
2909: Replacement for strchr() and index(), neither of which seem to be universal.
2910: */
2911:
2912: static char *
2913: #ifdef CK_ANSIC
2914: windex(char * s, char c)
2915: #else
2916: windex(s,c) char *s, c;
2917: #endif /* CK_ANSIC */
2918: /* windex */ {
2919: while (*s != NUL && *s != c) s++;
2920: if (*s == c) return(s); else return(NULL);
2921: }
2922:
2923: /*
2924: g e t t o k
2925:
2926: Returns the next token. If token is a NUMBER, sets tokval appropriately.
2927: */
2928: static char
2929: gettok() {
2930: while (isspace(*cp)) cp++ ;
2931: switch(*cp) {
2932: case '$': /* ??? */
2933: case '+': /* Add */
2934: case '-': /* Subtract or Negate */
2935: case '@': /* Greatest Common Divisor */
2936: case '*': /* Multiply */
2937: case '/': /* Divide */
2938: case '%': /* Modulus */
2939: case '<': /* Left shift */
2940: case '>': /* Right shift */
2941: case '&': /* And */
2942: case '|': /* Or */
2943: case '#': /* Exclusive Or */
2944: case '~': /* Not */
2945: case '^': /* Exponent */
2946: case '!': /* Factorial */
2947: case '(': /* Parens for grouping */
2948: case ')': return(*cp++); /* operator, just return it */
2949: case '\n':
2950: case '\0': return(EOT); /* end of line, return that */
2951: }
2952: if (isxdigit(*cp)) { /* digit, must be a number */
2953: char tbuf[80],*tp; /* buffer to accumulate number */
2954: int radix = 10; /* default radix */
2955: for (tp=tbuf; isxdigit(*cp); cp++)
2956: *tp++ = isupper(*cp) ? tolower(*cp) : *cp;
2957: *tp = '\0'; /* end number */
2958: switch(isupper(*cp) ? tolower(*cp) : *cp) { /* examine break char */
2959: case 'h':
2960: case 'x': radix = 16; cp++; break; /* if radix signifier... */
2961: case 'o':
2962: case 'q': radix = 8; cp++; break;
2963: case 't': radix = 2; cp++; break;
2964: }
2965: for (tp=tbuf,tokval=0; *tp != '\0'; tp++) {
2966: int dig;
2967: dig = *tp - '0'; /* convert number */
2968: if (dig > 10) dig -= 'a'-'0'-10;
2969: if (dig >= radix) {
2970: xerror = 1;
2971: if (cmdlvl == 0)
2972: printf("invalid digit '%c' in number\n",*tp);
2973: return(NUMBER);
2974: }
2975: tokval = radix*tokval + dig;
2976: }
2977: return(NUMBER);
2978: }
2979: if (cmdlvl == 0)
2980: printf("Invalid character '%c' in input\n",*cp);
2981: xerror = 1;
2982: cp++;
2983: return(gettok());
2984: }
2985:
2986: static long
2987: #ifdef CK_ANSIC
2988: expon(long x, long y)
2989: #else
2990: expon(x,y) long x,y;
2991: #endif /* CK_ANSIC */
2992: /* expon */ {
2993: long result = 1;
2994: int sign = 1;
2995: if (y < 0) return(0);
2996: if (x < 0) {
2997: x = -x;
2998: if (y & 1) sign = -1;
2999: }
3000: while (y != 0) {
3001: if (y & 1) result *= x;
3002: y >>= 1;
3003: if (y != 0) x *= x;
3004: }
3005: return(result * sign);
3006: }
3007:
3008: /*
3009: * factor ::= simple | simple ^ factor
3010: *
3011: */
3012: _PROTOTYP( static VOID simple, (void) );
3013:
3014: static VOID
3015: factor() {
3016: long oldval;
3017: simple();
3018: if (curtok == '^') {
3019: oldval = expval;
3020: curtok = gettok();
3021: factor();
3022: expval = expon(oldval,expval);
3023: }
3024: }
3025:
3026: /*
3027: * termp ::= NULL | {*,/,%,&} factor termp
3028: *
3029: */
3030: static VOID
3031: termp() {
3032: while (curtok == '*' || curtok == '/' || curtok == '%' || curtok == '&') {
3033: long oldval;
3034: char op;
3035: op = curtok;
3036: curtok = gettok(); /* skip past operator */
3037: oldval = expval;
3038: factor();
3039: switch(op) {
3040: case '*': expval = oldval * expval; break;
3041: case '/':
3042: if (expval == 0) expval = -1; /* don't divide by 0 */
3043: else expval = oldval / expval; break;
3044: case '%': expval = oldval % expval; break;
3045: case '&': expval = oldval & expval; break;
3046: }
3047: }
3048: }
3049:
3050: static long
3051: #ifdef CK_ANSIC
3052: fact(long x)
3053: #else
3054: fact(x) long x;
3055: #endif /* CK_ANSIC */
3056: /* fact */ { /* factorial */
3057: long result = 1;
3058: while (x > 1)
3059: result *= x--;
3060: return(result);
3061: }
3062:
3063: /*
3064: * term ::= factor termp
3065: *
3066: */
3067: static VOID
3068: term() {
3069: factor();
3070: termp();
3071: }
3072:
3073: static long
3074: #ifdef CK_ANSIC
3075: gcd(long x, long y)
3076: #else
3077: gcd(x,y) long x,y;
3078: #endif /* CK_ANSIC */
3079: /* gcd */ { /* Greatest Common Divisor */
3080: int nshift = 0;
3081: if (x < 0) x = -x;
3082: if (y < 0) y = -y; /* validate arguments */
3083: if (x == 0 || y == 0) return(x + y); /* this is bogus */
3084:
3085: while (!((x & 1) | (y & 1))) { /* get rid of powers of 2 */
3086: nshift++;
3087: x >>= 1;
3088: y >>= 1;
3089: }
3090: while (x != 1 && y != 1 && x != 0 && y != 0) {
3091: while (!(x & 1)) x >>= 1; /* eliminate unnecessary */
3092: while (!(y & 1)) y >>= 1; /* powers of 2 */
3093: if (x < y) { /* force x to be larger */
3094: long t;
3095: t = x;
3096: x = y;
3097: y = t;
3098: }
3099: x -= y;
3100: }
3101: if (x == 0 || y == 0) return((x + y) << nshift); /* gcd is non-zero one */
3102: else return((long) 1 << nshift); /* else gcd is 1 */
3103: }
3104:
3105: /*
3106: * exprp ::= NULL | {+,-,|,...} term exprp
3107: *
3108: */
3109: static VOID
3110: exprp() {
3111: while (windex("+-|<>#@",curtok) != NULL) {
3112: long oldval;
3113: char op;
3114: op = curtok;
3115: curtok = gettok(); /* skip past operator */
3116: oldval = expval;
3117: term();
3118: switch(op) {
3119: case '+' : expval = oldval + expval; break;
3120: case '-' : expval = oldval - expval; break;
3121: case '|' : expval = oldval | expval; break;
3122: case '#' : expval = oldval ^ expval; break;
3123: case '@' : expval = gcd(oldval,expval); break;
3124: case '<' : expval = oldval << expval; break;
3125: case '>' : expval = oldval >> expval; break;
3126: }
3127: }
3128: }
3129:
3130: /*
3131: * expr ::= term exprp
3132: *
3133: */
3134: static VOID
3135: expr() {
3136: term();
3137: exprp();
3138: }
3139:
3140: static long
3141: xparse() {
3142: curtok = gettok();
3143: expr();
3144: #ifdef COMMENT
3145: if (curtok == '$') {
3146: curtok = gettok();
3147: if (curtok != NUMBER) {
3148: if (cmdlvl == 0) printf("illegal radix\n");
3149: return(0);
3150: }
3151: curtok = gettok();
3152: }
3153: #endif /* COMMENT */
3154: if (curtok != EOT) {
3155: if (cmdlvl == 0)
3156: printf("extra characters after expression\n");
3157: xerror = 1;
3158: }
3159: return(expval);
3160: }
3161:
3162: char *
3163: evala(s) char *s; {
3164: char *p; /* Return pointer */
3165: long v; /* Numeric value */
3166:
3167: xerror = 0; /* Start out with no error */
3168: cp = s; /* Make the argument global */
3169: v = xparse(); /* Parse the string */
3170: p = numbuf; /* Convert long number to string */
3171: sprintf(p,"%ld",v);
3172: return(xerror ? "" : p); /* Return empty string on error */
3173: }
3174:
3175: /*
3176: * simplest ::= NUMBER | ( expr )
3177: *
3178: */
3179: static VOID
3180: simplest() {
3181: if (curtok == NUMBER) expval = tokval;
3182: else if (curtok == '(') {
3183: curtok = gettok(); /* skip over paren */
3184: expr();
3185: if (curtok != ')') {
3186: if (cmdlvl == 0) printf("missing right parenthesis\n");
3187: xerror = 1;
3188: }
3189: }
3190: else {
3191: if (cmdlvl == 0) printf("operator unexpected\n");
3192: xerror = 1;
3193: }
3194: curtok = gettok();
3195: }
3196:
3197: /*
3198: * simpler ::= simplest | simplest !
3199: *
3200: */
3201: static VOID
3202: simpler() {
3203: simplest();
3204: if (curtok == '!') {
3205: curtok = gettok();
3206: expval = fact(expval);
3207: }
3208: }
3209:
3210: /*
3211: * simple ::= {-,~} simpler | simpler
3212: *
3213: */
3214:
3215: static VOID
3216: simple() {
3217: if (curtok == '-' || curtok == '~') {
3218: int op = curtok;
3219: curtok = gettok(); /* skip over - sign */
3220: simpler(); /* parse the factor again */
3221: expval = op == '-' ? -expval : ~expval;
3222: } else simpler();
3223: }
3224: #endif /* NOSPL */
3225:
3226: #ifndef NOSPL
3227: /* D C L A R R A Y -- Declare an array */
3228:
3229: int /* Declare an array of size n */
3230: #ifdef CK_ANSIC
3231: dclarray(char a, int n)
3232: #else
3233: dclarray(a,n) char a; int n;
3234: #endif /* CK_ANSIC */
3235: /* dclarray */ {
3236: char **p; int i, n2;
3237:
3238: if (a > 63 && a < 96) a += 32; /* Convert to lowercase */
3239: if (a < 96 || a > 122) return(-1); /* Verify name */
3240: a -= 96; /* Convert name to number */
3241: if ((p = a_ptr[a]) != NULL) { /* Delete old array of same name */
3242: n2 = a_dim[a];
3243: for (i = 0; i <= n2; i++) /* First delete its elements */
3244: if (p[i]) free(p[i]);
3245: free(a_ptr[a]); /* Then the element list */
3246: a_ptr[a] = (char **) NULL; /* Remove pointer to element list */
3247: a_dim[a] = 0; /* Set dimension at zero. */
3248: }
3249: if (n == 0) return(0); /* If dimension 0, just deallocate. */
3250:
3251: p = (char **) malloc((n+1) * sizeof(char **)); /* Allocate for new array */
3252: if (p == NULL) return(-1); /* Check */
3253: a_ptr[a] = p; /* Save pointer to member list */
3254: a_dim[a] = n; /* Save dimension */
3255: for (i = 0; i <= n; i++) /* Initialize members to null */
3256: p[i] = NULL;
3257: return(0);
3258: }
3259:
3260: /* A R R A Y N A M -- Parse an array name */
3261:
3262: /*
3263: Call with pointer to string that starts with the array reference.
3264: String may begin with either \& or just &.
3265: On success,
3266: Returns letter ID (always lowercase) in argument c,
3267: which can also be accent grave (` = 96; '@' is converted to grave);
3268: Dimension or subscript in argument n;
3269: IMPORTANT: These arguments must be provided by the caller as addresses
3270: of ints (not chars), for example:
3271: char *s; int x, y;
3272: arraynam(s,&x,&y);
3273: On failure, returns a negative number, with args n and c set to zero.
3274: */
3275: int
3276: arraynam(ss,c,n) char *ss; int *c; int *n; {
3277: int i, y, pp;
3278: char x;
3279: char *s, *p, *sx, *vnp;
3280: char vnbuf[VNAML+1]; /* On stack to allow for */
3281: char ssbuf[VNAML+1]; /* recursive calls... */
3282: char sxbuf[VNAML+1];
3283:
3284: *c = *n = 0; /* Initialize return values */
3285: for (i = 0; i < (int)strlen(ss); i++) /* Check length */
3286: if (ss[i] == ']')
3287: break;
3288: if (i > VNAML) {
3289: printf("?Array reference too long - %s\n",ss);
3290: return(-9);
3291: }
3292: strncpy(vnbuf,ss,VNAML);
3293: vnp = vnbuf;
3294: if (vnbuf[0] == CMDQ && vnbuf[1] == '&') vnp++;
3295: if (*vnp != '&') {
3296: printf("?Not an array - %s\n",vnbuf);
3297: return(-9);
3298: }
3299: x = *(vnp + 1); /* Fold case of array name */
3300: /* We don't use isupper & tolower here on purpose because these */
3301: /* would produce undesired effects with accented letters. */
3302: if (x > 63 && x < 91) x = *(vnp +1) = x + 32;
3303: if ((x < 96) || (x > 122) || (*(vnp+2) != '[')) {
3304: printf("?Invalid format for array name - %s\n",vnbuf);
3305: return(-9);
3306: }
3307: *c = x; /* Return the array name */
3308: s = vnp+3; /* Get dimension */
3309: p = ssbuf;
3310: pp = 1; /* Bracket counter */
3311: for (i = 0; i < VNAML && *s != NUL; i++) { /* Copy up to ] */
3312: if (*s == '[') pp++;
3313: if (*s == ']' && --pp == 0) break;
3314: *p++ = *s++;
3315: }
3316: if (*s != ']') {
3317: printf("?No closing bracket on array dimension - %s\n",vnbuf);
3318: return(-9);
3319: }
3320: *p = NUL; /* Terminate subscript with null */
3321: p = ssbuf; /* Point to beginning of subscript */
3322: sx = sxbuf; /* Where to put expanded subscript */
3323: y = VNAML-1;
3324: xxstring(p,&sx,&y); /* Convert variables, etc. */
3325: if (!chknum(sxbuf)) { /* Make sure it's all digits */
3326: printf("?Array dimension or subscript must be numeric - %s\n",sxbuf);
3327: return(-9);
3328: }
3329: if ((y = atoi(sxbuf)) < 0) {
3330: if (cmflgs == 0) printf("\n");
3331: printf("?Array dimension or subscript must be positive or zero - %s\n",
3332: sxbuf);
3333: return(-9);
3334: }
3335: *n = y; /* Return the subscript or dimension */
3336: return(0);
3337: }
3338:
3339: int
3340: chkarray(a,i) int a, i; { /* Check if array is declared */
3341: int x; /* and if subscript is in range */
3342: if (a == 64) a = 96; /* Convert atsign to grave accent */
3343: x = a - 96; /* Values must be in range 96-122 */
3344: if (x < 0 || x > 26) return(-2); /* Not in range */
3345: if (a_ptr[x] == NULL) return(-1); /* Not declared */
3346: if (i > a_dim[x]) return(-2); /* Declared but out of range. */
3347: return(a_dim[x]); /* All ok, return dimension */
3348: }
3349:
3350: char *
3351: arrayval(a,i) int a, i; { /* Return value of \&a[i] */
3352: int x; char **p; /* (possibly NULL) */
3353:
3354: if (a == 64) a = 96; /* Convert atsign to grave accent */
3355: x = a - 96; /* Values must be in range 96-122 */
3356: if (x < 0 || x > 26) return(NULL); /* Not in range */
3357: if ((p = a_ptr[x]) == NULL) /* Array not declared */
3358: return(NULL);
3359: if (i > a_dim[x]) /* Subscript out of range. */
3360: return(NULL);
3361: return(p[i]); /* All ok, return pointer to value. */
3362: }
3363: #endif /* NOSPL */
3364:
3365: #ifndef NOSPL
3366: /* P A R S E V A R -- Parse a variable name or array reference. */
3367: /*
3368: Call with:
3369: s = pointer to candidate variable name or array reference.
3370: *c = address of integer in which to return variable ID.
3371: *i = address of integer in which to return array subscript.
3372: Returns:
3373: -2: syntax error in variable name or array reference.
3374: 1: successful parse of a simple variable, with ID in c.
3375: 2: successful parse of an array reference, w/ID in c and subscript in i.
3376: */
3377: int
3378: parsevar(s,c,i) char *s; int *c, *i; {
3379: char *p;
3380: int x,y,z;
3381:
3382: p = s;
3383: if (*s == CMDQ) s++; /* Point after backslash */
3384:
3385: if (*s != '%' && *s != '&') { /* Make sure it's % or & */
3386: printf("?Not a variable name - %s\n",p);
3387: return(-9);
3388: }
3389: if ((int)strlen(s) < 2) {
3390: printf("?Incomplete variable name - %s\n",p);
3391: return(-9);
3392: }
3393: if (*s == '%' && *(s+2) != '\0') {
3394: printf("?Only one character after '%%' in variable name, please\n");
3395: return(-9);
3396: }
3397: if (*s == '&' && *(s+2) != '[') {
3398: printf("?Array subscript expected - %s\n",p);
3399: return(-9);
3400: }
3401: if (*s == '%') { /* Simple variable. */
3402: y = *(s+1); /* Get variable ID letter/char */
3403: if (isupper(y)) y -= ('a'-'A'); /* Convert upper to lower case */
3404: *c = y; /* Set the return values. */
3405: *i = -1; /* No array subscript. */
3406: return(1); /* Return 1 = simple variable */
3407: }
3408: if (*s == '&') { /* Array reference. */
3409: if (arraynam(s,&x,&z) < 0) { /* Go parse it. */
3410: printf("?Invalid array reference - %s\n",p);
3411: return(-9);
3412: }
3413: if (chkarray(x,z) < 0) { /* Check if declared, etc. */
3414: printf("?Array not declared or subscript out of range\n");
3415: return(-9);
3416: }
3417: *c = x; /* Return array letter */
3418: *i = z; /* and subscript. */
3419: return(2);
3420: }
3421: return(-2); /* None of the above. */
3422: }
3423:
3424: #define VALN 20
3425:
3426: /* Get the numeric value of a variable */
3427: /*
3428: Call with pointer to variable name, pointer to int for return value.
3429: Returns:
3430: 0 on success with second arg containing the value.
3431: -1 on failure (bad variable syntax, variable not defined or not numeric).
3432: */
3433: int
3434: varval(s,v) char *s; int *v; {
3435: char valbuf[VALN+1]; /* s is pointer to variable name */
3436: char *p;
3437: int y;
3438:
3439: p = valbuf; /* Expand variable into valbuf. */
3440: y = VALN;
3441: if (xxstring(s,&p,&y) < 0) return(-1);
3442: p = valbuf; /* Make sure value is numeric */
3443: if (!chknum(p)) return(-1);
3444: *v = atoi(p); /* Convert numeric string to int */
3445: return(0);
3446: }
3447:
3448: /* Increment or decrement a variable */
3449: /* Returns -1 on failure, 0 on success, with 4th argument set to result */
3450:
3451: int
3452: incvar(s,x,z,r) char *s; int x, z, *r; { /* Increment a numeric variable */
3453: char valbuf[VALN+1]; /* s is pointer to variable name */
3454: /* x is amount to increment by */
3455: int n; /* z != 0 means add */
3456: /* z = 0 means subtract */
3457:
3458: if (varval(s,&n) < 0) /* Convert numeric string to int */
3459: return(-1);
3460: if (z) /* Increment it by the given amount */
3461: n += x;
3462: else /* or decrement as requested. */
3463: n -= x;
3464: sprintf(valbuf,"%d",n); /* Convert back to numeric string */
3465: addmac(s,valbuf); /* Replace old variable */
3466: *r = n; /* Return the integer value */
3467: return(0);
3468: }
3469: #endif /* NOSPL */
3470:
3471: /* Functions moved here from ckuusr.c to even out the module sizes... */
3472:
3473: #ifndef NOSPL /* Need xwords() function to break */
3474: #define XWORDS /* string up into words. */
3475: #endif /* NOSPL */
3476: #ifndef NODIAL
3477: #ifndef XWORDS
3478: #define XWORDS
3479: #endif /* XWORDS */
3480: #endif /* NODIAL */
3481:
3482: #ifdef XWORDS
3483: /*
3484: Breaks string s up into a list of up to max words.
3485: Pointers to each word go into the array list[].
3486: If list is NULL, then they are added to the macro table.
3487: */
3488:
3489: VOID
3490: xwords(s,max,list) char *s; int max; char *list[]; {
3491: char *p;
3492: int b, k, y, z;
3493: #ifndef NOSPL
3494: int macro;
3495: macro = (list == NULL);
3496: debug(F101,"xwords macro","",macro);
3497: #endif /* NOSPL */
3498:
3499: p = s; /* Pointer to beginning of string */
3500: b = 0; /* Flag for outer brace removal */
3501: k = 0; /* Flag for in-word */
3502: y = 0; /* Brace nesting level */
3503: z = 0; /* Argument counter, 0 thru max */
3504:
3505: while (1) { /* Go thru argument list */
3506: if (!s || (*s == '\0')) { /* No more characters? */
3507: if (k != 0) {
3508: if (z == max) break; /* Only go up to max. */
3509: z++; /* Count it. */
3510: #ifndef NOSPL
3511: if (macro) {
3512: varnam[1] = z + '0'; /* Assign last argument */
3513: addmac(varnam,p);
3514: } else
3515: #endif /* NOSPL */
3516: list[z] = p;
3517: break; /* And get out. */
3518: } else break;
3519: }
3520: if (k == 0 && (*s == SP || *s == HT)) { /* Eat leading blanks */
3521: s++;
3522: continue;
3523: } else if (*s == '{') { /* An opening brace */
3524: if (k == 0 && y == 0) { /* If leading brace */
3525: p = s+1; /* point past it */
3526: b = 1; /* and flag that we did this */
3527: }
3528: k = 1; /* Flag that we're in a word */
3529: y++; /* Count the brace. */
3530: } else if (*s == '}') { /* A closing brace. */
3531: y--; /* Count it. */
3532: if (y == 0 && b != 0) { /* If it matches the leading brace */
3533: *s = SP; /* change it to a space */
3534: b = 0; /* and we're not in braces any more */
3535: } else if (y < 0) k = 1; /* otherwise just start a new word. */
3536: } else if (*s != SP && *s != HT) { /* Nonspace means we're in a word */
3537: if (k == 0) p = s; /* Mark the beginning */
3538: k = 1; /* Set in-word flag */
3539: }
3540: /* If we're not inside a braced quantity, and we are in a word, and */
3541: /* we have hit whitespace, then we have an argument to assign. */
3542: if ((y < 1) && (k != 0) && (*s == SP || *s == HT)) {
3543: *s = '\0'; /* terminate the arg with null */
3544: k = 0; /* say we're not in a word any more */
3545: y = 0; /* start braces off clean again */
3546: if (z == max) break; /* Only go up to max. */
3547: z++; /* count this arg */
3548: #ifndef NOSPL
3549: if (macro) {
3550: varnam[1] = z + '0'; /* compute its name */
3551: addmac(varnam,p); /* add it to the macro table */
3552: } else
3553: #endif /* NOSPL */
3554: list[z] = p;
3555: p = s+1;
3556: }
3557: s++; /* Point past this character */
3558: }
3559: if ((z == 0) && (y > 1)) { /* Extra closing brace(s) at end */
3560: z++;
3561: #ifndef NOSPL
3562: if (macro) {
3563: varnam[1] = z + '0'; /* compute its name */
3564: addmac(varnam,p); /* Add rest of line to last arg */
3565: } else
3566: #endif /* NOSPL */
3567: list[z] = p;
3568: }
3569: #ifndef NOSPL
3570: if (macro) macargc[maclvl] = z + 1; /* Set \v(argc) variable */
3571: #endif /* NOSPL */
3572: return;
3573: }
3574: #endif /* XWORDS */
3575:
3576: #ifndef NOSPL
3577: /* D O D O -- Do a macro */
3578:
3579: /*
3580: Call with x = macro table index, s = pointer to arguments.
3581: Returns 0 on failure, 1 on success.
3582: */
3583:
3584: int
3585: dodo(x,s) int x; char *s; {
3586: int y;
3587:
3588: debug(F101,"dodo maclvl","",maclvl);
3589: if (++maclvl > MACLEVEL) { /* Make sure we have storage */
3590: debug(F101,"dodo maclvl too deep","",maclvl);
3591: --maclvl;
3592: printf("Macros nested too deeply\n");
3593: return(0);
3594: }
3595: macp[maclvl] = mactab[x].mval; /* Point to the macro body */
3596: macx[maclvl] = mactab[x].mval; /* Remember where the beginning is */
3597: debug(F111,"do macro",macp[maclvl],maclvl);
3598:
3599: cmdlvl++; /* Entering a new command level */
3600: if (cmdlvl > CMDSTKL) { /* Too many macros + TAKE files? */
3601: debug(F101,"dodo cmdlvl too deep","",cmdlvl);
3602: cmdlvl--;
3603: printf("?TAKE files and DO commands nested too deeply\n");
3604: return(0);
3605: }
3606: #ifdef VMS
3607: conres(); /* So Ctrl-C, etc, will work. */
3608: #endif /* VMS */
3609: ifcmd[cmdlvl] = 0;
3610: iftest[cmdlvl] = 0;
3611: count[cmdlvl] = 0;
3612: cmdstk[cmdlvl].src = CMD_MD; /* Say we're in a macro */
3613: cmdstk[cmdlvl].lvl = maclvl; /* and remember the macro level */
3614: mrval[maclvl] = NULL; /* Initialize return value */
3615:
3616: debug(F110,"do macro",mactab[x].kwd,0);
3617:
3618: /* Clear old %0..%9 arguments */
3619:
3620: addmac("%0",mactab[x].kwd); /* Define %0 = name of macro */
3621: varnam[0] = '%';
3622: varnam[2] = '\0';
3623: for (y = 1; y < 10; y++) { /* Clear args %1..%9 */
3624: varnam[1] = y + '0';
3625: delmac(varnam);
3626: }
3627:
3628: /* Assign the new args one word per arg, allowing braces to group words */
3629:
3630: xwords(s,9,NULL);
3631: return(1);
3632: }
3633:
3634: /* Insert "literal" quote around each comma-separated command to prevent */
3635: /* its premature expansion. Only do this if object command is surrounded */
3636: /* by braces. */
3637:
3638: static char* flit = "\\flit(";
3639:
3640: int
3641: litcmd(src,dest) char **src, **dest; {
3642: int bc = 0, pp = 0;
3643: char *s, *lp, *ss;
3644:
3645: s = *src;
3646: lp = *dest;
3647:
3648: while (*s == SP) s++; /* strip extra leading spaces */
3649: if (*s == '{') {
3650:
3651: pp = 0; /* paren counter */
3652: bc = 1; /* count leading brace */
3653: *lp++ = *s++; /* copy it */
3654: while (*s == SP) s++; /* strip interior leading spaces */
3655: ss = flit; /* point to "\flit(" */
3656: while (*lp++ = *ss++) ; /* copy it */
3657: lp--; /* back up over null */
3658: while (*s) { /* go thru rest of text */
3659: ss = flit; /* point back to start of "\flit(" */
3660: if (*s == '{') bc++; /* count brackets */
3661: if (*s == '(') pp++; /* and parens */
3662: if (*s == ')') pp--;
3663: if (*s == '}') { /* Closing brace. */
3664: if (--bc == 0) { /* Final one? */
3665: *lp++ = ')'; /* Add closing paren for "\flit()" */
3666: *lp++ = *s++;
3667: break;
3668: }
3669: }
3670: if (*s == ',' && pp == 0) { /* comma not inside of parens */
3671: *lp++ = ')'; /* closing ) of \flit( */
3672: *lp++ = ','; /* insert the comma */
3673: while (*lp++ = *ss++) ; /* start new "\flit(" */
3674: lp--; /* back up over null */
3675: s++; /* skip over comma in source string */
3676: while (*s++ == SP); /* eat leading spaces again. */
3677: s--; /* back up over nonspace */
3678: continue;
3679: }
3680: *lp++ = *s++; /* Copy anything but comma here. */
3681: }
3682: *lp = NUL;
3683: } else { /* No brackets around, */
3684: while (*lp++ = *s++) ; /* just copy. */
3685: lp--;
3686: }
3687: *src = s;
3688: *dest = lp;
3689: if (bc) return(-1);
3690: else return(0);
3691: }
3692: #endif /* NOSPL */
3693:
3694: int
3695: docd() { /* Do the CD command */
3696: int x;
3697: char *s;
3698:
3699: #ifdef GEMDOS
3700: if ((x = cmdir("Name of local directory, or carriage return",homdir,&s,
3701: NULL)) < 0 )
3702: #else
3703: if ((x = cmdir("Name of local directory, or carriage return",homdir,&s,
3704: xxstring)) < 0 )
3705: #endif /* GEMDOS */
3706: return(x);
3707: if (x == 2) {
3708: printf("?Wildcards not allowed in directory name\n");
3709: return(-9);
3710: }
3711: strcpy(line,s); /* Make a safe copy */
3712: s = line;
3713: if ((x = cmcfm()) < 0) /* Get confirmation */
3714: return(x);
3715: if (! zchdir(s)) {
3716: cwdf = 0;
3717: perror(s);
3718: } else cwdf = 1;
3719: #ifdef OS2
3720: printf("%s\n", zgtdir());
3721: #else /* Not OS2 */
3722: #ifndef MAC
3723: zsyscmd(PWDCMD); /* assume this works... */
3724: #endif /* MAC */
3725: #endif /* OS2 */
3726: return(cwdf);
3727: }
3728:
3729: VOID
3730: fixcmd() { /* Fix command parser after interruption */
3731: dostop(); /* Back to top level (also calls conint()). */
3732: bgchk(); /* Check background status */
3733: if (*psave) { /* If old prompt saved, */
3734: cmsetp(psave); /* restore it. */
3735: *psave = NUL;
3736: }
3737: success = 0; /* Tell parser last command failed */
3738: }
3739:
3740: VOID
3741: prtopt(s) char *s; { /* Print an option */
3742: static int x = 0; /* (used by SHOW VER) */
3743: int y; /* Does word wrap. */
3744: if (!s) { x = 0; return; } /* Call with null pointer to */
3745: y = (int)strlen(s); /* reset horizontal position. */
3746: x += y;
3747: if (x > 79) {
3748: printf("\n%s",s);
3749: x = y;
3750: } else printf("%s",s);
3751: }
3752:
3753: #endif /* NOICP */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.