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 (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
   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(" Info-Kermit@columbia.edu (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 */

Defined functions

doask defined in line 251; used 2 times
dobug defined in line 861; used 1 times
dodef defined in line 390; used 1 times
dodel defined in line 704; used 1 times
dodial defined in line 550; used 1 times
dodir defined in line 595; used 1 times
doelse defined in line 741; used 1 times
doenable defined in line 638; used 1 times
dofor defined in line 773; used 1 times
doget defined in line 1126; used 1 times
dogoto defined in line 1375; used 1 times
dogta defined in line 1311; used 1 times
doif defined in line 1493; used 1 times
doincr defined in line 355; used 1 times
doopen defined in line 1027; used 1 times
dopaus defined in line 885; used 1 times
dorenam defined in line 942; used 1 times
doreturn defined in line 976; used 1 times
ludial defined in line 475; used 1 times
xxstrcmp defined in line 225; used 12 times

Defined variables

cwdf defined in line 181; used 3 times
dialnum defined in line 154; used 9 times
ifc defined in line 160; used 10 times
ifcond defined in line 163; used 5 times
ifcp defined in line 164; used 6 times
iftab defined in line 127; used 2 times
mstab defined in line 99; used 2 times
nif defined in line 148; used 1 times
nms defined in line 113; used 1 times
nopn defined in line 125; used 1 times
not defined in line 161; used 3 times
opntab defined in line 116; used 2 times
p defined in line 215; used 57 times
s defined in line 215; used 184 times
x defined in line 214; used 170 times
y defined in line 214; used 162 times
z defined in line 214; used 51 times

Defined macros

fclose defined in line 34; never used
feof defined in line 30; used 1 times
fgets defined in line 32; used 2 times
fopen defined in line 33; used 1 times
rewind defined in line 31; used 2 times
xsystem defined in line 212; used 3 times
Last modified: 1992-11-24
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 11661
Valid CSS Valid XHTML 1.0 Strict