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

unix.superglobalmegacorp.com

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