|
|
1.1 root 1: #ifndef NOICP
2:
3: /* C K U U S 6 -- "User Interface" for Unix Kermit (Part 6) */
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, copy, or
11: redistribute this software so long as it is not sold for profit, provided this
12: copyright notice is retained.
13: */
14:
15: /* Includes */
16:
17: #include "ckcdeb.h"
18: #include "ckcasc.h"
19: #include "ckcker.h"
20: #include "ckuusr.h"
21: #include "ckcxla.h"
22: #include "ckcnet.h" /* Network symbols */
23:
24: #ifdef datageneral
25: #define fgets(stringbuf,max,fd) dg_fgets(stringbuf,max,fd)
26: #endif /* datageneral */
27:
28: #ifdef MAC /* internal MAC file routines */
29: #define feof mac_feof
30: #define rewind mac_rewind
31: #define fgets mac_fgets
32: #define fopen mac_fopen
33: #define fclose mac_fclose
34:
35: int mac_feof();
36: void mac_rewind();
37: char *mac_fgets();
38: FILE *mac_fopen();
39: int mac_fclose();
40: #endif /* MAC */
41:
42: /* External Kermit Variables, see ckmain.c for description. */
43:
44: extern int size, rpsiz, urpsiz, local, stdinf, sndsrc, xitsta,
45: displa, binary, parity, escape, xargc, flow,
46: turn, duplex, nfils, ckxech, pktlog, seslog, tralog, stdouf,
47: turnch, dfloc, keep, maxrps, warn, quiet, cnflg, tlevel, pflag,
48: mdmtyp, zincnt, fblksiz, frecl, frecfm, atcapr, atdiso, verwho;
49: extern int repars, terror, techo;
50:
51: extern long vernum, speed;
52: extern char *versio, *protv, *ckxv, *ckzv, *fnsv, *connv, *dftty, *cmdv;
53: extern char *dialv, *loginv, *for_def[], *whil_def[], *xif_def[];
54: extern char *ckxsys, *ckzsys, *cmarg, *cmarg2, **xargv, **cmlist;
55: extern char *DIRCMD, *PWDCMD, *DELCMD, *WHOCMD, ttname[], filnam[];
56: extern CHAR sstate;
57: extern char *zinptr;
58:
59: #ifndef NOMSEND /* Multiple SEND */
60: extern char *msfiles[];
61: #endif /* NOMSEND */
62: extern char fspec[]; /* Most recent filespec */
63:
64: /* Declarations from cmd package */
65:
66: #ifdef DCMDBUF
67: extern char *cmdbuf, *atmbuf; /* Command buffers */
68: #else
69: extern char cmdbuf[], atmbuf[]; /* Command buffers */
70: #endif /* DCMDBUF */
71:
72: #ifndef NOSPL
73: extern struct mtab *mactab;
74: extern int nmac;
75: #endif /* NOSPL */
76:
77: /* Declarations from ck?fio.c module */
78:
79: extern char *SPACMD; /* Space command, home directory. */
80: extern int backgrd, bgset; /* Kermit executing in background */
81:
82: #ifndef NOSPL
83: extern char vnambuf[]; /* Buffer for variable names */
84: extern char *vnp; /* Pointer to same */
85: #endif /* NOSPL */
86:
87: extern char psave[]; /* For saving & restoring prompt */
88: extern char tmpbuf[], *tp; /* Temporary buffer */
89:
90: /* Keyword tables specific to this module */
91:
92: /* Modem signal table */
93:
94: struct keytab mstab[] = {
95: #ifdef COMMENT
96: /* The forms preceded by backslash are for MS-DOS Kermit compatibility. */
97: /* But... \dsr doesn't work because \d = decimal constant introducer */
98: "\\cd", BM_DCD, CM_INV, /* Carrier Detect */
99: "\\cts", BM_CTS, CM_INV, /* Clear To Send */
100: "\\dsr", BM_DSR, CM_INV, /* Data Set Ready */
101: "\\ri", BM_RNG, CM_INV, /* Ring Indicator */
102: #endif /* COMMENT */
103: "cd", BM_DCD, 0, /* Carrier Detect */
104: "cts", BM_CTS, 0, /* Clear To Send */
105: "dsr", BM_DSR, 0, /* Data Set Ready */
106: "ri", BM_RNG, 0 /* Ring Indicator */
107: };
108: int nms = (sizeof(mstab) / sizeof(struct keytab));
109:
110: #ifndef NOSPL
111: struct keytab opntab[] = {
112: #ifndef NOPUSH
113: "!read", XYFZ_Y, 0,
114: "!write", XYFZ_X, 0,
115: #endif /* NOPUSH */
116: "append", XYFZ_A, 0,
117: "read", XYFZ_O, 0,
118: "write", XYFZ_N, 0
119: };
120: int nopn = (sizeof(opntab) / sizeof(struct keytab));
121:
122: struct keytab iftab[] = { /* IF commands */
123: "<", XXIFLT, 0,
124: "=", XXIFAE, 0,
125: ">", XXIFGT, 0,
126: "background", XXIFBG, 0,
127: "count", XXIFCO, 0,
128: "defined", XXIFDE, 0,
129: #ifdef COMMENT
130: "eof", XXIFEO, 0,
131: #endif /* COMMENT */
132: "equal", XXIFEQ, 0,
133: "exist", XXIFEX, 0,
134: "failure", XXIFFA, 0,
135: "llt", XXIFLL, 0,
136: "lgt", XXIFLG, 0,
137: "not", XXIFNO, 0,
138: "numeric", XXIFNU, 0,
139: "success", XXIFSU, 0
140: };
141: int nif = (sizeof(iftab) / sizeof(struct keytab));
142: #endif /* NOSPL */
143:
144: /* Variables and symbols local to this module */
145:
146: #ifndef NODIAL /* Remember DIAL number for REDIAL */
147: char *dialnum = (char *)0;
148: #endif /* NODIAL */
149:
150: #ifndef NOSPL
151: int ifc, /* IF case */
152: not = 0, /* Flag for IF NOT */
153: ifargs; /* Count of IF condition words */
154: char ifcond[100]; /* IF condition text */
155: char *ifcp; /* Pointer to IF condition text */
156: #ifdef DCMDBUF
157: extern int *ifcmd, *count, *iftest;
158: #else
159: extern int ifcmd[]; /* Last command was IF */
160: extern int iftest[]; /* Last IF was true */
161: extern int count[]; /* For IF COUNT, one for each cmdlvl */
162: #endif /* DCMDBUF */
163: #endif /* NOSPL */
164:
165: #ifdef DCMDBUF
166: extern char *line; /* Character buffer for anything */
167: #else
168: extern char line[];
169: #endif /* DCMDBUF */
170: extern char *lp; /* Pointer to line buffer */
171:
172: int cwdf = 0; /* CWD has been done */
173:
174: extern int en_cwd, en_del, en_dir, en_fin, /* Flags for ENABLE/DISABLE */
175: en_get, en_hos, en_sen, en_set, en_spa, en_typ, en_who, en_bye;
176:
177: extern FILE *tfile[]; /* File pointers for TAKE command */
178:
179: extern int success; /* Command success/failure flag */
180:
181: #ifndef NOSPL
182: extern int /* SET INPUT parameters. */
183: incase;
184:
185: extern int maclvl; /* Macro to execute */
186: extern char *macx[]; /* Index of current macro */
187: extern char *mrval[]; /* Macro return value */
188: extern char *macp[]; /* Pointer to macro */
189: extern int macargc[]; /* ARGC from macro invocation */
190:
191: extern char *m_arg[MACLEVEL][NARGS]; /* Stack of macro arguments */
192: extern char *g_var[]; /* Global variables %a, %b, etc */
193:
194: #ifdef DCMDBUF
195: extern struct cmdptr *cmdstk; /* The command stack itself */
196: #else
197: extern struct cmdptr cmdstk[]; /* The command stack itself */
198: #endif /* DCMDBUF */
199: extern int cmdlvl; /* Current position in command stack */
200: #endif /* NOSPL */
201:
202: #define xsystem(s) zsyscmd(s)
203:
204: static int x, y, z = 0;
205: static char *s, *p;
206:
207: #ifndef NOSPL
208:
209: /* Do the ASK, ASKQ, GETOK, and READ commands */
210:
211: #ifndef NOFRILLS
212: extern struct keytab yesno[];
213: extern int nyesno;
214: #endif /* NOFRILLS */
215:
216: int
217: doask(cx) int cx; {
218:
219: if (cx != XXGOK) { /* Get variable name */
220: if ((y = cmfld("Variable name","",&s,NULL)) < 0) {
221: if (y == -3) {
222: printf("?Variable name required\n");
223: return(-9);
224: } else return(y);
225: }
226: strcpy(line,s); /* Make a copy. */
227: lp = line;
228: if ((y = parsevar(s,&x,&z)) < 0) /* Check to make sure it's a */
229: return(y); /* variable name. */
230: }
231: if (cx == XXREA) { /* READ command */
232: if ((y = cmcfm()) < 0) /* Get confirmation */
233: return(y);
234: if (chkfn(ZRFILE) < 1) { /* File open? */
235: printf("?Read file not open\n");
236: return(0);
237: }
238: s = line+VNAML+1; /* Where to read into. */
239: y = zsinl(ZRFILE, s, LINBUFSIZ - VNAML - 1); /* Read a line. */
240: debug(F111,"read zsinl",s,y);
241: if (y < 0) { /* On EOF or other error, */
242: zclose(ZRFILE); /* close the file, */
243: delmac(lp); /* delete the variable, */
244: return(success = 0); /* and return failure. */
245: } else { /* Read was OK. */
246: success = (addmac(lp,s) < 0 ? 0 : 1); /* Define the variable */
247: debug(F111,"read addmac",lp,success);
248: return(success); /* Return success. */
249: }
250: }
251:
252: /* ASK, ASKQ, or GETOK */
253:
254: if ((y = cmtxt("Prompt, enclose in { braces } to preserve\n\
255: leading and trailing spaces, precede question mark with backslash (\\).",
256: "",&p,xxstring)) < 0) return(y);
257:
258: cmsavp(psave,80); /* Save old prompt */
259: if (*p == '{') { /* New prompt enclosed in braces? */
260: x = (int)strlen(p) - 1; /* Yes, strip them. */
261: if (p[x] == '}') {
262: p[x] = NUL;
263: p++;
264: }
265: }
266: cmsetp(p); /* Make new prompt */
267: if (cx == XXASKQ) { /* For ASKQ, */
268: concb((char)escape); /* put console in cbreak mode */
269: cmini(0); /* and no-echo mode. */
270: } else { /* For others, regular echoing. */
271: cmini(ckxech);
272: }
273: x = -1; /* This means to reparse. */
274: reprompt:
275: if (pflag) prompt(xxstring); /* Issue prompt. */
276: if (cx == XXGOK) {
277: #ifndef NOFRILLS
278: x = cmkey(yesno,nyesno,"","",xxstring); /* GETOK uses keyword table */
279: if (x < 0) { /* Parse error */
280: if (x == -3) { /* No answer? */
281: printf("Please respond Yes or No\n"); /* Make them answer */
282: cmini(ckxech);
283: }
284: goto reprompt;
285: }
286: if ((y = cmcfm()) < 0) /* Get confirmation */
287: goto reprompt;
288: cmsetp(psave); /* Restore prompt */
289: return(x); /* Return success or failure */
290: #else
291: ;
292: #endif /* NOFRILLS */
293: } else { /* ASK or ASKQ */
294: while (x == -1) { /* Prompt till they answer */
295: x = cmtxt("please respond.\n\
296: type \\? to include a question mark","",&s,NULL);
297: debug(F111," cmtxt",s,x);
298: }
299: if (cx == XXASKQ) /* ASKQ must echo CRLF here */
300: printf("\r\n");
301: if (x < 0) { /* If cmtxt parse error, */
302: cmsetp(psave); /* restore original prompt */
303: return(x); /* and return cmtxt's error code. */
304: }
305: if (*s == NUL) { /* If user typed a bare CR, */
306: cmsetp(psave); /* Restore old prompt, */
307: delmac(lp); /* delete variable if it exists, */
308: return(success = 1); /* and return. */
309: }
310: y = addmac(lp,s); /* Add it to the macro table. */
311: debug(F111,"ask addmac",lp,y);
312: cmsetp(psave); /* Restore old prompt. */
313: return(success = y < 0 ? 0 : 1);
314: }
315: }
316: #endif /* NOSPL */
317:
318: #ifndef NOSPL
319: int
320: doincr(cx) int cx; { /* INCREMENT, DECREMENT */
321: if ((y = cmfld("Variable name","",&s,NULL)) < 0) {
322: if (y == -3) {
323: printf("?Variable name required\n");
324: return(-9);
325: } else return(y);
326: }
327: if (*s != CMDQ) {
328: *vnambuf = CMDQ;
329: strncpy(vnambuf+1,s,VNAML-1);
330: } else strncpy(vnambuf,s,VNAML);
331:
332: if ((y = parsevar(vnambuf,&x,&z)) < 0)
333: return(y);
334:
335: if ((y = cmnum("by amount","1",10,&x,xxstring)) < 0) return(y);
336: if ((y = cmcfm()) < 0) return(y);
337:
338: z = (cx == XXINC ? 1 : 0); /* Increment or decrement? */
339:
340: if (incvar(vnambuf,x,z,&y) < 0) {
341: printf("?Variable %s not defined or not numeric\n",vnambuf);
342: return(success = 0);
343: }
344: return(success = 1);
345: }
346: #endif /* NOSPL */
347:
348:
349: /* Do the DEFINE and ASSIGN commands */
350:
351: #ifndef NOSPL
352: int
353: dodef(cx) int cx; {
354: if ((y = cmfld("Macro or variable name","",&s,NULL)) < 0) {
355: if (y == -3) {
356: printf("?Variable name required\n");
357: return(-9);
358: } else return(y);
359: }
360: debug(F110,"dodef",s,0);
361: strcpy(vnambuf,s);
362: vnp = vnambuf;
363: if (vnambuf[0] == CMDQ && (vnambuf[1] == '%' || vnambuf[1] == '&')) vnp++;
364: if (*vnp == '%' || *vnp == '&') {
365: if ((y = parsevar(vnp,&x,&z)) < 0) return(y);
366: debug(F101,"dodef","",x);
367: if (y == 1) { /* Simple variable */
368: if ((y = cmtxt("Definition of variable","",&s,NULL)) < 0)
369: return(y);
370: debug(F110,"xxdef var name",vnp,0);
371: debug(F110,"xxdef var def",s,0);
372: } else if (y == 2) { /* Array element */
373: if ((y = arraynam(s,&x,&z)) < 0) return(y);
374: if (x == 96) {
375: printf("?Argument vector array is read-only\n");
376: return(-9);
377: }
378: if (chkarray(x,z) < 0) return(-2);
379: if ((y = cmtxt("Definition of array element","",&s,NULL)) < 0)
380: return(y);
381: debug(F110,"xxdef array ref",vnp,0);
382: debug(F110,"xxdef array def",s,0);
383: }
384: } else { /* Macro */
385: if ((y = cmtxt("Definition of macro","",&s,NULL)) < 0) return(y);
386: debug(F110,"xxdef macro name",vnp,0);
387: debug(F110,"xxdef macro def",s,0);
388: if (*s == '{') { /* Allow macro def to be bracketed. */
389: s++; /* If it is, remove the brackets. */
390: y = (int)strlen(s); /* FOR command depends on this! */
391: if (y > 0 && s[y-1] == '}') s[y-1] = NUL;
392: }
393: }
394: if (*s == NUL) { /* No arg given, undefine */
395: delmac(vnp); /* silently... */
396: return(success = 1); /* even if it doesn't exist... */
397: }
398:
399: /* Defining a new macro or variable */
400:
401: if (cx == XXASS) { /* ASSIGN rather than DEFINE? */
402: int t;
403: t = LINBUFSIZ-1;
404: lp = line; /* If so, expand its value now */
405: xxstring(s,&lp,&t);
406: s = line;
407: }
408: debug(F111,"calling addmac",s,(int)strlen(s));
409:
410: y = addmac(vnp,s); /* Add it to the appropriate table. */
411: if (y < 0) {
412: printf("?%s failed\n",cx == XXASS ? "Assign" : "Define");
413: return(success = 0);
414: }
415: return(success = 1);
416: }
417: #endif /* NOSPL */
418:
419:
420: #ifndef NODIAL
421: int
422: dodial(cx) int cx; { /* DIAL or REDIAL */
423: if (cx == XXRED) { /* REDIAL or... */
424: if ((y = cmcfm()) < 0) return(y);
425: if (dialnum) {
426: s = dialnum;
427: } else {
428: printf("?No DIAL command given yet\n");
429: return(-9);
430: }
431: } else if (cx == XXDIAL) {
432: if ((x = cmtxt("Number to be dialed","",&s,xxstring)) < 0)
433: return(x);
434: if (s == NULL || (int)strlen(s) == 0) {
435: printf("?You must specify a number to dial\n");
436: return(-9);
437: }
438: if (dialnum) free(dialnum); /* Make copy for REDIAL */
439: dialnum = malloc((int)strlen(s) + 1);
440: if (dialnum) strcpy(dialnum,s);
441: } else return(-2);
442: #ifdef VMS
443: conres(); /* So Ctrl-C/Y will work */
444: #endif /* VMS */
445: success = ckdial(s); /* Try to dial */
446: #ifdef VMS
447: concb((char)escape); /* Back to command parsing mode */
448: #endif /* VMS */
449: return(success);
450: }
451: #endif /* NODIAL */
452:
453: #ifndef MAC
454: int /* Do the DIRECTORY command */
455: dodir() {
456: char *dc;
457: #ifdef VMS
458: if ((x = cmtxt("Directory/file specification","",&s,xxstring)) < 0)
459: return(x);
460: /* now do this the same as a shell command - helps with LAT */
461: conres(); /* make console normal */
462: lp = line;
463: if (!(dc = getenv("CK_DIR"))) dc = DIRCMD;
464: sprintf(lp,"%s %s",dc,s);
465: debug(F110,"Directory string: ", line, 0);
466: xsystem(lp);
467: return(success = 0);
468: #else
469: #ifdef AMIGA
470: if ((x = cmtxt("Directory/file specification","",&s,xxstring)) < 0)
471: return(x);
472: #else
473: #ifdef datageneral
474: if ((x = cmtxt("Directory/file specification","+",&s,xxstring)) < 0)
475: return(x);
476: #else /* General Case */
477: if ((x = cmdir("Directory/file specification","",&s,xxstring)) < 0)
478: if (x != -3) return(x);
479: strcpy(tmpbuf,s);
480: if ((y = cmcfm()) < 0) return(y);
481: s = tmpbuf;
482: #endif /* datageneral */
483: #endif /* AMIGA */
484: /* General case again */
485: lp = line;
486: if (!(dc = getenv("CK_DIR"))) dc = DIRCMD;
487: sprintf(lp,"%s %s",dc,s);
488: xsystem(line);
489: return(success = 1); /* who cares... */
490: #endif /* VMS */
491: }
492: #endif /* MAC */
493:
494: #ifndef NOFRILLS
495: /* Do the ENABLE and DISABLE commands */
496:
497: int
498: doenable(cx,x) int cx, x; {
499: y = ((cx == XXENA) ? 1 : 0);
500: switch (x) {
501: case EN_ALL:
502: en_cwd = en_del = en_dir = en_fin = en_get = en_bye = y;
503: en_sen = en_set = en_spa = en_typ = en_who = y;
504: #ifndef NOPUSH
505: en_hos = y;
506: #endif /* NOPUSH */
507: break;
508: case EN_BYE:
509: en_bye = y;
510: break;
511: case EN_CWD:
512: en_cwd = y;
513: break;
514: case EN_DEL:
515: en_del = y;
516: break;
517: case EN_DIR:
518: en_dir = y;
519: break;
520: case EN_FIN:
521: en_fin = y;
522: break;
523: case EN_GET:
524: en_get = y;
525: break;
526: #ifndef NOPUSH
527: case EN_HOS:
528: en_hos = y;
529: break;
530: #endif /* NOPUSH */
531: case EN_SEN:
532: en_sen = y;
533: break;
534: case EN_SET:
535: en_set = y;
536: break;
537: case EN_SPA:
538: en_spa = y;
539: break;
540: case EN_TYP:
541: en_typ = y;
542: break;
543: case EN_WHO:
544: en_who = y;
545: break;
546: default:
547: return(-2);
548: }
549: return(1);
550: }
551: #endif /* NOFRILLS */
552:
553: #ifndef NOFRILLS
554: int
555: dodel() { /* DELETE */
556: long zl;
557: if ((x = cmifi("File(s) to delete","",&s,&y,xxstring)) < 0) {
558: if (x == -3) {
559: printf("?A file specification is required\n");
560: return(-9);
561: } else return(x);
562: }
563: #ifdef MAC
564: strcpy(line,s);
565: #else
566: strncpy(tmpbuf,s,50); /* Make a safe copy of the name. */
567: debug(F110,"xxdel tmpbuf",s,0);
568: sprintf(line,"%s %s",DELCMD,s); /* Construct the system command. */
569: #endif /* MAC */
570: debug(F110,"xxdel line",line,0);
571: if ((y = cmcfm()) < 0) return(y); /* Confirm the user's command. */
572: #ifdef VMS
573: conres();
574: #endif /* VMS */
575: #ifdef MAC
576: s = line;
577: success = (zdelet(line) == 0);
578: #else
579: s = tmpbuf;
580: xsystem(line); /* Let the system do it. */
581: zl = zchki(tmpbuf);
582: success = (zl == -1L);
583: #endif /* MAC */
584: #ifndef NOSPL
585: if (cmdlvl == 0 && pflag)
586: #else
587: if (tlevel == 0 && pflag)
588: #endif /* NOSPL */
589: {
590: if (success)
591: printf("%s - deleted\n",s);
592: else
593: printf("%s - not deleted\n",s);
594: }
595: return(success);
596: }
597: #endif /* NOFRILLS */
598:
599: #ifndef NOSPL /* The ELSE command */
600: int
601: doelse() {
602: if (!ifcmd[cmdlvl]) {
603: printf("?ELSE doesn't follow IF\n");
604: return(-2);
605: }
606: ifcmd[cmdlvl] = 0;
607: if (!iftest[cmdlvl]) { /* If IF was false do ELSE part */
608: if (maclvl > -1) { /* In macro, */
609: pushcmd(); /* save rest of command. */
610: } else if (tlevel > -1) { /* In take file, */
611: pushcmd(); /* save rest of command. */
612: } else { /* If interactive, */
613: cmini(ckxech); /* just start a new command */
614: printf("\n"); /* (like in MS-DOS Kermit) */
615: if (pflag) prompt(xxstring);
616: }
617: } else { /* Condition is false */
618: if ((y = cmtxt("command to be ignored","",&s,NULL)) < 0)
619: return(y); /* Gobble up rest of line */
620: }
621: return(0);
622: }
623: #endif /* NOSPL */
624:
625: #ifndef NOSPL
626: int
627: dofor() { /* The FOR command. */
628: int fx, fy, fz; /* loop variables */
629: char *ap; /* macro argument pointer */
630:
631: if ((y = cmfld("Variable name","",&s,NULL)) < 0) { /* Get variable name */
632: if (y == -3) {
633: printf("?Variable name required\n");
634: return(-9);
635: } else return(y);
636: }
637: if ((y = parsevar(s,&x,&z)) < 0) /* Check it. */
638: return(y);
639:
640: lp = line; /* Build a copy of the command */
641: strcpy(lp,"_forx ");
642: lp += (int)strlen(line); /* "_for" macro. */
643: ap = lp; /* Save pointer to macro args. */
644:
645: if (*s == CMDQ) s++; /* Skip past backslash if any. */
646: while (*lp++ = *s++) ; /* copy it */
647: lp--; *lp++ = SP; /* add a space */
648:
649: if ((y = cmnum("initial value","",10,&fx,xxstring)) < 0) {
650: if (y == -3) return(-2);
651: else return(y);
652: }
653: s = atmbuf; /* Copy the atom buffer */
654: if ((int)strlen(s) < 1) goto badfor;
655: while (*lp++ = *s++) ; /* (what they actually typed) */
656: lp--; *lp++ = SP;
657:
658: if ((y = cmnum("final value","",10,&fy,xxstring)) < 0) {
659: if (y == -3) return(-2);
660: else return(y);
661: }
662: s = atmbuf; /* Same deal */
663: if ((int)strlen(s) < 1) goto badfor;
664: while (*lp++ = *s++) ;
665: lp--; *lp++ = SP;
666:
667: if ((y = cmnum("increment","1",10,&fz,xxstring)) < 0) {
668: if (y == -3) return(-2);
669: else return(y);
670: }
671: sprintf(tmpbuf,"%d ",fz);
672: s = atmbuf; /* same deal */
673: if ((int)strlen(s) < 1) goto badfor;
674: while (*lp++ = *s++) ;
675: lp--; *lp++ = SP;
676:
677: /* Insert the appropriate comparison operator */
678: if (fz < 0)
679: *lp++ = '<';
680: else
681: *lp++ = '>';
682: *lp++ = SP;
683:
684: if ((y = cmtxt("Command to execute","",&s,NULL)) < 0) return(y);
685: if ((int)strlen(s) < 1) return(-2);
686:
687: if (litcmd(&s,&lp) < 0) {
688: printf("?Unbalanced brackets\n");
689: return(0);
690: }
691: if (fz == 0) {
692: printf("?Zero increment not allowed\n");
693: return(0);
694: }
695: x = mlook(mactab,"_forx",nmac); /* Look up FOR macro definition */
696: if (x < 0) { /* Not there? */
697: addmmac("_forx",for_def); /* Put it back. */
698: if (mlook(mactab,"_forx",nmac) < 0) { /* Look it up again. */
699: printf("?FOR macro definition gone!\n"); /* Shouldn't happen. */
700: return(success = 0);
701: }
702: }
703: return(success = dodo(x,ap)); /* Execute the FOR macro. */
704:
705: badfor: printf("?Incomplete FOR command\n");
706: return(-2);
707: }
708: #endif /* NOSPL */
709:
710: #ifndef NOFRILLS
711: /* Do the BUG command */
712:
713: int
714: dobug() {
715: printf("\n%s,%s\n Numeric: %ld",versio,ckxsys,vernum);
716: if (verwho) printf("-%d",verwho);
717: printf("\nTo report C-Kermit bugs, send e-mail to:\n");
718: printf(" [email protected] (Internet)\n");
719: printf(" KERMIT@CUVMA (EARN/BITNET)\n");
720: printf(" ...!uunet!columbia.edu!info-kermit (Usenet)\n");
721: printf("Or write to:\n Kermit Development\n Columbia University\n");
722: printf(" Center for Computing Activities\n 612 W 115 Street\n");
723: printf(" New York, NY 10025 USA\nOr call:\n (212) 854-5126 (USA)\n\n");
724: #ifndef NOSHOW
725: #ifndef NOFRILLS
726: printf(
727: "Before reporting problems, please use the SHOW VERSION command\n");
728: printf(
729: "to get detailed program version and configuration information.\n\n");
730: #endif /* NOFRILLS */
731: #endif /* NOSHOW */
732: return(1);
733: }
734: #endif /* NOFRILLS */
735:
736: #ifndef NOSPL
737: int
738: dopaus(cx) int cx; {
739: /* Both should take not only secs but also hh:mm:ss as argument. */
740: if (cx == XXWAI)
741: y = cmnum("seconds to wait","1",10,&x,xxstring);
742: else y = cmnum("seconds to pause","1",10,&x,xxstring);
743: if (y < 0) return(y);
744: if (x < 0) x = 0;
745: switch (cx) {
746: case XXPAU: /* PAUSE */
747: if ((y = cmcfm()) < 0) return(y);
748: break;
749: case XXWAI: /* WAIT */
750: z = 0; /* Modem signal mask */
751: while (1) { /* Read zero or more signal names */
752: y = cmkey(mstab,nms,"modem signal","",xxstring);
753: if (y == -3) break; /* -3 means they typed CR */
754: if (y < 0) return(y); /* Other negatives are errors */
755: z |= y; /* OR the bit into the signal mask */
756: }
757: break;
758:
759: default:
760: return(-2);
761: }
762:
763: /* Command is entered, now do it. */
764:
765: while (x--) { /* Sleep loop */
766: int mdmsig;
767: if (y = conchk()) { /* Did they type something? */
768: while (y--) coninc(0); /* Yes, gobble it up */
769: break; /* And quit PAUSing or WAITing */
770: }
771: if (cx == XXWAI && z != 0) {
772: mdmsig = ttgmdm();
773: if (mdmsig < 0) return(success = 0);
774: if ((mdmsig & z) == z) return(success = 1);
775: }
776: sleep(1); /* No interrupt, sleep one second */
777: }
778: if (cx == XXWAI) success = 0;
779: else success = (x == -1); /* Set SUCCESS/FAILURE for PAUSE. */
780: return(0);
781: }
782: #endif /* NOSPL */
783:
784:
785: #ifndef NOFRILLS
786: int
787: dorenam() {
788: if ((x = cmifi("File to rename","",&s,&y,xxstring)) < 0) {
789: if (x == -3) {
790: printf("?Name of existing file required\n");
791: return(-9);
792: } else return(x);
793: }
794: if (y) { /* No wildcards allowed */
795: printf("\n?Please specify a single file\n");
796: return(-9);
797: }
798: strcpy(line,s); /* Make a safe copy of the old name */
799: p = line + (int)strlen(line) + 2; /* Place for new name */
800: if ((x = cmofi("New name","",&s,xxstring)) < 0) { /* Get new name */
801: if (x == -3) {
802: printf("?New name for file required\n");
803: return(-9);
804: } else return(x);
805: }
806: strcpy(p,s); /* Make a safe copy of the new name */
807: if ((y = cmcfm()) < 0) return(y);
808: #ifdef VMS
809: conres(); /* Let Ctrl-C work. */
810: #endif /* VMS */
811: return(zrename(line,p));
812: }
813: #endif /* NOFRILLS */
814:
815:
816: #ifndef NOSPL
817: /* Do the RETURN command */
818:
819: int
820: doreturn(s) char *s; {
821: int x; char *p;
822: if (maclvl < 0) {
823: printf("\n?Can't return from level %d\n",maclvl);
824: return(success = 0);
825: }
826: lp = line; /* Expand return value now */
827: x = LINBUFSIZ-1;
828: if (xxstring(s,&lp,&x) > -1) {
829: s = line;
830: }
831: x = (int)strlen(s); /* Is there a return value? */
832: if (x) { /* Yes */
833: p = malloc(x+2); /* Allocate a place to keep it */
834: if (p) { /* Did we get a place? */
835: strcpy(p, s); /* Yes, copy the string into it. */
836: mrval[maclvl] = p; /* Make return value point to it. */
837: } else { /* No, could not get space. */
838: mrval[maclvl] = NULL; /* Return null pointer. */
839: x = 0; /* Set failure return code. */
840: }
841: } else mrval[maclvl] = NULL; /* Blank return code */
842: popclvl(); /* Pop command level */
843: if (mrval[maclvl+1])
844: debug(F111,"&return",mrval[maclvl+1],maclvl);
845: else debug(F111,"&return","NULL",maclvl);
846: return(success = x ? 1 : 0); /* Return status code */
847: }
848: #endif /* NOSPL */
849:
850: #ifndef NOSPL
851: /* Do the OPEN command */
852:
853: int
854: doopen() { /* OPEN { append, read, write } */
855: int x, y, z; char *s;
856: static struct filinfo fcb; /* (must be static) */
857: if ((x = cmkey(opntab,nopn,"mode","",xxstring)) < 0) {
858: if (x == -3) {
859: printf("?Mode required\n");
860: return(-9);
861: } else return(x);
862: }
863: switch (x) {
864: case XYFZ_O: /* Old file (READ) */
865: if (chkfn(ZRFILE) > 0) {
866: printf("?Read file already open\n");
867: return(-2);
868: }
869: if ((z = cmifi("File to read","",&s,&y,xxstring)) < 0) {
870: if (z == -3) {
871: printf("?Input filename required\n");
872: return(-9);
873: } else return(z);
874: }
875: if (y) { /* No wildcards allowed */
876: printf("\n?Please specify a single file\n");
877: return(-2);
878: }
879: strcpy(line,s);
880: if ((int)strlen(line) < 1) return(-2);
881: if ((y = cmcfm()) < 0) return(y);
882: return(success = zopeni(ZRFILE,line));
883:
884: #ifndef MAC
885: #ifndef NOPUSH
886: case XYFZ_Y: /* Pipe/Process (READ) */
887: if (chkfn(ZRFILE) > 0) {
888: printf("?Read file already open\n");
889: return(-2);
890: }
891: if ((y = cmtxt("System command to read from","",&s,xxstring)) < 0) {
892: if (y == -3) {
893: printf("?Command name required\n");
894: return(-9);
895: } else return(y);
896: }
897: strcpy(line,s);
898: if ((int)strlen(line) < 1) return(-2);
899: if ((y = cmcfm()) < 0) return(y);
900: return(success = zxcmd(ZRFILE,line));
901:
902: case XYFZ_X: /* Write to pipe */
903: if (chkfn(ZWFILE) > 0) {
904: printf("?Write file already open\n");
905: return(-2);
906: }
907: if ((y = cmtxt("System command to write to","",&s,xxstring)) < 0) {
908: if (y == -3) {
909: printf("?Command name required\n");
910: return(-9);
911: } else return(y);
912: }
913: strcpy(line,s);
914: if ((int)strlen(line) < 1) return(-2);
915: if ((y = cmcfm()) < 0) return(y);
916: return(success = zxcmd(ZWFILE,line));
917: #endif /* NOPUSH */
918: #endif /* MAC */
919:
920: case XYFZ_N: /* New file (WRITE) */
921: case XYFZ_A: /* (APPEND) */
922: if ((z = cmofi("Name of local file to create","",&s,xxstring)) < 0) {
923: if (z == -3) {
924: printf("?Filename required\n");
925: return(-9);
926: } else return(z);
927: }
928: if (chkfn(ZWFILE) > 0) {
929: printf("?Write/Append file already open\n");
930: return(-2);
931: }
932: fcb.bs = fcb.cs = fcb.rl = fcb.fmt = fcb.org = fcb.cc = fcb.typ = 0;
933: fcb.lblopts = 0;
934: fcb.dsp = x; /* Create or Append */
935: strcpy(line,s);
936: if ((int)strlen(line) < 1) return(-2);
937: if ((y = cmcfm()) < 0) return(y);
938: return(success = zopeno(ZWFILE,line,NULL,&fcb));
939:
940: default:
941: printf("?Not implemented");
942: return(-2);
943: }
944: }
945: #endif /* NOSPL */
946:
947: /* Finish parsing and do the GET command */
948:
949: int
950: doget() {
951: int x;
952:
953:
954: cmarg2 = ""; /* Initialize as-name to nothing */
955: x = 0;
956: #ifdef NOFRILLS
957: if (*cmarg == NUL) {
958: printf("?Remote filespec required\n");
959: return(-3);
960: }
961: #else
962: /*
963: If remote file name omitted, get foreign and local names separately.
964: But multine GET is allowed only if NOFRILLS is not defined.
965: */
966: if (*cmarg == NUL) {
967:
968: if (tlevel > -1) { /* Input is from take file */
969:
970: if (fgets(line,100,tfile[tlevel]) == NULL)
971: fatal("take file ends prematurely in 'get'");
972: debug(F110,"take-get 2nd line",line,0);
973: for (x = (int)strlen(line);
974: x > 0 && (line[x-1] == LF || line[x-1] == CR);
975: x--)
976: line[x-1] = '\0';
977: cmarg = line;
978: if (fgets(cmdbuf,CMDBL,tfile[tlevel]) == NULL)
979: fatal("take file ends prematurely in 'get'");
980: for (x = (int)strlen(cmdbuf);
981: x > 0 && (cmdbuf[x-1] == LF || cmdbuf[x-1] == CR);
982: x--)
983: cmdbuf[x-1] = '\0';
984: if (*cmdbuf == NUL) cmarg2 = line; else cmarg2 = cmdbuf;
985: x = 0; /* Return code */
986: printf("%s",cmarg2);
987:
988: } else { /* Input is from terminal */
989:
990: cmsavp(psave,80);
991: cmsetp(" Remote file specification: "); /* Make new one */
992: cmini(ckxech);
993: x = -1;
994: if (pflag) prompt(xxstring);
995: while (x == -1) { /* Prompt till they answer */
996: x = cmtxt("Name of remote file(s)","",&cmarg,xxstring);
997: debug(F111," cmtxt",cmarg,x);
998: }
999: if (x < 0) {
1000: cmsetp(psave);
1001: return(x);
1002: }
1003: if (*cmarg == NUL) { /* If user types a bare CR, */
1004: printf("(cancelled)\n"); /* Forget about this. */
1005: cmsetp(psave); /* Restore old prompt, */
1006: return(0); /* and return. */
1007: }
1008: strcpy(line,cmarg); /* Make a safe copy */
1009: cmarg = line;
1010: cmsetp(" Local name to store it under: "); /* New prompt */
1011: cmini(ckxech);
1012: x = -1;
1013: if (pflag) prompt(xxstring);
1014: while (x == -1) { /* Again, parse till answered */
1015: x = cmofi("Local file name","",&cmarg2,xxstring);
1016: }
1017: if (x == -3) { /* If bare CR, */
1018: printf("(cancelled)\n"); /* escape from this... */
1019: cmsetp(psave); /* Restore old prompt, */
1020: return(0); /* and return. */
1021: } else if (x < 0) return(x); /* Handle parse errors. */
1022:
1023: x = -1; /* Get confirmation. */
1024: while (x == -1) x = cmcfm();
1025: cmsetp(psave); /* Restore old prompt. */
1026: }
1027: }
1028: #endif /* NOFRILLS */
1029: if (x == 0) { /* Good return from cmtxt or cmcfm, */
1030: debug(F110,"xxget cmarg",cmarg,0);
1031: strncpy(fspec,cmarg,FSPECL);
1032: debug(F111,"xxget fspec",fspec,FSPECL);
1033: sstate = 'r'; /* Set start state. */
1034: if (local) {
1035: displa = 1;
1036: ttflui();
1037: }
1038: }
1039: return(x);
1040: }
1041:
1042: #ifndef NOSPL
1043: int
1044: dogta(cx) int cx; {
1045: int i; char c; char mbuf[3]; char *p;
1046:
1047: if ((y = cmcfm()) < 0)
1048: return(y);
1049: if (cx == XXGTA)
1050: debug(F101,"_getargs maclvl","",maclvl);
1051: else if (cx == XXPTA)
1052: debug(F101,"_putargs maclvl","",maclvl);
1053: else
1054: return(-2);
1055: if (maclvl < 1)
1056: return(success = 0);
1057:
1058: #ifdef COMMENT
1059: #ifdef NEXT
1060: /*
1061: For some reason, this routine makes Kermit core dump on the next after
1062: it returns to docmd(). It works fine, as the debug log shows, but when
1063: docmd returns, it gets a memory fault.
1064: */
1065: else return(1);
1066: #endif /* NEXT */
1067: #endif /* COMMENT */
1068:
1069: mbuf[0] = '%'; mbuf[1] = '0'; mbuf[2] = '\0'; /* Argument name buf */
1070: for (i = 0; i < 10; i++) { /* For all args */
1071: c = (char) i + '0'; /* Make name */
1072: mbuf[1] = c; /* Insert digit */
1073: if (cx == XXGTA) { /* Get arg from level-2 */
1074: if (maclvl == 1) p = g_var[c]; /* If at level 1 use globals 0..9 */
1075: else p = m_arg[maclvl-2][i]; /* Otherwise they're on the stack */
1076: if (!p) {
1077: debug(F111,"_getarg p","(null pointer)",i);
1078: } else debug(F111,"_getarg p",p,i);
1079: addmac(mbuf,p);
1080: } else if (cx == XXPTA) { /* Put args level+2 */
1081: connoi(); /* Turn off interrupts. */
1082: maclvl -= 2; /* This is gross.. */
1083: p = m_arg[maclvl+2][i];
1084: if (p)
1085: debug(F111,"_putarg m_arg[maclvl+2][i]",p,i);
1086: else
1087: debug(F111,"_putarg m_arg[maclvl+2][i]","(null pointer)",i);
1088: addmac(mbuf,m_arg[maclvl+2][i]);
1089: maclvl += 2;
1090: #ifndef MAC
1091: conint(trap,stptrap); /* Restore interrupts */
1092: #endif /* MAC */
1093: } else return(success = 0);
1094: }
1095: debug(F101,"_get/putarg exit","",i);
1096: debug(F101,"_get/putarg exit maclvl","",maclvl);
1097: return(success = 1);
1098: }
1099: #endif /* NOSPL */
1100:
1101:
1102: #ifndef NOSPL
1103: /* Do the GOTO command */
1104:
1105: int
1106: dogoto(s) char *s; {
1107: int i, x, y;
1108: debug(F101,"goto cmdlvl","",cmdlvl);
1109: debug(F101,"goto maclvl","",maclvl);
1110: debug(F101,"goto tlevel","",tlevel);
1111: debug(F110,"goto before conversion",s,0);
1112: y = (int)strlen(s);
1113: if (*s != ':') { /* If the label mentioned */
1114: for (i = y; i > 0; i--) { /* does not begin with a colon, */
1115: s[i] = s[i-1]; /* then insert one. */
1116: } /* Also, convert to lowercase. */
1117: s[0] = ':';
1118: s[++y] = '\0';
1119: }
1120: debug(F111,"goto after conversion",s,y);
1121: if (s[1] == '.' || s[1] == SP || s[1] == NUL) {
1122: printf("?Bad label syntax - '%s'\n",s);
1123: return(success = 0);
1124: }
1125: if (cmdlvl == 0) {
1126: printf("?Nothing happens\n");
1127: return(success = 0);
1128: }
1129: while (cmdlvl > 0) { /* Only works inside macros & files */
1130: if (cmdstk[cmdlvl].src == CMD_MD) { /* GOTO inside macro */
1131: int i, m, flag;
1132: lp = macx[maclvl];
1133: m = (int)strlen(lp) - y + 1;
1134: debug(F111,"goto in macro",lp,m);
1135:
1136: flag = 1; /* flag for valid label position */
1137: for (i = 0; i < m; i++,lp++) { /* search for label in macro body */
1138: if (flag && *lp == SP) continue;
1139: if (*lp == ',') {
1140: flag = 1;
1141: continue;
1142: }
1143: if (flag && !xxstrcmp(s,lp,y)) /* Caseless string comparison */
1144: break;
1145: else flag = 0;
1146: }
1147: if (i == m) { /* didn't find the label */
1148: debug(F101,"goto failed at cmdlvl","",cmdlvl);
1149: if (!popclvl()) { /* pop up to next higher level */
1150: printf("?Label '%s' not found\n",s); /* if none */
1151: return(0); /* quit */
1152: } else continue; /* otherwise look again */
1153: }
1154: debug(F110,"goto found macro label",lp,0);
1155: macp[maclvl] = lp; /* set macro buffer pointer */
1156: return(1);
1157: } else if (cmdstk[cmdlvl].src == CMD_TF) {
1158: x = 0; /* GOTO issued in take file */
1159: rewind(tfile[tlevel]); /* Search file from beginning */
1160: while (! feof(tfile[tlevel])) {
1161: if (fgets(line,LINBUFSIZ,tfile[tlevel]) == NULL) /* Get line */
1162: break; /* If no more, done, label not found */
1163: lp = line; /* Got line */
1164: while (*lp == ' ' || *lp == '\t')
1165: lp++; /* Strip leading whitespace */
1166: if (!xxstrcmp(lp,s,y)) { /* Compare result with label */
1167: x = 1; /* Got it */
1168: break; /* done. */
1169: }
1170: }
1171: if (x == 0) { /* If not found, print message */
1172: debug(F101,"goto failed at cmdlvl","",cmdlvl);
1173: if (!popclvl()) { /* pop up to next higher level */
1174: printf("?Label '%s' not found\n",s); /* if none */
1175: return(0); /* quit */
1176: } else continue; /* otherwise look again */
1177: }
1178: return(x); /* Send back return code */
1179: }
1180: }
1181: printf("?Stack problem in GOTO\n",s); /* Shouldn't see this */
1182: return(0);
1183: }
1184: #endif /* NOSPL */
1185:
1186: #ifndef NOSPL
1187: /* Finish parsing and do the IF, XIF, and WHILE commands */
1188:
1189: int
1190: doif(cx) int cx; {
1191: int x, y, z; char *s, *p;
1192:
1193: not = 0; /* Flag for whether "NOT" was seen */
1194: z = 0; /* Initial IF condition */
1195: ifargs = 0; /* Count of IF condition words */
1196:
1197: ifagain:
1198: if ((ifc = cmkey(iftab,nif,"","",xxstring)) < 0) { /* If what?... */
1199: if (ifc == -3) {
1200: printf("?Condition required\n");
1201: return(-9);
1202: } else return(ifc);
1203: }
1204: switch (ifc) { /* set z = 1 for true, 0 for false */
1205: case XXIFNO: /* IF NOT */
1206: not ^= 1; /* So NOT NOT NOT ... will work */
1207: ifargs++;
1208: goto ifagain;
1209: case XXIFSU: /* IF SUCCESS */
1210: z = ( success != 0 );
1211: debug(F101,"if success","",z);
1212: ifargs += 1;
1213: break;
1214: case XXIFFA: /* IF FAILURE */
1215: z = ( success == 0 );
1216: debug(F101,"if failure","",z);
1217: ifargs += 1;
1218: break;
1219: case XXIFDE: /* IF DEFINED */
1220: if ((x = cmfld("Macro or variable name","",&s,NULL)) < 0) {
1221: if (x == -3) return(-2);
1222: else return(x);
1223: }
1224: strcpy(line,s); /* Make a copy */
1225: if ((int)strlen(line) < 1) return(-2);
1226: lp = line;
1227: if (line[0] == CMDQ && (line[1] == '%' || line[1] == '&')) lp++;
1228: if (*lp == '%') { /* Is it a variable? */
1229: x = *(lp + 1); /* Fold case */
1230: if (isupper(x)) *(lp + 1) = tolower(x);
1231: if (x >= '0' && x <= '9' && maclvl > -1) /* Digit is macro arg */
1232: z = ( (m_arg[maclvl][x - '0'] != (char *)0)
1233: && (int)strlen(m_arg[maclvl][x - '0']) != 0);
1234: else /* Otherwise it's a global variable */
1235: z = ( (g_var[x] != (char *)0)
1236: && (int)strlen(g_var[x]) != 0 );
1237: } else if (*lp == '&') { /* Array reference */
1238: int cc, nn;
1239: if (arraynam(lp,&cc,&nn) < 0)
1240: z = 0;
1241: else z = (arrayval(cc,nn) == NULL ? 0 : 1);
1242: } else { /* Otherwise it's a macro name */
1243: z = ( mxlook(mactab,lp,nmac) > -1 ); /* Look for exact match */
1244: }
1245: debug(F111,"if defined",s,z);
1246: ifargs += 2;
1247: break;
1248:
1249: case XXIFBG: /* IF BACKGROUND */
1250: if (backgrd != 0 || bgset > 0) z = 1; else z = 0;
1251: ifargs += 1;
1252: break;
1253:
1254: case XXIFCO: /* IF COUNT */
1255: z = ( --count[cmdlvl] > 0 );
1256: debug(F101,"if count","",z);
1257: ifargs += 1;
1258: break;
1259:
1260: case XXIFEX: /* IF EXIST */
1261: if ((x = cmfld("File","",&s,xxstring)) < 0) {
1262: if (x == -3) {
1263: printf("?Filename required\n");
1264: return(-9);
1265: } else return(x);
1266: }
1267: z = ( zchki(s) > -1L );
1268: debug(F101,"if exist","",z);
1269: ifargs += 2;
1270: break;
1271:
1272: case XXIFEQ: /* IF EQUAL (string comparison) */
1273: case XXIFLL: /* IF Lexically Less Than */
1274: case XXIFLG: /* If Lexically Greater Than */
1275: if ((x = cmfld("first word or variable name","",&s,xxstring)) < 0) {
1276: if (x == -3) {
1277: printf("?Text required\n");
1278: return(-9);
1279: } else return(x);
1280: }
1281: x = (int)strlen(s);
1282: if (x > LINBUFSIZ-1) {
1283: printf("?IF: strings too long\n");
1284: return(-2);
1285: }
1286: lp = line; /* lp points to first string */
1287: strcpy(lp,s);
1288: if ((y = cmfld("second word or variable name","",&s,xxstring)) < 0) {
1289: if (y == -3) {
1290: printf("?Text required\n");
1291: return(-9);
1292: } else return(y);
1293: }
1294: y = (int)strlen(s);
1295: if (x + y + 2 > LINBUFSIZ) {
1296: printf("?IF: strings too long\n");
1297: return(-2);
1298: }
1299: tp = lp + y + 2; /* tp points to second string */
1300: strcpy(tp,s);
1301: if (incase) /* INPUT CASE OBSERVE */
1302: x = strcmp(lp,tp);
1303: else /* INPUT CASE IGNORE */
1304: x = xxstrcmp(lp,tp,y);
1305: switch (ifc) {
1306: case XXIFEQ: /* IF EQUAL (string comparison) */
1307: z = (x == 0);
1308: break;
1309: case XXIFLL: /* IF Lexically Less Than */
1310: z = (x < 0);
1311: break;
1312: case XXIFLG: /* If Lexically Greater Than */
1313: z = (x > 0);
1314: break;
1315: }
1316: ifargs += 3;
1317: break;
1318:
1319: case XXIFAE: /* IF (arithmetically) = */
1320: case XXIFLT: /* IF (arithmetically) < */
1321: case XXIFGT: { /* IF (arithmetically) > */
1322: /* Really should use longs here... */
1323: /* But cmnum parses ints. */
1324: int n1, n2;
1325: x = cmfld("first number or variable name","",&s,xxstring);
1326: if (x == -3) {
1327: printf("?Quantity required\n");
1328: return(-9);
1329: }
1330: if (x < 0) return(x);
1331: debug(F101,"xxifgt cmfld","",x);
1332: lp = line;
1333: strcpy(lp,s);
1334: debug(F110,"xxifgt exp1",lp,0);
1335: if (!xxstrcmp(lp,"count",5)) {
1336: n1 = count[cmdlvl];
1337: } else if (!xxstrcmp(lp,"version",7)) {
1338: n1 = (int) vernum;
1339: } else if (!xxstrcmp(lp,"argc",4)) {
1340: n1 = (int) macargc[maclvl];
1341: } else {
1342: if (!chknum(lp)) return(-2);
1343: n1 = atoi(lp);
1344: }
1345: y = cmfld("second number or variable name","",&s,xxstring);
1346: if (y == -3) {
1347: printf("?Quantity required\n");
1348: return(-9);
1349: }
1350: if (y < 0) return(y);
1351: if ((int)strlen(s) < 1) return(-2);
1352: x = (int)strlen(lp);
1353: tp = line + x + 2;
1354: strcpy(tp,s);
1355: debug(F110,"xxifgt exp2",tp,0);
1356: if (!xxstrcmp(tp,"count",5)) {
1357: n2 = count[cmdlvl];
1358: } else if (!xxstrcmp(tp,"version",7)) {
1359: n2 = (int) vernum;
1360: } else if (!xxstrcmp(tp,"argc",4)) {
1361: n2 = (int) macargc[maclvl];
1362: } else {
1363: if (!chknum(tp)) return(-2);
1364: n2 = atoi(tp);
1365: }
1366: debug(F101,"xxifft ifc","",ifc);
1367: z = ((n1 < n2 && ifc == XXIFLT)
1368: || (n1 == n2 && ifc == XXIFAE)
1369: || (n1 > n2 && ifc == XXIFGT));
1370: debug(F101,"xxifft n1","",n1);
1371: debug(F101,"xxifft n2","",n2);
1372: debug(F101,"xxifft z","",z);
1373: ifargs += 3;
1374: break; }
1375:
1376: case XXIFNU: /* IF NUMERIC */
1377: x = cmfld("variable name or constant","",&s,xxstring);
1378: if (x == -3) {
1379: printf("?Quantity required\n");
1380: return(-9);
1381: }
1382: if (x < 0) return(x);
1383: debug(F101,"xxifnu cmfld","",x);
1384: lp = line;
1385: strcpy(lp,s);
1386: debug(F110,"xxifnu quantity",lp,0);
1387: z = chknum(lp);
1388: ifargs += 2;
1389: break;
1390:
1391: default: /* Shouldn't happen */
1392: return(-2);
1393: }
1394:
1395: switch (cx) { /* Separate handling for IF and XIF */
1396:
1397: case XXIF: /* This is IF... */
1398: ifcmd[cmdlvl] = 1; /* We just completed an IF command */
1399: if (not) z = !z; /* Handle NOT here */
1400: if (z) { /* Condition is true */
1401: iftest[cmdlvl] = 1; /* Remember that IF succeeded */
1402: if (maclvl > -1) { /* In macro, */
1403: pushcmd(); /* save rest of command. */
1404: } else if (tlevel > -1) { /* In take file, */
1405: debug(F100, "doif: pushing command", "", 0);
1406: pushcmd(); /* save rest of command. */
1407: } else { /* If interactive, */
1408: cmini(ckxech); /* just start a new command */
1409: printf("\n"); /* (like in MS-DOS Kermit) */
1410: if (pflag) prompt(xxstring);
1411: }
1412: } else { /* Condition is false */
1413: iftest[cmdlvl] = 0; /* Remember command failed. */
1414: if ((y = cmtxt("command to be ignored","",&s,NULL)) < 0)
1415: return(y); /* Gobble up rest of line */
1416: }
1417: return(0);
1418:
1419: case XXIFX: { /* This is XIF (Extended IF) */
1420: char *p;
1421: char e[5];
1422: int i;
1423: if ((y = cmtxt("Object command","",&s,NULL)) < 0)
1424: return(y); /* Get object command. */
1425: p = s;
1426: lp = line;
1427: if (litcmd(&p,&lp) < 0) { /* Insert quotes in THEN-part */
1428: return(-2);
1429: }
1430: if (!z) { /* Use ELSE-part, if any */
1431: lp = line; /* Write over THEN part. */
1432: *lp = NUL;
1433: while (*p == SP) p++; /* Strip trailing spaces */
1434: if (*p) { /* At end? */
1435: for (i = 0; i < 4; i++) e[i] = *p++; /* No, check for ELSE */
1436: if (xxstrcmp(e,"else",4)) return(-2); /* No, syntax error */
1437: if (litcmd(&p,&lp) < 0) { /* Insert quotes */
1438: return(-2);
1439: }
1440: while (*p == SP) p++; /* Strip trailing spaces */
1441: if (*p) return(-2); /* Should be nothing here. */
1442: }
1443: }
1444: if (line[0]) {
1445: x = mlook(mactab,"_xif",nmac); /* get index of "_xif" macro. */
1446: if (x < 0) { /* Not there? */
1447: addmmac("_xif",xif_def); /* Put it back. */
1448: if (mlook(mactab,"_xif",nmac) < 0) { /* Look it up again. */
1449: printf("?XIF macro gone!\n");
1450: return(success = 0);
1451: }
1452: }
1453: dodo(x,line); /* Do the XIF macro */
1454: }
1455: return(0);
1456: }
1457: case XXWHI: { /* WHILE Command */
1458: p = cmdbuf; /* Capture IF condition */
1459: ifcond[0] = NUL; /* from command buffer */
1460: while (*p == SP) p++;
1461: while (*p != SP) p++;
1462: ifcp = ifcond;
1463: strcpy(ifcp,"{ \\flit(if not ");
1464: ifcp += (int)strlen(ifcp);
1465: while (*p != '{' && *p != NUL) *ifcp++ = *p++;
1466: p = " goto wbot) } ";
1467: while (*ifcp++ = *p++) ;
1468: debug(F110,"WHILE cmd",ifcond,0);
1469:
1470: if ((y = cmtxt("Object command","",&s,NULL)) < 0)
1471: return(y); /* Get object command. */
1472: p = s;
1473: lp = line;
1474: if (litcmd(&p,&lp) < 0) { /* Insert quotes in object command */
1475: return(-2);
1476: }
1477: debug(F110,"WHILE body",line,0);
1478: if (line[0]) {
1479: char *p;
1480: x = mlook(mactab,"_while",nmac); /* index of "_while" macro. */
1481: if (x < 0) { /* Not there? */
1482: addmmac("_while",whil_def); /* Put it back. */
1483: if (mlook(mactab,"_while",nmac) < 0) { /* Look it up again */
1484: printf("?WHILE macro definition gone!\n");
1485: return(success = 0);
1486: }
1487: }
1488: p = malloc((int)strlen(ifcond) + (int)strlen(line) + 2);
1489: if (p) {
1490: strcpy(p,ifcond);
1491: strcat(p,line);
1492: debug(F110,"WHILE dodo",p,0);
1493: dodo(x,p);
1494: free(p);
1495: } else {
1496: printf("?Can't allocate storage for WHILE command");
1497: return(success = 0);
1498: }
1499: }
1500: return(0);
1501: }
1502: default:
1503: return(-2);
1504: }
1505: }
1506: #endif /* NOSPL */
1507:
1508: /* Set up a TAKE command file */
1509:
1510: int
1511: dotake(s) char *s; {
1512: if ((tfile[++tlevel] = fopen(s,"r")) == NULL) {
1513: perror(s);
1514: debug(F110,"Failure to open",s,0);
1515: success = 0;
1516: tlevel--;
1517: } else {
1518: #ifdef VMS
1519: conres(); /* So Ctrl-C will work */
1520: #endif /* VMS */
1521: #ifndef NOSPL
1522: cmdlvl++; /* Entering a new command level */
1523: if (cmdlvl > CMDSTKL) {
1524: cmdlvl--;
1525: printf("?TAKE files and DO commands nested too deeply\n");
1526: return(success = 0);
1527: }
1528: ifcmd[cmdlvl] = 0;
1529: iftest[cmdlvl] = 0;
1530: count[cmdlvl] = 0;
1531: cmdstk[cmdlvl].src = CMD_TF; /* Say we're in a TAKE file */
1532: cmdstk[cmdlvl].lvl = tlevel; /* nested at this level */
1533: #endif /* NOSPL */
1534: }
1535: return(1);
1536: }
1537: #endif /* NOICP */
1538:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.