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