|
|
1.1 ! root 1: #ifndef NOICP ! 2: ! 3: /* C K U U S 4 -- "User Interface" for Unix Kermit, part 4 */ ! 4: ! 5: /* ! 6: Author: Frank da Cruz ([email protected], [email protected]), ! 7: Columbia University Center for Computing Activities. ! 8: First released January 1985. ! 9: Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New ! 10: York. Permission is granted to any individual or institution to use, copy, or ! 11: redistribute this software so long as it is not sold for profit, provided this ! 12: copyright notice is retained. ! 13: */ ! 14: ! 15: /* ! 16: File ckuus4.c -- Functions moved from other ckuus*.c modules to even ! 17: out their sizes. ! 18: */ ! 19: #include "ckcdeb.h" ! 20: #include "ckcasc.h" ! 21: #include "ckcker.h" ! 22: #include "ckuusr.h" ! 23: #include "ckuver.h" ! 24: #include "ckcnet.h" /* Network symbols */ ! 25: ! 26: #ifndef NOCSETS ! 27: #include "ckcxla.h" ! 28: #endif /* NOCSETS */ ! 29: ! 30: #ifndef AMIGA ! 31: #ifndef MAC ! 32: #include <signal.h> ! 33: #include <setjmp.h> ! 34: #endif /* MAC */ ! 35: #endif /* AMIGA */ ! 36: ! 37: #ifdef SUNX25 ! 38: extern int revcall, closgr, cudata, npadx3; ! 39: int x25ver; ! 40: extern char udata[MAXCUDATA]; ! 41: extern CHAR padparms[MAXPADPARMS+1]; ! 42: extern struct keytab padx3tab[]; ! 43: #endif /* SUNX25 */ ! 44: ! 45: #ifdef NETCONN ! 46: extern char ipaddr[]; ! 47: #endif /* NETCONN */ ! 48: ! 49: #ifndef NOSPL ! 50: /* This needs to be internationalized... */ ! 51: char *months[] = { ! 52: "Jan", "Feb", "Mar", "Apr", "May", "Jun", ! 53: "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ! 54: }; ! 55: #endif /* NOSPL */ ! 56: ! 57: #ifdef UNIX ! 58: extern int ttyfd; ! 59: #endif /* UNIX */ ! 60: ! 61: extern struct keytab colxtab[]; ! 62: ! 63: extern CHAR ! 64: eol, mypadc, mystch, padch, seol, stchr; ! 65: ! 66: extern char ! 67: flfnam[], kermrc[], ttname[], ! 68: *ckxsys, *versio, **xargv, *zinptr; ! 69: ! 70: extern int ! 71: atcapr, autopar, bctr, bctu, bgset, bigrbsiz, bigsbsiz, binary, carrier, ! 72: cdtimo, cmask, crunched, delay, duplex, ebq, ebqflg, escape, flow, fmask, ! 73: fncact, fncnv, haslock, incase, inecho, keep, len, local, lscapr, lscapu, ! 74: maxnam, maxpath, maxrps, maxsps, maxtry, mdmspd, mdmtyp, mypadn, ncolx, ! 75: nettype, network, nmac, noinit, npad, parity, pktlog, pkttim, quiet, rcflag, ! 76: retrans, rpackets, rptflg, rptq, rtimo, seslog, sessft, sosi, spackets, ! 77: spsiz, spsizf, spsizr, srvtim, stayflg, success, timef, timeouts, tralog, ! 78: tsecs, ttnproto, turn, turnch, urpsiz, wmax, wslotn, wslotr, xargc, xargs, ! 79: zincnt; ! 80: ! 81: extern long ! 82: ffc, filcnt, rptn, speed, tfc, tlci, tlco, vernum; ! 83: ! 84: #ifndef NOSPL ! 85: extern char fspec[], myhost[]; ! 86: #endif /* NOSPL */ ! 87: ! 88: #ifdef DCMDBUF ! 89: extern char *line; ! 90: #else ! 91: extern char line[]; ! 92: #endif /* DCMDBUF */ ! 93: ! 94: extern char pktfil[], /* Packet log file name */ ! 95: #ifdef DEBUG ! 96: debfil[], /* Debug log file name */ ! 97: #endif /* DEBUG */ ! 98: #ifdef TLOG ! 99: trafil[], /* Transaction log file name */ ! 100: #endif /* TLOG */ ! 101: sesfil[]; /* Session log file name */ ! 102: ! 103: #ifndef NOXMIT /* TRANSMIT command variables */ ! 104: extern char xmitbuf[]; ! 105: extern int xmitf, xmitl, xmitp, xmitx, xmits, xmitw; ! 106: #endif /* NOXMIT */ ! 107: ! 108: #ifndef NOSPL ! 109: /* Script programming language items */ ! 110: extern char **a_ptr[]; /* Arrays */ ! 111: extern int a_dim[]; ! 112: extern char inpbuf[]; /* Buffer for INPUT and REINPUT */ ! 113: extern char *inpbp; /* And pointer to same */ ! 114: static char *inpbps = inpbuf; /* And another */ ! 115: extern int maclvl; /* Macro invocation level */ ! 116: extern struct mtab *mactab; /* Macro table */ ! 117: extern char *mrval[]; ! 118: extern int macargc[], cmdlvl; ! 119: extern char *m_arg[MACLEVEL][10]; /* You have to put in the dimensions */ ! 120: extern char *g_var[GVARS]; /* for external 2-dimensional arrays. */ ! 121: #ifdef DCMDBUF ! 122: extern int *count; ! 123: #else ! 124: extern int count[]; ! 125: #endif /* DCMDBUF */ ! 126: #endif /* NOSPL */ ! 127: ! 128: #ifdef VMS ! 129: extern int frecl; ! 130: #ifdef COMMENT ! 131: /* Not needed after all */ ! 132: extern int frecfm, forg, fcctrl; ! 133: #endif /* COMMENT */ ! 134: #endif /* VMS */ ! 135: ! 136: #ifndef NODIAL ! 137: /* DIAL-related variables */ ! 138: extern int nmdm, dialhng, dialtmo, dialksp, dialdpy, dialmnp; ! 139: extern char *dialini, *dialnum; ! 140: extern struct keytab mdmtab[]; ! 141: #endif /* NODIAL */ ! 142: ! 143: #ifndef NOCSETS ! 144: /* Translation stuff */ ! 145: extern int fcharset, tcharset, tslevel, language, nlng, tcsr, tcsl; ! 146: extern struct keytab lngtab[]; ! 147: extern struct csinfo fcsinfo[], tcsinfo[]; ! 148: extern struct langinfo langs[]; ! 149: #ifdef CK_ANSIC ! 150: extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* Character set */ ! 151: extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* translation functions */ ! 152: #else ! 153: extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(); /* Character set */ ! 154: extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(); /* translation functions. */ ! 155: #endif /* CK_ANSIC */ ! 156: #endif /* NOCSETS */ ! 157: ! 158: #ifndef NOSPL ! 159: /* Built-in variable names, maximum length VNAML (20 characters) */ ! 160: ! 161: struct keytab vartab[] = { ! 162: "argc", VN_ARGC, 0, ! 163: "args", VN_ARGS, 0, ! 164: "count", VN_COUN, CM_INV, ! 165: "cpu", VN_CPU, 0, ! 166: "date", VN_DATE, 0, ! 167: "directory", VN_DIRE, 0, ! 168: "filespec", VN_FILE, 0, ! 169: "fsize", VN_FFC, 0, ! 170: "home", VN_HOME, 0, ! 171: "host", VN_HOST, 0, ! 172: "input", VN_IBUF, 0, ! 173: "line", VN_LINE, 0, ! 174: "ndate", VN_NDAT, 0, ! 175: "ntime", VN_NTIM, 0, ! 176: "platform", VN_SYSV, 0, ! 177: "program", VN_PROG, 0, ! 178: "return", VN_RET, 0, ! 179: "speed", VN_SPEE, 0, ! 180: "status", VN_SUCC, 0, ! 181: "system", VN_SYST, 0, ! 182: "tfsize", VN_TFC, 0, ! 183: "time", VN_TIME, 0, ! 184: #ifdef UNIX ! 185: "ttyfd", VN_TTYF, 0, ! 186: #endif /* UNIX */ ! 187: "version", VN_VERS, 0 ! 188: }; ! 189: int nvars = (sizeof(vartab) / sizeof(struct keytab)); ! 190: #endif /* NOSPL */ ! 191: ! 192: #ifndef NOSPL ! 193: struct keytab fnctab[] = { /* Function names */ ! 194: "character", FN_CHR, 0, /* Character */ ! 195: "contents", FN_CON, 0, /* Definition (contents) of variable */ ! 196: "definition", FN_DEF, 0, /* Return definition of given macro */ ! 197: "evaluate", FN_EVA, 0, /* Evaluate given arith expression */ ! 198: "execute", FN_EXE, 0, /* Execute given macro */ ! 199: "files", FN_FC, 0, /* File count */ ! 200: "index", FN_IND, 0, /* Index (string search) */ ! 201: "length", FN_LEN, 0, /* Return length of argument */ ! 202: "literal", FN_LIT, 0, /* Return argument literally */ ! 203: "lower", FN_LOW, 0, /* Return lowercased argument */ ! 204: "lpad", FN_LPA, 0, /* Return left-padded argument */ ! 205: "maximum", FN_MAX, 0, /* Return maximum of two arguments */ ! 206: "minimim", FN_MIN, 0, /* Return minimum of two arguments */ ! 207: #ifdef COMMENT ! 208: /* not needed because \feval() has it */ ! 209: "modulus", FN_MOD, 0, /* Return modulus of two arguments */ ! 210: #endif /* COMMENT */ ! 211: "nextfile", FN_FIL, 0, /* Next file in list */ ! 212: "repeat", FN_REP, 0, /* Repeat argument given # of times */ ! 213: #ifndef NOFRILLS ! 214: "reverse", FN_REV, 0, /* Reverse the argument string */ ! 215: #endif /* NOFRILLS */ ! 216: "rpad", FN_RPA, 0, /* Right-pad the argument */ ! 217: "substring", FN_SUB, 0, /* Extract substring from argument */ ! 218: "upper", FN_UPP, 0 /* Return uppercased argument */ ! 219: }; ! 220: int nfuncs = (sizeof(fnctab) / sizeof(struct keytab)); ! 221: #endif /* NOSPL */ ! 222: ! 223: #ifndef NOSPL /* Buffer for expansion of */ ! 224: #define VVBUFL 60 /* built-in variables. */ ! 225: char vvbuf[VVBUFL]; ! 226: #endif /* NOSPL */ ! 227: ! 228: struct keytab disptb[] = { /* Log file disposition */ ! 229: "append", 1, 0, ! 230: "new", 0, 0 ! 231: }; ! 232: ! 233: /* P R E S C A N -- Quick look thru command-line args for init file name */ ! 234: /* Also for -d (debug), -z (force foreground), -S (stay) */ ! 235: ! 236: VOID ! 237: prescan() { ! 238: int yargc; char **yargv; ! 239: char x; ! 240: ! 241: yargc = xargc; ! 242: yargv = xargv; ! 243: strcpy(kermrc,KERMRC); /* Default init file name */ ! 244: #ifndef NOCMDL ! 245: while (--yargc > 0) { /* Look for -y on command line */ ! 246: yargv++; ! 247: if (**yargv == '-') { /* Option starting with dash */ ! 248: x = *(*yargv+1); /* Get option letter */ ! 249: if (x == 'Y') { /* Is it Y (= no init file?) */ ! 250: noinit = 1; ! 251: continue; ! 252: } else if (x == 'y') { /* Is it y? */ ! 253: yargv++, yargc--; /* Yes, count and check argument */ ! 254: if (yargc < 1) fatal("missing name in -y"); ! 255: strcpy(kermrc,*yargv); /* Replace init file name */ ! 256: rcflag = 1; /* Flag that this has been done */ ! 257: continue; ! 258: } else if (x == 'd') { /* Do this early as possible! */ ! 259: debopn("debug.log",0); ! 260: continue; ! 261: } else if (x == 'z') { /* = SET BACKGROUND OFF */ ! 262: bgset = 0; ! 263: continue; ! 264: } else if (x == 'S') { ! 265: stayflg = 1; ! 266: continue; ! 267: } ! 268: } ! 269: } ! 270: #endif /* NOCMDL */ ! 271: } ! 272: ! 273: static int tr_int; /* Flag if TRANSMIT interrupted */ ! 274: ! 275: #ifndef MAC ! 276: SIGTYP ! 277: trtrap(foo) int foo; { /* TRANSMIT interrupt trap */ ! 278: tr_int = 1; /* (Need arg for ANSI C) */ ! 279: SIGRETURN; ! 280: } ! 281: #endif /* MAC */ ! 282: ! 283: #ifndef NOXMIT ! 284: /* T R A N S M I T -- Raw upload */ ! 285: ! 286: /* Obey current line, duplex, parity, flow, text/binary settings. */ ! 287: /* Returns 0 upon apparent success, 1 on obvious failure. */ ! 288: ! 289: /*** ! 290: Things to add: ! 291: . Make both text and binary mode obey set file bytesize. ! 292: . Maybe allow user to specify terminators other than CR? ! 293: . Maybe allow user to specify prompts other than single characters? ! 294: ***/ ! 295: ! 296: /* T R A N S M I T -- Raw upload */ ! 297: ! 298: /* s is the filename, t is the turnaround (prompt) character */ ! 299: ! 300: /* ! 301: Maximum number of characters to buffer. ! 302: Must be less than LINBUFSIZ ! 303: */ ! 304: #define XMBUFS 120 ! 305: ! 306: int ! 307: #ifdef CK_ANSIC ! 308: transmit(char * s, char t) ! 309: #else ! 310: transmit(s,t) char *s; char t; ! 311: #endif /* CK_ANSIC */ ! 312: /* transmit */ { ! 313: #ifdef MAC ! 314: extern char sstate; ! 315: int count = 100; ! 316: #else ! 317: SIGTYP (* oldsig)(); /* For saving old interrupt trap. */ ! 318: #endif /* MAC */ ! 319: long zz; ! 320: int z = 1; /* Return code. 0=fail, 1=succeed. */ ! 321: int x, c, i; /* Workers... */ ! 322: CHAR csave; ! 323: char *p; ! 324: ! 325: #ifndef NOCSETS ! 326: int tcs = TC_TRANSP; /* Intermediate (xfer) char set */ ! 327: int langsv = L_USASCII; /* Save current language */ ! 328: ! 329: _PROTOTYP ( CHAR (*sxo), (CHAR) ) = NULL; /* Translation functions */ ! 330: _PROTOTYP ( CHAR (*rxo), (CHAR) ) = NULL; ! 331: _PROTOTYP ( CHAR (*sxi), (CHAR) ) = NULL; ! 332: _PROTOTYP ( CHAR (*rxi), (CHAR) ) = NULL; ! 333: #endif /* NOCSETS */ ! 334: ! 335: if (zopeni(ZIFILE,s) == 0) { /* Open the file to be transmitted */ ! 336: printf("?Can't open file %s\n",s); ! 337: return(0); ! 338: } ! 339: x = -1; /* Open the communication line */ ! 340: if (ttopen(ttname,&x,mdmtyp,cdtimo) < 0) { /* (no harm if already open) */ ! 341: printf("Can't open device %s\n",ttname); ! 342: return(0); ! 343: } ! 344: zz = x ? speed : -1L; ! 345: if (binary) { /* Binary file transmission */ ! 346: if (ttvt(zz,flow) < 0) { /* So no Xon/Xoff! */ ! 347: printf("Can't condition line\n"); ! 348: return(0); ! 349: } ! 350: } else { ! 351: if (ttpkt(zz,flow,parity) < 0) { /* Put the line in "packet mode" */ ! 352: printf("Can't condition line\n"); /* so Xon/Xoff will work, etc. */ ! 353: return(0); ! 354: } ! 355: } ! 356: ! 357: #ifndef NOCSETS ! 358: /* Set up character set translations */ ! 359: if (binary == 0) { ! 360: #ifdef KANJI ! 361: /* Kanji not supported yet */ ! 362: if (fcsinfo[tcsr].alphabet == AL_JAPAN || ! 363: fcsinfo[tcsl].alphabet == AL_JAPAN ) ! 364: tcs = TC_TRANSP; ! 365: else ! 366: #endif /* KANJI */ ! 367: #ifdef CYRILLIC ! 368: if (fcsinfo[tcsl].alphabet == AL_CYRIL) ! 369: tcs = TC_CYRILL; ! 370: else ! 371: #endif /* CYRILLIC */ ! 372: tcs = TC_1LATIN; ! 373: ! 374: if (tcsr == tcsl || binary) { /* Remote and local sets the same? */ ! 375: sxo = rxo = NULL; /* Or file type is not text? */ ! 376: sxi = rxi = NULL; ! 377: } else { /* Otherwise, set up */ ! 378: sxo = xls[tcs][tcsl]; /* translation function */ ! 379: rxo = xlr[tcs][tcsr]; /* pointers for output functions */ ! 380: sxi = xls[tcs][tcsr]; /* and for input functions. */ ! 381: rxi = xlr[tcs][tcsl]; ! 382: } ! 383: /* ! 384: This is to prevent use of zmstuff() and zdstuff() by translation functions. ! 385: They only work with disk i/o, not with communication i/o. Luckily Russian ! 386: translation functions don't do any stuffing... ! 387: */ ! 388: langsv = language; ! 389: language = L_USASCII; ! 390: } ! 391: #endif /* NOCSETS */ ! 392: ! 393: i = 0; /* Beginning of buffer. */ ! 394: #ifndef MAC ! 395: #ifndef AMIGA ! 396: oldsig = signal(SIGINT, trtrap); /* Save current interrupt trap. */ ! 397: #endif /* AMIGA */ ! 398: #endif /* MAC */ ! 399: tr_int = 0; /* Have not been interrupted (yet). */ ! 400: z = 1; /* Return code presumed good. */ ! 401: #ifdef VMS ! 402: conres(); ! 403: #endif /* VMS */ ! 404: ! 405: c = 0; /* Initial condition */ ! 406: while (c > -1) { /* Loop for all characters in file */ ! 407: #ifdef MAC ! 408: /* ! 409: * It is expensive to run the miniparser so don't do it for ! 410: * every character. ! 411: */ ! 412: if (--count < 0) { ! 413: count = 100; ! 414: miniparser(1); ! 415: if (sstate == 'a') { ! 416: sstate = '\0'; ! 417: z = 0; ! 418: break; ! 419: } ! 420: } ! 421: #else /* Not MAC */ ! 422: if (tr_int) { /* Interrupted? */ ! 423: printf("^C...\n"); /* Print message */ ! 424: z = 0; ! 425: break; ! 426: } ! 427: #endif /* MAC */ ! 428: c = zminchar(); /* Get a file character */ ! 429: debug(F101,"transmit char","",c); ! 430: ! 431: if (binary) { /* If binary file, */ ! 432: if (c == -1) /* if at eof, */ ! 433: break; /* quit, */ ! 434: else if (ttoc(dopar((char) c)) < 0) { /* else just send the char */ ! 435: printf("?Can't transmit character\n"); ! 436: z = 0; ! 437: break; ! 438: } ! 439: if (xmitw) msleep(xmitw); /* Pause if requested */ ! 440: if (xmitx) { /* Echoing? */ ! 441: if (duplex) { /* for half duplex */ ! 442: conoc((char)c); /* echo locally. */ ! 443: } else { /* For full duplex, */ ! 444: x = ttinc(1); /* try to read back echo */ ! 445: if (x > -1) conoc((char)x); /* and display it. */ ! 446: } ! 447: } else ttflui(); /* Not echoing, just flush input. */ ! 448: ! 449: } else { /* Text mode, line at a time. */ ! 450: ! 451: if (c == '\n') { /* Got a line */ ! 452: if (i == 0) { /* Blank line? */ ! 453: if (xmitf) /* Yes, insert fill if asked. */ ! 454: line[i++] = dopar((char) xmitf); ! 455: } ! 456: if (i == 0 || line[i-1] != dopar(CR)) ! 457: line[i++] = dopar(CR); /* Terminate it with CR */ ! 458: if (xmitl) line[i++] = dopar('\n'); /* Include LF if asked */ ! 459: ! 460: } else if (c != -1) { /* Not a newline, regular character */ ! 461: csave = c; /* Remember untranslated version */ ! 462: #ifndef NOCSETS ! 463: /* Translate character sets */ ! 464: if (sxo) c = (*sxo)((CHAR)c); /* From local to intermediate */ ! 465: if (rxo) c = (*rxo)((CHAR)c); /* From intermediate to remote */ ! 466: #endif /* NOCSETS */ ! 467: ! 468: if (xmits && parity && (c & 0200)) { /* If shifting */ ! 469: line[i++] = dopar(SO); /* needs to be done, */ ! 470: line[i++] = dopar((char)c); /* do it here, */ ! 471: line[i++] = dopar(SI); /* crudely. */ ! 472: } else { ! 473: line[i++] = dopar((char)c); /* else, just char itself */ ! 474: } ! 475: } ! 476: ! 477: /* Send characters if buffer full, or at end of line, or at end of file */ ! 478: ! 479: if (i >= XMBUFS || c == '\n' || c == -1) { ! 480: p = line; ! 481: line[i] = '\0'; ! 482: debug(F111,"transmit buf",p,i); ! 483: if (ttol((CHAR *)p,i) < 0) { /* try to send it. */ ! 484: printf("Can't send buffer\n"); ! 485: z = 0; ! 486: break; ! 487: } ! 488: i = 0; /* Reset buffer pointer. */ ! 489: ! 490: /* Worry about echoing here. "xmitx" is SET TRANSMIT ECHO flag. */ ! 491: ! 492: if (duplex && xmitx) /* If local echo, echo it */ ! 493: conoll(p); ! 494: if (xmitw) /* Give receiver time to digest. */ ! 495: msleep(xmitw); ! 496: if (t != 0 && c == '\n') { /* Want a turnaround character */ ! 497: x = 0; /* Wait for it */ ! 498: while (x != t) { ! 499: if ((x = ttinc(1)) < 0) break; ! 500: if (xmitx && !duplex) { /* Echo any echoes */ ! 501: #ifndef NOCSETS ! 502: if (sxi) x = (*sxi)((CHAR)x); /* But translate */ ! 503: if (rxi) x = (*rxi)((CHAR)x); /* them first... */ ! 504: #endif /* NOCSETS */ ! 505: conoc((char) x); ! 506: } ! 507: } ! 508: } else if (xmitx && !duplex) { /* Otherwise, */ ! 509: while (ttchk() > 0) { /* echo for as long as */ ! 510: if ((x = ttinc(0)) < 0) break; /* anything is there. */ ! 511: #ifndef NOCSETS ! 512: if (sxi) x = (*sxi)((CHAR)x); /* Translate first */ ! 513: if (rxi) x = (*rxi)((CHAR)x); ! 514: #endif /* NOCSETS */ ! 515: conoc((char)x); ! 516: } ! 517: } else ttflui(); /* Otherwise just flush input buffer */ ! 518: } /* End of buffer-dumping block */ ! 519: } /* End of text mode */ ! 520: } /* End of character-reading loop */ ! 521: ! 522: if (*xmitbuf) { /* Anything to send at EOF? */ ! 523: p = xmitbuf; /* Yes, point to string. */ ! 524: while (*p) /* Send it. */ ! 525: ttoc(dopar(*p++)); /* Don't worry about echo here. */ ! 526: } ! 527: ! 528: #ifndef AMIGA ! 529: #ifndef MAC ! 530: signal(SIGINT,oldsig); /* put old signal action back. */ ! 531: #endif /* MAC */ ! 532: #endif /* AMIGA */ ! 533: #ifdef VMS ! 534: concb(escape); /* Put terminal back, */ ! 535: #endif /* VMS */ ! 536: zclose(ZIFILE); /* close file, */ ! 537: #ifndef NOCSETS ! 538: language = langsv; /* restore language, */ ! 539: #endif /* NOCSETS */ ! 540: return(z); /* and return successfully. */ ! 541: } ! 542: #endif /* NOXMIT */ ! 543: ! 544: #ifdef MAC ! 545: /* ! 546: This code is not used any more, except on the Macintosh. Instead we call ! 547: system to do the typing. Revive this code if your system can't be called ! 548: to do this. ! 549: */ ! 550: ! 551: /* D O T Y P E -- Type a file */ ! 552: ! 553: int ! 554: dotype(s) char *s; { ! 555: ! 556: #ifdef MAC ! 557: extern char sstate; ! 558: int count = 100; ! 559: #else ! 560: SIGTYP (* oldsig)(); /* For saving old interrupt trap. */ ! 561: #endif /* MAC */ ! 562: int z; /* Return code. */ ! 563: int c; /* Worker. */ ! 564: ! 565: if (zopeni(ZIFILE,s) == 0) { /* Open the file to be transmitted */ ! 566: printf("?Can't open %s\n",s); ! 567: return(0); ! 568: } ! 569: #ifndef AMIGA ! 570: #ifndef MAC ! 571: oldsig = signal(SIGINT, trtrap); /* Save current interrupt trap. */ ! 572: #endif /* MAC */ ! 573: #endif /* AMIGA */ ! 574: ! 575: tr_int = 0; /* Have not been interrupted (yet). */ ! 576: z = 1; /* Return code presumed good. */ ! 577: ! 578: #ifdef VMS ! 579: conoc(CR); /* On VMS, display blank line first */ ! 580: conoc(LF); ! 581: conres(); /* So Ctrl-C/Y will work */ ! 582: #endif /* VMS */ ! 583: while ((c = zminchar()) != -1) { /* Loop for all characters in file */ ! 584: #ifdef MAC ! 585: /* ! 586: * It is expensive to run the miniparser so don't do it for ! 587: * every character. ! 588: */ ! 589: if (--count < 0) { ! 590: count = 100; ! 591: miniparser(1); ! 592: if (sstate == 'a') { ! 593: sstate = '\0'; ! 594: z = 0; ! 595: break; ! 596: } ! 597: } ! 598: putchar(c); ! 599: #else /* Not MAC */ ! 600: if (tr_int) { /* Interrupted? */ ! 601: printf("^C...\n"); /* Print message */ ! 602: z = 0; ! 603: break; ! 604: } ! 605: conoc(c); /* Echo character on screen */ ! 606: #endif /* MAC */ ! 607: } ! 608: #ifndef AMIGA ! 609: #ifndef MAC ! 610: signal(SIGINT,oldsig); /* put old signal action back. */ ! 611: #endif /* MAC */ ! 612: #endif /* AMIGA */ ! 613: ! 614: tr_int = 0; ! 615: #ifdef VMS ! 616: concb(escape); /* Get back in command-parsing mode, */ ! 617: #endif /* VMS */ ! 618: zclose(ZIFILE); /* close file, */ ! 619: return(z); /* and return successfully. */ ! 620: } ! 621: #endif /* MAC */ ! 622: ! 623: #ifndef NOCSETS ! 624: ! 625: _PROTOTYP( CHAR (*sxx), (CHAR) ); /* Local translation function */ ! 626: _PROTOTYP( CHAR (*rxx), (CHAR) ); /* Local translation function */ ! 627: _PROTOTYP( CHAR zl1as, (CHAR) ); /* Latin-1 to ascii */ ! 628: _PROTOTYP( CHAR xl1as, (CHAR) ); /* ditto */ ! 629: ! 630: /* X L A T E -- Translate a local file from one character set to another */ ! 631: ! 632: /* ! 633: Translates input file (fin) from character set csin to character set csout ! 634: and puts the result in the output file (fout). The two character sets are ! 635: file character sets from fcstab. ! 636: */ ! 637: ! 638: int ! 639: xlate(fin, fout, csin, csout) char *fin, *fout; int csin, csout; { ! 640: ! 641: #ifndef MAC ! 642: SIGTYP (* oldsig)(); /* For saving old interrupt trap. */ ! 643: #endif /* MAC */ ! 644: int filecode; /* Code for output file */ ! 645: ! 646: int z = 1; /* Return code. */ ! 647: int c, tcs; /* Workers */ ! 648: ! 649: if (zopeni(ZIFILE,fin) == 0) { /* Open the file to be translated */ ! 650: printf("?Can't open input file %s\n",fin); ! 651: return(0); ! 652: } ! 653: #ifdef MAC ! 654: /* ! 655: If user specified no output file, it goes to the screen. For the Mac, ! 656: this must be done a special way (result goes to a new window); the Mac ! 657: doesn't have a "controlling terminal" device name. ! 658: */ ! 659: filecode = !strcmp(fout,CTTNAM) ? ZCTERM : ZOFILE; ! 660: #else ! 661: filecode = ZOFILE; ! 662: #endif /* MAC */ ! 663: ! 664: if (zopeno(filecode,fout,NULL,NULL) == 0) { /* And the output file */ ! 665: printf("?Can't open output file %s\n",fout); ! 666: return(0); ! 667: } ! 668: #ifndef AMIGA ! 669: #ifndef MAC ! 670: oldsig = signal(SIGINT, trtrap); /* Save current interrupt trap. */ ! 671: #endif /* MAC */ ! 672: #endif /* AMIGA */ ! 673: ! 674: tr_int = 0; /* Have not been interrupted (yet). */ ! 675: z = 1; /* Return code presumed good. */ ! 676: ! 677: #ifdef KANJI ! 678: /* Kanji not supported yet */ ! 679: if (fcsinfo[csin].alphabet == AL_JAPAN) ! 680: tcs = TC_TRANSP; ! 681: else ! 682: #endif /* KANJI */ ! 683: #ifdef CYRILLIC ! 684: if (fcsinfo[csout].alphabet == AL_CYRIL) ! 685: tcs = TC_CYRILL; ! 686: else ! 687: #endif /* CYRILLIC */ ! 688: tcs = TC_1LATIN; ! 689: ! 690: printf("%s (%s) => %s (%s)\n", /* Say what we're doing. */ ! 691: fin, fcsinfo[csin].name, ! 692: fout,fcsinfo[csout].name ! 693: ); ! 694: printf("via %s", tcsinfo[tcs].name); ! 695: if (language) ! 696: printf(", language: %s\n",langs[language].description); ! 697: printf("\n\n"); ! 698: ! 699: if (csin == csout) { /* Input and output sets the same? */ ! 700: sxx = rxx = NULL; /* If so, no translation. */ ! 701: } else { /* Otherwise, set up */ ! 702: sxx = xls[tcs][csin]; /* translation function */ ! 703: rxx = xlr[tcs][csout]; /* pointers. */ ! 704: if (rxx == zl1as) rxx = xl1as; ! 705: } ! 706: while ((c = zminchar()) != -1) { /* Loop for all characters in file */ ! 707: if (tr_int) { /* Interrupted? */ ! 708: printf("^C...\n"); /* Print message */ ! 709: z = 0; ! 710: break; ! 711: } ! 712: if (sxx) c = (*sxx)((CHAR)c); /* From fcs1 to tcs */ ! 713: if (rxx) c = (*rxx)((CHAR)c); /* from tcs to fcs2 */ ! 714: ! 715: if (zchout(ZOFILE,(char)c) < 0) { /* Output the translated character */ ! 716: printf("File output error\n"); ! 717: z = 0; ! 718: break; ! 719: } ! 720: } ! 721: #ifndef AMIGA ! 722: #ifndef MAC ! 723: signal(SIGINT,oldsig); /* put old signal action back. */ ! 724: #endif /* MAC */ ! 725: #endif /* AMIGA */ ! 726: ! 727: tr_int = 0; ! 728: zclose(ZIFILE); /* close files, */ ! 729: zclose(ZOFILE); ! 730: return(z); /* and return successfully. */ ! 731: } ! 732: #endif /* NOCSETS */ ! 733: ! 734: /* D O L O G -- Do the log command */ ! 735: ! 736: int ! 737: dolog(x) int x; { ! 738: int y, disp; char *s; ! 739: ! 740: switch (x) { ! 741: ! 742: #ifdef DEBUG ! 743: case LOGD: ! 744: y = cmofi("Name of debugging log file","debug.log",&s,xxstring); ! 745: break; ! 746: #endif /* DEBUG */ ! 747: ! 748: case LOGP: ! 749: y = cmofi("Name of packet log file","packet.log",&s,xxstring); ! 750: break; ! 751: ! 752: case LOGS: ! 753: y = cmofi("Name of session log file","session.log",&s,xxstring); ! 754: break; ! 755: ! 756: #ifdef TLOG ! 757: case LOGT: ! 758: y = cmofi("Name of transaction log file","transact.log",&s, ! 759: xxstring); ! 760: break; ! 761: #endif /* TLOG */ ! 762: ! 763: default: ! 764: printf("\n?Unknown log designator - %d\n",x); ! 765: return(-2); ! 766: } ! 767: if (y < 0) return(y); ! 768: ! 769: strcpy(line,s); ! 770: s = line; ! 771: if ((y = cmkey(disptb,2,"Disposition","new",xxstring)) < 0) ! 772: return(y); ! 773: disp = y; ! 774: if ((y = cmcfm()) < 0) return(y); ! 775: ! 776: switch (x) { ! 777: ! 778: #ifdef DEBUG ! 779: case LOGD: ! 780: return(deblog = debopn(s,disp)); ! 781: #endif /* DEBUG */ ! 782: ! 783: case LOGP: ! 784: return(pktlog = pktopn(s,disp)); ! 785: ! 786: case LOGS: ! 787: return(seslog = sesopn(s,disp)); ! 788: ! 789: #ifdef TLOG ! 790: case LOGT: ! 791: return(tralog = traopn(s,disp)); ! 792: #endif /* TLOG */ ! 793: ! 794: default: ! 795: return(-2); ! 796: } ! 797: } ! 798: ! 799: int ! 800: pktopn(s,disp) char *s; int disp; { ! 801: extern char pktfil[]; ! 802: static struct filinfo xx; ! 803: int y; ! 804: ! 805: zclose(ZPFILE); ! 806: if(s[0] == '\0') return(0); ! 807: if (disp) { ! 808: xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0; ! 809: xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = '\0'; ! 810: xx.lblopts = 0; ! 811: y = zopeno(ZPFILE,s,NULL,&xx); ! 812: } else y = zopeno(ZPFILE,s,NULL,NULL); ! 813: if (y > 0) ! 814: strcpy(pktfil,s); ! 815: else ! 816: *pktfil = '\0'; ! 817: return(y); ! 818: } ! 819: ! 820: int ! 821: traopn(s,disp) char *s; int disp; { ! 822: #ifdef TLOG ! 823: extern char trafil[]; ! 824: static struct filinfo xx; ! 825: int y; ! 826: ! 827: zclose(ZTFILE); ! 828: if(s[0] == '\0') return(0); ! 829: if (disp) { ! 830: xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0; ! 831: xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = '\0'; ! 832: xx.lblopts = 0; ! 833: y = zopeno(ZTFILE,s,NULL,&xx); ! 834: } else y = zopeno(ZTFILE,s,NULL,NULL); ! 835: if (y > 0) { ! 836: strcpy(trafil,s); ! 837: tlog(F110,"Transaction Log:",versio,0L); ! 838: #ifndef MAC ! 839: tlog(F100,ckxsys,"",0L); ! 840: #endif /* MAC */ ! 841: ztime(&s); ! 842: tlog(F100,s,"",0L); ! 843: } else *trafil = '\0'; ! 844: return(y); ! 845: #else ! 846: return(0); ! 847: #endif ! 848: } ! 849: ! 850: int ! 851: sesopn(s,disp) char * s; int disp; { ! 852: extern char sesfil[]; ! 853: static struct filinfo xx; ! 854: int y; ! 855: ! 856: zclose(ZSFILE); ! 857: if(s[0] == '\0') return(0); ! 858: if (disp) { ! 859: xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0; ! 860: xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = '\0'; ! 861: xx.lblopts = 0; ! 862: y = zopeno(ZSFILE,s,NULL,&xx); ! 863: } else y = zopeno(ZSFILE,s,NULL,NULL); ! 864: if (y > 0) ! 865: strcpy(sesfil,s); ! 866: else ! 867: *sesfil = '\0'; ! 868: return(y); ! 869: } ! 870: ! 871: int ! 872: debopn(s,disp) char *s; int disp; { ! 873: #ifdef DEBUG ! 874: char *tp; ! 875: static struct filinfo xx; ! 876: ! 877: zclose(ZDFILE); ! 878: ! 879: if (disp) { ! 880: xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0; ! 881: xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = '\0'; ! 882: xx.lblopts = 0; ! 883: deblog = zopeno(ZDFILE,s,NULL,&xx); ! 884: } else deblog = zopeno(ZDFILE,s,NULL,NULL); ! 885: if (deblog > 0) { ! 886: strcpy(debfil,s); ! 887: debug(F110,"Debug Log ",versio,0); ! 888: #ifndef MAC ! 889: debug(F100,ckxsys,"",0); ! 890: #endif /* MAC */ ! 891: ztime(&tp); ! 892: debug(F100,tp,"",0); ! 893: } else *debfil = '\0'; ! 894: return(deblog); ! 895: #else ! 896: return(0); ! 897: #endif ! 898: } ! 899: ! 900: char * ! 901: #ifdef CK_ANSIC ! 902: parnam(char c) ! 903: #else ! 904: parnam(c) char c; ! 905: #endif /* CK_ANSIC */ ! 906: /* parnam */ { ! 907: switch (c) { ! 908: case 'e': return("even"); ! 909: case 'o': return("odd"); ! 910: case 'm': return("mark"); ! 911: case 's': return("space"); ! 912: case 0: return("none"); ! 913: default: return("invalid"); ! 914: } ! 915: } ! 916: ! 917: #ifndef NOSHOW ! 918: ! 919: /* S H O P A R -- Show Parameters */ ! 920: ! 921: #ifdef SUNX25 ! 922: VOID ! 923: shox25() { ! 924: if (nettype == NET_SX25) { ! 925: printf("SunLink X.25 V%d.%d",x25ver / 10,x25ver % 10); ! 926: if (ttnproto == NP_X3) printf(", PAD X.3, X.28, X.29 protocol,"); ! 927: printf("\n Reverse charge call %s", ! 928: revcall ? "selected" : "not selected"); ! 929: printf (", Closed user group "); ! 930: if (closgr > -1) ! 931: printf ("%d",closgr); ! 932: else ! 933: printf ("not selected"); ! 934: printf (","); ! 935: printf("\n Call user data %s.", cudata ? udata : "not selected"); ! 936: } ! 937: } ! 938: #endif /* SUNX25 */ ! 939: ! 940: VOID ! 941: shoparc() { ! 942: int i; char *s; ! 943: long zz; ! 944: ! 945: puts("Communications Parameters:"); ! 946: ! 947: if (network) { ! 948: printf(" Host: %s",ttname); ! 949: } else { ! 950: printf(" Line: %s, speed: ",ttname); ! 951: if ((zz = ttgspd()) < 0) { ! 952: printf("unknown"); ! 953: } else { ! 954: if (speed == 8880) printf("75/1200"); else printf("%ld",zz); ! 955: } ! 956: } ! 957: printf(", mode: "); ! 958: if (local) printf("local"); else printf("remote"); ! 959: if (network == 0) { ! 960: #ifndef NODIAL ! 961: for (i = 0; i < nmdm; i++) { ! 962: if (mdmtab[i].kwval == mdmtyp) { ! 963: printf(", modem: %s",mdmtab[i].kwd); ! 964: break; ! 965: } ! 966: } ! 967: #endif /* NODIAL */ ! 968: } else { ! 969: if (nettype == NET_TCPA) printf(", TCP/IP/streams"); ! 970: if (nettype == NET_TCPB) printf(", TCP/IP/sockets"); ! 971: if (nettype == NET_DEC) printf(", DECnet"); ! 972: #ifdef SUNX25 ! 973: shox25(); ! 974: #endif /* SUNX25 */ ! 975: if (ttnproto == NP_TELNET) printf(", telnet protocol"); ! 976: } ! 977: if (local) { ! 978: i = parity ? 7 : 8; ! 979: if (i == 8) i = (cmask == 0177) ? 7 : 8; ! 980: printf("\n Terminal bits: %d, p",i); ! 981: } else printf("\n P"); ! 982: printf("arity: %s",parnam((char)parity)); ! 983: printf(", duplex: "); ! 984: if (duplex) printf("half, "); else printf("full, "); ! 985: printf("flow: "); ! 986: if (flow == FLO_XONX) printf("xon/xoff"); ! 987: else if (flow == FLO_NONE) printf("none"); ! 988: #ifdef UTEK ! 989: else if (flow == FLO_HARD) printf("idtr/octs"); ! 990: #else ! 991: else if (flow == FLO_RTSC) printf("rts/cts"); ! 992: #endif /* UTEK */ ! 993: else if (flow == FLO_DTRC) printf("dtr/cd"); ! 994: else printf("%d",flow); ! 995: printf(", handshake: "); ! 996: if (turn) printf("%d\n",turnch); else printf("none\n"); ! 997: if (local && !network) { /* Lockfile & carrier stuff */ ! 998: if (carrier == CAR_OFF) s = "off"; ! 999: else if (carrier == CAR_ON) s = "on"; ! 1000: else if (carrier == CAR_AUT) s = "auto"; ! 1001: else s = "unknown"; ! 1002: printf(" Carrier: %s", s); ! 1003: if (carrier == CAR_ON) { ! 1004: if (cdtimo) printf(", timeout: %d sec", cdtimo); ! 1005: else printf(", timeout: none"); ! 1006: } ! 1007: #ifdef UNIX ! 1008: if (haslock && *flfnam) { /* Lockfiles only apply to UNIX... */ ! 1009: printf(", lockfile: %s\n",flfnam); ! 1010: } ! 1011: #else ! 1012: printf("\n"); ! 1013: #endif /* UNIX */ ! 1014: printf(" Escape character: %d (^%c)\n",escape,ctl(escape)); ! 1015: } ! 1016: } ! 1017: ! 1018: VOID ! 1019: shonet() { ! 1020: #ifdef NETCONN ! 1021: printf("Supported networks:\n"); ! 1022: #ifdef VMS ! 1023: #ifdef MULTINET ! 1024: printf(" TGV MultiNet TCP/IP\n"); ! 1025: #else ! 1026: printf(" None\n"); ! 1027: #endif /* MULTINET */ ! 1028: ! 1029: #else /* Not VMS */ ! 1030: ! 1031: #ifdef TCPSOCKET ! 1032: printf(" TCP/IP (sockets library)\n"); ! 1033: #endif /* TCPSOCKET */ ! 1034: #ifdef TCPSTREAM ! 1035: printf(" TCP/IP (streams)\n"); ! 1036: #endif /* TCPSTREAM */ ! 1037: #ifdef TNCODE ! 1038: printf(" TELNET protocol\n"); ! 1039: #endif /* TNCODE */ ! 1040: #ifdef SUNX25 ! 1041: printf(" SunLink X.25\n"); ! 1042: #endif /* SUNX25 */ ! 1043: #endif /* VMS */ ! 1044: ! 1045: printf("Active SET HOST connection:\n"); ! 1046: if (network) { ! 1047: printf(" %s",ttname); ! 1048: if (*ipaddr) printf(" [%s]",ipaddr); ! 1049: printf("\n Via: "); ! 1050: if (nettype == NET_TCPA) printf("TCP/IP (streams)\n"); ! 1051: else if (nettype == NET_TCPB) printf("TCP/IP (sockets)\n"); ! 1052: else if (nettype == NET_SX25) printf("SunLink X.25\n"); ! 1053: else if (nettype == NET_DEC) printf("DECnet\n"); ! 1054: #ifdef SUNX25 ! 1055: if (nettype == NET_SX25) shox25(); ! 1056: #endif /* SUNX25 */ ! 1057: #ifdef TNCODE ! 1058: if (ttnproto == NP_TELNET) printf(" TELNET protocol\n"); ! 1059: #endif /* TNCODE */ ! 1060: } else printf(" None\n"); ! 1061: #else /* Not NETCONN */ ! 1062: printf("No network support\n"); ! 1063: #endif /* NETCONN */ ! 1064: } ! 1065: ! 1066: #ifndef NODIAL ! 1067: ! 1068: VOID ! 1069: shodial() { ! 1070: if (mdmtyp >= 0 || local != 0) doshodial(); ! 1071: } ! 1072: ! 1073: int ! 1074: doshodial() { ! 1075: char c, *s; ! 1076: printf(" Dial hangup: %s, dial timeout: ", ! 1077: dialhng ? "on" : "off"); ! 1078: if (dialtmo > 0) ! 1079: printf("%d sec", dialtmo); ! 1080: else ! 1081: printf("auto"); ! 1082: printf("\n Dial kermit-spoof: %s",dialksp ? "on" : "off"); ! 1083: printf(", dial display: %s\n",dialdpy ? "on" : "off"); ! 1084: printf(" Dial speed-matching: %s",mdmspd ? "off" : "on"); ! 1085: printf(", dial mnp-enable: %s\n",dialmnp ? "on" : "off"); ! 1086: printf(" Dial init-string: "); ! 1087: s = getdws(mdmtyp); /* Ask dial module for it */ ! 1088: if (s == NULL || !(*s)) { /* Empty? */ ! 1089: printf("none\n"); ! 1090: } else { /* Not empty. */ ! 1091: while (c = *s++) /* Can contain controls */ ! 1092: if (c > 31 && c < 127) { putchar(c); } /* so display them */ ! 1093: else printf("\\{%d}",c); /* in backslash notation */ ! 1094: printf("\n"); ! 1095: } ! 1096: printf(" Redial number: %s\n",dialnum ? dialnum : "none"); ! 1097: return(0); ! 1098: } ! 1099: #endif /* NODIAL */ ! 1100: ! 1101: #ifdef SUNX25 ! 1102: VOID ! 1103: shopad() { ! 1104: int i; ! 1105: printf("\nX.3 PAD Parameters:\n"); ! 1106: for (i = 0; i < npadx3; i++) ! 1107: printf(" [%d] %s %d\n",padx3tab[i].kwval,padx3tab[i].kwd, ! 1108: padparms[padx3tab[i].kwval]); ! 1109: } ! 1110: #endif /* SUNX25 */ ! 1111: ! 1112: VOID ! 1113: shomdm() { ! 1114: int y; ! 1115: y = ttgmdm(); ! 1116: switch (y) { ! 1117: case -3: printf("Modem signals unavailable in this version of Kermit\n"); ! 1118: break; ! 1119: case -2: printf("No modem control for this device\n"); break; ! 1120: case -1: printf("Modem signals unavailable\n"); break; ! 1121: default: ! 1122: #ifndef MAC ! 1123: printf(" Carrier Detect (CD): %s\n",(y & BM_DCD) ? "On": "Off"); ! 1124: printf(" Dataset Ready (DSR): %s\n",(y & BM_DSR) ? "On": "Off"); ! 1125: #endif /* MAC */ ! 1126: printf(" Clear To Send (CTS): %s\n",(y & BM_CTS) ? "On": "Off"); ! 1127: #ifndef MAC ! 1128: printf(" Ring Indicator (RI): %s\n",(y & BM_RNG) ? "On": "Off"); ! 1129: #endif /* MAC */ ! 1130: printf(" Data Terminal Ready (DTR): %s\n",(y & BM_DTR) ? "On": "Off"); ! 1131: #ifndef MAC ! 1132: printf(" Request to Send (RTS): %s\n",(y & BM_RTS) ? "On": "Off"); ! 1133: #endif /* MAC */ ! 1134: } ! 1135: } ! 1136: ! 1137: /* Show File Parameters */ ! 1138: ! 1139: VOID ! 1140: shoparf() { ! 1141: char *s; int i; ! 1142: printf("\nFile parameters: "); ! 1143: #ifdef COMMENT ! 1144: printf("Blocksize: %5d ",fblksiz); ! 1145: #endif /* COMMENT */ ! 1146: printf(" Attributes: "); ! 1147: if (atcapr) printf("on"); else printf("off"); ! 1148: #ifdef VMS ! 1149: printf(" Record-Length: %5d",frecl); ! 1150: #endif /* VMS */ ! 1151: printf("\n Names: "); ! 1152: printf("%-12s",(fncnv) ? "converted" : "literal"); ! 1153: #ifdef DEBUG ! 1154: #ifndef MAC ! 1155: printf(" Debugging Log: "); ! 1156: if (deblog) printf("%s",debfil); else printf("none"); ! 1157: #endif /* MAC */ ! 1158: #endif /* DEBUG */ ! 1159: ! 1160: printf("\n Type: "); ! 1161: switch (binary) { ! 1162: case XYFT_T: s = "text"; break; ! 1163: #ifdef VMS ! 1164: case XYFT_B: s = "binary fixed"; break; ! 1165: case XYFT_I: s = "image"; break; ! 1166: case XYFT_L: s = "labeled"; break; ! 1167: case XYFT_U: s = "binary undef"; break; ! 1168: #else ! 1169: case XYFT_B: s = "binary"; break; ! 1170: #endif /* VMS */ ! 1171: default: s = "?"; break; ! 1172: } ! 1173: printf("%-12s",s); ! 1174: #ifdef COMMENT ! 1175: printf(" Organization: "); ! 1176: switch (forg) { ! 1177: case XYFO_I: printf("%-10s","indexed"); break; ! 1178: case XYFO_R: printf("%-10s","relative"); break; ! 1179: case XYFO_S: printf("%-10s","sequential"); break; ! 1180: } ! 1181: #endif /* COMMENT */ ! 1182: #ifndef MAC ! 1183: printf(" Packet Log: "); ! 1184: if (pktlog) printf(pktfil); else printf("none"); ! 1185: #endif /* MAC */ ! 1186: #ifdef UNIX ! 1187: printf(" Longest filename: %d",maxnam); ! 1188: #endif /* UNIX */ ! 1189: printf("\n Collide: "); ! 1190: for (i = 0; i < ncolx; i++) ! 1191: if (colxtab[i].kwval == fncact) break; ! 1192: printf("%-12s", (i == ncolx) ? "unknown" : colxtab[i].kwd); ! 1193: ! 1194: #ifdef COMMENT ! 1195: printf(" Format: "); ! 1196: switch (frecfm) { ! 1197: case XYFF_F: printf("%-10s","fixed"); break; ! 1198: case XYFF_VB: printf("%-10s","rcw"); break; ! 1199: case XYFF_S: printf("%-10s","stream"); break; ! 1200: case XYFF_U: printf("%-10s","undefined"); break; ! 1201: case XYFF_V: printf("%-10s","variable"); break; ! 1202: } ! 1203: #endif /* COMMENT */ ! 1204: #ifndef MAC ! 1205: printf(" Session Log: "); ! 1206: if (seslog) printf(sesfil); else printf("none"); ! 1207: #endif /* MAC */ ! 1208: #ifdef UNIX ! 1209: printf(" Longest pathname: %d",maxpath); ! 1210: #endif /* UNIX */ ! 1211: printf("\n Display: "); ! 1212: if (quiet) printf("%-12s","off"); else printf("%-12s","on"); ! 1213: #ifdef COMMENT ! 1214: printf("Carriage-Control: "); ! 1215: switch (fcctrl) { ! 1216: case XYFP_F: printf("%-10s","fortran"); break; ! 1217: case XYFP_N: printf("%-10s","newline"); break; ! 1218: case XYFP_P: printf("%-10s","machine"); break; ! 1219: case XYFP_X: printf("%-10s","none"); break; ! 1220: } ! 1221: #endif /* COMMENT */ ! 1222: #ifdef TLOG ! 1223: #ifndef MAC ! 1224: printf(" Transaction Log: "); ! 1225: if (tralog) printf(trafil); else printf("none"); ! 1226: #endif /* MAC */ ! 1227: #endif /* TLOG */ ! 1228: #ifndef NOCSETS ! 1229: if (binary == XYFT_T) { ! 1230: shocharset(); ! 1231: } else ! 1232: #endif /* NOCSETS */ ! 1233: printf("\n"); ! 1234: printf("\nFile Byte Size: %d",(fmask == 0177) ? 7 : 8); ! 1235: printf(", Incomplete Files: "); ! 1236: if (keep) printf("keep"); else printf("discard"); ! 1237: #ifdef KERMRC ! 1238: printf(", Init file: %s",kermrc); ! 1239: #endif /* KERMRC */ ! 1240: printf("\n"); ! 1241: } ! 1242: ! 1243: VOID ! 1244: shoparp() { ! 1245: printf("\nProtocol Parameters: Send Receive"); ! 1246: if (timef || spsizf) printf(" (* = override)"); ! 1247: printf("\n Timeout: %11d%9d", rtimo, pkttim); ! 1248: if (timef) printf("*"); else printf(" "); ! 1249: #ifndef NOSERVER ! 1250: printf(" Server timeout:%4d\n",srvtim); ! 1251: #endif /* NOSERVER */ ! 1252: printf( " Padding: %11d%9d", npad, mypadn); ! 1253: printf(" Block Check: %6d\n",bctr); ! 1254: printf( " Pad Character:%11d%9d", padch, mypadc); ! 1255: printf(" Delay: %6d\n",delay); ! 1256: printf( " Packet Start: %11d%9d", mystch, stchr); ! 1257: printf(" Max Retries: %6d\n",maxtry); ! 1258: printf( " Packet End: %11d%9d", seol, eol); ! 1259: if (ebqflg) ! 1260: printf(" 8th-Bit Prefix: '%c'",ebq); ! 1261: printf( "\n Packet Length:%11d", spsizf ? spsizr : spsiz); ! 1262: printf( spsizf ? "*" : " " ); printf("%8d", urpsiz); ! 1263: printf( (urpsiz > 94) ? " (94)" : " "); ! 1264: if (rptflg) ! 1265: printf(" Repeat Prefix: '%c'",rptq); ! 1266: printf( "\n Length Limit: %11d%9d", maxsps, maxrps); ! 1267: printf(" Window:%12d set, %d used\n",wslotr,wslotn); ! 1268: printf( " Buffer Size: %11d%9d", bigsbsiz, bigrbsiz); ! 1269: printf(" Locking-Shift: "); ! 1270: if (lscapu == 2) { ! 1271: printf("forced\n"); ! 1272: } else { ! 1273: printf("%s", (lscapr ? "enabled" : "disabled")); ! 1274: if (lscapr) printf(",%s%s", (lscapu ? " " : " not "), "used"); ! 1275: printf("\n"); ! 1276: } ! 1277: } ! 1278: ! 1279: #ifndef NOCSETS ! 1280: VOID ! 1281: shoparl() { ! 1282: int i; ! 1283: printf("\nAvailable Languages:\n"); ! 1284: for (i = 0; i < MAXLANG; i++) { ! 1285: printf(" %s\n",langs[i].description); ! 1286: } ! 1287: printf("\nCurrent Language: %s\n",langs[language].description); ! 1288: shocharset(); ! 1289: printf("\n\n"); ! 1290: } ! 1291: ! 1292: VOID ! 1293: shocharset() { ! 1294: printf("\nFile Character-Set: %s (",fcsinfo[fcharset].name); ! 1295: if (fcsinfo[fcharset].size == 128) printf("7-bit)"); ! 1296: else printf("8-bit)"); ! 1297: printf("\nTransfer Character-Set"); ! 1298: if (tslevel == TS_L2) ! 1299: printf(": (international)"); ! 1300: else if (tcharset == TC_TRANSP) ! 1301: printf(": Transparent"); ! 1302: else ! 1303: printf(": %s",tcsinfo[tcharset].name); ! 1304: } ! 1305: #endif /* NOCSETS */ ! 1306: ! 1307: VOID ! 1308: shopar() { ! 1309: #ifndef MAC ! 1310: printf("\n%s,%s\n",versio,ckxsys); ! 1311: #endif /* MAC */ ! 1312: shoparc(); ! 1313: shoparp(); ! 1314: shoparf(); ! 1315: } ! 1316: #endif /* NOSHOW */ ! 1317: ! 1318: /* D O S T A T -- Display file transfer statistics. */ ! 1319: ! 1320: int ! 1321: dostat() { ! 1322: printf("\nMost recent transaction --\n"); ! 1323: printf(" parity: %s",parnam((char)parity)); ! 1324: if (autopar) printf(" (detected automatically)"); ! 1325: printf("\n files: %ld\n",filcnt); ! 1326: printf(" characters last file : %ld\n",ffc); ! 1327: printf(" total file characters : %ld\n",tfc); ! 1328: printf(" communication line in : %ld\n",tlci); ! 1329: printf(" communication line out : %ld\n",tlco); ! 1330: printf(" packets sent : %d\n", spackets); ! 1331: printf(" packets received : %d\n", rpackets); ! 1332: printf(" damaged packets rec'd : %d\n", crunched); ! 1333: printf(" timeouts : %d\n", timeouts); ! 1334: printf(" retransmissions : %d\n", retrans); ! 1335: printf(" window slots used : %d\n", wmax); ! 1336: printf(" elapsed time : %d sec\n",tsecs); ! 1337: if (speed <= 0L) speed = ttgspd(); ! 1338: if (speed > 0L) { ! 1339: if (speed == 8880) ! 1340: printf(" transmission rate : 75/1200 bps\n"); ! 1341: else ! 1342: printf(" transmission rate : %ld bps\n",speed); ! 1343: } ! 1344: if (filcnt > 0) { ! 1345: if (tsecs > 0) { ! 1346: long lx; ! 1347: lx = (tfc * 10L) / (long) tsecs; ! 1348: printf(" effective data rate : %ld cps\n",lx/10L); ! 1349: if (speed > 0L && speed != 8880L && network == 0) { ! 1350: lx = (lx * 100L) / speed; ! 1351: printf(" efficiency (percent) : %ld\n",lx); ! 1352: } ! 1353: } ! 1354: printf(" packet length : %d (send), %d (receive)\n", ! 1355: spsizf ? spsizr : spsiz, urpsiz); ! 1356: printf(" block check type used : %d\n",bctu); ! 1357: printf(" compression : "); ! 1358: if (rptflg) printf("yes [%c] (%d)\n",rptq,rptn); else printf("no\n"); ! 1359: printf(" 8th bit prefixing : "); ! 1360: if (ebqflg) printf("yes [%c]\n",ebq); else printf("no\n"); ! 1361: printf(" locking shifts : %s\n\n", lscapu ? "yes" : "no"); ! 1362: } else printf("\n"); ! 1363: return(1); ! 1364: } ! 1365: ! 1366: /* D O C O N E C T -- Do the connect command */ ! 1367: ! 1368: /* Note, we don't call this directly from dial, because we need to give */ ! 1369: /* the user a chance to change parameters (e.g. parity) after the */ ! 1370: /* connection is made. */ ! 1371: ! 1372: int ! 1373: doconect() { ! 1374: int x; ! 1375: conres(); /* Put console back to normal */ ! 1376: x = conect(); /* Connect */ ! 1377: concb((char)escape); /* Put console into cbreak mode, */ ! 1378: return(x); /* for more command parsing. */ ! 1379: } ! 1380: ! 1381: #ifndef NOSPL ! 1382: /* The INPUT command */ ! 1383: ! 1384: #ifdef NETCONN ! 1385: extern int tn_init; ! 1386: #ifndef IAC ! 1387: #define IAC 255 ! 1388: #endif /* IAC */ ! 1389: #endif /* NETCONN */ ! 1390: ! 1391: int ! 1392: doinput(timo,s) int timo; char *s; { ! 1393: int x, y, i, icn; ! 1394: char *xp, *xq = (char *)0; ! 1395: CHAR c; ! 1396: ! 1397: if (local) { /* Put line in "ttvt" mode */ ! 1398: y = ttvt(speed,flow); /* if not already. */ ! 1399: if (y < 0) { ! 1400: printf("?Can't condition line for INPUT\n"); ! 1401: return(0); /* Watch out for failure. */ ! 1402: } ! 1403: } ! 1404: y = (int)strlen(s); ! 1405: debug(F111,"doinput",s,y); ! 1406: if (timo <= 0) timo = 1; /* Give at least 1 second timeout */ ! 1407: x = 0; /* Return code, assume failure */ ! 1408: i = 0; /* String pattern match position */ ! 1409: ! 1410: if (!incase) { /* INPUT CASE = IGNORE? */ ! 1411: xp = malloc(y+2); /* Make a separate copy of the */ ! 1412: if (!xp) { /* input string for editing. */ ! 1413: printf("?malloc error 5\n"); ! 1414: return(x); ! 1415: } else xq = xp; /* Save pointer to beginning */ ! 1416: ! 1417: while (*s) { /* Convert to lowercase */ ! 1418: *xp = *s; ! 1419: if (isupper(*xp)) *xp = tolower(*xp); ! 1420: xp++; s++; ! 1421: } ! 1422: *xp = NUL; /* Terminate the search string. */ ! 1423: s = xq; /* Point back to beginning. */ ! 1424: } ! 1425: inpbps = inpbp; /* Save current pointer. */ ! 1426: rtimer(); /* Get current time. */ ! 1427: while (1) { /* Character-getting loop */ ! 1428: if (local) { /* One case for local */ ! 1429: y = ttinc(1); /* Get character from comm line. */ ! 1430: debug(F101,"input ttinc(1) returns","",y); ! 1431: if (icn = conchk()) { /* Interrupted from keyboard? */ ! 1432: debug(F101,"input interrupted from keyboard","",icn); ! 1433: while (icn--) coninc(0); /* Yes, read what was typed. */ ! 1434: break; /* And fail. */ ! 1435: } ! 1436: } else { /* Another for remote */ ! 1437: y = coninc(1); ! 1438: debug(F101,"input coninc(1) returns","",y); ! 1439: } ! 1440: if (y > -1) { /* A character arrived */ ! 1441: #ifdef NETCONN ! 1442: /* Check for telnet protocol negotiation */ ! 1443: if (network && (ttnproto == NP_TELNET) && ((y & 0xff) == IAC)) { ! 1444: switch (tn_doop((CHAR)(y & 0xff),duplex)) { ! 1445: case 2: duplex = 0; continue; ! 1446: case 1: duplex = 1; ! 1447: default: continue; ! 1448: } ! 1449: } ! 1450: #endif /* NETCONN */ ! 1451: ! 1452: /* Real input character to be checked */ ! 1453: ! 1454: c = cmask & (CHAR) y; /* Mask off parity */ ! 1455: if (c) *inpbp++ = c; /* Store result in circular buffer */ ! 1456: if (inpbp >= inpbuf + INPBUFSIZ) { /* Time to wrap around? */ ! 1457: inpbp = inpbuf; /* Yes. */ ! 1458: *(inpbp+INPBUFSIZ) = NUL; /* Make sure it's null-terminated. */ ! 1459: } ! 1460: #ifdef MAC ! 1461: { ! 1462: extern char *ttermw; /* fake pointer cast */ ! 1463: if (inecho) { ! 1464: outchar(ttermw, c); /* echo to terminal window */ ! 1465: /* this might be too much overhead to do here ? */ ! 1466: updatecommand(ttermw); ! 1467: } ! 1468: } ! 1469: #else /* Not MAC */ ! 1470: if (inecho) conoc(c); /* Echo and log the input character */ ! 1471: #endif /* MAC */ ! 1472: if (seslog) { ! 1473: #ifdef UNIX ! 1474: if (sessft != 0 || c != '\r') ! 1475: #endif /* UNIX */ ! 1476: if (zchout(ZSFILE,c) < 0) seslog = 0; ! 1477: } ! 1478: if (!incase) { /* Ignore alphabetic case? */ ! 1479: if (isupper(c)) c = tolower(c); /* Yes */ ! 1480: } ! 1481: debug(F000,"doinput char","",c); ! 1482: debug(F000,"compare char","",s[i]); ! 1483: if (c == s[i]) i++; else i = 0; /* Check for match */ ! 1484: if (s[i] == '\0') { /* Matched all the way to end? */ ! 1485: x = 1; /* Yes, */ ! 1486: break; /* done. */ ! 1487: } ! 1488: } ! 1489: if (gtimer() > timo) /* Did not match, timer exceeded? */ ! 1490: break; ! 1491: } /* Still have time left, continue. */ ! 1492: if (!incase) if (xq) free(xq); /* Done, free dynamic memory. */ ! 1493: return(x); /* Return the return code. */ ! 1494: } ! 1495: #endif /* NOSPL */ ! 1496: ! 1497: #ifndef NOSPL ! 1498: /* REINPUT Command */ ! 1499: ! 1500: /* Note, the timeout parameter is required, but ignored. */ ! 1501: /* Syntax is compatible with MS-DOS Kermit except timeout can't be omitted. */ ! 1502: /* This function only looks at the characters already received */ ! 1503: /* and does not read any new characters from the communication line. */ ! 1504: ! 1505: int ! 1506: doreinp(timo,s) int timo; char *s; { ! 1507: int x, y, i; ! 1508: char *xx, *xp, *xq = (char *)0; ! 1509: CHAR c; ! 1510: ! 1511: y = (int)strlen(s); ! 1512: debug(F111,"doreinput",s,y); ! 1513: ! 1514: x = 0; /* Return code, assume failure */ ! 1515: i = 0; /* String pattern match position */ ! 1516: ! 1517: if (!incase) { /* INPUT CASE = IGNORE? */ ! 1518: xp = malloc(y+2); /* Make a separate copy of the */ ! 1519: if (!xp) { /* search string. */ ! 1520: printf("?malloc error 6\n"); ! 1521: return(x); ! 1522: } else xq = xp; /* Keep pointer to beginning. */ ! 1523: while (*s) { /* Yes, convert to lowercase */ ! 1524: *xp = *s; ! 1525: if (isupper(*xp)) *xp = tolower(*xp); ! 1526: xp++; s++; ! 1527: } ! 1528: *xp = NUL; /* Terminate it! */ ! 1529: s = xq; /* Move search pointer to it. */ ! 1530: } ! 1531: xx = inpbp; /* Current INPUT buffer pointer */ ! 1532: do { ! 1533: c = *xx++; /* Get next character */ ! 1534: if (xx >= inpbuf + INPBUFSIZ) xx = inpbuf; /* Wrap around */ ! 1535: if (!incase) { /* Ignore alphabetic case? */ ! 1536: if (isupper(c)) c = tolower(c); /* Yes */ ! 1537: } ! 1538: debug(F000,"doreinp char","",c); ! 1539: debug(F000,"compare char","",s[i]); ! 1540: if (c == s[i]) i++; else i = 0; /* Check for match */ ! 1541: if (s[i] == '\0') { /* Matched all the way to end? */ ! 1542: x = 1; /* Yes, */ ! 1543: break; /* done. */ ! 1544: } ! 1545: } while (xx != inpbp); /* Until back where we started. */ ! 1546: ! 1547: if (!incase) if (xq) free(xq); /* Free this if it was malloc'd. */ ! 1548: return(x); /* Return search result. */ ! 1549: } ! 1550: #ifndef NOSPL ! 1551: ! 1552: #endif /* NOSPL */ ! 1553: /* X X S T R I N G -- Interpret strings containing backslash escapes */ ! 1554: ! 1555: /* ! 1556: Copies result to new string. ! 1557: strips enclosing braces or doublequotes. ! 1558: interprets backslash escapes. ! 1559: returns 0 on success, nonzero on failure. ! 1560: tries to be compatible with MS-DOS Kermit. ! 1561: ! 1562: Syntax of input string: ! 1563: string = chars | "chars" | {chars} ! 1564: chars = (c*e*)* ! 1565: where c = any printable character, ascii 32-126 ! 1566: and e = a backslash escape ! 1567: and * means 0 or more repetitions of preceding quantity ! 1568: backslash escape = \operand ! 1569: operand = {number} | number | fname(operand) | v(name) | $(name) | m(name) ! 1570: number = [r]n[n[n]]], i.e. an optional radix code followed by 1-3 digits ! 1571: radix code is oO (octal), hHxX (hex), dD or none (decimal). ! 1572: */ ! 1573: ! 1574: #ifndef NOFRILLS ! 1575: int ! 1576: yystring(s,s2) char *s; char **s2; { /* Reverse a string */ ! 1577: int x; ! 1578: static char *new; ! 1579: new = *s2; ! 1580: if (!s || !new) return(-1); /* Watch out for null pointers. */ ! 1581: if ((x = (int)strlen(s)) == 0) { /* Recursion done. */ ! 1582: *new = '\0'; ! 1583: return(0); ! 1584: } ! 1585: x--; /* Otherwise, call self */ ! 1586: *new++ = s[x]; /* to reverse rest of string. */ ! 1587: s[x] = 0; ! 1588: return(yystring(s,&new)); ! 1589: } ! 1590: #endif /* NOFRILLS */ ! 1591: ! 1592: #define FNVALL 1000 ! 1593: char fnval[FNVALL+2]; /* Return value */ ! 1594: ! 1595: char * /* Evaluate builtin function */ ! 1596: fneval(fn,argp,argn) char *fn, *argp[]; int argn; { ! 1597: int i, j, k, len1, len2, n, x, y; ! 1598: char *bp[FNARGS]; /* Pointers to malloc'd strings */ ! 1599: char *p, *s; ! 1600: ! 1601: if (!fn) fn = ""; /* Paranoia */ ! 1602: debug(F111,"fneval",fn,argn); ! 1603: debug(F110,"fneval",argp[0],0); ! 1604: y = lookup(fnctab,fn,nfuncs,&x); ! 1605: if (y < 0) /* bad function name */ ! 1606: return(""); /* so value is null */ ! 1607: ! 1608: #ifdef DEBUG ! 1609: if (deblog) { ! 1610: int j; ! 1611: for (j = 0; j < argn; j++) ! 1612: debug(F111,"fneval function arg",argp[j],j); ! 1613: } ! 1614: #endif ! 1615: if (y == FN_LIT) /* literal(arg1) */ ! 1616: return(argp[0] ? argp[0] : ""); /* return a pointer to arg itself */ ! 1617: ! 1618: if (y == FN_CON) { /* Contents of variable, unexpanded. */ ! 1619: char c; ! 1620: if (!(p = argp[0]) || !*p) return(""); ! 1621: if (*p == CMDQ) p++; ! 1622: if ((c = *p) == '%') { /* Scalar variable. */ ! 1623: c = *++p; /* Get ID character. */ ! 1624: p = ""; /* Assume definition is empty */ ! 1625: if (!c) return(p); /* Double paranoia */ ! 1626: if (c >= '0' && c <= '9') { /* Digit for macro arg */ ! 1627: c -= '0'; /* convert character to integer */ ! 1628: if (maclvl < 0) /* Digit variables are global */ ! 1629: p = g_var[c]; /* if no macro is active */ ! 1630: else /* otherwise */ ! 1631: p = m_arg[maclvl][c]; /* they're on the stack */ ! 1632: } else { ! 1633: if (isupper(c)) c -= ('a'-'A'); ! 1634: p = g_var[c]; /* Letter for global variable */ ! 1635: } ! 1636: return(p ? p : ""); ! 1637: } ! 1638: if (c == '&') { /* Array reference. */ ! 1639: int vbi, d; ! 1640: if (arraynam(p,&vbi,&d) < 0) /* Get name and subscript */ ! 1641: return(""); ! 1642: if (chkarray(vbi,d) > 0) { /* Array is declared? */ ! 1643: vbi -= 'a'; /* Convert name to index */ ! 1644: if (a_dim[vbi] >= d) { /* If subscript in range */ ! 1645: char **ap; ! 1646: ap = a_ptr[vbi]; /* get data pointer */ ! 1647: if (ap) { /* and if there is one */ ! 1648: return(ap[d]); /* return what it points to */ ! 1649: } ! 1650: } ! 1651: } ! 1652: return(p ? p : ""); /* Otherwise its enexpanded value. */ ! 1653: } ! 1654: } ! 1655: for (i = 0; i < argn; i++) { /* Not literal, expand the args */ ! 1656: n = 1024; /* allow 1K per expanded arg, yow! */ ! 1657: bp[i] = s = malloc(n); /* get the new space */ ! 1658: if (bp[i] == NULL) { /* handle failure to get space */ ! 1659: for (k = 0; k < i; k++) if (bp[k]) free(bp[k]); ! 1660: debug(F101,"fneval malloc failure, arg","",i); ! 1661: return(""); ! 1662: } ! 1663: p = argp[i] ? argp[i] : ""; ! 1664: if (xxstring(p,&s,&n) < 0) { /* Expand arg into new space */ ! 1665: debug(F101,"fneval xxstring fails, arg","",i); ! 1666: for (k = 0; k <= i; k++) /* Free up previous space on error */ ! 1667: if (bp[k]) free(bp[k]); ! 1668: return(""); /* and return null string. */ ! 1669: } ! 1670: debug(F101,"fneval xxstring n","",n); ! 1671: } ! 1672: #ifdef DEBUG ! 1673: if (deblog) { ! 1674: int j; ! 1675: for (j = 0; j < argn; j++) { ! 1676: debug(F111,"fneval arg post eval",argp[j],j); ! 1677: debug(F111,"fneval evaluated arg",bp[j],j); ! 1678: } ! 1679: } ! 1680: #endif /* DEBUG */ ! 1681: ! 1682: switch (y) { /* Do function on expanded args */ ! 1683: ! 1684: case FN_DEF: ! 1685: k = mlook(mactab,bp[0],nmac); /* def(arg1) - Return a macro def */ ! 1686: p = (k > -1) ? mactab[k].mval : ""; ! 1687: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]); ! 1688: return(p ? p : ""); ! 1689: ! 1690: case FN_EVA: /* eval(arg1) */ ! 1691: p = evala(bp[0]); ! 1692: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]); ! 1693: return(p ? p : ""); ! 1694: ! 1695: case FN_EXE: /* execute(arg1) */ ! 1696: j = (int)strlen(s = bp[0]); /* Length of macro invocation */ ! 1697: p = ""; /* Initialize return value to null */ ! 1698: if (j) { /* If there is a macro to execute */ ! 1699: while (*s == SP) s++,j--; /* strip leading spaces */ ! 1700: p = s; /* remember beginning of macro name */ ! 1701: for (i = 0; i < j; i++) { /* find end of macro name */ ! 1702: if (*s == SP) break; ! 1703: s++; ! 1704: } ! 1705: if (*s == SP) { /* if there was a space after */ ! 1706: *s++ = NUL; /* terminate the macro name */ ! 1707: while (*s == SP) s++; /* skip past any extra spaces */ ! 1708: } else s = ""; /* maybe there are no arguments */ ! 1709: if (p && *p) ! 1710: k = mlook(mactab,p,nmac); /* Look up the macro name */ ! 1711: else k = -1; ! 1712: ! 1713: p = ""; /* Initialize return value */ ! 1714: if (k >= 0) { /* If macro found in table */ ! 1715: if ((j = dodo(k,s)) > 0) { /* Go set it up (like DO cmd) */ ! 1716: if (cmpush() > -1) { /* Push command parser state */ ! 1717: extern int ifc; ! 1718: int ifcsav = ifc; /* Save IF condition (kludge) */ ! 1719: k = parser(1); /* Call parser to execute the macro */ ! 1720: cmpop(); /* Pop command parser */ ! 1721: ifc = ifcsav; /* Restore IF condition */ ! 1722: if (k == 0) { /* No errors, ignore action cmds. */ ! 1723: p = mrval[maclvl+1]; /* If OK, set return value. */ ! 1724: if (p == NULL) p = ""; ! 1725: } ! 1726: } else { /* Can't push any more */ ! 1727: debug(F100,"fexec pushed too deep","",0); ! 1728: printf("\n?\\fexec() too deeply nested\n"); ! 1729: while (cmpop() > -1) ; ! 1730: p = ""; ! 1731: } ! 1732: } ! 1733: } ! 1734: } ! 1735: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]); ! 1736: return(p ? p : ""); ! 1737: ! 1738: case FN_FC: /* File count. */ ! 1739: p = fnval; ! 1740: *p = NUL; ! 1741: if (argn > 0) { ! 1742: k = zxpand(bp[0]); ! 1743: sprintf(fnval,"%d",k); ! 1744: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]); ! 1745: } ! 1746: return(p); ! 1747: ! 1748: case FN_FIL: /* Next file in list. */ ! 1749: p = fnval; /* (no args) */ ! 1750: *p = NUL; ! 1751: znext(p); ! 1752: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]); ! 1753: return(p ? p : ""); ! 1754: ! 1755: case FN_IND: /* index(arg1,arg2) */ ! 1756: if (argn > 1) { /* Only works if we have 2 args */ ! 1757: int start; ! 1758: len1 = (int)strlen(bp[0]); /* length of string to look for */ ! 1759: len2 = (int)strlen(s = bp[1]); /* length of string to look in */ ! 1760: if (len1 < 0) return(""); /* paranoia */ ! 1761: if (len2 < 0) return(""); ! 1762: j = len2 - len1; /* length difference */ ! 1763: start = 0; /* starting position */ ! 1764: if (argn > 2) { ! 1765: if (chknum(bp[2])) { ! 1766: start = atoi(bp[2]) - 1; ! 1767: if (start < 0) start = 0; ! 1768: } ! 1769: } ! 1770: if (j < 0 || start > j) { /* search string is longer */ ! 1771: p = "0"; ! 1772: } else { ! 1773: if (!incase) { /* input case ignore? */ ! 1774: lower(bp[0]); ! 1775: lower(bp[1]); ! 1776: } ! 1777: s = bp[1] + start; /* Point to beginning of target */ ! 1778: p = "0"; ! 1779: for (i = 0; i <= (j - start); i++) { /* Now compare */ ! 1780: if (!strncmp(bp[0],s++,len1)) { ! 1781: sprintf(fnval,"%d",i+1+start); ! 1782: p = fnval; ! 1783: break; ! 1784: } ! 1785: } ! 1786: } ! 1787: } else p = "0"; ! 1788: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]); ! 1789: return(p); ! 1790: ! 1791: case FN_CHR: /* character(arg1) */ ! 1792: if (chknum(bp[0])) { ! 1793: i = atoi(bp[0]) & 255; ! 1794: p = fnval; ! 1795: *p++ = i; ! 1796: *p = NUL; ! 1797: p = fnval; ! 1798: } else p = ""; ! 1799: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]); ! 1800: return(p); ! 1801: ! 1802: case FN_LEN: /* length(arg1) */ ! 1803: p = fnval; ! 1804: sprintf(p,"%d",(int)strlen(bp[0])); ! 1805: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]); ! 1806: return(p); ! 1807: ! 1808: case FN_LOW: /* lower(arg1) */ ! 1809: s = bp[0]; ! 1810: p = fnval; ! 1811: ! 1812: while (*s) { ! 1813: if (isupper(*s)) ! 1814: *p = tolower(*s); ! 1815: else ! 1816: *p = *s; ! 1817: p++; s++; ! 1818: } ! 1819: *p = NUL; ! 1820: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]); ! 1821: p = fnval; ! 1822: return(p); ! 1823: ! 1824: case FN_MAX: /* max(arg1,arg2) */ ! 1825: case FN_MIN: /* min(arg1,arg2) */ ! 1826: case FN_MOD: /* mod(arg1,arg2) */ ! 1827: if (chknum(bp[0]) && chknum(bp[1])) { ! 1828: i = atoi(bp[0]); ! 1829: j = atoi(bp[1]); ! 1830: switch (y) { ! 1831: case FN_MAX: ! 1832: if (j < i) j = i; ! 1833: break; ! 1834: case FN_MIN: ! 1835: if (j > i) j = i; ! 1836: break; ! 1837: case FN_MOD: ! 1838: j = i % j; ! 1839: break; ! 1840: } ! 1841: p = fnval; ! 1842: sprintf(p,"%d",j); ! 1843: } else p = ""; ! 1844: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]); ! 1845: return(p); ! 1846: ! 1847: case FN_SUB: /* substr(arg1,arg2,arg3) */ ! 1848: if (((argn > 1) && (int)strlen(bp[1]) && !rdigits(bp[1])) || ! 1849: ((argn > 2) && (int)strlen(bp[2]) && !rdigits(bp[2]))) { ! 1850: p = ""; /* if either, return null */ ! 1851: } else { ! 1852: p = fnval; /* pointer to result */ ! 1853: j = (argn > 1) ? atoi(bp[1]) : 1; /* start position */ ! 1854: k = (argn > 2) ? atoi(bp[2]) : 1023; /* length */ ! 1855: if (k > 0 && j <= (int)strlen(bp[0])) { /* if start pos in range */ ! 1856: s = bp[0]+j-1; /* point to source string */ ! 1857: for (i = 0; (i < k) && (*p++ = *s++); i++) ; /* copy */ ! 1858: } ! 1859: *p = NUL; /* terminate the result */ ! 1860: p = fnval; /* and point to it. */ ! 1861: } ! 1862: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]); /* Free temp mem */ ! 1863: return(p); ! 1864: ! 1865: case FN_UPP: /* upper(arg1) */ ! 1866: s = bp[0]; ! 1867: p = fnval; ! 1868: while (*s) { ! 1869: if (islower(*s)) ! 1870: *p = toupper(*s); ! 1871: else ! 1872: *p = *s; ! 1873: p++; s++; ! 1874: } ! 1875: *p = NUL; ! 1876: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]); ! 1877: p = fnval; ! 1878: return(p); ! 1879: ! 1880: case FN_REP: /* Repeat */ ! 1881: p = ""; /* Return value */ ! 1882: if (chknum(bp[1])) { /* Repeat count */ ! 1883: n = atoi(bp[1]); ! 1884: if (n > 0) { /* Make n copies */ ! 1885: p = fnval; ! 1886: *p = '\0'; ! 1887: k = (int)strlen(bp[0]); /* Make sure string has some length */ ! 1888: if (k > 0) { ! 1889: for (i = 0; i < n; i++) { ! 1890: s = bp[0]; ! 1891: for (j = 0; j < k; j++) { ! 1892: if ((p - fnval) >= FNVALL) { /* Protect against */ ! 1893: p = ""; /* core dumps... */ ! 1894: break; ! 1895: } else *p++ = *s++; ! 1896: } ! 1897: } ! 1898: } ! 1899: } ! 1900: } ! 1901: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]); ! 1902: p = fnval; ! 1903: return(p); ! 1904: ! 1905: #ifndef NOFRILLS ! 1906: case FN_REV: ! 1907: p = fnval; ! 1908: yystring(bp[0],&p); ! 1909: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]); ! 1910: return(p); ! 1911: #endif /* NOFRILLS */ ! 1912: ! 1913: case FN_RPA: /* RPAD and LPAD */ ! 1914: case FN_LPA: ! 1915: *fnval = NUL; /* Return value */ ! 1916: if (argn == 1) { /* If a number wasn't given */ ! 1917: p = fnval; /* just return the original string */ ! 1918: strncpy(p,bp[0],FNVALL); ! 1919: } else if (chknum(bp[1])) { /* Repeat count */ ! 1920: char pc; ! 1921: n = atoi(bp[1]); ! 1922: if (n >= 0) { /* Pad it out */ ! 1923: p = fnval; ! 1924: k = (int)strlen(bp[0]); /* Length of string to be padded */ ! 1925: pc = (argn < 3) ? SP : *bp[2]; /* Padding character */ ! 1926: if (n > FNVALL) n = FNVALL-1; /* protect against overruns */ ! 1927: if (k > FNVALL) k = FNVALL-1; /* and silly args. */ ! 1928: if (k > n) k = n; ! 1929: if (y == FN_RPA) { /* RPAD */ ! 1930: strncpy(p,bp[0],k); ! 1931: p += k; ! 1932: for (i = k; i < n; i++) ! 1933: *p++ = pc; ! 1934: } else { /* LPAD */ ! 1935: n -= k; ! 1936: for (i = 0; i < n; i++) ! 1937: *p++ = pc; ! 1938: strncpy(p,bp[0],k); ! 1939: p += k; ! 1940: } ! 1941: *p = NUL; ! 1942: } ! 1943: } ! 1944: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]); ! 1945: p = fnval; ! 1946: return(p); ! 1947: ! 1948: default: ! 1949: return(""); ! 1950: } ! 1951: } ! 1952: #endif /* NOSPL */ ! 1953: ! 1954: #ifndef NOSPL ! 1955: ! 1956: char * /* Evaluate builtin variable */ ! 1957: nvlook(s) char *s; { ! 1958: int x, y; ! 1959: long z; ! 1960: char *p; ! 1961: ! 1962: x = 30; ! 1963: p = vvbuf; ! 1964: if (xxstring(s,&p,&x) < 0) { ! 1965: y = -1; ! 1966: } else { ! 1967: s = vvbuf; ! 1968: if ((y = lookup(vartab,s,nvars,&x)) < 0) return(NULL); ! 1969: } ! 1970: switch (y) { ! 1971: case VN_ARGC: /* ARGC */ ! 1972: sprintf(vvbuf,"%d",macargc[maclvl]); ! 1973: return(vvbuf); ! 1974: ! 1975: case VN_ARGS: /* ARGS */ ! 1976: sprintf(vvbuf,"%d",xargs); ! 1977: return(vvbuf); ! 1978: ! 1979: case VN_COUN: /* COUNT */ ! 1980: sprintf(vvbuf,"%d",count[cmdlvl]); ! 1981: return(vvbuf); ! 1982: ! 1983: case VN_DATE: /* DATE */ ! 1984: ztime(&p); /* Get "asctime" string */ ! 1985: if (p == NULL || *p == NUL) return(NULL); ! 1986: vvbuf[0] = p[8]; /* dd */ ! 1987: vvbuf[1] = p[9]; ! 1988: vvbuf[2] = SP; ! 1989: vvbuf[3] = p[4]; /* mmm */ ! 1990: vvbuf[4] = p[5]; ! 1991: vvbuf[5] = p[6]; ! 1992: vvbuf[6] = SP; ! 1993: for (x = 20; x < 24; x++) /* yyyy */ ! 1994: vvbuf[x - 13] = p[x]; ! 1995: vvbuf[11] = NUL; ! 1996: return(vvbuf); ! 1997: ! 1998: case VN_NDAT: /* Numeric date */ ! 1999: ztime(&p); /* Get "asctime" string */ ! 2000: if (p == NULL || *p == NUL) return(NULL); ! 2001: for (x = 20; x < 24; x++) /* yyyy */ ! 2002: vvbuf[x - 20] = p[x]; ! 2003: vvbuf[6] = (p[8] == ' ') ? '0' : p[8]; vvbuf[7] = p[9]; /* dd */ ! 2004: for (x = 0; x < 12; x++) /* mm */ ! 2005: if (!strncmp(p+4,months[x],3)) break; ! 2006: if (x == 12) { ! 2007: vvbuf[4] = vvbuf[5] = '?'; ! 2008: } else { ! 2009: x++; ! 2010: vvbuf[4] = (x < 10) ? '0' : '1'; ! 2011: vvbuf[5] = (x % 10) + 48; ! 2012: } ! 2013: vvbuf[8] = NUL; ! 2014: return(vvbuf); ! 2015: ! 2016: case VN_DIRE: /* DIRECTORY */ ! 2017: return(zgtdir()); ! 2018: ! 2019: case VN_FILE: /* filespec */ ! 2020: return(fspec); ! 2021: ! 2022: case VN_HOST: /* host name */ ! 2023: if (*myhost) { /* If known */ ! 2024: return(myhost); /* return it. */ ! 2025: } else { /* Otherwise */ ! 2026: strcpy(vvbuf,"unknown"); /* just say "unknown" */ ! 2027: return(vvbuf); ! 2028: } ! 2029: ! 2030: case VN_SYST: /* System type */ ! 2031: #ifdef UNIX ! 2032: strcpy(vvbuf,"UNIX"); ! 2033: #else ! 2034: #ifdef VMS ! 2035: strcpy(vvbuf,"VMS"); ! 2036: #else ! 2037: #ifdef OSK ! 2038: strcpy(vvbuf,"OS9/68K"); ! 2039: #else ! 2040: #ifdef AMIGA ! 2041: strcpy(vvbuf,"Amiga"); ! 2042: #else ! 2043: #ifdef MAC ! 2044: strcpy(vvbuf,"Macintosh"); ! 2045: #else ! 2046: #ifdef OS2 ! 2047: strcpy(vvbuf,"OS/2"); ! 2048: #else ! 2049: strcpy(vvbuf,"unknown"); ! 2050: #endif /* OS2 */ ! 2051: #endif /* MAC */ ! 2052: #endif /* AMIGA */ ! 2053: #endif /* OSK */ ! 2054: #endif /* VMS */ ! 2055: #endif /* UNIX */ ! 2056: return(vvbuf); ! 2057: ! 2058: case VN_SYSV: /* System herald */ ! 2059: for (x = y = 0; x < VVBUFL; x++) { ! 2060: if (ckxsys[x] == SP && y == 0) continue; ! 2061: vvbuf[y++] = (ckxsys[x] == SP) ? '_' : ckxsys[x]; ! 2062: } ! 2063: vvbuf[y] = NUL; ! 2064: return(vvbuf); ! 2065: ! 2066: case VN_TIME: /* TIME. Assumes that ztime returns */ ! 2067: ztime(&p); /* "Thu Feb 8 12:00:00 1990" */ ! 2068: if (p == NULL || *p == NUL) /* like asctime()! */ ! 2069: return(NULL); ! 2070: for (x = 11; x < 19; x++) /* copy hh:mm:ss */ ! 2071: vvbuf[x - 11] = p[x]; /* to vvbuf */ ! 2072: vvbuf[8] = NUL; /* terminate */ ! 2073: return(vvbuf); /* and return it */ ! 2074: ! 2075: case VN_NTIM: /* Numeric time */ ! 2076: ztime(&p); /* "Thu Feb 8 12:00:00 1990" */ ! 2077: if (p == NULL || *p == NUL) /* like asctime()! */ ! 2078: return(NULL); ! 2079: z = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17); ! 2080: sprintf(vvbuf,"%ld",z); ! 2081: return(vvbuf); ! 2082: ! 2083: #ifdef UNIX ! 2084: case VN_TTYF: /* TTY file descriptor */ ! 2085: sprintf(vvbuf,"%d",ttyfd); ! 2086: return(vvbuf); ! 2087: #endif /* UNIX */ ! 2088: ! 2089: case VN_VERS: /* Numeric Kermit version number */ ! 2090: sprintf(vvbuf,"%ld",vernum); ! 2091: return(vvbuf); ! 2092: ! 2093: case VN_HOME: /* Home directory */ ! 2094: #ifdef UNIX ! 2095: sprintf(vvbuf,"%s/",zhome()); ! 2096: return(vvbuf); ! 2097: #else ! 2098: return(zhome()); ! 2099: #endif /* UNIX */ ! 2100: ! 2101: case VN_IBUF: /* INPUT buffer */ ! 2102: return(inpbuf); ! 2103: ! 2104: case VN_SPEE: { /* Transmission SPEED */ ! 2105: long t; ! 2106: t = ttgspd(); ! 2107: if (t < 0L) ! 2108: sprintf(vvbuf,"unknown"); ! 2109: else ! 2110: sprintf(vvbuf,"%ld",t); ! 2111: return(vvbuf); ! 2112: } ! 2113: case VN_SUCC: /* SUCCESS flag */ ! 2114: sprintf(vvbuf,"%d",(success == 0) ? 1 : 0); ! 2115: return(vvbuf); ! 2116: ! 2117: case VN_LINE: /* LINE */ ! 2118: p = (char *) ttname; ! 2119: return(p); ! 2120: ! 2121: case VN_PROG: /* Program name */ ! 2122: #ifdef MAC ! 2123: return("Mac-Kermit"); ! 2124: #else ! 2125: return("C-Kermit"); ! 2126: #endif /* MAC */ ! 2127: ! 2128: case VN_RET: /* Value of most recent RETURN */ ! 2129: p = mrval[maclvl+1]; ! 2130: if (p == NULL) p = ""; ! 2131: return(p); ! 2132: ! 2133: case VN_FFC: /* Size of most recent file */ ! 2134: sprintf(vvbuf, "%ld", ffc); ! 2135: return(vvbuf); ! 2136: ! 2137: case VN_TFC: /* Size of most recent file group */ ! 2138: sprintf(vvbuf, "%ld", tfc); ! 2139: return(vvbuf); ! 2140: ! 2141: case VN_CPU: /* CPU type */ ! 2142: #ifdef CKCPU ! 2143: return(CKCPU); ! 2144: #else ! 2145: return("unknown"); ! 2146: #endif /* CKCPU */ ! 2147: ! 2148: default: ! 2149: return(NULL); ! 2150: } ! 2151: } ! 2152: #endif /* NOSPL */ ! 2153: ! 2154: /* ! 2155: X X S T R I N G -- Expand variables and backslash codes. ! 2156: ! 2157: int xxtstring(s,&s2,&n); ! 2158: ! 2159: Expands \ escapes via recursive descent. ! 2160: Argument s is a pointer to string to expand (source). ! 2161: Argument s2 is the address of where to put result (destination). ! 2162: Argument n is the length of the destination string (to prevent overruns). ! 2163: Returns -1 on failure, 0 on success, ! 2164: with destination string null-terminated and s2 pointing to the ! 2165: terminating null, so that subsequent characters can be added. ! 2166: */ ! 2167: ! 2168: #define XXDEPLIM 100 /* Recursion depth limit */ ! 2169: ! 2170: int ! 2171: xxstring(s,s2,n) char *s; char **s2; int *n; { ! 2172: int x, /* Current character */ ! 2173: y, /* Worker */ ! 2174: pp, /* Paren level */ ! 2175: argn, /* Function argument counter */ ! 2176: n2, /* Local copy of n */ ! 2177: d, /* Array dimension */ ! 2178: vbi, /* Variable id (integer form) */ ! 2179: argl; /* String argument length */ ! 2180: ! 2181: char vb, /* Variable id (char form) */ ! 2182: *vp, /* Pointer to variable definition */ ! 2183: *new, /* Local pointer to target string */ ! 2184: *p, /* Worker */ ! 2185: *q; /* Worker */ ! 2186: char *r = (char *)0; /* For holding function args */ ! 2187: char *r2 = (char *)0; ! 2188: ! 2189: #ifndef NOSPL ! 2190: char vnambuf[VNAML]; /* Buffer for variable/function name */ ! 2191: char *argp[FNARGS]; /* Pointers to function args */ ! 2192: #endif /* NOSPL */ ! 2193: ! 2194: static int depth = 0; /* Call depth, avoid overflow */ ! 2195: ! 2196: n2 = *n; /* Make local copies of args */ ! 2197: new = *s2; /* for one less level of indirection */ ! 2198: ! 2199: depth++; /* Sink to a new depth */ ! 2200: if (depth > XXDEPLIM) { /* Too deep? */ ! 2201: printf("?definition is circular or too deep\n"); ! 2202: depth = 0; ! 2203: *new = NUL; ! 2204: return(-1); ! 2205: } ! 2206: if (!s || !new) { /* Watch out for null pointers */ ! 2207: depth = 0; ! 2208: *new = NUL; ! 2209: return(-1); ! 2210: } ! 2211: argl = (int)strlen(s); /* Get length of source string */ ! 2212: debug(F111,"xxstring",s,argl); ! 2213: if (argl < 0) { /* Watch out for garbage */ ! 2214: depth = 0; ! 2215: *new = NUL; ! 2216: return(-1); ! 2217: } ! 2218: while ( x = *s ) { /* Loop for all characters */ ! 2219: if (x != CMDQ) { /* Is it the command-quote char? */ ! 2220: *new++ = *s++; /* No, normal char, just copy */ ! 2221: if (n2-- < 0) { /* and count it, careful of overflow */ ! 2222: return(-1); ! 2223: } ! 2224: continue; ! 2225: } ! 2226: ! 2227: /* We have the command-quote character. */ ! 2228: ! 2229: x = *(s+1); /* Get the following character. */ ! 2230: switch (x) { /* Act according to variable type */ ! 2231: #ifndef NOSPL ! 2232: case '%': /* Variable */ ! 2233: s += 2; /* Get the letter or digit */ ! 2234: vb = *s++; /* and move source pointer past it */ ! 2235: vp = NULL; /* Assume definition is empty */ ! 2236: if (vb >= '0' && vb <= '9') { /* Digit for macro arg */ ! 2237: if (maclvl < 0) /* Digit variables are global */ ! 2238: vp = g_var[vb]; /* if no macro is active */ ! 2239: else /* otherwise */ ! 2240: vp = m_arg[maclvl][vb - '0']; /* they're on the stack */ ! 2241: } else { ! 2242: if (isupper(vb)) vb -= ('a'-'A'); ! 2243: vp = g_var[vb]; /* Letter for global variable */ ! 2244: } ! 2245: if (vp) { /* If definition not empty */ ! 2246: if (xxstring(vp,&new,&n2) < 0) { /* call self to evaluate it */ ! 2247: return(-1); /* Pass along failure */ ! 2248: } ! 2249: } ! 2250: break; ! 2251: case '&': /* An array reference */ ! 2252: if (arraynam(s,&vbi,&d) < 0) { /* Get name and subscript */ ! 2253: return(-1); ! 2254: } ! 2255: pp = 0; /* Bracket counter */ ! 2256: while (*s) { /* Advance source pointer */ ! 2257: if (*s == '[') pp++; ! 2258: if (*s == ']' && --pp == 0) break; ! 2259: s++; ! 2260: } ! 2261: if (*s == ']') s++; /* past the closing bracket. */ ! 2262: if (chkarray(vbi,d) > 0) { /* Array is declared? */ ! 2263: vbi -= 96; /* Convert name to index */ ! 2264: if (a_dim[vbi] >= d) { /* If subscript in range */ ! 2265: char **ap; ! 2266: ap = a_ptr[vbi]; /* get data pointer */ ! 2267: if (ap) { /* and if there is one */ ! 2268: if (ap[d]) { /* If definition not empty */ ! 2269: if (xxstring(ap[d],&new,&n2) < 0) { /* evaluate */ ! 2270: return(-1); /* Pass along failure */ ! 2271: } ! 2272: } ! 2273: } ! 2274: } ! 2275: } ! 2276: break; ! 2277: ! 2278: case 'F': /* A builtin function */ ! 2279: case 'f': ! 2280: q = vnambuf; /* Copy the name */ ! 2281: y = 0; /* into a separate buffer */ ! 2282: s+=2; /* point past 'F' */ ! 2283: while (y++ < VNAML) { ! 2284: if (*s == '(') { s++; break; } /* Look for open paren */ ! 2285: if ((*q = *s) == NUL) break; /* or end of string */ ! 2286: s++; q++; ! 2287: } ! 2288: *q = NUL; /* Terminate function name */ ! 2289: if (y >= VNAML) { /* Handle pathological case */ ! 2290: while (*s && (*s != '(')) /* of very long string entered */ ! 2291: s++; /* as function name. */ ! 2292: if (*s == ')') s++; /* Skip past it. */ ! 2293: } ! 2294: r = r2 = malloc(argl+2); /* And make a place to copy args */ ! 2295: debug(F101,"xxstring r2","",r2); ! 2296: if (!r2) { /* Watch out for malloc failure */ ! 2297: depth = 0; ! 2298: *new = NUL; ! 2299: return(-1); ! 2300: } ! 2301: argn = 0; /* Argument counter */ ! 2302: argp[argn++] = r; /* Point to first argument */ ! 2303: y = 0; /* Completion flag */ ! 2304: pp = 1; /* Paren level (already have one). */ ! 2305: while (*r = *s) { /* Copy each argument, char by char. */ ! 2306: if (*r == '(') pp++; /* Count an opening paren. */ ! 2307: if (*r == ')') { /* Closing paren, count it. */ ! 2308: if (--pp == 0) { /* Final one? */ ! 2309: *r = NUL; /* Make it a terminating null */ ! 2310: s++; ! 2311: y = 1; /* Flag we've got all the args */ ! 2312: break; ! 2313: } ! 2314: } ! 2315: if (*r == ',') { /* Comma */ ! 2316: if (pp == 1) { /* If not within ()'s, */ ! 2317: *r = NUL; /* new arg, skip past it, */ ! 2318: argp[argn++] = r+1; /* point to new arg. */ ! 2319: if (argn == FNARGS) /* Too many args */ ! 2320: break; ! 2321: } /* Otherwise just skip past */ ! 2322: } ! 2323: s++; r++; /* Advance pointers */ ! 2324: } ! 2325: debug(F110,"xxstring function name",vnambuf,0); ! 2326: if (!y) { /* If we didn't find closing paren */ ! 2327: debug(F101,"xxstring r2 before free","",r2); ! 2328: if (r2) free(r2); /* free the temporary storage */ ! 2329: return(-1); /* and return failure. */ ! 2330: } ! 2331: #ifdef DEBUG ! 2332: if (deblog) ! 2333: for (y = 0; y < argn; y++) ! 2334: debug(F111,"xxstring function arg",argp[y],y); ! 2335: #endif /* DEBUG */ ! 2336: vp = fneval(vnambuf,argp,argn); /* Evaluate the function. */ ! 2337: if (vp) { /* If definition not empty */ ! 2338: while (*new++ = *vp++) /* copy it to output string */ ! 2339: if (n2-- < 0) return(-1); /* mindful of overflow */ ! 2340: new--; /* Back up over terminating null */ ! 2341: n2++; /* to allow for further deposits. */ ! 2342: } ! 2343: if (r2) { ! 2344: debug(F101,"xxstring freeing r2","",r2); ! 2345: free(r2); /* Now free the temporary storage */ ! 2346: r2 = NULL; ! 2347: } ! 2348: break; ! 2349: case '$': /* An environment variable */ ! 2350: case 'V': /* Or a named builtin variable. */ ! 2351: case 'v': ! 2352: case 'M': /* Or a macro = long variable */ ! 2353: case 'm': ! 2354: p = s+2; /* $/V/M must be followed by (name) */ ! 2355: if (*p != '(') { /* as in \$(HOME) or \V(count) */ ! 2356: *new++ = *s++; /* If not, just copy it */ ! 2357: if (n2-- < 0) { ! 2358: return(-1); ! 2359: } ! 2360: break; ! 2361: } ! 2362: p++; /* Point to 1st char of name */ ! 2363: q = vnambuf; /* Copy the name */ ! 2364: y = 0; /* into a separate buffer */ ! 2365: while (y++ < VNAML) { /* Watch out for name too long */ ! 2366: if (*p == ')') { /* Name properly terminated with ')' */ ! 2367: p++; /* Move source pointer past ')' */ ! 2368: break; ! 2369: } ! 2370: if ((*q = *p) == NUL) /* String ends before ')' */ ! 2371: break; ! 2372: p++; q++; /* Advance pointers */ ! 2373: } ! 2374: *q = NUL; /* Terminate the variable name */ ! 2375: if (y >= VNAML) { /* Handle pathological case */ ! 2376: while (*p && (*p != ')')) /* of very long string entered */ ! 2377: p++; /* as variable name. */ ! 2378: if (*p == ')') p++; /* Skip ahead to the end of it. */ ! 2379: } ! 2380: s = p; /* Adjust global source pointer */ ! 2381: debug(F110,"xxstring vname",vnambuf,0); ! 2382: if (x == '$') { /* Look up its value */ ! 2383: vp = getenv(vnambuf); /* This way for environment variable */ ! 2384: } else if (x == 'm' || x == 'M') { /* or this way for macro */ ! 2385: y = mlook(mactab,vnambuf,nmac); /* contents (= long variable */ ! 2386: vp = (y > -1) ? mactab[y].mval : ""; /* name)... */ ! 2387: } else { /* or */ ! 2388: vp = nvlook(vnambuf); /* this way for builtin variable */ ! 2389: } ! 2390: if (vp) { /* If definition not empty */ ! 2391: while (*new++ = *vp++) /* copy it to output string. */ ! 2392: if (n2-- < 0) { ! 2393: return(-1); ! 2394: } ! 2395: new--; /* Back up over terminating null */ ! 2396: n2++; /* to allow for further deposits. */ ! 2397: } ! 2398: break; ! 2399: #endif /* NOSPL */ /* Handle \nnn even if NOSPL. */ ! 2400: default: /* Maybe it's a backslash code */ ! 2401: y = xxesc(&s); /* Go interpret it */ ! 2402: if (y < 0) { /* Upon failure */ ! 2403: *new++ = x; /* Just quote the next character */ ! 2404: s += 2; /* Move past the pair */ ! 2405: n2 -= 2; ! 2406: if (n2 < 0) { ! 2407: return(-1); ! 2408: } ! 2409: continue; /* and go back for more */ ! 2410: } else { ! 2411: *new++ = y; /* else deposit interpreted value */ ! 2412: if (n2-- < 0) { ! 2413: return(-1); ! 2414: } ! 2415: } ! 2416: } ! 2417: } ! 2418: *new = NUL; /* Terminate the new string */ ! 2419: depth--; /* Adjust stack depth gauge */ ! 2420: *s2 = new; /* Copy results back into */ ! 2421: *n = n2; /* the argument addresses */ ! 2422: return(0); /* and return. */ ! 2423: } ! 2424: ! 2425: /* X X S T R C M P -- Caseless string comparison */ ! 2426: ! 2427: int ! 2428: xxstrcmp(s1,s2,n) char *s1, *s2; int n; { /* Caseless string comparison. */ ! 2429: char t1, t2; /* 1 if s1 > t1 */ ! 2430: int n1, n2; /* 0 if s1 = s2 */ ! 2431: /* -1 if s1 < t1 */ ! 2432: if (!s1) s1 = ""; /* Get lengths and watch out */ ! 2433: n1 = (int)strlen(s1); /* for null pointers. */ ! 2434: if (!s2) s2 = ""; ! 2435: n2 = (int)strlen(s2); ! 2436: ! 2437: if (n > n1) n = n1; ! 2438: if (n > n2) n = n2; ! 2439: ! 2440: while (n--) { ! 2441: t1 = *s1++; /* Get next character from each. */ ! 2442: if (isupper(t1)) t1 = tolower(t1); ! 2443: t2 = *s2++; ! 2444: if (isupper(t2)) t2 = tolower(t2); ! 2445: if (t1 < t2) return(-1); /* s1 < s2 */ ! 2446: if (t1 > t2) return(1); /* s1 > s2 */ ! 2447: } ! 2448: return(0); /* They're equal */ ! 2449: } ! 2450: ! 2451: #endif /* NOICP */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.