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