1: #ifndef NOICP 2: 3: /* C K U U S 5 -- "User Interface" for Unix Kermit, part 5 */ 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 "ckcnet.h" 23: #ifndef NOCSETS 24: #include "ckcxla.h" 25: #endif /* NOCSETS */ 26: #ifdef MAC 27: #include "ckmasm.h" 28: #endif /* MAC */ 29: 30: /* For formatted screens, "more?" prompting, etc. */ 31: 32: #define SCRNLEN 21 /* Screen length */ 33: #define SCRNWID 79 /* Screen width */ 34: 35: #ifdef FT18 36: #define isxdigit(c) isdigit(c) 37: #endif /* FT18 */ 38: 39: #ifdef MAC /* Internal MAC file routines */ 40: #define feof mac_feof 41: #define rewind mac_rewind 42: #define fgets mac_fgets 43: #define fopen mac_fopen 44: #define fclose mac_fclose 45: 46: int mac_feof(); 47: void mac_rewind(); 48: char *mac_fgets(); 49: FILE *mac_fopen(); 50: int mac_fclose(); 51: #endif /* MAC */ 52: 53: /* External variables */ 54: 55: extern int carrier, cdtimo, local, backgrd, bgset, sosi, suspend, 56: displa, binary, deblog, escape, xargs, flow, cmdmsk, 57: duplex, ckxech, pktlog, seslog, tralog, what, 58: keep, warn, tlevel, cwdf, nfuncs, unkcs, msgflg, 59: mdmtyp, zincnt, cmask, rcflag, success, xitsta, pflag, lf_opts, tnlm, tn_nlm; 60: 61: extern char *ccntab[]; 62: 63: #ifndef NOFRILLS 64: extern int en_cwd, en_del, en_dir, en_fin, en_bye, 65: en_get, en_hos, en_sen, en_set, en_spa, en_typ, en_who; 66: #endif /* NOFRILLS */ 67: extern long vernum; 68: extern int srvtim, srvdis, incase, inecho, intime, insilence, nvars, verwho; 69: extern char *protv, *fnsv, *cmdv, *userv, *ckxv, *ckzv, *ckzsys, *xlav, 70: *cknetv, *clcmds; 71: extern char *connv, *dialv, *loginv, *nvlook(); 72: 73: #ifndef NOSCRIPT 74: extern int secho; 75: #endif /* NOSCRIPT */ 76: 77: #ifndef NODIAL 78: extern int nmdm; 79: extern struct keytab mdmtab[]; 80: #endif /* NODIAL */ 81: 82: #ifdef NETCONN 83: extern int tn_init, network, ttnproto; 84: #endif /* NETCONN */ 85: 86: #ifdef OS2 87: extern int tt_type, tt_arrow, tt_keypad, tt_wrap; 88: #endif /* OS2 */ 89: extern int tt_crd; 90: 91: #ifndef NOCSETS 92: extern int language, nfilc, tcsr, tcsl; 93: extern struct keytab fcstab[]; 94: #ifndef MAC 95: extern struct keytab ttcstab[]; 96: #endif /* MAC */ 97: #endif /* NOCSETS */ 98: 99: extern int atcapr, 100: atenci, atenco, atdati, atdato, atleni, atleno, atblki, atblko, 101: attypi, attypo, atsidi, atsido, atsysi, atsyso, atdisi, atdiso; 102: 103: extern long speed; 104: 105: extern char *DIRCMD, *PWDCMD, *DELCMD; 106: #ifndef NOXMIT 107: extern int xmitf, xmitl, xmitp, xmitx, xmits, xmitw; 108: extern char xmitbuf[]; 109: #endif /* NOXMIT */ 110: 111: extern char **xargv, *versio, *ckxsys, *dftty, *cmarg, *lp; 112: 113: #ifdef DCMDBUF 114: extern char *cmdbuf, *atmbuf; /* Command buffers */ 115: #ifndef NOSPL 116: extern char *savbuf; /* Command buffers */ 117: #endif /* NOSPL */ 118: #else 119: extern char cmdbuf[], atmbuf[]; /* Command buffers */ 120: #ifndef NOSPL 121: extern char savbuf[]; /* Command buffers */ 122: #endif /* NOSPL */ 123: #endif /* DCMDBUF */ 124: 125: extern char toktab[], ttname[], psave[]; 126: extern CHAR sstate; 127: extern int cmflgs, techo, terror, repars, ncmd; 128: extern struct keytab cmdtab[]; 129: 130: #ifndef MAC 131: #ifndef NOSETKEY 132: KEY *keymap; 133: MACRO *macrotab; 134: #endif /* NOSETKEY */ 135: #endif /* MAC */ 136: 137: #ifndef NOSPL 138: extern struct mtab *mactab; 139: extern struct keytab vartab[], fnctab[]; 140: extern int cmdlvl, maclvl, nmac, mecho, merror; 141: #endif /* NOSPL */ 142: 143: FILE *tfile[MAXTAKE]; /* TAKE file stack */ 144: char *tfnam[MAXTAKE]; 145: 146: #ifndef NOSPL 147: /* Local declarations */ 148: 149: int nulcmd = 0; /* Flag for next cmd to be ignored */ 150: 151: /* Definitions for built-in macros */ 152: 153: /* First, the single line macros, installed with addmac()... */ 154: 155: /* IBM-LINEMODE macro */ 156: char *m_ibm = "set parity mark, set dupl half, set handsh xon, set flow none"; 157: 158: /* FATAL macro */ 159: char *m_fat = "if def \\%1 echo \\%1, if not = \\v(local) 0 hangup, stop 1"; 160: 161: #ifdef COMMENT 162: /* 163: Long macro definitions were formerly done like this. But some compilers 164: cannot handle continued string constants, others cannot handle string 165: constants that are this long. So these definitions have been broken up 166: into pieces and put into arrays, see below. 167: */ 168: char *m_forx = "if def _floop ass \\%9 \\fdef(_floop),else def \\%9,\ 169: ass _floop { _getargs,\ 170: define \\\\\\%1 \\%2,:top,if \\%5 \\\\\\%1 \\%3 goto bot,\ 171: \\%6,:inc, incr \\\\\\%1 \\%4,goto top,:bot,_putargs,return},\ 172: def break goto bot, def continue goto inc,\ 173: do _floop \\%1 \\%2 \\%3 \\%4 { \\%5 },assign _floop \\fcont(\\%9)"; 174: 175: char *m_while = "if def _wloop ass \\%9 \\fdef(_wloop),\ 176: ass _wloop {_getargs,:wtest,\\%1,\\%2,goto wtest,:wbot,_putargs,return},\ 177: def break goto wbot, def continue goto wtest,\ 178: do _wloop,assign _wloop \\fcont(\\%9)"; 179: 180: char *m_xif = "ass \\%9 \\fdef(_ify),ass _ify {_getargs, \\%1, _putargs},\ 181: do _ify,ass _ify \\fcont(\\%9)"; 182: #endif /* COMMENT */ 183: 184: /* Now the multiline macros, defined with addmmac()... */ 185: 186: /* FOR macro */ 187: char *for_def[] = { "_assign _for\\v(cmdlevel) { _getargs,", 188: "define \\\\\\%1 \\%2,:top,if \\%5 \\\\\\%1 \\%3 goto bot,", 189: "\\%6,:inc,incr \\\\\\%1 \\%4,goto top,:bot,_putargs},", 190: "def break goto bot, def continue goto inc,", 191: "do _for\\v(cmdlevel) \\%1 \\%2 \\%3 \\%4 { \\%5 },_assign _for\\v(cmdlevel)", 192: ""}; 193: #ifdef COMMENT 194: /* 195: This one didn't work right. When an interior loop finished executing, 196: the definition of the enclosing loop was restored, but the new definition 197: could be in a different location in memory, so its macro execution pointer 198: could (and usually was) pointing at garbage. 199: */ 200: char *old_for_def[] = { "if def _floop ass \\%9 \\fdef(_floop),else def \\%9,", 201: "ass _floop { _getargs,", 202: "define \\\\\\%1 \\%2,:top,if \\%5 \\\\\\%1 \\%3 goto bot,", 203: "\\%6,:inc, incr \\\\\\%1 \\%4,goto top,:bot,_putargs,return},", 204: "def break goto bot, def continue goto inc,", 205: "do _floop \\%1 \\%2 \\%3 \\%4 { \\%5 },assign _floop \\fcont(\\%9)", 206: ""}; 207: #endif /* COMMENT */ 208: 209: /* WHILE macro */ 210: char *whil_def[] = { "_assign _whi\\v(cmdlevel) {_getargs,", 211: ":wtest,\\%1,\\%2,goto wtest,:wbot,_putargs},", 212: "def break goto wbot, def continue goto wtest,", 213: "do _whi\\v(cmdlevel),_assign _whi\\v(cmdlevel)", 214: ""}; 215: #ifdef COMMENT 216: /* 217: Same deal as FOR loop... 218: */ 219: char *old_whil_def[] = { "if def _wloop asg \\%9 \\fdef(_wloop),", 220: "asg _wloop {_getargs,:wtest,\\%1,\\%2,goto wtest,:wbot,_putargs,return},", 221: "def break goto wbot, def continue goto wtest,", 222: "do _wloop,assign _wloop \\fcont(\\%9)", 223: ""}; 224: #endif /* COMMENT */ 225: 226: /* XIF macro */ 227: char *xif_def[] = { 228: "_assign _if\\v(cmdlevel) {_getargs,\\%1,_putargs},", 229: "do _if\\v(cmdlevel),_assign _if\\v(cmdlevel)", 230: ""}; 231: #ifdef COMMENT 232: /* Same deal */ 233: char *old_xif_def[] = { 234: "asg \\%9 \\fdef(_ify),ass _ify {_getargs, \\%1, _putargs},", 235: "do _ify,ass _ify \\fcont(\\%9)", 236: ""}; 237: #endif /* COMMENT */ 238: 239: /* Variables declared here for use by other ckuus*.c modules */ 240: /* Space is allocated here to save room in ckuusr.c */ 241: 242: #ifdef DCMDBUF 243: struct cmdptr *cmdstk; 244: int *ifcmd, *count, *iftest; 245: #else 246: struct cmdptr cmdstk[CMDSTKL]; 247: int ifcmd[CMDSTKL], count[CMDSTKL], iftest[CMDSTKL]; 248: #endif /* DCMDBUF */ 249: 250: char *m_arg[MACLEVEL][NARGS]; 251: char *g_var[GVARS], *macp[MACLEVEL], *mrval[MACLEVEL]; 252: int macargc[MACLEVEL]; 253: char *macx[MACLEVEL]; 254: extern char varnam[]; 255: 256: char **a_ptr[27]; /* Array pointers, for arrays a-z */ 257: int a_dim[27]; /* Dimensions for each array */ 258: 259: char inpbuf[INPBUFSIZ] = { NUL }; /* Buffer for INPUT and REINPUT */ 260: char inpbufa[2] = { NUL, NUL }; /* Null terminators for INPUT buffer */ 261: char inchar[2] = { NUL, NUL }; /* Last character that was INPUT */ 262: int incount = 0; /* INPUT character count */ 263: 264: char lblbuf[50]; /* Buffer for labels */ 265: #endif /* NOSPL */ 266: 267: #ifdef DCMDBUF 268: char *line; /* Character buffer for anything */ 269: #else 270: char line[LINBUFSIZ]; 271: #endif /* DCMDBUF */ 272: 273: #ifdef CK_CURSES 274: #ifndef TRMBUFL 275: #define TRMBUFL 1024 276: #endif /* TRMBUFL */ 277: #ifdef DCMDBUF 278: char *trmbuf; /* Character buffer for termcap */ 279: #else 280: char trmbuf[TRMBUFL]; 281: #endif /* DCMDBUF */ 282: #endif /* CK_CURSES */ 283: 284: extern char pktfil[], 285: #ifdef DEBUG 286: debfil[], 287: #endif /* DEBUG */ 288: #ifdef TLOG 289: trafil[], 290: #endif /* TLOG */ 291: sesfil[], 292: cmdstr[]; 293: #ifndef NOFRILLS 294: extern int rmailf, rprintf; /* REMOTE MAIL & PRINT items */ 295: extern char optbuf[]; 296: #endif /* NOFRILLS */ 297: 298: char *homdir = ""; /* Pointer to home directory string */ 299: 300: char tmpbuf[50], *tp; /* Temporary buffer */ 301: char numbuf[20]; /* Buffer for numeric strings. */ 302: char kermrc[100]; /* Name of initialization file */ 303: int noinit = 0; /* Flag for skipping init file */ 304: 305: #ifndef NOSPL 306: _PROTOTYP( static long expon, (long, long) ); 307: _PROTOTYP( static long gcd, (long, long) ); 308: _PROTOTYP( static long fact, (long) ); 309: int /* Initialize macro data structures. */ 310: macini() { /* Allocate mactab and preset the first element. */ 311: if (!(mactab = (struct mtab *) malloc(sizeof(struct mtab) * MAC_MAX))) 312: return(-1); 313: mactab[0].kwd = NULL; 314: mactab[0].mval = NULL; 315: mactab[0].flgs = 0; 316: return(0); 317: } 318: #endif /* NOSPL */ 319: 320: /* C M D I N I -- Initialize the interactive command parser */ 321: 322: VOID 323: cmdini() { 324: int i, x, y, z; 325: #ifndef NOSPL 326: /* 327: On stack in case of recursion! 328: */ 329: char vnambuf[VNAML]; /* Buffer for variable names */ 330: #endif /* NOSPL */ 331: 332: #ifndef MAC 333: #ifndef NOSETKEY /* Allocate & initialize the keymap */ 334: if (!(keymap = (KEY *) malloc(sizeof(KEY)*KMSIZE))) 335: fatal("cmdini: no memory for keymap"); 336: if (!(macrotab = (MACRO *) malloc(sizeof(MACRO)*KMSIZE))) 337: fatal("cmdini: no memory for macrotab"); 338: for ( i = 0; i < KMSIZE; i++ ) { 339: keymap[i] = i; 340: macrotab[i] = NULL; 341: } 342: #ifdef OS2 343: keymapinit(); 344: #endif /* OS2 */ 345: #endif /* NOSETKEY */ 346: #endif /* MAC */ 347: 348: #ifdef DCMDBUF 349: if (cmsetup() < 0) fatal("Can't allocate command buffers!"); 350: #ifndef NOSPL 351: if (!(cmdstk = (struct cmdptr *) malloc(sizeof(struct cmdptr)*CMDSTKL))) 352: fatal("cmdini: no memory for cmdstk"); 353: if (!(ifcmd = (int *) malloc(sizeof(int)*CMDSTKL))) 354: fatal("cmdini: no memory for ifcmd"); 355: if (!(count = (int *) malloc(sizeof(int)*CMDSTKL))) 356: fatal("cmdini: no memory for count"); 357: if (!(iftest = (int *) malloc(sizeof(int)*CMDSTKL))) 358: fatal("cmdini: no memory for iftest"); 359: #endif /* NOSPL */ 360: #ifdef CK_CURSES 361: /* 362: Termcap buffer for fullscreen display, UNIX only. VMS does it another way. 363: The fullscreen display is not supported on AOS/VS or OS-9, etc, yet, and 364: the Mac has its own built-in fullscreen display. 365: */ 366: #ifdef UNIX 367: if (!(trmbuf = malloc(TRMBUFL+1))) 368: fatal("cmdini: no memory for termcap buffer"); 369: #endif /* UNIX */ 370: #endif /* CK_CURSES */ 371: if (!(line = malloc(LINBUFSIZ))) 372: fatal("cmdini: no memory for line"); 373: #endif /* DCMDBUF */ 374: 375: #ifndef NOSPL 376: if (macini() < 0) fatal("Can't allocate macro buffers!"); 377: #endif /* NOSPL */ 378: 379: #ifdef AMIGA 380: if (tlevel < 0) 381: concb(escape); 382: #endif /* AMIGA */ 383: 384: #ifndef NOSPL 385: cmdlvl = 0; /* Start at command level 0 */ 386: cmdstk[cmdlvl].src = CMD_KB; 387: cmdstk[cmdlvl].lvl = 0; 388: #endif /* NOSPL */ 389: 390: tlevel = -1; /* Take file level = keyboard */ 391: for (i = 0; i < MAXTAKE; i++) /* Initialize command file names */ 392: tfnam[i] = NULL; 393: 394: #ifdef MAC 395: cmsetp("Mac-Kermit>"); /* Set default prompt */ 396: #else 397: cmsetp("C-Kermit>"); /* Set default prompt */ 398: #endif /* MAC */ 399: 400: #ifndef NOSPL 401: initmac(); /* Initialize macro table */ 402: /* Add one-line macros */ 403: addmac("ibm-linemode",m_ibm); /* Add built-in macros. */ 404: addmac("fatal",m_fat); /* FATAL macro. */ 405: /* Add multiline macros */ 406: addmmac("_forx",for_def); /* FOR macro. */ 407: addmmac("_xif",xif_def); /* XIF macro. */ 408: addmmac("_while",whil_def); /* WHILE macro. */ 409: /* Fill in command line argument vector */ 410: sprintf(vnambuf,"\\&@[%d]",xargs); /* Command line argument vector */ 411: y = arraynam(vnambuf,&x,&z); /* goes in array \&@[] */ 412: if (y > -1) { 413: dclarray((char)x,z); /* Declare the array */ 414: for (i = 0; i < xargs; i++) { /* Fill it */ 415: sprintf(vnambuf,"\\&@[%d]",i); 416: addmac(vnambuf,xargv[i]); 417: } 418: } 419: *vnambuf = NUL; 420: #endif /* NOSPL */ 421: 422: /* Get our home directory now. This needed in lots of places. */ 423: 424: homdir = zhome(); 425: 426: /* If skipping init file ('-Y' on Kermit command line), return now. */ 427: 428: if (noinit) return; 429: 430: #ifdef OS2 431: /* 432: The -y init file must be fully specified or in the current directory. 433: KERMRC is looked for via INIT, PATH and DPATH in that order. Finally, our 434: own executable file path is taken and the .EXE suffix is replaced by .INI 435: and this is tried as initialization file. 436: */ 437: if (rcflag) { 438: strcpy(line, kermrc); 439: } else { 440: _searchenv(kermrc,"INIT",line); 441: if (line[0] == 0) 442: _searchenv(kermrc,"PATH",line); 443: if (line[0] == 0) 444: _searchenv(kermrc,"DPATH",line); 445: if (line[0] == 0) { 446: char *pgmptr = GetLoadPath(); 447: if (pgmptr) { 448: lp = strrchr(pgmptr, '.'); 449: strncpy(line, pgmptr, lp - pgmptr); 450: strcpy(line + (lp - pgmptr), ".ini"); 451: } 452: } 453: } 454: if ((tfile[0] = fopen(line,"r")) != NULL) { 455: tlevel = 0; 456: if (tfnam[tlevel] = malloc(strlen(line)+1)) 457: strcpy(tfnam[tlevel],line); 458: #ifndef NOSPL 459: cmdlvl++; 460: cmdstk[cmdlvl].src = CMD_TF; 461: cmdstk[cmdlvl].lvl = tlevel; 462: ifcmd[cmdlvl] = 0; 463: iftest[cmdlvl] = 0; 464: count[cmdlvl] = 0; 465: #endif /* NOSPL */ 466: debug(F110,"init file",line,0); 467: } else { 468: debug(F100,"no init file","",0); 469: } 470: #else /* not OS2 */ 471: lp = line; 472: lp[0] = '\0'; 473: #ifdef GEMDOS 474: zkermini(line,rcflag, kermrc); 475: #else 476: #ifdef VMS 477: zkermini(line,LINBUFSIZ,kermrc); 478: #else /* not VMS */ 479: if (rcflag) { /* If init file name from cmd line */ 480: strcpy(lp,kermrc); /* use it */ 481: } else { /* otherwise */ 482: if (homdir) { /* look in home directory for it */ 483: strcpy(lp,homdir); 484: if (lp[0] == '/') strcat(lp,"/"); 485: } 486: strcat(lp,kermrc); /* and use the default name */ 487: } 488: #endif /* VMS */ 489: #endif /* GEMDOS */ 490: 491: #ifdef AMIGA 492: reqoff(); /* disable requestors */ 493: #endif /* AMIGA */ 494: 495: debug(F110,"ini file is",line,0); 496: if ((tfile[0] = fopen(line,"r")) != NULL) { 497: tlevel = 0; 498: if (tfnam[tlevel] = malloc(strlen(line)+1)) 499: strcpy(tfnam[tlevel],line); 500: #ifndef NOSPL 501: cmdlvl++; 502: ifcmd[cmdlvl] = 0; 503: iftest[cmdlvl] = 0; 504: count[cmdlvl] = 0; 505: debug(F101,"open ok","",cmdlvl); 506: cmdstk[cmdlvl].src = CMD_TF; 507: cmdstk[cmdlvl].lvl = tlevel; 508: #endif /* NOSPL */ 509: debug(F110,"init file",line,0); 510: } 511: if (homdir && (tlevel < 0)) { 512: strcpy(lp,kermrc); 513: if ((tfile[0] = fopen(line,"r")) != NULL) { 514: tlevel = 0; 515: if (tfnam[tlevel] = malloc(strlen(line)+1)) 516: strcpy(tfnam[tlevel],line); 517: #ifndef NOSPL 518: cmdlvl++; 519: cmdstk[cmdlvl].src = CMD_TF; 520: cmdstk[cmdlvl].lvl = tlevel; 521: ifcmd[cmdlvl] = 0; 522: iftest[cmdlvl] = 0; 523: count[cmdlvl] = 0; 524: #endif /* NOSPL */ 525: } 526: } 527: #endif /* OS2 */ 528: #ifdef AMIGA 529: reqpop(); /* Restore requestors */ 530: #endif /* AMIGA */ 531: } 532: 533: #ifndef NOSPL 534: /* 535: G E T N C M 536: 537: Get next command from current macro definition. 538: 539: Moved to a separate routine in edit 181 to allow multiline GET 540: to work when issued in a macro. 541: 542: Command is copied into string pointed to by argument s, max length n. 543: Returns: 544: 0 if a string was copied, -1 if there was no string to copy. 545: */ 546: int 547: getncm(s,n) char *s; int n; { 548: int y, kp = 0, pp = 0; 549: char *s2; 550: 551: s2 = s; 552: *s = NUL; /* Copy next cmd to command buffer. */ 553: 554: debug(F111,"getncm",s,n); 555: 556: for (y = 0; 557: macp[maclvl] && *macp[maclvl] && y < n; 558: y++, s++, macp[maclvl]++) { 559: 560: *s = *macp[maclvl]; /* Get next character */ 561: debug(F000,"char","",*s); 562: /* 563: Allow braces around macro definition to prevent commas from being turned to 564: end-of-lines and also treat any commas within parens as text so that 565: multiple-argument functions won't cause the command to break prematurely. 566: */ 567: if (*s == '{') kp++; /* Count braces */ 568: if (*s == '}') kp--; 569: if (*s == '(') pp++; /* Count parentheses. */ 570: if (*s == ')') pp--; 571: if (*s == ',' && pp <= 0 && kp <= 0) { 572: macp[maclvl]++; 573: debug(F110,"next cmd",s,0); 574: kp = pp = 0; 575: break; 576: } 577: } /* Reached end. */ 578: if (*s2 == NUL) { /* If nothing was copied, */ 579: debug(F100,"getncm eom","",0); 580: popclvl(); /* pop command level. */ 581: return(-1); 582: } else { /* otherwise, tack CR onto end */ 583: *s++ = CR; 584: *s = '\0'; 585: if (mecho && pflag) 586: printf("%s\n",s2); 587: debug(F101,"getncm returns ptr to",s2,0); 588: } 589: return(0); 590: } 591: #endif /* NOSPL */ 592: 593: /* 594: G E T N C T 595: 596: Get next command from current TAKE file. 597: 598: Moved to a separate routine in edit 181 to allow multiline GET 599: to work when issued in a macro. 600: 601: Command is copied into string pointed to by argument s, max length n. 602: Returns: 603: 0 if a string was copied, 604: -1 on EOF, 605: -2 on malloc failure 606: -3 if line not properly terminated 607: */ 608: int 609: getnct(s,n) char *s; int n; { 610: int i, j; 611: char c, *s2, *lp, *lp2; 612: 613: s2 = s; /* Remember original pointer */ 614: 615: debug(F101,"getnct","",n); 616: if (!(lp2 = (char *) malloc(n+1))) { /* Get a temporary buffer */ 617: debug(F101,"getnct malloc failure","",0); 618: return(-2); 619: } 620: lp = lp2; /* Make a working pointer */ 621: /* (lp2 must not change!) */ 622: 623: while (1) { /* Loop to read lines from file */ 624: 625: if (fgets(lp2,n,tfile[tlevel]) == NULL) { /* EOF */ 626: free(lp2); /* Free temporary storage */ 627: *s = NUL; /* Make destination be empty */ 628: return(-1); /* Return failure code */ 629: } 630: debug(F110,"Line from TAKE file",lp2,0); /* Got a line */ 631: if (techo && pflag) /* If TAKE ECHO ON, */ 632: printf("%s",lp2); /* echo it. */ 633: 634: lp = lp2; /* Make a working pointer */ 635: 636: /* Trim trailing whitespace */ 637: 638: j = strlen(lp2) - 1; /* Position of line terminator */ 639: if (j < 0) j = 0; 640: c = lp2[j]; /* Value of line terminator */ 641: if (c < LF || c > CR) { /* It's not a terminator */ 642: debug(F111,"getnct bad line",lp2,c); 643: if (feof(tfile[tlevel]) && j > 0 && j < n) { 644: printf("Warning: Last line of TAKE file lacks terminator\n"); 645: c = lp2[++j] = '\n'; 646: } else return(-3); 647: } 648: for (i = j - 1; i > -1; i--) /* Back up over spaces and tabs */ 649: if (lp2[i] != SP && lp2[i] != HT && lp2[i] != NUL) 650: break; 651: lp2[i+1] = c; /* Move after last nonblank char */ 652: lp2[i+2] = NUL; /* Terminate the string */ 653: while (*s++ = *lp++) { /* Copy result to target buffer */ 654: if (--n < 2) { 655: printf("?Command too long, maximum length: %d.\n",CMDBL); 656: free(lp2); 657: return(dostop()); 658: } 659: 660: /* Check for trailing comment, " ;" or " #" */ 661: 662: if ((s > s2 + 1) && 663: (*(s-1) == ';' || *(s-1) == '#') && 664: (*(s-2) == SP || *(s-2) == HT)) { 665: debug(F100,"Trailing comment","",0); 666: s -= 2; /* Got one, back up buffer pointer */ 667: n += 2; /* and adjust free space count. */ 668: while ((s >= s2) /* Trim whitespace again. */ 669: && (*s == SP || *s == HT)) 670: s--, n++; 671: s++; /* Point after last character */ 672: *s++ = c; /* Put back line terminator */ 673: *s++ = NUL; /* and string terminator */ 674: n -= 3; /* Adjust free count */ 675: debug(F110,"Comment trimmed & terminated",s2,0); 676: break; 677: } 678: } 679: 680: /* Check whether this line is continued */ 681: 682: debug(F000,"Last char in line","",*(s-3)); 683: if (*(s - 3) != CMDQ && *(s - 3) != '-') /* Line continued? */ 684: break; /* No, done. */ 685: s -= 3; /* No, back up pointer */ 686: debug(F100,"Got continue char","",0); /* and continue */ 687: } 688: untab(s2); /* Done, convert tabs to spaces */ 689: free(lp2); /* Free temporary storage */ 690: return(0); /* Return success */ 691: } 692: 693: /* P A R S E R -- Top-level interactive command parser. */ 694: 695: /* 696: Call with: 697: m = 0 for normal behavior: keep parsing and executing commands 698: until an action command is parsed, then return with a 699: Kermit start-state as the value of this function. 700: m = 1 to parse only one command, can also be used to call parser() 701: recursively. 702: m = 2 to read but do not execute one command. 703: In all cases, parser() returns: 704: 0 if no Kermit protocol action required 705: > 0 with a Kermit protocol start-state. 706: < 0 upon error. 707: */ 708: int 709: parser(m) int m; { 710: int tfcode, xx, yy, zz; /* Workers */ 711: 712: #ifndef NOSPL 713: int inlevel; /* Level we were called at */ 714: #endif /* NOSPL */ 715: char *cbp; /* Command buffer pointer */ 716: #ifdef MAC 717: extern char *lfiles; /* Fake extern cast */ 718: #endif /* MAC */ 719: 720: #ifdef AMIGA 721: reqres(); /* restore AmigaDOS requestors */ 722: #endif /* AMIGA */ 723: 724: what = W_COMMAND; /* Now we're parsing commands. */ 725: #ifndef NOSPL 726: if (cmdlvl == 0) /* If at top (interactive) level, */ 727: #else 728: if (tlevel < 0) 729: #endif /* NOSPL */ 730: concb((char)escape); /* put console in cbreak mode. */ 731: 732: #ifndef NOSPL 733: ifcmd[0] = 0; /* Command-level related variables */ 734: iftest[0] = 0; /* initialize variables at top level */ 735: count[0] = 0; /* of stack... */ 736: inlevel = cmdlvl; /* Current macro level */ 737: debug(F101,"&parser entry maclvl","",maclvl); 738: debug(F101,"&parser entry inlevel","",inlevel); 739: debug(F101,"&parser entry tlevel","",tlevel); 740: debug(F101,"&parser entry cmdlvl","",cmdlvl); 741: debug(F101,"&parser entry m","",m); 742: #endif /* NOSPL */ 743: 744: /* 745: sstate becomes nonzero when a command has been parsed that requires some 746: action from the protocol module. Any non-protocol actions, such as local 747: directory listing or terminal emulation, are invoked directly from below. 748: */ 749: #ifdef COMMENT 750: if (local && pflag) /* Just returned from connect? */ 751: printf("\n"); 752: #endif /* COMMENT */ 753: sstate = 0; /* Start with no start state. */ 754: #ifndef NOFRILLS 755: rmailf = rprintf = 0; /* MAIL and PRINT modifiers for SEND */ 756: *optbuf = NUL; /* MAIL and PRINT options */ 757: #endif /* NOFRILLS */ 758: while (sstate == 0) { /* Parse cmds until action requested */ 759: debug(F100,"top of parse loop","",0); 760: 761: /* Take requested action if there was an error in the previous command */ 762: 763: #ifndef MAC 764: conint(trap,stptrap); /* In case we were just fg'd */ 765: bgchk(); /* Check background status */ 766: #endif /* MAC */ 767: 768: debug(F101,"tlevel","",tlevel); 769: #ifndef NOSPL /* In case we just reached top level */ 770: debug(F101,"cmdlvl","",cmdlvl); 771: if (cmdlvl == 0) concb((char)escape); 772: #else 773: if (tlevel < 0) concb((char)escape); 774: #endif /* NOSPL */ 775: 776: #ifndef NOSPL 777: if (success == 0) { 778: if (cmdstk[cmdlvl].src == CMD_TF && terror) { 779: printf("Command error: take file terminated.\n"); 780: popclvl(); 781: if (cmdlvl == 0) return(0); 782: } 783: if (cmdstk[cmdlvl].src == CMD_MD && merror) { 784: printf("Command error: macro terminated.\n"); 785: popclvl(); 786: if (m && (cmdlvl < inlevel)) 787: return((int) sstate); 788: } 789: } 790: 791: nulcmd = (m == 2); 792: #else 793: if (success == 0 && tlevel > -1 && terror) { 794: printf("Command error: take file terminated.\n"); 795: popclvl(); 796: cmini(ckxech); /* Clear the cmd buffer. */ 797: if (tlevel < 0) /* Just popped out of cmd files? */ 798: return(0); /* End of init file or whatever. */ 799: } 800: #endif /* NOSPL */ 801: 802: #ifdef MAC 803: /* Check for TAKE initiated by menu. */ 804: if ((tlevel == -1) && lfiles) 805: startlfile(); 806: #endif /* MAC */ 807: 808: /* If in TAKE file, check for EOF */ 809: #ifndef NOSPL 810: #ifdef MAC 811: if 812: #else 813: while 814: #endif /* MAC */ 815: ((cmdstk[cmdlvl].src == CMD_TF) /* If end of take file */ 816: && (tlevel > -1) 817: && feof(tfile[tlevel])) { 818: popclvl(); /* pop command level */ 819: cmini(ckxech); /* and clear the cmd buffer. */ 820: if (cmdlvl == 0) /* Just popped out of all cmd files? */ 821: return(0); /* End of init file or whatever. */ 822: } 823: #ifdef MAC 824: miniparser(1); 825: if (sstate == 'a') { /* if cmd-. cancel */ 826: debug(F100, "parser: cancel take due to sstate", "", sstate); 827: sstate = '\0'; 828: dostop(); 829: return(0); /* End of init file or whatever. */ 830: } 831: #endif /* MAC */ 832: 833: #else /* NOSPL */ 834: if ((tlevel > -1) && feof(tfile[tlevel])) { /* If end of take */ 835: popclvl(); /* Pop up one level. */ 836: cmini(ckxech); /* and clear the cmd buffer. */ 837: if (tlevel < 0) /* Just popped out of cmd files? */ 838: return(0); /* End of init file or whatever. */ 839: } 840: #endif /* NOSPL */ 841: 842: #ifndef NOSPL 843: if (cmdstk[cmdlvl].src == CMD_MD) { /* Executing a macro? */ 844: debug(F100,"parser macro","",0); 845: maclvl = cmdstk[cmdlvl].lvl; /* Get current level */ 846: debug(F101,"parser maclvl","",maclvl); 847: cbp = cmdbuf; /* Copy next cmd to command buffer. */ 848: *cbp = NUL; 849: if (*savbuf) { /* In case then-part of 'if' command */ 850: strcpy(cbp,savbuf); /* was saved, restore it. */ 851: *savbuf = '\0'; 852: } else { /* Else get next cmd from macro def */ 853: if (getncm(cbp,CMDBL) < 0) { 854: if (m && (cmdlvl < inlevel)) 855: return((int) sstate); 856: else /* if (!m) */ continue; 857: } 858: } 859: debug(F110,"cmdbuf from macro",cmdbuf,0); 860: 861: } else if (cmdstk[cmdlvl].src == CMD_TF) 862: #else 863: if (tlevel > -1) 864: #endif /* NOSPL */ 865: { 866: #ifndef NOSPL 867: if (*savbuf) { /* In case THEN-part of IF command */ 868: strcpy(cmdbuf,savbuf); /* was saved, restore it. */ 869: *savbuf = '\0'; 870: } else 871: #endif /* NOSPL */ 872: 873: /* Get next line from TAKE file */ 874: 875: if ((tfcode = getnct(cmdbuf,CMDBL)) < 0) { 876: if (tfcode < -1) { /* Error */ 877: printf("?Error in TAKE command file: %s\n", 878: (tfcode == -2) ? "Memory allocation failure" : 879: "Line too long or contains NUL characters" 880: ); 881: popclvl(); 882: } 883: continue; /* -1 means EOF */ 884: } 885: 886: /* If interactive, get next command from user. */ 887: 888: } else { /* User types it in. */ 889: if (pflag) prompt(xxstring); 890: cmini(ckxech); 891: } 892: 893: /* Now know where next command is coming from. Parse and execute it. */ 894: 895: repars = 1; /* 1 = command needs parsing */ 896: displa = 0; /* Assume no file transfer display */ 897: 898: while (repars) { /* Parse this cmd until entered. */ 899: debug(F101,"parser top of while loop","",0); 900: cmres(); /* Reset buffer pointers. */ 901: xx = cmkey2(cmdtab,ncmd,"Command","",toktab,xxstring); 902: debug(F101,"top-level cmkey2","",xx); 903: if (xx == -5) { 904: yy = chktok(toktab); 905: debug(F101,"top-level cmkey token","",yy); 906: ungword(); 907: switch (yy) { 908: #ifndef NOPUSH 909: case '!': xx = XXSHE; break; /* Shell escape */ 910: #endif /* NOPUSH */ 911: case '#': xx = XXCOM; break; /* Comment */ 912: case ';': xx = XXCOM; break; /* Comment */ 913: #ifndef NOSPL 914: case ':': xx = XXLBL; break; /* GOTO label */ 915: #endif /* NOSPL */ 916: #ifndef NOPUSH 917: case '@': xx = XXSHE; break; /* Shell (DCL) escape */ 918: #endif /* NOPUSH */ 919: default: 920: printf("\n?Invalid - %s\n",cmdbuf); 921: xx = -2; 922: } 923: } 924: 925: #ifndef NOSPL 926: /* Special handling for IF..ELSE */ 927: 928: if (ifcmd[cmdlvl]) /* Count stmts after IF */ 929: ifcmd[cmdlvl]++; 930: if (ifcmd[cmdlvl] > 2 && xx != XXELS && xx != XXCOM) 931: ifcmd[cmdlvl] = 0; 932: 933: /* Execute the command and take action based on return code. */ 934: 935: if (nulcmd) { /* Ignoring this command? */ 936: xx = XXCOM; /* Make this command a comment. */ 937: } 938: #endif /* NOSPL */ 939: 940: zz = docmd(xx); /* Parse rest of command & execute. */ 941: debug(F101,"docmd returns","",zz); 942: #ifdef MAC 943: if (tlevel > -1) { 944: if (sstate == 'a') { /* if cmd-. cancel */ 945: debug(F110, "parser: cancel take, sstate:", "a", 0); 946: sstate = '\0'; 947: dostop(); 948: return(0); /* End of init file or whatever. */ 949: } 950: } 951: #endif /* MAC */ 952: switch (zz) { 953: case -4: /* EOF (e.g. on redirected stdin) */ 954: doexit(GOOD_EXIT,xitsta); /* ...exit successfully */ 955: case -1: /* Reparse needed */ 956: repars = 1; /* Just set reparse flag and */ 957: continue; 958: case -6: /* Invalid command given w/no args */ 959: case -2: /* Invalid command given w/args */ 960: #ifdef COMMENT 961: #ifndef NOSPL 962: /* This is going to be really ugly... */ 963: yy = mlook(mactab,atmbuf,nmac); /* Look in macro table */ 964: if (yy > -1) { /* If it's there */ 965: if (zz == -2) { /* insert "do" */ 966: char *mp; 967: mp = malloc((int)strlen(cmdbuf) + 5); 968: if (!mp) { 969: printf("?malloc error 1\n"); 970: return(-2); 971: } 972: sprintf(mp,"do %s ",cmdbuf); 973: strcpy(cmdbuf,mp); 974: free(mp); 975: } else sprintf(cmdbuf,"do %s %c",atmbuf, CR); 976: if (ifcmd[cmdlvl] == 2) /* This one doesn't count! */ 977: ifcmd[cmdlvl]--; 978: debug(F111,"stuff cmdbuf",cmdbuf,zz); 979: repars = 1; /* go for reparse */ 980: continue; 981: } else { 982: char *p; 983: int n; 984: p = cmdbuf; 985: lp = line; 986: n = LINBUFSIZ; 987: if (cmflgs == 0) printf("\n"); 988: if (xxstring(p,&lp,&n) > -1) 989: printf("?Invalid: %s\n",line); 990: else 991: printf("?Invalid: %s\n",cmdbuf); 992: } /* (fall thru...) */ 993: #else 994: printf("?Invalid: %s\n",cmdbuf); 995: #endif /* NOSPL */ 996: #else 997: printf("?Invalid: %s\n",cmdbuf); 998: #endif /* COMMENT */ 999: 1000: case -9: /* Bad, error message already done */ 1001: success = 0; 1002: debug(F110,"top-level cmkey failed",cmdbuf,0); 1003: if (pflag == 0) /* if background, terminate */ 1004: fatal("Kermit command error in background execution"); 1005: cmini(ckxech); /* (fall thru) */ 1006: 1007: case -3: /* Empty command OK at top level */ 1008: repars = 0; /* Don't need to reparse. */ 1009: continue; /* Go back and get another command. */ 1010: 1011: default: /* Command was successful. */ 1012: #ifndef NOSPL 1013: debug(F101,"parser preparing to continue","",maclvl); 1014: #endif /* NOSPL */ 1015: repars = 0; /* Don't need to reparse. */ 1016: continue; /* Go back and get another command. */ 1017: } 1018: } 1019: #ifndef NOSPL 1020: debug(F101,"parser breaks out of while loop","",maclvl); 1021: if (m && (cmdlvl < inlevel)) return((int) sstate); 1022: #endif /* NOSPL */ 1023: } 1024: 1025: /* Got an action command, return start state. */ 1026: 1027: #ifdef COMMENT 1028: /* This is done in ckcpro.w instead, no need to do it twice. */ 1029: /* Interrupts off only if remote */ 1030: if (!local) connoi(); 1031: #endif /* COMMENT */ 1032: return((int) sstate); 1033: } 1034: 1035: #ifndef NOSPL 1036: /* OUTPUT command */ 1037: 1038: int /* This could easily become a macro */ 1039: #ifdef CK_ANSIC 1040: xxout(char c) 1041: #else 1042: xxout(c) char c; 1043: #endif /* CK_ANSIC */ 1044: /* xxout */ { /* Function to output a character. */ 1045: debug(F101,"xxout","",c); 1046: if (local) /* If in local mode */ 1047: return(ttoc(c)); /* then to the external line */ 1048: else return(conoc(c)); /* otherwise to the console. */ 1049: } 1050: 1051: /* Returns 0 on failure, 1 on success */ 1052: 1053: int 1054: dooutput(s) char *s; { 1055: int x, y, quote; 1056: 1057: if (local) { /* Condition external line */ 1058: y = ttvt(speed,flow); 1059: if (y < 0) return(0); 1060: } 1061: quote = 0; /* Initialize backslash (\) quote */ 1062: 1063: #ifdef COMMENT 1064: /* This is done automatically in ttopen() now... */ 1065: #ifdef TNCODE 1066: if (network && ttnproto == NP_TELNET) /* If telnet connection, */ 1067: if (!tn_init++) tn_ini(); /* initialize it if necessary */ 1068: #endif /* TNCODE */ 1069: #endif /* COMMENT */ 1070: while (x = *s++) { /* Loop through the string */ 1071: y = 0; /* Error code, 0 = no error. */ 1072: if (x == CMDQ) { /* Look for \b or \B in string */ 1073: quote++; /* Got \ */ 1074: continue; /* Get next character */ 1075: } else if (quote) { /* This character is quoted */ 1076: if (quote == 1 && (x == 'b' || x == 'B')) { /* If \b or \B */ 1077: debug(F100,"OUTPUT BREAK","",0); 1078: ttsndb(); /* send BREAK signal */ 1079: quote = 0; /* Turn off quote flag */ 1080: continue; /* and not the b or B */ 1081: #ifdef CK_LBRK 1082: } else if (quote == 1 && (x == 'l' || x == 'L')) { /* \l or \L */ 1083: debug(F100,"OUTPUT Long BREAK","",0); 1084: ttsndlb(); /* send Long BREAK signal */ 1085: quote = 0; /* Turn off quote flag */ 1086: continue; /* and not the l or L */ 1087: #endif /* CK_LBRK */ 1088: } else { /* if \ not followed by b or B */ 1089: y = xxout(dopar(CMDQ)); /* output the backslash. */ 1090: quote = 0; /* Turn off quote flag */ 1091: } 1092: } else quote = 0; /* Turn off quote flag */ 1093: y = xxout(dopar((char)x)); /* Output this character */ 1094: if (y < 0) { 1095: printf("output error.\n"); 1096: return(0); 1097: } 1098: if (x == '\015') { /* User typed carriage return */ 1099: if (tnlm /* If TERMINAL NEWLINE-MODE is ON */ 1100: #ifdef TNCODE 1101: || (network && /* Or we have a network connection */ 1102: ttnproto == NP_TELNET && /* using TELNET protocol */ 1103: tn_nlm /* and TELNET NEWLINE-MODE is ON */ 1104: ) 1105: #endif /* TNCODE */ 1106: ) 1107: xxout(dopar('\012')); /* Send LF too (CR => CRLF) */ 1108: } 1109: if (seslog && duplex) 1110: if (zchout(ZSFILE,(char)x) < 0) seslog = 0; 1111: } 1112: return(1); 1113: } 1114: #endif /* NOSPL */ 1115: 1116: 1117: /* Display version herald and initial prompt */ 1118: 1119: VOID 1120: herald() { 1121: int x = 0; 1122: if (bgset > 0 || (bgset != 0 && backgrd != 0)) x = 1; 1123: debug(F101,"herald","",backgrd); 1124: if (x == 0) 1125: #ifdef datageneral 1126: printf("%s,%s\nType ? or HELP for help\n",versio,ckxsys); 1127: #else 1128: printf("%s,%s\n\rType ? or HELP for help\n",versio,ckxsys); 1129: #endif /* datageneral */ 1130: } 1131: #ifndef NOSPL 1132: /* M L O O K -- Lookup the macro name in the macro table */ 1133: 1134: /* 1135: Call this way: v = mlook(table,word,n); 1136: 1137: table - a 'struct mtab' table. 1138: word - the target string to look up in the table. 1139: n - the number of elements in the table. 1140: 1141: The keyword table must be arranged in ascending alphabetical order, and 1142: all letters must be lowercase. 1143: 1144: Returns the table index, 0 or greater, if the name was found, or: 1145: 1146: -3 if nothing to look up (target was null), 1147: -2 if ambiguous, 1148: -1 if not found. 1149: 1150: A match is successful if the target matches a keyword exactly, or if 1151: the target is a prefix of exactly one keyword. It is ambiguous if the 1152: target matches two or more keywords from the table. 1153: */ 1154: int 1155: mlook(table,cmd,n) struct mtab table[]; char *cmd; int n; { 1156: 1157: int i, v, cmdlen; 1158: 1159: /* Lowercase & get length of target, if it's null return code -3. */ 1160: 1161: if ((((cmdlen = lower(cmd))) == 0) || (n < 1)) return(-3); 1162: 1163: /* Not null, look it up */ 1164: 1165: for (i = 0; i < n-1; i++) { 1166: if (!strcmp(table[i].kwd,cmd) || 1167: ((v = !strncmp(table[i].kwd,cmd,cmdlen)) && 1168: strncmp(table[i+1].kwd,cmd,cmdlen))) { 1169: return(i); 1170: } 1171: if (v) return(-2); 1172: } 1173: 1174: /* Last (or only) element */ 1175: 1176: if (!strncmp(table[n-1].kwd,cmd,cmdlen)) { 1177: return(n-1); 1178: } else return(-1); 1179: } 1180: 1181: /* mxlook is like mlook, but an exact full-length match is required */ 1182: 1183: int 1184: mxlook(table,cmd,n) char *cmd; struct mtab table[]; int n; { 1185: int i, cmdlen; 1186: if ((((cmdlen = lower(cmd))) == 0) || (n < 1)) return(-3); 1187: for (i = 0; i < n; i++) 1188: if (((int)strlen(table[i].kwd) == cmdlen) && 1189: (!strncmp(table[i].kwd,cmd,cmdlen))) return(i); 1190: return(-1); 1191: } 1192: 1193: /* 1194: This routine is for the benefit of those compilers that can't handle 1195: long string constants or continued lines within them. Long predefined 1196: macros like FOR, WHILE, and XIF have their contents broken up into 1197: arrays of string pointers. This routine concatenates them back into a 1198: single string again, and then calls the real addmac() routine to enter 1199: the definition into the macro table. 1200: */ 1201: int 1202: addmmac(nam,s) char *nam, *s[]; { /* Add a multiline macro definition */ 1203: int i, x, y; char *p; 1204: x = 0; /* Length counter */ 1205: for (i = 0; (y = (int)strlen(s[i])) > 0; i++) { /* Add up total length */ 1206: debug(F111,"addmmac line",s[i],y); 1207: x += y; 1208: } 1209: debug(F101,"addmmac lines","",i); 1210: debug(F101,"addmmac loop exit","",y); 1211: debug(F111,"addmmac length",nam,x); 1212: if (x < 0) return(-1); 1213: 1214: p = malloc(x+1); /* Allocate space for all of it. */ 1215: if (!p) { 1216: printf("?addmmac malloc error: %s\n",nam); 1217: debug(F110,"addmmac malloc error",nam,0); 1218: return(-1); 1219: } 1220: *p = '\0'; /* Start off with null string. */ 1221: for (i = 0; *s[i]; i++) /* Concatenate them all together. */ 1222: strcat(p,s[i]); 1223: y = (int)strlen(p); /* Final precaution. */ 1224: debug(F111,"addmmac constructed string",p,y); 1225: if (y == x) { 1226: y = addmac(nam,p); /* Add result to the macro table. */ 1227: } else { 1228: debug(F100,"addmmac length mismatch","",0); 1229: printf("\n!addmmac internal error!\n"); 1230: y = -1; 1231: } 1232: free(p); /* Free the temporary copy. */ 1233: return(y); 1234: } 1235: 1236: /* Here is the real addmac routine. */ 1237: 1238: int 1239: addmac(nam,def) char *nam, *def; { /* Add a macro to the macro table */ 1240: int i, x, y, z, namlen, deflen; 1241: char *p, c; 1242: 1243: if (!nam) return(-1); 1244: namlen = (int)strlen(nam); /* Get argument lengths */ 1245: debug(F111,"addmac nam",nam,namlen); 1246: if (!def) { /* Watch out for null pointer */ 1247: deflen = 0; 1248: debug(F111,"addmac def","(null pointer)",deflen); 1249: } else { 1250: deflen = (int)strlen(def); 1251: debug(F111,"addmac def",def,deflen); 1252: } 1253: if (deflen < 0) return(-1); /* strlen() failure, fail. */ 1254: if (namlen < 1) return(-1); /* No name given, fail. */ 1255: 1256: if (*nam == CMDQ) nam++; /* Backslash quote? */ 1257: if (*nam == '%') { /* Yes, if it's a variable name, */ 1258: delmac(nam); /* Delete any old value. */ 1259: if (!(c = *(nam + 1))) return(-1); /* Variable name letter or digit */ 1260: if (deflen < 1) { /* Null definition */ 1261: p = NULL; /* Better not malloc or strcpy! */ 1262: } else { /* A substantial definition */ 1263: p = malloc(deflen + 1); /* Allocate space for it */ 1264: if (!p) { 1265: printf("?addmac malloc error 2\n"); 1266: return(-1); 1267: } else strcpy(p,def); /* Copy definition into new space */ 1268: } 1269: 1270: /* Now p points to the definition, or is a null pointer */ 1271: 1272: if (p) 1273: debug(F110,"addmac p",p,0); 1274: else 1275: debug(F110,"addmac p","(null pointer)",0); 1276: 1277: if (c >= '0' && c <= '9') { /* Digit variable */ 1278: if (maclvl < 0) { /* Are we calling or in a macro? */ 1279: g_var[c] = p; /* No, it's a global "top level" one */ 1280: debug(F101,"addmac numeric global maclvl","",maclvl); 1281: } else { /* Yes, it's a macro argument */ 1282: m_arg[maclvl][c - '0'] = p; 1283: debug(F101,"addmac macro arg maclvl","",maclvl); 1284: } 1285: } else { /* It's a global variable */ 1286: if (c < 33 || c > GVARS) return(-1); 1287: if (isupper(c)) c = tolower(c); 1288: g_var[c] = p; /* Put pointer in global-var table */ 1289: debug(F100,"addmac global","",0); 1290: } 1291: return(0); 1292: } else if (*nam == '&') { /* An array reference? */ 1293: char **q; 1294: if ((y = arraynam(nam,&x,&z)) < 0) /* If syntax is bad */ 1295: return(-1); /* return -1. */ 1296: if (chkarray(x,z) < 0) /* If array not declared or */ 1297: return(-2); /* subscript out of range, ret -2 */ 1298: delmac(nam); /* Delete any current definition. */ 1299: x -= 96; /* Convert name letter to index. */ 1300: if ((q = a_ptr[x]) == NULL) /* If array not declared, */ 1301: return(-3); /* return -3. */ 1302: if (deflen > 0) { 1303: if ((p = malloc(deflen+1)) == NULL) { /* Allocate space */ 1304: printf("addmac macro error 7: %s\n",nam); 1305: return(-4); /* for new def, return -4 on fail. */ 1306: } 1307: strcpy(p,def); /* Copy definition into new space. */ 1308: } else p = NULL; 1309: q[z] = p; /* Store pointer to it. */ 1310: return(0); /* Done. */ 1311: } else debug(F110,"addmac macro def",nam,0); 1312: 1313: /* Not a macro argument or a variable, so it's a macro definition */ 1314: 1315: lower(nam); /* Lowercase the name */ 1316: if (mxlook(mactab,nam,nmac) > -1) /* Look up, requiring exact match */ 1317: delmac(nam); /* if it's there, delete it. */ 1318: debug(F111,"addmac table size",nam,nmac); 1319: for (y = 0; /* Find the alphabetical slot */ 1320: y < MAC_MAX && mactab[y].kwd != NULL && strcmp(nam,mactab[y].kwd) > 0; 1321: y++) ; 1322: if (y == MAC_MAX) { /* No more room. */ 1323: debug(F101,"addmac table overflow","",y); 1324: return(-1); 1325: } else debug(F111,"addmac position",nam,y); 1326: if (mactab[y].kwd != NULL) { /* Must insert */ 1327: for (i = nmac; i > y; i--) { /* Move the rest down one slot */ 1328: mactab[i].kwd = mactab[i-1].kwd; 1329: mactab[i].mval = mactab[i-1].mval; 1330: mactab[i].flgs = mactab[i-1].flgs; 1331: } 1332: } 1333: p = malloc(namlen + 1); /* Allocate space for name */ 1334: if (!p) { 1335: printf("?addmac malloc error 3: %s\n",nam); 1336: return(-1); 1337: } 1338: strcpy(p,nam); /* Copy name into new space */ 1339: mactab[y].kwd = p; /* Add pointer to table */ 1340: 1341: if (deflen > 0) { /* Same deal for definition */ 1342: p = malloc(deflen + 1); /* but watch out for null pointer */ 1343: if (p == NULL) { 1344: printf("?addmac malloc error 5: %s\n", nam); 1345: free(mactab[y].kwd); 1346: mactab[y].kwd = NULL; 1347: return(-1); 1348: } else strcpy(p,def); /* Copy the definition */ 1349: } else p = NULL; 1350: mactab[y].mval = p; 1351: mactab[y].flgs = 0; 1352: nmac++; /* Count this macro */ 1353: return(y); 1354: } 1355: 1356: int 1357: delmac(nam) char *nam; { /* Delete the named macro */ 1358: int i, x, z; 1359: char *p, c; 1360: 1361: if (!nam) return(0); /* Watch out for null pointer */ 1362: debug(F110,"delmac nam",nam,0); 1363: if (*nam == CMDQ) nam++; 1364: if (*nam == '%') { /* If it's a variable name */ 1365: if (!(c = *(nam+1))) return(0); /* Get variable name letter or digit */ 1366: p = (char *)0; /* Initialize value pointer */ 1367: if (maclvl > -1 && c >= '0' && c <= '9') { /* Digit? */ 1368: p = m_arg[maclvl][c - '0']; /* Get pointer from macro-arg table */ 1369: m_arg[maclvl][c - '0'] = NULL; /* Zero the table pointer */ 1370: } else { /* It's a global variable */ 1371: if (c < 33 || c > GVARS) return(0); 1372: p = g_var[c]; /* Get pointer from global-var table */ 1373: g_var[c] = NULL; /* Zero the table entry */ 1374: } 1375: if (p) { 1376: debug(F110,"delmac def",p,0); 1377: free(p); /* Free the storage */ 1378: } else debug(F110,"delmac def","(null pointer)",0); 1379: return(0); 1380: } 1381: 1382: if (*nam == '&') { /* An array reference? */ 1383: char **q; 1384: if (arraynam(nam,&x,&z) < 0) /* If syntax is bad */ 1385: return(-1); /* return -1. */ 1386: x -= 96; /* Convert name to number. */ 1387: if ((q = a_ptr[x]) == NULL) /* If array not declared, */ 1388: return(-2); /* return -2. */ 1389: if (z > a_dim[x]) /* If subscript out of range, */ 1390: return(-3); /* return -3. */ 1391: if (q[z]) { /* If there is an old value, */ 1392: debug(F110,"delman def",q[z],0); 1393: free(q[z]); /* delete it. */ 1394: q[z] = NULL; 1395: } else debug(F110,"delmac def","(null pointer)",0); 1396: } 1397: 1398: /* Not a variable or an array, so it must be a macro. */ 1399: 1400: if ((x = mlook(mactab,nam,nmac)) < 0) { /* Look it up */ 1401: debug(F111,"delmac mlook",nam,x); 1402: return(x); 1403: } 1404: if (mactab[x].kwd) /* Free the storage for the name */ 1405: free(mactab[x].kwd); 1406: if (mactab[x].mval) /* and for the definition */ 1407: free(mactab[x].mval); 1408: 1409: for (i = x; i < nmac; i++) { /* Now move up the others. */ 1410: mactab[i].kwd = mactab[i+1].kwd; 1411: mactab[i].mval = mactab[i+1].mval; 1412: mactab[i].flgs = mactab[i+1].flgs; 1413: } 1414: nmac--; /* One less macro */ 1415: mactab[nmac].kwd = NULL; /* Delete last item from table */ 1416: mactab[nmac].mval = NULL; 1417: mactab[nmac].flgs = 0; 1418: return(0); 1419: } 1420: 1421: VOID 1422: initmac() { /* Init macro & variable tables */ 1423: int i, j; 1424: 1425: nmac = 0; /* No macros */ 1426: for (i = 0; i < MAC_MAX; i++) { /* Initialize the macro table */ 1427: mactab[i].kwd = NULL; 1428: mactab[i].mval = NULL; 1429: mactab[i].flgs = 0; 1430: } 1431: for (i = 0; i < MACLEVEL; i++) { /* Init the macro argument tables */ 1432: mrval[i] = NULL; 1433: for (j = 0; j < 10; j++) { 1434: m_arg[i][j] = NULL; 1435: } 1436: } 1437: for (i = 0; i < GVARS; i++) { /* And the global variables table */ 1438: g_var[i] = NULL; 1439: } 1440: for (i = 0; i < 26; i++) { /* And the table of arrays */ 1441: a_ptr[i] = (char **) NULL; /* Null pointer for each */ 1442: a_dim[i] = 0; /* and a dimension of zero */ 1443: } 1444: } 1445: 1446: int 1447: popclvl() { /* Pop command level, return cmdlvl */ 1448: if (cmdlvl < 1) { /* If we're already at top level */ 1449: cmdlvl = 0; /* just make sure all the */ 1450: tlevel = -1; /* stack pointers are set right */ 1451: maclvl = -1; /* and return */ 1452: } else if (cmdstk[cmdlvl].src == CMD_TF) { /* Reading from TAKE file? */ 1453: if (tlevel > -1) { /* Yes, */ 1454: if (tfnam[tlevel]) { 1455: free(tfnam[tlevel]); 1456: tfnam[tlevel] = NULL; 1457: } 1458: fclose(tfile[tlevel--]); /* close it and pop take level */ 1459: cmdlvl--; /* pop command level */ 1460: } else tlevel = -1; 1461: } else if (cmdstk[cmdlvl].src == CMD_MD) { /* In a macro? */ 1462: if (maclvl > -1) { /* Yes, */ 1463: debug(F111,"popclvl before",macx[maclvl],maclvl); 1464: macp[maclvl] = ""; /* set macro pointer to null string */ 1465: *cmdbuf = '\0'; /* clear the command buffer */ 1466: if (mrval[maclvl+1]) { /* Free any deeper return values. */ 1467: free(mrval[maclvl+1]); 1468: mrval[maclvl+1] = NULL; 1469: } 1470: maclvl--; /* pop macro level */ 1471: cmdlvl--; /* and command level */ 1472: debug(F111,"popclvl after ", 1473: macx[maclvl] ? macx[maclvl] : "",maclvl); 1474: } else maclvl = -1; 1475: } 1476: #ifndef MAC 1477: if (cmdlvl < 1) { /* If back at top level */ 1478: conint(trap,stptrap); /* Fix interrupts */ 1479: bgchk(); /* Check background status */ 1480: concb((char)escape); /* Go into cbreak mode */ 1481: } 1482: #endif /* MAC */ 1483: return(cmdlvl < 1 ? 0 : cmdlvl); /* Return command level */ 1484: } 1485: #else /* No script programming language */ 1486: int popclvl() { /* Just close current take file. */ 1487: if (tlevel > -1) { /* if any... */ 1488: if (tfnam[tlevel]) { 1489: free(tfnam[tlevel]); 1490: tfnam[tlevel] = NULL; 1491: } 1492: fclose(tfile[tlevel--]); 1493: } 1494: if (tlevel == -1) { /* And if back at top level */ 1495: conint(trap,stptrap); /* check and set interrupts */ 1496: bgchk(); /* and background status */ 1497: concb((char)escape); /* and go back into cbreak mode. */ 1498: } 1499: return(tlevel + 1); 1500: } 1501: #endif /* NOSPL */ 1502: 1503: /* STOP - get back to C-Kermit prompt, no matter where from. */ 1504: 1505: int 1506: dostop() { 1507: while ( popclvl() ) ; /* Pop all macros & take files */ 1508: #ifndef NOSPL 1509: while (cmpop() > -1) ; /* And all recursive cmd pkg invocations */ 1510: #endif /* NOSPL */ 1511: cmini(ckxech); /* Clear the command buffer. */ 1512: return(0); 1513: } 1514: 1515: 1516: /* Close the given log */ 1517: 1518: int 1519: doclslog(x) int x; { 1520: int y; 1521: switch (x) { 1522: #ifdef DEBUG 1523: case LOGD: 1524: if (deblog == 0) { 1525: printf("?Debugging log wasn't open\n"); 1526: return(0); 1527: } 1528: *debfil = '\0'; 1529: deblog = 0; 1530: return(zclose(ZDFILE)); 1531: #endif /* DEBUG */ 1532: 1533: case LOGP: 1534: if (pktlog == 0) { 1535: printf("?Packet log wasn't open\n"); 1536: return(0); 1537: } 1538: *pktfil = '\0'; 1539: pktlog = 0; 1540: return(zclose(ZPFILE)); 1541: 1542: case LOGS: 1543: if (seslog == 0) { 1544: printf("?Session log wasn't open\n"); 1545: return(0); 1546: } 1547: *sesfil = '\0'; 1548: seslog = 0; 1549: return(zclose(ZSFILE)); 1550: 1551: #ifdef TLOG 1552: case LOGT: 1553: if (tralog == 0) { 1554: printf("?Transaction log wasn't open\n"); 1555: return(0); 1556: } 1557: *trafil = '\0'; 1558: tralog = 0; 1559: return(zclose(ZTFILE)); 1560: #endif /* TLOG */ 1561: 1562: #ifndef NOSPL 1563: case LOGW: /* WRITE file */ 1564: case LOGR: /* READ file */ 1565: y = (x == LOGR) ? ZRFILE : ZWFILE; 1566: if (chkfn(y) < 1) /* If no file to close */ 1567: return(1); /* succeed silently. */ 1568: return(zclose(y)); /* Otherwise, close the file. */ 1569: #endif /* NOSPL */ 1570: 1571: default: 1572: printf("\n?Unexpected log designator - %ld\n", x); 1573: return(0); 1574: } 1575: } 1576: 1577: #ifndef NOSERVER 1578: #ifndef NOFRILLS 1579: static char *nm[] = { "disabled", "enabled" }; 1580: #endif /* NOFRILLS */ 1581: #endif /* NOSERVER */ 1582: 1583: static int slc = 0; /* Screen line count */ 1584: 1585: #ifndef NOSHOW 1586: #ifndef NOFRILLS 1587: #define xxdiff(v,sys) strncmp(v,sys,strlen(sys)) 1588: VOID 1589: shover() { 1590: printf("\nVersions:\n %s\n Numeric: %ld",versio,vernum); 1591: if (verwho) printf("-%d",verwho); 1592: printf(xxdiff(ckxv,ckxsys) ? "\n %s for%s\n" : "\n %s\n",ckxv,ckxsys); 1593: printf(xxdiff(ckzv,ckzsys) ? " %s for%s\n" : " %s\n",ckzv,ckzsys); 1594: printf(" %s\n",protv); 1595: printf(" %s\n",fnsv); 1596: printf(" %s\n %s\n",cmdv,userv); 1597: #ifndef NOCSETS 1598: printf(" %s\n",xlav); 1599: #endif /* NOCSETS */ 1600: #ifndef MAC 1601: printf(" %s\n",connv); 1602: #endif /* MAC */ 1603: #ifndef NODIAL 1604: printf(" %s\n",dialv); 1605: #endif /* NODIAL */ 1606: #ifndef NOSCRIPT 1607: printf(" %s\n",loginv); 1608: #endif /* NOSCRIPT */ 1609: #ifdef NETCONN 1610: printf(" %s\n",cknetv); 1611: #endif /* NETCONN */ 1612: printf("\n"); 1613: } 1614: 1615: VOID 1616: shofea() { 1617: #ifdef OS2 1618: #ifdef M_I286 1619: printf("\nOS/2 16-bit.\n"); 1620: #else 1621: printf("\nOS/2 32-bit.\n"); 1622: #endif /* M_I286 */ 1623: #endif /* OS2 */ 1624: printf("\nSpecial features:\n"); 1625: #ifdef NETCONN 1626: printf(" Network support (type SHOW NET for further info)\n"); 1627: #endif /* NETCONN */ 1628: #ifndef NOCSETS 1629: printf(" Latin-1 (West European) character-set translation\n"); 1630: #ifdef LATIN2 1631: printf(" Latin-2 (East European) character-set translation\n"); 1632: #endif /* LATIN2 */ 1633: #ifdef CYRILLIC 1634: printf(" Cyrillic (Russian, Ukrainian, etc) character-set translation\n"); 1635: #endif /* CYRILLIC */ 1636: #ifdef KANJI 1637: printf(" Kanji (Japanese) character-set translation\n"); 1638: #endif /* KANJI */ 1639: #endif /* NOCSETS */ 1640: 1641: #ifdef CK_CURSES 1642: printf(" Fullscreen file transfer display\n"); 1643: #endif /* CK_CURSES */ 1644: 1645: printf("\nFeatures not included:\n"); 1646: #ifndef CK_CURSES 1647: #ifndef MAC 1648: printf(" No fullscreen file transfer display\n"); 1649: #endif /* MAC */ 1650: #endif /* CK_CURSES */ 1651: #ifdef NOSERVER 1652: printf(" No server mode\n"); 1653: #endif /* NOSERVER */ 1654: #ifdef NODEBUG 1655: printf(" No debugging\n"); 1656: #endif /* NODEBUG */ 1657: #ifdef NOTLOG 1658: printf(" No transaction log\n"); 1659: #endif /* NOTLOG */ 1660: #ifdef NOHELP 1661: printf(" No built-in help\n"); 1662: #endif /* NOHELP */ 1663: #ifndef NETCONN 1664: printf(" No network support\n"); 1665: #endif /* NETCONN */ 1666: #ifdef NOMSEND 1667: printf(" No MSEND command\n"); 1668: #endif /* NOMSEND */ 1669: #ifdef NODIAL 1670: printf(" No DIAL command\n"); 1671: #else 1672: #ifdef MINIDIAL 1673: printf(" DIAL command for modems other than Hayes, CCITT, and Unknown\n"); 1674: #endif /* MINIDIAL */ 1675: #endif /* NODIAL */ 1676: #ifdef NOXMIT 1677: printf(" No TRANSMIT command\n"); 1678: #endif /* NOXMIT */ 1679: #ifdef NOSCRIPT 1680: printf(" No SCRIPT command\n"); 1681: #endif /* NOSCRIPT */ 1682: #ifdef NOSPL 1683: printf(" No script programming features\n"); 1684: #endif /* NOSPL */ 1685: #ifdef NOCSETS 1686: printf(" No character-set translation\n"); 1687: #else 1688: #ifndef LATIN2 1689: printf(" No Latin-2 character-set translation\n"); 1690: #endif /* LATIN2 */ 1691: #ifdef NOCYRIL 1692: printf(" No Cyrillic character-set translation\n"); 1693: #endif /* NOCYRIL */ 1694: #ifndef KANJI 1695: printf(" No Kanji character-set translation\n"); 1696: #endif /* KANJI */ 1697: #endif /* NOCSETS */ 1698: #ifdef NOCMDL 1699: printf(" No command-line arguments\n"); 1700: #endif /* NOCMDL */ 1701: #ifdef NOFRILLS 1702: printf(" No frills\n"); 1703: #endif /* NOFRILLS */ 1704: #ifdef NOPUSH 1705: printf(" No escape to system\n"); 1706: #endif /* NOPUSH */ 1707: #ifdef NOJC 1708: #ifdef UNIX 1709: printf(" No UNIX job control\n"); 1710: #endif /* UNIX */ 1711: #endif /* NOJC */ 1712: #ifdef NOSETKEY 1713: printf(" No SET KEY command\n"); 1714: #endif /* NOSETKEY */ 1715: #ifdef NOESCSEQ 1716: printf(" No ANSI escape sequence recognition\n"); 1717: #endif /* NOESCSEQ */ 1718: #ifndef PARSENSE 1719: printf(" No automatic parity detection\n"); 1720: #endif /* PARSENSE */ 1721: /* 1722: Print all of Kermit's compile-time options, as well as C preprocessor 1723: predefined symbols that might affect us... 1724: */ 1725: printf("\nCompiler options:\n"); 1726: #ifdef DEBUG 1727: #ifdef IFDEBUG 1728: prtopt(" IFDEBUG"); 1729: #else 1730: prtopt(" DEBUG"); 1731: #endif /* IFDEBUG */ 1732: #endif /* DEBUG */ 1733: #ifdef TLOG 1734: prtopt(" TLOG"); 1735: #endif /* TLOG */ 1736: #ifdef NODIAL 1737: prtopt(" NODIAL"); 1738: #endif /* NODIAL */ 1739: #ifdef MINIDIAL 1740: prtopt(" MINIDIAL"); 1741: #endif /* MINIDIAL */ 1742: #ifdef DYNAMIC 1743: prtopt(" DYNAMIC"); 1744: #endif /* IFDEBUG */ 1745: #ifndef NOSPL 1746: sprintf(line," CMDDEP=%d",CMDDEP); 1747: prtopt(line); 1748: #endif /* NOSPL */ 1749: #ifdef UNIX 1750: prtopt(" UNIX"); 1751: #endif /* UNIX */ 1752: #ifdef VMS 1753: prtopt(" VMS"); 1754: #endif /* VMS */ 1755: #ifdef vms 1756: prtopt(" vms"); 1757: #endif /* vms */ 1758: #ifdef VMSSHARE 1759: prtopt(" VMSSHARE"); 1760: #endif /* VMSSHARE */ 1761: #ifdef datageneral 1762: prtopt(" datageneral"); 1763: #endif /* datageneral */ 1764: #ifdef apollo 1765: prtopt(" apollo"); 1766: #endif /* apollo */ 1767: #ifdef aegis 1768: prtopt(" aegis"); 1769: #endif /* aegis */ 1770: #ifdef A986 1771: prtopt(" A986"); 1772: #endif /* A986 */ 1773: #ifdef AMIGA 1774: prtopt(" AMIGA"); 1775: #endif /* AMIGA */ 1776: #ifdef CONVEX9 1777: prtopt(" CONVEX9"); 1778: #endif /* CONVEX9 */ 1779: #ifdef MAC 1780: prtopt(" MAC"); 1781: #endif /* MAC */ 1782: #ifdef AUX 1783: prtopt(" AUX"); 1784: #endif /* AUX */ 1785: #ifdef OS2 1786: prtopt(" OS2"); 1787: #endif /* OS2 */ 1788: #ifdef OS9 1789: prtopt(" OS9"); 1790: #endif /* OS9 */ 1791: #ifdef MSDOS 1792: prtopt(" MSDOS"); 1793: #endif /* MSDOS */ 1794: #ifdef DIRENT 1795: prtopt(" DIRENT"); 1796: #endif /* DIRENT */ 1797: #ifdef SDIRENT 1798: prtopt(" SDIRENT"); 1799: #endif /* SDIRENT */ 1800: #ifdef NDIR 1801: prtopt(" NDIR"); 1802: #endif /* NDIR */ 1803: #ifdef XNDIR 1804: prtopt(" XNDIR"); 1805: #endif /* XNDIR */ 1806: #ifdef MATCHDOT 1807: prtopt(" MATCHDOT"); 1808: #endif /* MATCHDOT */ 1809: #ifdef SAVEDUID 1810: prtopt(" SAVEDUID"); 1811: #endif /* SAVEDUID */ 1812: #ifdef NOCCTRAP 1813: prtopt(" NOCCTRAP"); 1814: #endif /* NOCCTRAP */ 1815: #ifdef SUNX25 1816: prtopt(" SUNX25"); 1817: #endif /* SUNX25 */ 1818: #ifdef DECNET 1819: prtopt(" DECNET"); 1820: #endif /* DECNET */ 1821: #ifdef ATT7300 1822: prtopt(" ATT7300"); 1823: #endif /* ATT7300 */ 1824: #ifdef ATT6300 1825: prtopt(" ATT6300"); 1826: #endif /* ATT6300 */ 1827: #ifdef HDBUUCP 1828: prtopt(" HDBUUCP"); 1829: #endif /* HDBUUCP */ 1830: #ifdef NOUUCP 1831: prtopt(" NOUUCP"); 1832: #endif /* NOUUCP */ 1833: #ifdef LONGFN 1834: prtopt(" LONGFN"); 1835: #endif /* LONGFN */ 1836: #ifdef RDCHK 1837: prtopt(" RDCHK"); 1838: #endif /* RDCHK */ 1839: #ifdef NAP 1840: prtopt(" NAP"); 1841: #endif /* NAP */ 1842: #ifdef NAPHACK 1843: prtopt(" NAPHACK"); 1844: #endif /* NAPHACK */ 1845: #ifdef NOIEXTEN 1846: prtopt(" NOIEXTEN"); 1847: #endif /* NOIEXTEN */ 1848: #ifdef EXCELAN 1849: prtopt(" EXCELAN"); 1850: #endif /* EXCELAN */ 1851: #ifdef PARAMH 1852: prtopt(" PARAMH"); 1853: #endif /* PARAMH */ 1854: #ifdef INTERLAN 1855: prtopt(" INTERLAN"); 1856: #endif /* INTERLAN */ 1857: #ifdef NOFILEH 1858: prtopt(" NOFILEH"); 1859: #endif /* NOFILEH */ 1860: #ifdef NOSYSIOCTLH 1861: prtopt(" NOSYSIOCTLH"); 1862: #endif /* NOSYSIOCTLH */ 1863: #ifdef DCLPOPEN 1864: prtopt(" DCLPOPEN"); 1865: #endif /* DCLPOPEN */ 1866: #ifdef NOSETBUF 1867: prtopt(" NOSETBUF"); 1868: #endif /* NOSETBUF */ 1869: #ifdef NOFDZERO 1870: prtopt(" NOFDZERO"); 1871: #endif /* NOFDZERO */ 1872: #ifdef NOPOPEN 1873: prtopt(" NOPOPEN"); 1874: #endif /* NOPOPEN */ 1875: #ifdef NOPARTIAL 1876: prtopt(" NOPARTIAL"); 1877: #endif /* NOPARTIAL */ 1878: #ifdef NOSETREU 1879: prtopt(" NOSETREU"); 1880: #endif /* NOSETREU */ 1881: #ifdef _POSIX_SOURCE 1882: prtopt(" _POSIX_SOURCE"); 1883: #endif /* _POSIX_SOURCE */ 1884: #ifdef LCKDIR 1885: prtopt(" LCKDIR"); 1886: #endif /* LCKDIR */ 1887: #ifdef ACUCNTRL 1888: prtopt(" ACUCNTRL"); 1889: #endif /* ACUCNTRL */ 1890: #ifdef BSD4 1891: prtopt(" BSD4"); 1892: #endif /* BSD4 */ 1893: #ifdef BSD44 1894: prtopt(" BSD44"); 1895: #endif /* BSD44 */ 1896: #ifdef BSD41 1897: prtopt(" BSD41"); 1898: #endif /* BSD41 */ 1899: #ifdef BSD43 1900: prtopt(" BSD43"); 1901: #endif /* BSD43 */ 1902: #ifdef BSD29 1903: prtopt(" BSD29"); 1904: #endif /* BSD29 */ 1905: #ifdef V7 1906: prtopt(" V7"); 1907: #endif /* V7 */ 1908: #ifdef AIX370 1909: prtopt(" AIX370"); 1910: #endif /* AIX370 */ 1911: #ifdef RTAIX 1912: prtopt(" RTAIX"); 1913: #endif /* RTAIX */ 1914: #ifdef HPUX 1915: prtopt(" HPUX"); 1916: #endif /* HPUX */ 1917: #ifdef HPUXPRE65 1918: prtopt(" HPUXPRE65"); 1919: #endif /* HPUXPRE65 */ 1920: #ifdef DGUX 1921: prtopt(" DGUX"); 1922: #endif /* DGUX */ 1923: #ifdef DGUX430 1924: prtopt(" DGUX430"); 1925: #endif /* DGUX430 */ 1926: #ifdef DGUX540 1927: prtopt(" DGUX540"); 1928: #endif /* DGUX540 */ 1929: #ifdef sony_news 1930: prtopt(" sony_news"); 1931: #endif /* sony_news */ 1932: #ifdef CIE 1933: prtopt(" CIE"); 1934: #endif /* CIE */ 1935: #ifdef XENIX 1936: prtopt(" XENIX"); 1937: #endif /* XENIX */ 1938: #ifdef SCO_XENIX 1939: prtopt(" SCO_XENIX"); 1940: #endif /* SCO_XENIX */ 1941: #ifdef ISIII 1942: prtopt(" ISIII"); 1943: #endif /* ISIII */ 1944: #ifdef I386IX 1945: prtopt(" I386IX"); 1946: #endif /* I386IX */ 1947: #ifdef RTU 1948: prtopt(" RTU"); 1949: #endif /* RTU */ 1950: #ifdef PROVX1 1951: prtopt(" PROVX1"); 1952: #endif /* PROVX1 */ 1953: #ifdef TOWER1 1954: prtopt(" TOWER1"); 1955: #endif /* TOWER1 */ 1956: #ifdef UTEK 1957: prtopt(" UTEK"); 1958: #endif /* UTEK */ 1959: #ifdef ZILOG 1960: prtopt(" ZILOG"); 1961: #endif /* ZILOG */ 1962: #ifdef TRS16 1963: prtopt(" TRS16"); 1964: #endif /* TRS16 */ 1965: #ifdef MINIX 1966: prtopt(" MINIX"); 1967: #endif /* MINIX */ 1968: #ifdef C70 1969: prtopt(" C70"); 1970: #endif /* C70 */ 1971: #ifdef AIXPS2 1972: prtopt(" AIXPS2"); 1973: #endif /* AIXPS2 */ 1974: #ifdef AIXRS 1975: prtopt(" AIXRS"); 1976: #endif /* AIXRS */ 1977: #ifdef UTSV 1978: prtopt(" UTSV"); 1979: #endif /* UTSV */ 1980: #ifdef ATTSV 1981: prtopt(" ATTSV"); 1982: #endif /* ATTSV */ 1983: #ifdef SVR3 1984: prtopt(" SVR3"); 1985: #endif /* SVR3 */ 1986: #ifdef SVR4 1987: prtopt(" SVR4"); 1988: #endif /* SVR4 */ 1989: #ifdef DELL_SVR4 1990: prtopt(" DELL_SVR4"); 1991: #endif /* DELL_SVR4 */ 1992: #ifdef ICL_SVR4 1993: prtopt(" ICL_SVR4"); 1994: #endif /* ICL_SVR4 */ 1995: #ifdef OSF 1996: prtopt(" OSF"); 1997: #endif /* OSF */ 1998: #ifdef PTX 1999: prtopt(" PTX"); 2000: #endif /* PTX */ 2001: #ifdef POSIX 2002: prtopt(" POSIX"); 2003: #endif /* POSIX */ 2004: #ifdef SOLARIS 2005: prtopt(" SOLARIS"); 2006: #endif /* SOLARIS */ 2007: #ifdef SUNOS4 2008: prtopt(" SUNOS4"); 2009: #endif /* SUNOS4 */ 2010: #ifdef SUN4S5 2011: prtopt(" SUN4S5"); 2012: #endif /* SUN4S5 */ 2013: #ifdef ENCORE 2014: prtopt(" ENCORE"); 2015: #endif /* ENCORE */ 2016: #ifdef ultrix 2017: prtopt(" ultrix"); 2018: #endif 2019: #ifdef sxaE50 2020: prtopt(" sxaE50"); 2021: #endif 2022: #ifdef mips 2023: prtopt(" mips"); 2024: #endif 2025: #ifdef MIPS 2026: prtopt(" MIPS"); 2027: #endif 2028: #ifdef vax 2029: prtopt(" vax"); 2030: #endif 2031: #ifdef VAX 2032: prtopt(" VAX"); 2033: #endif 2034: #ifdef sun 2035: prtopt(" sun"); 2036: #endif 2037: #ifdef sun3 2038: prtopt(" sun3"); 2039: #endif 2040: #ifdef sun386 2041: prtopt(" sun386"); 2042: #endif 2043: #ifdef _SUN 2044: prtopt(" _SUN"); 2045: #endif 2046: #ifdef sun4 2047: prtopt(" sun4"); 2048: #endif 2049: #ifdef sparc 2050: prtopt(" sparc"); 2051: #endif 2052: #ifdef NEXT 2053: prtopt(" NEXT"); 2054: #endif 2055: #ifdef NeXT 2056: prtopt(" NeXT"); 2057: #endif 2058: #ifdef sgi 2059: prtopt(" sgi"); 2060: #endif 2061: #ifdef M_SYS5 2062: prtopt(" M_SYS5"); 2063: #endif 2064: #ifdef __SYSTEM_FIVE 2065: prtopt(" __SYSTEM_FIVE"); 2066: #endif 2067: #ifdef sysV 2068: prtopt(" sysV"); 2069: #endif 2070: #ifdef M_XENIX /* SCO Xenix V and UNIX/386 */ 2071: prtopt(" M_XENIX"); 2072: #endif 2073: #ifdef M_UNIX 2074: prtopt(" M_UNIX"); 2075: #endif 2076: #ifdef M_I386 2077: prtopt(" M_I386"); 2078: #endif 2079: #ifdef _M_I386 2080: prtopt(" _M_I386"); 2081: #endif 2082: #ifdef i386 2083: prtopt(" i386"); 2084: #endif 2085: #ifdef i286 2086: prtopt(" i286"); 2087: #endif 2088: #ifdef M_I286 2089: prtopt(" M_I286"); 2090: #endif 2091: #ifdef mc68000 2092: prtopt(" mc68000"); 2093: #endif 2094: #ifdef mc68010 2095: prtopt(" mc68010"); 2096: #endif 2097: #ifdef mc68020 2098: prtopt(" mc68020"); 2099: #endif 2100: #ifdef mc68030 2101: prtopt(" mc68030"); 2102: #endif 2103: #ifdef mc68040 2104: prtopt(" mc68040"); 2105: #endif 2106: #ifdef M_68000 2107: prtopt(" M_68000"); 2108: #endif 2109: #ifdef M_68010 2110: prtopt(" M_68010"); 2111: #endif 2112: #ifdef M_68020 2113: prtopt(" M_68020"); 2114: #endif 2115: #ifdef M_68030 2116: prtopt(" M_68030"); 2117: #endif 2118: #ifdef M_68040 2119: prtopt(" M_68040"); 2120: #endif 2121: #ifdef m68k 2122: prtopt(" m68k"); 2123: #endif 2124: #ifdef m88k 2125: prtopt(" m88k"); 2126: #endif 2127: #ifdef pdp11 2128: prtopt(" pdp11"); 2129: #endif 2130: #ifdef iAPX 2131: prtopt(" iAPX"); 2132: #endif 2133: #ifdef __hp9000s800 2134: prtopt(" __hp9000s800"); 2135: #endif 2136: #ifdef __hp9000s500 2137: prtopt(" __hp9000s500"); 2138: #endif 2139: #ifdef __hp9000s300 2140: prtopt(" __hp9000s300"); 2141: #endif 2142: #ifdef __hp9000s200 2143: prtopt(" __hp9000s200"); 2144: #endif 2145: #ifdef AIX 2146: prtopt(" AIX"); 2147: #endif 2148: #ifdef _AIXFS 2149: prtopt(" _AIXFS"); 2150: #endif 2151: #ifdef u370 2152: prtopt(" u370"); 2153: #endif 2154: #ifdef u3b 2155: prtopt(" u3b"); 2156: #endif 2157: #ifdef u3b2 2158: prtopt(" u3b2"); 2159: #endif 2160: #ifdef multimax 2161: prtopt(" multimax"); 2162: #endif 2163: #ifdef balance 2164: prtopt(" balance"); 2165: #endif 2166: #ifdef ibmrt 2167: prtopt(" ibmrt"); 2168: #endif 2169: #ifdef _IBMRT 2170: prtopt(" _IBMRT"); 2171: #endif 2172: #ifdef ibmrs6000 2173: prtopt(" ibmrs6000"); 2174: #endif 2175: #ifdef _AIX 2176: prtopt(" _AIX"); 2177: #endif /* _AIX */ 2178: #ifdef _IBMR2 2179: prtopt(" _IBMR2"); 2180: #endif 2181: #ifdef __STRICT_BSD__ 2182: prtopt(" __STRICT_BSD__"); 2183: #endif 2184: #ifdef __STRICT_ANSI__ 2185: prtopt(" __STRICT_ANSI__"); 2186: #endif 2187: #ifdef _ANSI_C_SOURCE 2188: prtopt(" _ANSI_C_SOURCE"); 2189: #endif 2190: #ifdef __STDC__ 2191: prtopt(" __STDC__"); 2192: #endif 2193: #ifdef __GNUC__ /* gcc in ansi mode */ 2194: prtopt(" __GNUC__"); 2195: #endif 2196: #ifdef GNUC /* gcc in traditional mode */ 2197: prtopt(" GNUC"); 2198: #endif 2199: #ifdef CK_ANSIC 2200: prtopt(" CK_ANSIC"); 2201: #endif 2202: #ifdef CK_ANSILIBS 2203: prtopt(" CK_ANSILIBS"); 2204: #endif 2205: #ifdef _XOPEN_SOURCE 2206: prtopt(" _XOPEN_SOURCE"); 2207: #endif 2208: #ifdef _ALL_SOURCE 2209: prtopt(" _ALL_SOURCE"); 2210: #endif 2211: #ifdef _SC_JOB_CONTROL 2212: prtopt(" _SC_JOB_CONTROL"); 2213: #endif 2214: #ifdef _POSIX_JOB_CONTROL 2215: prtopt(" _POSIX_JOB_CONTROL"); 2216: #endif 2217: #ifdef SVR3JC 2218: prtopt(" SVR3JC"); 2219: #endif 2220: #ifdef _386BSD 2221: prtopt(" _386BSD"); 2222: #endif 2223: #ifdef _BSD 2224: prtopt(" _BSD"); 2225: #endif 2226: #ifdef TERMIOX 2227: prtopt(" TERMIOX"); 2228: #endif /* TERMIOX */ 2229: #ifdef STERMIOX 2230: prtopt(" STERMIOX"); 2231: #endif /* STERMIOX */ 2232: #ifdef CK_CURSES 2233: prtopt(" CK_CURSES"); 2234: #endif /* CK_CURSES */ 2235: #ifdef CK_DTRCD 2236: prtopt(" CK_DTRCD"); 2237: #endif /* CK_DTRCD */ 2238: #ifdef CK_DTRCTS 2239: prtopt(" CK_DTRCTS"); 2240: #endif /* CK_DTRCTS */ 2241: #ifdef CK_RTSCTS 2242: prtopt(" CK_RTSCTS"); 2243: #endif /* CK_RTSCTS */ 2244: prtopt((char *)0); 2245: printf("\n\n"); 2246: } 2247: #endif /* NOFRILLS */ 2248: #endif /* NOSHOW */ 2249: 2250: #ifdef VMS 2251: int 2252: sholbl() { 2253: printf("VMS Labeled File Features:\n"); 2254: printf(" acl %s (ACL info %s)\n", 2255: lf_opts & LBL_ACL ? "on " : "off", 2256: lf_opts & LBL_ACL ? "preserved" : "discarded"); 2257: printf(" backup-date %s (backup date/time %s)\n", 2258: lf_opts & LBL_BCK ? "on " : "off", 2259: lf_opts & LBL_BCK ? "preserved" : "discarded"); 2260: printf(" name %s (original filename %s)\n", 2261: lf_opts & LBL_NAM ? "on " : "off", 2262: lf_opts & LBL_NAM ? "preserved" : "discarded"); 2263: printf(" owner %s (original file owner id %s)\n", 2264: lf_opts & LBL_OWN ? "on " : "off", 2265: lf_opts & LBL_OWN ? "preserved" : "discarded"); 2266: printf(" path %s (original file's disk:[directory] %s)\n", 2267: lf_opts & LBL_PTH ? "on " : "off", 2268: lf_opts & LBL_PTH ? "preserved" : "discarded"); 2269: } 2270: #endif /* VMS */ 2271: 2272: #ifndef NOSHOW 2273: VOID 2274: shotcs(cs1,cs2) int cs1, cs2; { /* Show terminal character set */ 2275: #ifndef NOCSETS 2276: #ifndef MAC 2277: int y; 2278: char *s; 2279: #ifdef CK_ANSIC 2280: int gettcs(int, int); 2281: #else 2282: int gettcs(); 2283: #endif /* CK_ANSIC */ 2284: 2285: printf(" Terminal character-set"); 2286: if (cs1 == cs2) { 2287: printf(": transparent\n"); 2288: } else { 2289: s = "unknown"; 2290: for (y = 0; y <= nfilc; y++) /* Look up name in keyword table */ 2291: if (ttcstab[y].kwval == cs2) { 2292: if (ttcstab[y].flgs & CM_INV) /* Skip synonyms */ 2293: continue; 2294: s = ttcstab[y].kwd; 2295: break; 2296: } 2297: printf("s:\n Remote: %s\n Local: ",s); 2298: s = "unknown"; 2299: for (y = 0; y <= nfilc; y++) 2300: if (ttcstab[y].kwval == cs1) { 2301: if (ttcstab[y].flgs & CM_INV) /* Skip synonyms */ 2302: continue; 2303: s = ttcstab[y].kwd; 2304: break; 2305: } 2306: printf("%s",s); 2307: if (cs2 != cs1) { 2308: switch(gettcs(cs2,cs1)) { 2309: case TC_USASCII: s = "ascii"; break; 2310: case TC_1LATIN: s = "latin1-iso"; break; 2311: case TC_2LATIN: s = "latin2-iso"; break; 2312: case TC_CYRILL: s = "cyrillic-iso"; break; 2313: case TC_JEUC: s = "japanese-euc"; break; 2314: default: s = "transparent"; break; 2315: } 2316: printf("\n Via: %s\n",s); 2317: } 2318: } 2319: #endif /* MAC */ 2320: #endif /* NOCSETS */ 2321: } 2322: #endif /* NOSHOW */ 2323: 2324: #ifndef NOSHOW 2325: int 2326: doshow(x) int x; { 2327: int y, i; long zz; 2328: char *s; 2329: 2330: #ifndef NOSETKEY 2331: if (x == SHKEY) { /* SHOW KEY */ 2332: int c; 2333: KEY ch; 2334: CHAR *s; 2335: 2336: if ((y = cmcfm()) < 0) return(y); 2337: #ifdef MAC 2338: printf("Not implemented\n"); 2339: return(0); 2340: #else /* Not MAC */ 2341: printf(" Press key: "); 2342: #ifdef UNIX 2343: #ifdef NOSETBUF 2344: fflush(stdout); 2345: #endif /* NOSETBUF */ 2346: #endif /* UNIX */ 2347: conbin((char)escape); /* Put terminal in binary mode */ 2348: c = congks(0); /* Get character or scan code */ 2349: concb((char)escape); /* Restore terminal to cbreak mode */ 2350: if (c < 0) { /* Check for error */ 2351: printf("?Error reading key\n"); 2352: return(0); 2353: } 2354: #ifndef OS2 2355: /* 2356: Do NOT mask when it can be a raw scan code, perhaps > 255 2357: */ 2358: c &= cmdmsk; /* Apply command mask */ 2359: #endif /* OS2 */ 2360: printf("\n Key code \\%d => ",c); 2361: if (macrotab[c]) { /* See if there's a macro */ 2362: printf("String: "); /* If so, display its definition */ 2363: s = macrotab[c]; 2364: while (ch = *s++) 2365: if (ch < 32 || ch == 127 2366: /* 2367: Systems whose native character sets have graphic characters in C1... 2368: */ 2369: #ifndef NEXT /* NeXT */ 2370: #ifndef AUX /* Macintosh */ 2371: #ifndef XENIX /* IBM PC */ 2372: #ifndef OS2 /* IBM PC */ 2373: || (ch > 127 && ch < 160) 2374: #endif /* OS2 */ 2375: #endif /* XENIX */ 2376: #endif /* AUX */ 2377: #endif /* NEXT */ 2378: ) 2379: printf("\\{%d}",ch); /* Display control characters */ 2380: else putchar((char) ch); /* in backslash notation */ 2381: printf("\n"); 2382: } else { /* No macro, show single character */ 2383: printf("Character: "); 2384: ch = keymap[c]; 2385: if (ch < 32 || ch == 127 || ch > 255 2386: #ifndef NEXT 2387: #ifndef AUX 2388: #ifndef XENIX 2389: #ifndef OS2 2390: || (ch > 127 && ch < 160) 2391: #endif /* OS2 */ 2392: #endif /* XENIX */ 2393: #endif /* AUX */ 2394: #endif /* NEXT */ 2395: ) 2396: printf("\\%d",(unsigned int) ch); 2397: else printf("%c \\%d",ch,(unsigned int) ch); 2398: } 2399: if (ch == (KEY) c) 2400: printf(" (self, no translation)\n"); 2401: else printf("\n"); 2402: return(1); 2403: #endif /* MAC */ 2404: } 2405: #endif /* NOSETKEY */ 2406: 2407: #ifndef NOSPL 2408: if (x == SHMAC) { /* SHOW MACRO */ 2409: x = cmfld("Macro name, or carriage return to see them all","",&s, 2410: NULL); 2411: if (x == -3) /* This means they want see all */ 2412: *line = '\0'; 2413: else if (x < 0) /* Otherwise negative = parse error */ 2414: return(x); 2415: else /* 0 or greater */ 2416: strcpy(line,s); /* means they typed something */ 2417: if ((y = cmcfm()) < 0) return(y); /* Get confirmation */ 2418: if (*line) { 2419: slc = 0; /* Initial SHO MAC line number */ 2420: x = mlook(mactab,s,nmac); /* Look up what they typed */ 2421: switch (x) { 2422: case -3: /* Nothing to look up */ 2423: return(0); 2424: case -1: /* Not found */ 2425: printf("%s - not found\n",s); 2426: return(0); 2427: case -2: /* Ambiguous, matches more than one */ 2428: y = (int)strlen(line); 2429: slc = 1; 2430: for (x = 0; x < nmac; x++) 2431: if (!strncmp(mactab[x].kwd,line,y)) 2432: if (shomac(mactab[x].kwd,mactab[x].mval) < 0) break; 2433: return(1); 2434: default: /* Matches one exactly */ 2435: shomac(mactab[x].kwd,mactab[x].mval); 2436: return(1); 2437: } 2438: } else { /* They want to see them all */ 2439: printf("Macros:\n"); 2440: slc = 1; 2441: for (y = 0; y < nmac; y++) 2442: if (shomac(mactab[y].kwd,mactab[y].mval) < 0) break; 2443: return(1); 2444: } 2445: } 2446: #endif /* NOSPL */ 2447: 2448: /* 2449: Other SHOW commands only have two fields. Get command confirmation here, 2450: then handle with big switch() statement. 2451: */ 2452: if ((y = cmcfm()) < 0) return(y); 2453: switch (x) { 2454: 2455: #ifdef SUNX25 2456: case SHPAD: 2457: shopad(); 2458: break; 2459: #endif /* SUNX25 */ 2460: 2461: #ifdef NETCONN 2462: case SHNET: 2463: shonet(); 2464: break; 2465: #endif /* NETCONN */ 2466: 2467: case SHPAR: 2468: shopar(); 2469: break; 2470: 2471: case SHATT: 2472: shoatt(); 2473: break; 2474: 2475: #ifndef NOSPL 2476: case SHCOU: 2477: printf(" %d\n",count[cmdlvl]); 2478: break; 2479: #endif /* NOSPL */ 2480: 2481: #ifndef NOSERVER 2482: case SHSER: /* Show Server */ 2483: #ifndef NOFRILLS 2484: printf("Function Status:\n"); 2485: printf(" GET %s\n",nm[en_get]); 2486: printf(" SEND %s\n",nm[en_sen]); 2487: printf(" REMOTE CD/CWD %s\n",nm[en_cwd]); 2488: printf(" REMOTE DELETE %s\n",nm[en_del]); 2489: printf(" REMOTE DIRECTORY %s\n",nm[en_dir]); 2490: printf(" REMOTE HOST %s\n",nm[en_hos]); 2491: printf(" REMOTE SET %s\n",nm[en_set]); 2492: printf(" REMOTE SPACE %s\n",nm[en_spa]); 2493: printf(" REMOTE TYPE %s\n",nm[en_typ]); 2494: printf(" REMOTE WHO %s\n",nm[en_who]); 2495: printf(" BYE %s\n",nm[en_bye]); 2496: printf(" FINISH %s\n",nm[en_fin]); 2497: #endif /* NOFRILLS */ 2498: printf("Server timeout: %d\n",srvtim); 2499: printf("Server display: %s\n\n", srvdis ? "on" : "off"); 2500: break; 2501: #endif /* NOSERVER */ 2502: 2503: case SHSTA: /* Status of last command */ 2504: printf( " %s\n", success ? "SUCCESS" : "FAILURE" ); 2505: return(0); /* Don't change it */ 2506: 2507: #ifdef MAC 2508: case SHSTK: { /* Stack for MAC debugging */ 2509: long sp; 2510: 2511: sp = -1; 2512: loadA0 ((char *)&sp); /* set destination address */ 2513: SPtoaA0(); /* move SP to destination */ 2514: printf("Stack at 0x%x\n", sp); 2515: show_queue(); /* more debugging */ 2516: break; 2517: } 2518: #endif /* MAC */ 2519: 2520: case SHTER: 2521: printf(" Command bytesize: %d bits\n", 2522: (cmdmsk == 0377) ? 8 : 7); 2523: printf(" Terminal bytesize: %d bits\n", 2524: (cmask == 0377) ? 8 : 7); 2525: #ifdef OS2 2526: printf(" Terminal type: %s\n", 2527: (tt_type == TT_VT102) ? "VT102" : "VT52"); 2528: 2529: #endif /* OS2 */ 2530: printf(" Terminal echo: %s\n", duplex ? "local" : "remote"); 2531: printf(" Terminal locking-shift: %s\n", sosi ? "on" : "off"); 2532: printf(" Terminal newline-mode: %s\n", tnlm ? "on" : "off"); 2533: printf(" Terminal cr-display: %s\n", 2534: tt_crd ? "crlf" : "normal"); 2535: #ifdef OS2 2536: /* Should show cursor and colors here too... */ 2537: printf(" Terminal arrow-keys: %s\n", 2538: tt_arrow ? "cursor" : "application"); 2539: printf(" Terminal keypad-mode: %s\n", 2540: tt_keypad ? "numeric" : "application"); 2541: printf(" Terminal wrap: %s\n", tt_wrap ? "on" : "off"); 2542: #endif /* OS2 */ 2543: 2544: #ifndef NOCSETS 2545: shotcs(tcsl,tcsr); 2546: #endif /* NOCSETS */ 2547: printf(" CONNECT-mode escape character: %d (Ctrl-%c, %s)\n", 2548: escape,ctl(escape),(escape == 127 ? "DEL" : ccntab[escape])); 2549: #ifdef UNIX 2550: printf(" Suspend: %s\n", suspend ? "on" : "off"); 2551: #endif /* UNIX */ 2552: break; 2553: 2554: #ifndef NOFRILLS 2555: case SHVER: 2556: shover(); 2557: break; 2558: #endif /* NOFRILLS */ 2559: 2560: #ifndef NOSPL 2561: case SHBUI: /* Built-in variables */ 2562: i = 0; 2563: for (y = 0; y < nvars; y++) { 2564: printf(" \\v(%s) = %s\n",vartab[y].kwd,nvlook(vartab[y].kwd)); 2565: if (++i > SCRNLEN) { /* More than a screenful... */ 2566: if (!askmore()) 2567: break; 2568: else 2569: i = 0; 2570: } 2571: } 2572: break; 2573: 2574: case SHFUN: /* Functions */ 2575: for (y = 0; y < nfuncs; y++) 2576: printf(" \\f%s()\n",fnctab[y].kwd); 2577: break; 2578: 2579: case SHVAR: /* Global variables */ 2580: x = 0; /* Variable count */ 2581: slc = 1; /* Screen line count for "more?" */ 2582: for (y = 33; y < GVARS; y++) 2583: if (g_var[y]) { 2584: if (x++ == 0) printf("Global variables:\n"); 2585: sprintf(line," \\%%%c",y); 2586: if (shomac(line,g_var[y]) < 0) break; 2587: } 2588: if (!x) printf(" No variables defined\n"); 2589: break; 2590: 2591: case SHARG: /* Args */ 2592: if (maclvl > -1) { 2593: printf("Macro arguments at level %d\n",maclvl); 2594: for (y = 0; y < 10; y++) 2595: if (m_arg[maclvl][y]) 2596: printf(" \\%%%d = %s\n",y,m_arg[maclvl][y]); 2597: } else { 2598: printf(" No macro arguments at top level\n"); 2599: } 2600: break; 2601: 2602: case SHARR: /* Arrays */ 2603: x = 0; 2604: for (y = 0; y < 27; y++) 2605: if (a_ptr[y]) { 2606: if (x == 0) printf("Declared arrays:\n"); 2607: x = 1; 2608: printf(" \\&%c[%d]\n",(y == 0) ? 64 : y + 96, a_dim[y]); 2609: } 2610: if (!x) printf(" No arrays declared\n"); 2611: break; 2612: #endif /* NOSPL */ 2613: 2614: case SHPRO: /* Protocol parameters */ 2615: shoparp(); 2616: printf("\n"); 2617: break; 2618: 2619: case SHCOM: /* Communication parameters */ 2620: printf("\n"); 2621: shoparc(); 2622: #ifndef NODIAL 2623: printf("\n"); 2624: #ifdef NETCONN 2625: if (!network) 2626: #endif /* NETCONN */ 2627: shodial(); 2628: #endif /* NODIAL */ 2629: printf("\n"); 2630: shomdm(); 2631: printf("\n"); 2632: break; 2633: 2634: case SHFIL: /* File parameters */ 2635: shoparf(); 2636: printf("\n"); 2637: break; 2638: 2639: #ifndef NOCSETS 2640: case SHLNG: /* Languages */ 2641: shoparl(); 2642: break; 2643: #endif /* NOCSETS */ 2644: 2645: #ifndef NOSPL 2646: case SHSCR: /* Scripts */ 2647: printf(" Take Echo: %s\n", techo ? "On" : "Off"); 2648: printf(" Take Error: %s\n", terror ? "On" : "Off"); 2649: printf(" Macro Echo: %s\n", mecho ? "On" : "Off"); 2650: printf(" Macro Error: %s\n", merror ? "On" : "Off"); 2651: printf(" Input Case: %s\n", incase ? "Observe" : "Ignore"); 2652: printf(" Input Echo: %s\n", inecho ? "On" : "Off"); 2653: printf(" Input Silence: %d\n", insilence); 2654: printf(" Input Timeout: %s\n", intime ? "Quit" : "Proceed"); 2655: #ifndef NOSCRIPT 2656: printf(" Script Echo: %s\n", secho ? "On" : "Off"); 2657: #endif /* NOSCRIPT */ 2658: break; 2659: #endif /* NOSPL */ 2660: 2661: #ifndef NOXMIT 2662: case SHXMI: 2663: printf(" File type: %s\n", binary ? "binary" : "text"); 2664: #ifndef NOCSETS 2665: shotcs(tcsl,tcsr); 2666: #endif /* NOCSETS */ 2667: printf(" Terminal echo: %s\n", duplex ? "local" : "remote"); 2668: printf(" Transmit EOF: "); 2669: if (*xmitbuf == NUL) { 2670: printf("none\n"); 2671: } else { 2672: char *p; 2673: p = xmitbuf; 2674: while (*p) { 2675: if (*p < SP) 2676: printf("^%c",ctl(*p)); 2677: else 2678: printf("%c",*p); 2679: p++; 2680: } 2681: printf("\n"); 2682: } 2683: if (xmitf) 2684: printf(" Transmit Fill: %d (fill character for blank lines)\n", 2685: xmitf); 2686: else printf(" Transmit Fill: none\n"); 2687: printf(" Transmit Linefeed: %s\n", 2688: xmitl ? "on (send linefeeds too)" : "off"); 2689: if (xmitp) 2690: printf(" Transmit Prompt: %d (host line end character)\n",xmitp); 2691: else printf(" Transmit Prompt: none\n"); 2692: printf(" Transmit Echo: %s\n", 2693: xmitx ? "on" : "off"); 2694: printf(" Transmit Locking-Shift: %s\n",xmits ? "on" : "off"); 2695: printf(" Transmit Pause: %d milliseconds\n", xmitw); 2696: break; 2697: #endif /* NOXMIT */ 2698: 2699: case SHMOD: /* SHOW MODEM */ 2700: shmdmlin(); 2701: printf("\n"); 2702: shomdm(); 2703: break; 2704: 2705: #ifndef MAC 2706: case SHDFLT: 2707: zsyscmd(PWDCMD); 2708: break; 2709: #endif /* MAC */ 2710: 2711: case SHESC: 2712: printf(" Escape character: Ctrl-%c (ASCII %d, %s)\r\n", 2713: ctl(escape), escape, (escape == 127 ? "DEL" : ccntab[escape])); 2714: break; 2715: 2716: #ifndef NODIAL 2717: case SHDIA: 2718: shmdmlin(); 2719: printf(", speed: "); 2720: if ((zz = ttgspd()) < 0) { 2721: printf("unknown\n"); 2722: } else { 2723: if (zz == 8880) printf("75/1200\n"); else printf("%ld\n",zz); 2724: } 2725: doshodial(); 2726: if (carrier == CAR_OFF) s = "off"; 2727: else if (carrier == CAR_ON) s = "on"; 2728: else if (carrier == CAR_AUT) s = "auto"; 2729: else s = "unknown"; 2730: printf(" Carrier: %s", s); 2731: if (carrier == CAR_ON) { 2732: if (cdtimo) printf(", timeout: %d sec", cdtimo); 2733: else printf(", timeout: none"); 2734: } 2735: if (local 2736: #ifdef NETCONN 2737: && !network 2738: #endif /* NETCONN */ 2739: ) { 2740: printf("\n%s modem signals:\n",ttname); 2741: shomdm(); 2742: } else printf("\n"); 2743: break; 2744: #endif /* NODIAL */ 2745: 2746: #ifdef VMS 2747: case SHLBL: /* Labeled file info */ 2748: sholbl(); 2749: break; 2750: #endif /* VMS */ 2751: 2752: case SHCSE: /* Character sets */ 2753: #ifdef NOCSETS 2754: printf( 2755: " Character set translation is not supported in this version of C-Kermit\n"); 2756: #else 2757: shocharset(); 2758: printf("\n Unknown-Char-Set: %s\n", 2759: unkcs ? "Keep" : "Discard"); 2760: shotcs(tcsl,tcsr); 2761: printf("\n"); 2762: #endif /* NOCSETS */ 2763: break; 2764: 2765: #ifndef NOFRILLS 2766: case SHFEA: /* Features */ 2767: shofea(); 2768: break; 2769: #endif /* NOFRILLS */ 2770: 2771: default: 2772: printf("\nNothing to show...\n"); 2773: return(-2); 2774: } 2775: return(success = 1); 2776: } 2777: 2778: VOID 2779: shmdmlin() { /* Briefly show modem & line */ 2780: int i; 2781: #ifndef NODIAL 2782: #ifndef MINIDIAL 2783: extern int tbmodel; 2784: _PROTOTYP( char * gtbmodel, (void) ); 2785: #endif /* MINIDIAL */ 2786: #endif /* NODIAL */ 2787: if (local) 2788: printf(" Line: %s, Modem: ",ttname); 2789: else 2790: printf(" Communication device not yet selected with SET LINE\n Modem: "); 2791: #ifndef NODIAL 2792: for (i = 0; i < nmdm; i++) { 2793: if (mdmtab[i].kwval == mdmtyp) { 2794: printf("%s",mdmtab[i].kwd); 2795: break; 2796: } 2797: } 2798: #ifndef MINIDIAL 2799: if (tbmodel) printf(" (%s)",gtbmodel()); /* Telebit model info */ 2800: #endif /* MINIDIAL */ 2801: #else 2802: printf("(disabled)"); 2803: #endif /* NODIAL */ 2804: } 2805: #endif /* NOSHOW */ 2806: 2807: #ifdef GEMDOS 2808: isxdigit(c) int c; { 2809: return(isdigit(c) || 2810: (c >= 'a' && c <= 'f') || 2811: (c >= 'A' && c <= 'F')); 2812: } 2813: #endif /* GEMDOS */ 2814: 2815: #ifndef NOSHOW 2816: #ifndef NOSPL 2817: int /* SHO MACROS */ 2818: shomac(s1, s2) char *s1, *s2; { 2819: int x, n, pp; 2820: pp = 0; /* Parenthesis counter */ 2821: 2822: if (!s1) 2823: return(0); 2824: else 2825: printf("\n%s = ",s1); /* Print blank line and macro name */ 2826: slc++; /* Count the line */ 2827: n = (int)strlen(s1) + 4; /* Width of current line */ 2828: if (!s2) s2 = "(null definition)"; 2829: 2830: while (x = *s2++) { /* Loop thru definition */ 2831: if (x == '(') pp++; /* Treat commas within parens */ 2832: if (x == ')') pp--; /* as ordinary text */ 2833: if (pp < 0) pp = 0; /* Outside parens, */ 2834: if (x == ',' && pp == 0) { /* comma becomes comma-dash-NL. */ 2835: putchar(','); 2836: putchar('-'); 2837: x = '\n'; 2838: } 2839: putchar(x); /* Output the character */ 2840: if (x == '\n') { /* If it was a newline */ 2841: #ifdef UNIX 2842: #ifdef NOSETBUF 2843: fflush(stdout); 2844: #endif /* NOSETBUF */ 2845: #endif /* UNIX */ 2846: putchar(' '); /* Indent the next line 1 space */ 2847: while(*s2 == ' ') s2++; /* skip past leading blanks */ 2848: n = 2; /* restart the character counter */ 2849: slc++; /* and increment the line counter. */ 2850: } else if (++n > SCRNWID) { /* If line is too wide */ 2851: putchar('-'); /* output a dash */ 2852: putchar(NL); /* and a newline */ 2853: #ifdef UNIX 2854: #ifdef NOSETBUF 2855: fflush(stdout); 2856: #endif /* NOSETBUF */ 2857: #endif /* UNIX */ 2858: n = 1; /* and restart the char counter */ 2859: slc++; /* and increment the line counter */ 2860: } 2861: if (n < 3 && slc > SCRNLEN) { /* If new line and screen is full */ 2862: if (!askmore()) return(-1); /* ask if they want more. */ 2863: n = 1; /* They do, start a new line */ 2864: slc = 0; /* and restart line counter */ 2865: } 2866: } 2867: putchar(NL); /* End of definition */ 2868: if (++slc > SCRNLEN) { 2869: if (!askmore()) return(-1); 2870: slc = 0; 2871: } 2872: return(0); 2873: } 2874: #endif /* NOSPL */ 2875: #endif /* NOSHOW */ 2876: 2877: #ifndef NOSHOW 2878: int 2879: shoatt() { 2880: printf("Attributes: %s\n", atcapr ? "On" : "Off"); 2881: if (!atcapr) return(0); 2882: printf(" Blocksize: %s\n", atblki ? "On" : "Off"); 2883: printf(" Date: %s\n", atdati ? "On" : "Off"); 2884: printf(" Disposition: %s\n", atdisi ? "On" : "Off"); 2885: printf(" Encoding (Character Set): %s\n", atenci ? "On" : "Off"); 2886: printf(" Length: %s\n", atleni ? "On" : "Off"); 2887: printf(" Type (text/binary): %s\n", attypi ? "On" : "Off"); 2888: printf(" System ID: %s\n", atsidi ? "On" : "Off"); 2889: printf(" System Info: %s\n", atsysi ? "On" : "Off"); 2890: return(0); 2891: } 2892: #endif /* NOSHOW */ 2893: 2894: #ifndef NOSPL 2895: /* Evaluate an arithmetic expression. */ 2896: /* Code adapted from ev, by Howie Kaye of Columbia U & others. */ 2897: 2898: static int xerror; 2899: static char *cp; 2900: static long tokval; 2901: static char curtok; 2902: static long expval; 2903: 2904: #define LONGBITS (8*sizeof (long)) 2905: #define NUMBER 'N' 2906: #define EOT 'E' 2907: 2908: /* 2909: Replacement for strchr() and index(), neither of which seem to be universal. 2910: */ 2911: 2912: static char * 2913: #ifdef CK_ANSIC 2914: windex(char * s, char c) 2915: #else 2916: windex(s,c) char *s, c; 2917: #endif /* CK_ANSIC */ 2918: /* windex */ { 2919: while (*s != NUL && *s != c) s++; 2920: if (*s == c) return(s); else return(NULL); 2921: } 2922: 2923: /* 2924: g e t t o k 2925: 2926: Returns the next token. If token is a NUMBER, sets tokval appropriately. 2927: */ 2928: static char 2929: gettok() { 2930: while (isspace(*cp)) cp++ ; 2931: switch(*cp) { 2932: case '$': /* ??? */ 2933: case '+': /* Add */ 2934: case '-': /* Subtract or Negate */ 2935: case '@': /* Greatest Common Divisor */ 2936: case '*': /* Multiply */ 2937: case '/': /* Divide */ 2938: case '%': /* Modulus */ 2939: case '<': /* Left shift */ 2940: case '>': /* Right shift */ 2941: case '&': /* And */ 2942: case '|': /* Or */ 2943: case '#': /* Exclusive Or */ 2944: case '~': /* Not */ 2945: case '^': /* Exponent */ 2946: case '!': /* Factorial */ 2947: case '(': /* Parens for grouping */ 2948: case ')': return(*cp++); /* operator, just return it */ 2949: case '\n': 2950: case '\0': return(EOT); /* end of line, return that */ 2951: } 2952: if (isxdigit(*cp)) { /* digit, must be a number */ 2953: char tbuf[80],*tp; /* buffer to accumulate number */ 2954: int radix = 10; /* default radix */ 2955: for (tp=tbuf; isxdigit(*cp); cp++) 2956: *tp++ = isupper(*cp) ? tolower(*cp) : *cp; 2957: *tp = '\0'; /* end number */ 2958: switch(isupper(*cp) ? tolower(*cp) : *cp) { /* examine break char */ 2959: case 'h': 2960: case 'x': radix = 16; cp++; break; /* if radix signifier... */ 2961: case 'o': 2962: case 'q': radix = 8; cp++; break; 2963: case 't': radix = 2; cp++; break; 2964: } 2965: for (tp=tbuf,tokval=0; *tp != '\0'; tp++) { 2966: int dig; 2967: dig = *tp - '0'; /* convert number */ 2968: if (dig > 10) dig -= 'a'-'0'-10; 2969: if (dig >= radix) { 2970: xerror = 1; 2971: if (cmdlvl == 0) 2972: printf("invalid digit '%c' in number\n",*tp); 2973: return(NUMBER); 2974: } 2975: tokval = radix*tokval + dig; 2976: } 2977: return(NUMBER); 2978: } 2979: if (cmdlvl == 0) 2980: printf("Invalid character '%c' in input\n",*cp); 2981: xerror = 1; 2982: cp++; 2983: return(gettok()); 2984: } 2985: 2986: static long 2987: #ifdef CK_ANSIC 2988: expon(long x, long y) 2989: #else 2990: expon(x,y) long x,y; 2991: #endif /* CK_ANSIC */ 2992: /* expon */ { 2993: long result = 1; 2994: int sign = 1; 2995: if (y < 0) return(0); 2996: if (x < 0) { 2997: x = -x; 2998: if (y & 1) sign = -1; 2999: } 3000: while (y != 0) { 3001: if (y & 1) result *= x; 3002: y >>= 1; 3003: if (y != 0) x *= x; 3004: } 3005: return(result * sign); 3006: } 3007: 3008: /* 3009: * factor ::= simple | simple ^ factor 3010: * 3011: */ 3012: _PROTOTYP( static VOID simple, (void) ); 3013: 3014: static VOID 3015: factor() { 3016: long oldval; 3017: simple(); 3018: if (curtok == '^') { 3019: oldval = expval; 3020: curtok = gettok(); 3021: factor(); 3022: expval = expon(oldval,expval); 3023: } 3024: } 3025: 3026: /* 3027: * termp ::= NULL | {*,/,%,&} factor termp 3028: * 3029: */ 3030: static VOID 3031: termp() { 3032: while (curtok == '*' || curtok == '/' || curtok == '%' || curtok == '&') { 3033: long oldval; 3034: char op; 3035: op = curtok; 3036: curtok = gettok(); /* skip past operator */ 3037: oldval = expval; 3038: factor(); 3039: switch(op) { 3040: case '*': expval = oldval * expval; break; 3041: case '/': 3042: if (expval == 0) expval = -1; /* don't divide by 0 */ 3043: else expval = oldval / expval; break; 3044: case '%': expval = oldval % expval; break; 3045: case '&': expval = oldval & expval; break; 3046: } 3047: } 3048: } 3049: 3050: static long 3051: #ifdef CK_ANSIC 3052: fact(long x) 3053: #else 3054: fact(x) long x; 3055: #endif /* CK_ANSIC */ 3056: /* fact */ { /* factorial */ 3057: long result = 1; 3058: while (x > 1) 3059: result *= x--; 3060: return(result); 3061: } 3062: 3063: /* 3064: * term ::= factor termp 3065: * 3066: */ 3067: static VOID 3068: term() { 3069: factor(); 3070: termp(); 3071: } 3072: 3073: static long 3074: #ifdef CK_ANSIC 3075: gcd(long x, long y) 3076: #else 3077: gcd(x,y) long x,y; 3078: #endif /* CK_ANSIC */ 3079: /* gcd */ { /* Greatest Common Divisor */ 3080: int nshift = 0; 3081: if (x < 0) x = -x; 3082: if (y < 0) y = -y; /* validate arguments */ 3083: if (x == 0 || y == 0) return(x + y); /* this is bogus */ 3084: 3085: while (!((x & 1) | (y & 1))) { /* get rid of powers of 2 */ 3086: nshift++; 3087: x >>= 1; 3088: y >>= 1; 3089: } 3090: while (x != 1 && y != 1 && x != 0 && y != 0) { 3091: while (!(x & 1)) x >>= 1; /* eliminate unnecessary */ 3092: while (!(y & 1)) y >>= 1; /* powers of 2 */ 3093: if (x < y) { /* force x to be larger */ 3094: long t; 3095: t = x; 3096: x = y; 3097: y = t; 3098: } 3099: x -= y; 3100: } 3101: if (x == 0 || y == 0) return((x + y) << nshift); /* gcd is non-zero one */ 3102: else return((long) 1 << nshift); /* else gcd is 1 */ 3103: } 3104: 3105: /* 3106: * exprp ::= NULL | {+,-,|,...} term exprp 3107: * 3108: */ 3109: static VOID 3110: exprp() { 3111: while (windex("+-|<>#@",curtok) != NULL) { 3112: long oldval; 3113: char op; 3114: op = curtok; 3115: curtok = gettok(); /* skip past operator */ 3116: oldval = expval; 3117: term(); 3118: switch(op) { 3119: case '+' : expval = oldval + expval; break; 3120: case '-' : expval = oldval - expval; break; 3121: case '|' : expval = oldval | expval; break; 3122: case '#' : expval = oldval ^ expval; break; 3123: case '@' : expval = gcd(oldval,expval); break; 3124: case '<' : expval = oldval << expval; break; 3125: case '>' : expval = oldval >> expval; break; 3126: } 3127: } 3128: } 3129: 3130: /* 3131: * expr ::= term exprp 3132: * 3133: */ 3134: static VOID 3135: expr() { 3136: term(); 3137: exprp(); 3138: } 3139: 3140: static long 3141: xparse() { 3142: curtok = gettok(); 3143: expr(); 3144: #ifdef COMMENT 3145: if (curtok == '$') { 3146: curtok = gettok(); 3147: if (curtok != NUMBER) { 3148: if (cmdlvl == 0) printf("illegal radix\n"); 3149: return(0); 3150: } 3151: curtok = gettok(); 3152: } 3153: #endif /* COMMENT */ 3154: if (curtok != EOT) { 3155: if (cmdlvl == 0) 3156: printf("extra characters after expression\n"); 3157: xerror = 1; 3158: } 3159: return(expval); 3160: } 3161: 3162: char * 3163: evala(s) char *s; { 3164: char *p; /* Return pointer */ 3165: long v; /* Numeric value */ 3166: 3167: xerror = 0; /* Start out with no error */ 3168: cp = s; /* Make the argument global */ 3169: v = xparse(); /* Parse the string */ 3170: p = numbuf; /* Convert long number to string */ 3171: sprintf(p,"%ld",v); 3172: return(xerror ? "" : p); /* Return empty string on error */ 3173: } 3174: 3175: /* 3176: * simplest ::= NUMBER | ( expr ) 3177: * 3178: */ 3179: static VOID 3180: simplest() { 3181: if (curtok == NUMBER) expval = tokval; 3182: else if (curtok == '(') { 3183: curtok = gettok(); /* skip over paren */ 3184: expr(); 3185: if (curtok != ')') { 3186: if (cmdlvl == 0) printf("missing right parenthesis\n"); 3187: xerror = 1; 3188: } 3189: } 3190: else { 3191: if (cmdlvl == 0) printf("operator unexpected\n"); 3192: xerror = 1; 3193: } 3194: curtok = gettok(); 3195: } 3196: 3197: /* 3198: * simpler ::= simplest | simplest ! 3199: * 3200: */ 3201: static VOID 3202: simpler() { 3203: simplest(); 3204: if (curtok == '!') { 3205: curtok = gettok(); 3206: expval = fact(expval); 3207: } 3208: } 3209: 3210: /* 3211: * simple ::= {-,~} simpler | simpler 3212: * 3213: */ 3214: 3215: static VOID 3216: simple() { 3217: if (curtok == '-' || curtok == '~') { 3218: int op = curtok; 3219: curtok = gettok(); /* skip over - sign */ 3220: simpler(); /* parse the factor again */ 3221: expval = op == '-' ? -expval : ~expval; 3222: } else simpler(); 3223: } 3224: #endif /* NOSPL */ 3225: 3226: #ifndef NOSPL 3227: /* D C L A R R A Y -- Declare an array */ 3228: 3229: int /* Declare an array of size n */ 3230: #ifdef CK_ANSIC 3231: dclarray(char a, int n) 3232: #else 3233: dclarray(a,n) char a; int n; 3234: #endif /* CK_ANSIC */ 3235: /* dclarray */ { 3236: char **p; int i, n2; 3237: 3238: if (a > 63 && a < 96) a += 32; /* Convert to lowercase */ 3239: if (a < 96 || a > 122) return(-1); /* Verify name */ 3240: a -= 96; /* Convert name to number */ 3241: if ((p = a_ptr[a]) != NULL) { /* Delete old array of same name */ 3242: n2 = a_dim[a]; 3243: for (i = 0; i <= n2; i++) /* First delete its elements */ 3244: if (p[i]) free(p[i]); 3245: free(a_ptr[a]); /* Then the element list */ 3246: a_ptr[a] = (char **) NULL; /* Remove pointer to element list */ 3247: a_dim[a] = 0; /* Set dimension at zero. */ 3248: } 3249: if (n == 0) return(0); /* If dimension 0, just deallocate. */ 3250: 3251: p = (char **) malloc((n+1) * sizeof(char **)); /* Allocate for new array */ 3252: if (p == NULL) return(-1); /* Check */ 3253: a_ptr[a] = p; /* Save pointer to member list */ 3254: a_dim[a] = n; /* Save dimension */ 3255: for (i = 0; i <= n; i++) /* Initialize members to null */ 3256: p[i] = NULL; 3257: return(0); 3258: } 3259: 3260: /* A R R A Y N A M -- Parse an array name */ 3261: 3262: /* 3263: Call with pointer to string that starts with the array reference. 3264: String may begin with either \& or just &. 3265: On success, 3266: Returns letter ID (always lowercase) in argument c, 3267: which can also be accent grave (` = 96; '@' is converted to grave); 3268: Dimension or subscript in argument n; 3269: IMPORTANT: These arguments must be provided by the caller as addresses 3270: of ints (not chars), for example: 3271: char *s; int x, y; 3272: arraynam(s,&x,&y); 3273: On failure, returns a negative number, with args n and c set to zero. 3274: */ 3275: int 3276: arraynam(ss,c,n) char *ss; int *c; int *n; { 3277: int i, y, pp; 3278: char x; 3279: char *s, *p, *sx, *vnp; 3280: char vnbuf[VNAML+1]; /* On stack to allow for */ 3281: char ssbuf[VNAML+1]; /* recursive calls... */ 3282: char sxbuf[VNAML+1]; 3283: 3284: *c = *n = 0; /* Initialize return values */ 3285: for (i = 0; i < (int)strlen(ss); i++) /* Check length */ 3286: if (ss[i] == ']') 3287: break; 3288: if (i > VNAML) { 3289: printf("?Array reference too long - %s\n",ss); 3290: return(-9); 3291: } 3292: strncpy(vnbuf,ss,VNAML); 3293: vnp = vnbuf; 3294: if (vnbuf[0] == CMDQ && vnbuf[1] == '&') vnp++; 3295: if (*vnp != '&') { 3296: printf("?Not an array - %s\n",vnbuf); 3297: return(-9); 3298: } 3299: x = *(vnp + 1); /* Fold case of array name */ 3300: /* We don't use isupper & tolower here on purpose because these */ 3301: /* would produce undesired effects with accented letters. */ 3302: if (x > 63 && x < 91) x = *(vnp +1) = x + 32; 3303: if ((x < 96) || (x > 122) || (*(vnp+2) != '[')) { 3304: printf("?Invalid format for array name - %s\n",vnbuf); 3305: return(-9); 3306: } 3307: *c = x; /* Return the array name */ 3308: s = vnp+3; /* Get dimension */ 3309: p = ssbuf; 3310: pp = 1; /* Bracket counter */ 3311: for (i = 0; i < VNAML && *s != NUL; i++) { /* Copy up to ] */ 3312: if (*s == '[') pp++; 3313: if (*s == ']' && --pp == 0) break; 3314: *p++ = *s++; 3315: } 3316: if (*s != ']') { 3317: printf("?No closing bracket on array dimension - %s\n",vnbuf); 3318: return(-9); 3319: } 3320: *p = NUL; /* Terminate subscript with null */ 3321: p = ssbuf; /* Point to beginning of subscript */ 3322: sx = sxbuf; /* Where to put expanded subscript */ 3323: y = VNAML-1; 3324: xxstring(p,&sx,&y); /* Convert variables, etc. */ 3325: if (!chknum(sxbuf)) { /* Make sure it's all digits */ 3326: printf("?Array dimension or subscript must be numeric - %s\n",sxbuf); 3327: return(-9); 3328: } 3329: if ((y = atoi(sxbuf)) < 0) { 3330: if (cmflgs == 0) printf("\n"); 3331: printf("?Array dimension or subscript must be positive or zero - %s\n", 3332: sxbuf); 3333: return(-9); 3334: } 3335: *n = y; /* Return the subscript or dimension */ 3336: return(0); 3337: } 3338: 3339: int 3340: chkarray(a,i) int a, i; { /* Check if array is declared */ 3341: int x; /* and if subscript is in range */ 3342: if (a == 64) a = 96; /* Convert atsign to grave accent */ 3343: x = a - 96; /* Values must be in range 96-122 */ 3344: if (x < 0 || x > 26) return(-2); /* Not in range */ 3345: if (a_ptr[x] == NULL) return(-1); /* Not declared */ 3346: if (i > a_dim[x]) return(-2); /* Declared but out of range. */ 3347: return(a_dim[x]); /* All ok, return dimension */ 3348: } 3349: 3350: char * 3351: arrayval(a,i) int a, i; { /* Return value of \&a[i] */ 3352: int x; char **p; /* (possibly NULL) */ 3353: 3354: if (a == 64) a = 96; /* Convert atsign to grave accent */ 3355: x = a - 96; /* Values must be in range 96-122 */ 3356: if (x < 0 || x > 26) return(NULL); /* Not in range */ 3357: if ((p = a_ptr[x]) == NULL) /* Array not declared */ 3358: return(NULL); 3359: if (i > a_dim[x]) /* Subscript out of range. */ 3360: return(NULL); 3361: return(p[i]); /* All ok, return pointer to value. */ 3362: } 3363: #endif /* NOSPL */ 3364: 3365: #ifndef NOSPL 3366: /* P A R S E V A R -- Parse a variable name or array reference. */ 3367: /* 3368: Call with: 3369: s = pointer to candidate variable name or array reference. 3370: *c = address of integer in which to return variable ID. 3371: *i = address of integer in which to return array subscript. 3372: Returns: 3373: -2: syntax error in variable name or array reference. 3374: 1: successful parse of a simple variable, with ID in c. 3375: 2: successful parse of an array reference, w/ID in c and subscript in i. 3376: */ 3377: int 3378: parsevar(s,c,i) char *s; int *c, *i; { 3379: char *p; 3380: int x,y,z; 3381: 3382: p = s; 3383: if (*s == CMDQ) s++; /* Point after backslash */ 3384: 3385: if (*s != '%' && *s != '&') { /* Make sure it's % or & */ 3386: printf("?Not a variable name - %s\n",p); 3387: return(-9); 3388: } 3389: if ((int)strlen(s) < 2) { 3390: printf("?Incomplete variable name - %s\n",p); 3391: return(-9); 3392: } 3393: if (*s == '%' && *(s+2) != '\0') { 3394: printf("?Only one character after '%%' in variable name, please\n"); 3395: return(-9); 3396: } 3397: if (*s == '&' && *(s+2) != '[') { 3398: printf("?Array subscript expected - %s\n",p); 3399: return(-9); 3400: } 3401: if (*s == '%') { /* Simple variable. */ 3402: y = *(s+1); /* Get variable ID letter/char */ 3403: if (isupper(y)) y -= ('a'-'A'); /* Convert upper to lower case */ 3404: *c = y; /* Set the return values. */ 3405: *i = -1; /* No array subscript. */ 3406: return(1); /* Return 1 = simple variable */ 3407: } 3408: if (*s == '&') { /* Array reference. */ 3409: if (arraynam(s,&x,&z) < 0) { /* Go parse it. */ 3410: printf("?Invalid array reference - %s\n",p); 3411: return(-9); 3412: } 3413: if (chkarray(x,z) < 0) { /* Check if declared, etc. */ 3414: printf("?Array not declared or subscript out of range\n"); 3415: return(-9); 3416: } 3417: *c = x; /* Return array letter */ 3418: *i = z; /* and subscript. */ 3419: return(2); 3420: } 3421: return(-2); /* None of the above. */ 3422: } 3423: 3424: #define VALN 20 3425: 3426: /* Get the numeric value of a variable */ 3427: /* 3428: Call with pointer to variable name, pointer to int for return value. 3429: Returns: 3430: 0 on success with second arg containing the value. 3431: -1 on failure (bad variable syntax, variable not defined or not numeric). 3432: */ 3433: int 3434: varval(s,v) char *s; int *v; { 3435: char valbuf[VALN+1]; /* s is pointer to variable name */ 3436: char *p; 3437: int y; 3438: 3439: p = valbuf; /* Expand variable into valbuf. */ 3440: y = VALN; 3441: if (xxstring(s,&p,&y) < 0) return(-1); 3442: p = valbuf; /* Make sure value is numeric */ 3443: if (!chknum(p)) return(-1); 3444: *v = atoi(p); /* Convert numeric string to int */ 3445: return(0); 3446: } 3447: 3448: /* Increment or decrement a variable */ 3449: /* Returns -1 on failure, 0 on success, with 4th argument set to result */ 3450: 3451: int 3452: incvar(s,x,z,r) char *s; int x, z, *r; { /* Increment a numeric variable */ 3453: char valbuf[VALN+1]; /* s is pointer to variable name */ 3454: /* x is amount to increment by */ 3455: int n; /* z != 0 means add */ 3456: /* z = 0 means subtract */ 3457: 3458: if (varval(s,&n) < 0) /* Convert numeric string to int */ 3459: return(-1); 3460: if (z) /* Increment it by the given amount */ 3461: n += x; 3462: else /* or decrement as requested. */ 3463: n -= x; 3464: sprintf(valbuf,"%d",n); /* Convert back to numeric string */ 3465: addmac(s,valbuf); /* Replace old variable */ 3466: *r = n; /* Return the integer value */ 3467: return(0); 3468: } 3469: #endif /* NOSPL */ 3470: 3471: /* Functions moved here from ckuusr.c to even out the module sizes... */ 3472: 3473: #ifndef NOSPL /* Need xwords() function to break */ 3474: #define XWORDS /* string up into words. */ 3475: #endif /* NOSPL */ 3476: #ifndef NODIAL 3477: #ifndef XWORDS 3478: #define XWORDS 3479: #endif /* XWORDS */ 3480: #endif /* NODIAL */ 3481: 3482: #ifdef XWORDS 3483: /* 3484: Breaks string s up into a list of up to max words. 3485: Pointers to each word go into the array list[]. 3486: If list is NULL, then they are added to the macro table. 3487: */ 3488: 3489: VOID 3490: xwords(s,max,list) char *s; int max; char *list[]; { 3491: char *p; 3492: int b, k, y, z; 3493: #ifndef NOSPL 3494: int macro; 3495: macro = (list == NULL); 3496: debug(F101,"xwords macro","",macro); 3497: #endif /* NOSPL */ 3498: 3499: p = s; /* Pointer to beginning of string */ 3500: b = 0; /* Flag for outer brace removal */ 3501: k = 0; /* Flag for in-word */ 3502: y = 0; /* Brace nesting level */ 3503: z = 0; /* Argument counter, 0 thru max */ 3504: 3505: while (1) { /* Go thru argument list */ 3506: if (!s || (*s == '\0')) { /* No more characters? */ 3507: if (k != 0) { 3508: if (z == max) break; /* Only go up to max. */ 3509: z++; /* Count it. */ 3510: #ifndef NOSPL 3511: if (macro) { 3512: varnam[1] = z + '0'; /* Assign last argument */ 3513: addmac(varnam,p); 3514: } else 3515: #endif /* NOSPL */ 3516: list[z] = p; 3517: break; /* And get out. */ 3518: } else break; 3519: } 3520: if (k == 0 && (*s == SP || *s == HT)) { /* Eat leading blanks */ 3521: s++; 3522: continue; 3523: } else if (*s == '{') { /* An opening brace */ 3524: if (k == 0 && y == 0) { /* If leading brace */ 3525: p = s+1; /* point past it */ 3526: b = 1; /* and flag that we did this */ 3527: } 3528: k = 1; /* Flag that we're in a word */ 3529: y++; /* Count the brace. */ 3530: } else if (*s == '}') { /* A closing brace. */ 3531: y--; /* Count it. */ 3532: if (y == 0 && b != 0) { /* If it matches the leading brace */ 3533: *s = SP; /* change it to a space */ 3534: b = 0; /* and we're not in braces any more */ 3535: } else if (y < 0) k = 1; /* otherwise just start a new word. */ 3536: } else if (*s != SP && *s != HT) { /* Nonspace means we're in a word */ 3537: if (k == 0) p = s; /* Mark the beginning */ 3538: k = 1; /* Set in-word flag */ 3539: } 3540: /* If we're not inside a braced quantity, and we are in a word, and */ 3541: /* we have hit whitespace, then we have an argument to assign. */ 3542: if ((y < 1) && (k != 0) && (*s == SP || *s == HT)) { 3543: *s = '\0'; /* terminate the arg with null */ 3544: k = 0; /* say we're not in a word any more */ 3545: y = 0; /* start braces off clean again */ 3546: if (z == max) break; /* Only go up to max. */ 3547: z++; /* count this arg */ 3548: #ifndef NOSPL 3549: if (macro) { 3550: varnam[1] = z + '0'; /* compute its name */ 3551: addmac(varnam,p); /* add it to the macro table */ 3552: } else 3553: #endif /* NOSPL */ 3554: list[z] = p; 3555: p = s+1; 3556: } 3557: s++; /* Point past this character */ 3558: } 3559: if ((z == 0) && (y > 1)) { /* Extra closing brace(s) at end */ 3560: z++; 3561: #ifndef NOSPL 3562: if (macro) { 3563: varnam[1] = z + '0'; /* compute its name */ 3564: addmac(varnam,p); /* Add rest of line to last arg */ 3565: } else 3566: #endif /* NOSPL */ 3567: list[z] = p; 3568: } 3569: #ifndef NOSPL 3570: if (macro) macargc[maclvl] = z + 1; /* Set \v(argc) variable */ 3571: #endif /* NOSPL */ 3572: return; 3573: } 3574: #endif /* XWORDS */ 3575: 3576: #ifndef NOSPL 3577: /* D O D O -- Do a macro */ 3578: 3579: /* 3580: Call with x = macro table index, s = pointer to arguments. 3581: Returns 0 on failure, 1 on success. 3582: */ 3583: 3584: int 3585: dodo(x,s) int x; char *s; { 3586: int y; 3587: 3588: debug(F101,"dodo maclvl","",maclvl); 3589: if (++maclvl > MACLEVEL) { /* Make sure we have storage */ 3590: debug(F101,"dodo maclvl too deep","",maclvl); 3591: --maclvl; 3592: printf("Macros nested too deeply\n"); 3593: return(0); 3594: } 3595: macp[maclvl] = mactab[x].mval; /* Point to the macro body */ 3596: macx[maclvl] = mactab[x].mval; /* Remember where the beginning is */ 3597: debug(F111,"do macro",macp[maclvl],maclvl); 3598: 3599: cmdlvl++; /* Entering a new command level */ 3600: if (cmdlvl > CMDSTKL) { /* Too many macros + TAKE files? */ 3601: debug(F101,"dodo cmdlvl too deep","",cmdlvl); 3602: cmdlvl--; 3603: printf("?TAKE files and DO commands nested too deeply\n"); 3604: return(0); 3605: } 3606: #ifdef VMS 3607: conres(); /* So Ctrl-C, etc, will work. */ 3608: #endif /* VMS */ 3609: ifcmd[cmdlvl] = 0; 3610: iftest[cmdlvl] = 0; 3611: count[cmdlvl] = 0; 3612: cmdstk[cmdlvl].src = CMD_MD; /* Say we're in a macro */ 3613: cmdstk[cmdlvl].lvl = maclvl; /* and remember the macro level */ 3614: mrval[maclvl] = NULL; /* Initialize return value */ 3615: 3616: debug(F110,"do macro",mactab[x].kwd,0); 3617: 3618: /* Clear old %0..%9 arguments */ 3619: 3620: addmac("%0",mactab[x].kwd); /* Define %0 = name of macro */ 3621: varnam[0] = '%'; 3622: varnam[2] = '\0'; 3623: for (y = 1; y < 10; y++) { /* Clear args %1..%9 */ 3624: varnam[1] = y + '0'; 3625: delmac(varnam); 3626: } 3627: 3628: /* Assign the new args one word per arg, allowing braces to group words */ 3629: 3630: xwords(s,9,NULL); 3631: return(1); 3632: } 3633: 3634: /* Insert "literal" quote around each comma-separated command to prevent */ 3635: /* its premature expansion. Only do this if object command is surrounded */ 3636: /* by braces. */ 3637: 3638: static char* flit = "\\flit("; 3639: 3640: int 3641: litcmd(src,dest) char **src, **dest; { 3642: int bc = 0, pp = 0; 3643: char *s, *lp, *ss; 3644: 3645: s = *src; 3646: lp = *dest; 3647: 3648: while (*s == SP) s++; /* strip extra leading spaces */ 3649: if (*s == '{') { 3650: 3651: pp = 0; /* paren counter */ 3652: bc = 1; /* count leading brace */ 3653: *lp++ = *s++; /* copy it */ 3654: while (*s == SP) s++; /* strip interior leading spaces */ 3655: ss = flit; /* point to "\flit(" */ 3656: while (*lp++ = *ss++) ; /* copy it */ 3657: lp--; /* back up over null */ 3658: while (*s) { /* go thru rest of text */ 3659: ss = flit; /* point back to start of "\flit(" */ 3660: if (*s == '{') bc++; /* count brackets */ 3661: if (*s == '(') pp++; /* and parens */ 3662: if (*s == ')') pp--; 3663: if (*s == '}') { /* Closing brace. */ 3664: if (--bc == 0) { /* Final one? */ 3665: *lp++ = ')'; /* Add closing paren for "\flit()" */ 3666: *lp++ = *s++; 3667: break; 3668: } 3669: } 3670: if (*s == ',' && pp == 0) { /* comma not inside of parens */ 3671: *lp++ = ')'; /* closing ) of \flit( */ 3672: *lp++ = ','; /* insert the comma */ 3673: while (*lp++ = *ss++) ; /* start new "\flit(" */ 3674: lp--; /* back up over null */ 3675: s++; /* skip over comma in source string */ 3676: while (*s++ == SP); /* eat leading spaces again. */ 3677: s--; /* back up over nonspace */ 3678: continue; 3679: } 3680: *lp++ = *s++; /* Copy anything but comma here. */ 3681: } 3682: *lp = NUL; 3683: } else { /* No brackets around, */ 3684: while (*lp++ = *s++) ; /* just copy. */ 3685: lp--; 3686: } 3687: *src = s; 3688: *dest = lp; 3689: if (bc) return(-1); 3690: else return(0); 3691: } 3692: #endif /* NOSPL */ 3693: 3694: int 3695: docd() { /* Do the CD command */ 3696: int x; 3697: char *s; 3698: 3699: #ifdef GEMDOS 3700: if ((x = cmdir("Name of local directory, or carriage return",homdir,&s, 3701: NULL)) < 0 ) 3702: #else 3703: if ((x = cmdir("Name of local directory, or carriage return",homdir,&s, 3704: xxstring)) < 0 ) 3705: #endif /* GEMDOS */ 3706: return(x); 3707: if (x == 2) { 3708: printf("?Wildcards not allowed in directory name\n"); 3709: return(-9); 3710: } 3711: strcpy(line,s); /* Make a safe copy */ 3712: s = line; 3713: if ((x = cmcfm()) < 0) /* Get confirmation */ 3714: return(x); 3715: if (! zchdir(s)) { 3716: cwdf = 0; 3717: perror(s); 3718: } else cwdf = 1; 3719: #ifdef OS2 3720: printf("%s\n", zgtdir()); 3721: #else /* Not OS2 */ 3722: #ifndef MAC 3723: zsyscmd(PWDCMD); /* assume this works... */ 3724: #endif /* MAC */ 3725: #endif /* OS2 */ 3726: return(cwdf); 3727: } 3728: 3729: VOID 3730: fixcmd() { /* Fix command parser after interruption */ 3731: dostop(); /* Back to top level (also calls conint()). */ 3732: bgchk(); /* Check background status */ 3733: if (*psave) { /* If old prompt saved, */ 3734: cmsetp(psave); /* restore it. */ 3735: *psave = NUL; 3736: } 3737: success = 0; /* Tell parser last command failed */ 3738: } 3739: 3740: VOID 3741: prtopt(s) char *s; { /* Print an option */ 3742: static int x = 0; /* (used by SHOW VER) */ 3743: int y; /* Does word wrap. */ 3744: if (!s) { x = 0; return; } /* Call with null pointer to */ 3745: y = (int)strlen(s); /* reset horizontal position. */ 3746: x += y; 3747: if (x > 79) { 3748: printf("\n%s",s); 3749: x = y; 3750: } else printf("%s",s); 3751: } 3752: 3753: #endif /* NOICP */