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