|
|
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.