Annotation of coherent/g/usr/bin/ckermit/ckuus4.c, revision 1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.