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

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

unix.superglobalmegacorp.com

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