Annotation of coherent/e/bin/cku179/ckuus5.c, revision 1.1.1.1

1.1       root        1: #ifndef NOICP
                      2: 
                      3: /*  C K U U S 5 --  "User Interface" for Unix Kermit, part 5  */
                      4:  
                      5: /*
                      6:  Author: Frank da Cruz ([email protected], [email protected]),
                      7:  Columbia University Center for Computing Activities.
                      8:  First released January 1985.
                      9:  Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New 
                     10:  York.  Permission is granted to any individual or institution to use, copy, or
                     11:  redistribute this software so long as it is not sold for profit, provided this
                     12:  copyright notice is retained.
                     13: */
                     14: 
                     15: /* Includes */
                     16: 
                     17: #include "ckcdeb.h"
                     18: #include "ckcasc.h"
                     19: #include "ckcker.h"
                     20: #include "ckuusr.h"
                     21: #include "ckcnet.h"
                     22: #ifndef NOCSETS
                     23: #include "ckcxla.h"
                     24: #endif /* NOCSETS */
                     25: #ifdef MAC
                     26: #include "ckmasm.h"
                     27: #endif /* MAC */
                     28: 
                     29: #ifdef FT18
                     30: #define isxdigit(c) isdigit(c)
                     31: #endif /* FT18 */
                     32: 
                     33: #ifdef MAC                             /* Internal MAC file routines */
                     34: #define feof mac_feof
                     35: #define rewind mac_rewind
                     36: #define fgets mac_fgets
                     37: #define fopen mac_fopen
                     38: #define fclose mac_fclose
                     39: 
                     40: int mac_feof();
                     41: void mac_rewind();
                     42: char *mac_fgets();
                     43: FILE *mac_fopen();
                     44: int mac_fclose();
                     45: #endif /* MAC */
                     46: 
                     47: /* External variables */
                     48: 
                     49: extern int local, backgrd, bgset, sosi, suspend,
                     50:   displa, binary, deblog, escape, xargs, flow, cmdmsk,
                     51:   duplex, ckxech, pktlog, seslog, tralog, what,
                     52:   keep, warn, quiet, tlevel, cwdf, nfuncs,
                     53:   mdmtyp, zincnt, cmask, rcflag, success, xitsta, pflag, lf_opts, tnlm;
                     54: 
                     55: #ifndef NOFRILLS
                     56: extern int en_cwd, en_del, en_dir, en_fin, en_bye,
                     57:   en_get, en_hos, en_sen, en_set, en_spa, en_typ, en_who;
                     58: #endif /* NOFRILLS */
                     59: extern long vernum;
                     60: extern int srvtim, srvdis, incase, inecho, intime, nvars, verwho;
                     61: extern char *protv, *fnsv, *cmdv, *userv, *ckxv, *ckzv, *ckzsys, *xlav,
                     62:  *cknetv, *clcmds;
                     63: extern char *connv, *dialv, *loginv, *nvlook();
                     64: 
                     65: #ifndef NOSCRIPT
                     66: extern int secho;
                     67: #endif /* NOSCRIPT */
                     68: 
                     69: #ifndef NODIAL
                     70: extern int nmdm;
                     71: extern struct keytab mdmtab[];
                     72: #endif /* NODIAL */
                     73: 
                     74: #ifdef NETCONN
                     75: extern int tn_init, network, ttnproto;
                     76: #endif /* NETCONN */
                     77: 
                     78: #ifdef OS2PM
                     79: extern int Term_mode;
                     80: #endif /* OS2 */
                     81: 
                     82: #ifndef NOCSETS
                     83: extern int language, nfilc, tcsr, tcsl;
                     84: extern struct keytab fcstab[];
                     85: #endif /* NOCSETS */
                     86: 
                     87: extern int atcapr,
                     88:   atenci, atenco, atdati, atdato, atleni, atleno, atblki, atblko,
                     89:   attypi, attypo, atsidi, atsido, atsysi, atsyso, atdisi, atdiso; 
                     90: 
                     91: extern long speed;
                     92: 
                     93: extern char *DIRCMD, *PWDCMD, *DELCMD;
                     94: #ifndef NOXMIT
                     95: extern int xmitf, xmitl, xmitp, xmitx, xmits, xmitw;
                     96: extern char xmitbuf[];
                     97: #endif /* NOXMIT */
                     98: 
                     99: extern char **xargv, *versio, *ckxsys, *dftty, *cmarg, *homdir, *lp;
                    100: 
                    101: #ifdef DCMDBUF
                    102: extern char *cmdbuf, *atmbuf;          /* Command buffers */
                    103: #ifndef NOSPL
                    104: extern char *savbuf;                   /* Command buffers */
                    105: #endif /* NOSPL */
                    106: #else
                    107: extern char cmdbuf[], atmbuf[];                /* Command buffers */
                    108: #ifndef NOSPL
                    109: extern char savbuf[];                  /* Command buffers */
                    110: #endif /* NOSPL */
                    111: #endif /* DCMDBUF */
                    112: 
                    113: extern char toktab[], ttname[], psave[];
                    114: extern CHAR sstate;
                    115: extern int cmflgs, techo, terror, repars, ncmd;
                    116: extern struct keytab cmdtab[];
                    117: 
                    118: #ifndef MAC
                    119: #ifndef NOSETKEY
                    120: KEY *keymap;
                    121: MACRO *macrotab;
                    122: #endif /* NOSETKEY */
                    123: #endif /* MAC */
                    124: 
                    125: #ifndef NOSPL
                    126: extern struct mtab *mactab;
                    127: extern struct keytab vartab[], fnctab[];
                    128: extern int cmdlvl, maclvl, nmac, mecho, merror;
                    129: #endif /* NOSPL */
                    130: 
                    131: FILE *tfile[MAXTAKE];                  /* TAKE file stack */
                    132: 
                    133: #ifndef NOSPL
                    134: /* Local declarations */
                    135: 
                    136: int nulcmd = 0;                        /* Flag for next cmd to be ignored */
                    137: 
                    138: /* Definitions for built-in macros */
                    139: 
                    140: /* First, the single line macros, installed with addmac()... */
                    141: 
                    142: /* IBM-LINEMODE macro */
                    143: char *m_ibm = "set parity mark, set dupl half, set handsh xon, set flow none";
                    144: 
                    145: /* FATAL macro */
                    146: char *m_fat = "if def \\%1 echo \\%1, stop";
                    147: 
                    148: #ifdef COMMENT
                    149: /*
                    150:   Long macro definitions were formerly done like this.  But some compilers
                    151:   cannot handle continued string constants, others cannot handle string
                    152:   constants that are this long.  So these definitions have been broken up
                    153:   into pieces and put into arrays, see below.
                    154: */
                    155: char *m_forx = "if def _floop ass \\%9 \\fdef(_floop),else def \\%9,\
                    156: ass _floop { _getargs,\
                    157: define \\\\\\%1 \\%2,:top,if \\%5 \\\\\\%1 \\%3 goto bot,\
                    158: \\%6,:inc, incr \\\\\\%1 \\%4,goto top,:bot,_putargs,return},\
                    159: def break goto bot, def continue goto inc,\
                    160: do _floop \\%1 \\%2 \\%3 \\%4 { \\%5 },assign _floop \\fcont(\\%9)";
                    161: 
                    162: char *m_while = "if def _wloop ass \\%9 \\fdef(_wloop),\
                    163: ass _wloop {_getargs,:wtest,\\%1,\\%2,goto wtest,:wbot,_putargs,return},\
                    164: def break goto wbot, def continue goto wtest,\
                    165: do _wloop,assign _wloop \\fcont(\\%9)";
                    166: 
                    167: char *m_xif = "ass \\%9 \\fdef(_ify),ass _ify {_getargs, \\%1, _putargs},\
                    168: do _ify,ass _ify \\fcont(\\%9)";
                    169: #endif /* COMMENT */
                    170: 
                    171: /* Now the multiline macros, defined with addmmac()... */
                    172: 
                    173: /* FOR macro */
                    174: char *for_def[] = { "if def _floop ass \\%9 \\fdef(_floop),else def \\%9,",
                    175: "ass _floop { _getargs,",
                    176: "define \\\\\\%1 \\%2,:top,if \\%5 \\\\\\%1 \\%3 goto bot,",
                    177: "\\%6,:inc, incr \\\\\\%1 \\%4,goto top,:bot,_putargs,return},",
                    178: "def break goto bot, def continue goto inc,",
                    179: "do _floop \\%1 \\%2 \\%3 \\%4 { \\%5 },assign _floop \\fcont(\\%9)",
                    180: ""};
                    181: 
                    182: /* WHILE macro */
                    183: char *whil_def[] = { "if def _wloop ass \\%9 \\fdef(_wloop),",
                    184: "ass _wloop {_getargs,:wtest,\\%1,\\%2,goto wtest,:wbot,_putargs,return},",
                    185: "def break goto wbot, def continue goto wtest,",
                    186: "do _wloop,assign _wloop \\fcont(\\%9)",
                    187: ""};
                    188: 
                    189: /* XIF macro */
                    190: char *xif_def[] = {
                    191: "ass \\%9 \\fdef(_ify),ass _ify {_getargs, \\%1, _putargs},",
                    192: "do _ify,ass _ify \\fcont(\\%9)",
                    193: ""};
                    194: 
                    195: /* Variables declared here for use by other ckuus*.c modules */
                    196: /* Space is allocated here to save room in ckuusr.c */
                    197: 
                    198: #ifdef DCMDBUF
                    199: struct cmdptr *cmdstk;
                    200: int *ifcmd, *count, *iftest;
                    201: #else
                    202: struct cmdptr cmdstk[CMDSTKL];
                    203: int ifcmd[CMDSTKL], count[CMDSTKL], iftest[CMDSTKL];
                    204: #endif /* DCMDBUF */
                    205: 
                    206: char *m_arg[MACLEVEL][NARGS];
                    207: char *g_var[GVARS], *macp[MACLEVEL], *mrval[MACLEVEL];
                    208: int macargc[MACLEVEL];
                    209: char *macx[MACLEVEL];
                    210: extern char varnam[];
                    211: 
                    212: char **a_ptr[27];                      /* Array pointers, for arrays a-z */
                    213: int a_dim[27];                         /* Dimensions for each array */
                    214: 
                    215: char inpbuf[INPBUFSIZ];                        /* Buffer for INPUT and REINPUT */
                    216: char vnambuf[VNAML];                   /* Buffer for variable names */
                    217: char *vnp;                             /* Pointer to same */
                    218: char lblbuf[50];                       /* Buffer for labels */
                    219: #endif /* NOSPL */
                    220: 
                    221: #ifdef DCMDBUF
                    222: char *line;                            /* Character buffer for anything */
                    223: #else
                    224: char line[LINBUFSIZ];
                    225: #endif /* DCMDBUF */
                    226: 
                    227: extern char pktfil[],
                    228: #ifdef DEBUG
                    229:   debfil[],
                    230: #endif /* DEBUG */
                    231: #ifdef TLOG
                    232:   trafil[],
                    233: #endif /* TLOG */
                    234:   sesfil[],
                    235:   cmdstr[];
                    236: #ifndef NOFRILLS
                    237: extern int rmailf, rprintf;            /* REMOTE MAIL & PRINT items */
                    238: extern char optbuf[];
                    239: #endif /* NOFRILLS */
                    240: 
                    241: char *homdir;                          /* Pointer to home directory string */
                    242: 
                    243: char tmpbuf[50], *tp;                  /* Temporary buffer */
                    244: char numbuf[20];                       /* Buffer for numeric strings. */
                    245: char kermrc[100];                      /* Name of initialization file */
                    246: int noinit = 0;                                /* Flag for skipping init file */
                    247: 
                    248: #ifndef NOSPL
                    249: _PROTOTYP( static long expon, (long, long) );
                    250: _PROTOTYP( static long gcd, (long, long) );
                    251: _PROTOTYP( static long fact, (long) );
                    252: int                                    /* Initialize macro data structures. */
                    253: macini() {            /* Allocate mactab and preset the first element. */
                    254:     if (!(mactab = (struct mtab *) malloc(sizeof(struct mtab) * MAC_MAX)))
                    255:        return(-1);
                    256:     mactab[0].kwd = NULL;
                    257:     mactab[0].mval = NULL;
                    258:     mactab[0].flgs = 0;
                    259:     return(0);
                    260: }
                    261: #endif /* NOSPL */
                    262: 
                    263: /*  C M D I N I  --  Initialize the interactive command parser  */
                    264:  
                    265: VOID
                    266: cmdini() {
                    267:     int i, x, y, z;
                    268: 
                    269: #ifndef MAC
                    270: #ifndef NOSETKEY                       /* Allocate & initialize the keymap */
                    271:     if (!(keymap = (KEY *) malloc(sizeof(KEY)*KMSIZE)))
                    272:       fatal("cmdini: no memory for keymap");
                    273:     if (!(macrotab = (MACRO *) malloc(sizeof(MACRO)*KMSIZE)))
                    274:       fatal("cmdini: no memory for macrotab");
                    275:     for ( i = 0; i < KMSIZE; i++ ) {
                    276:        keymap[i] = i;
                    277:        macrotab[i] = NULL;
                    278:     }
                    279: #endif /* NOSETKEY */
                    280: #endif /* MAC */
                    281: 
                    282: #ifdef DCMDBUF
                    283:     if (cmsetup() < 0) fatal("Can't allocate command buffers!");
                    284: #ifndef NOSPL
                    285:     if (!(cmdstk = (struct cmdptr *) malloc(sizeof(struct cmdptr)*CMDSTKL)))
                    286:        fatal("cmdini: no memory for cmdstk");
                    287:     if (!(ifcmd = (int *) malloc(sizeof(int)*CMDSTKL)))
                    288:        fatal("cmdini: no memory for ifcmd");
                    289:     if (!(count = (int *) malloc(sizeof(int)*CMDSTKL)))
                    290:        fatal("cmdini: no memory for count");
                    291:     if (!(iftest = (int *) malloc(sizeof(int)*CMDSTKL)))
                    292:        fatal("cmdini: no memory for iftest");
                    293: #endif /* NOSPL */
                    294:     if (!(line = malloc(LINBUFSIZ)))
                    295:        fatal("cmdini: no memory for line");
                    296: #ifdef COMMENT
                    297:     if (!(m_arg = (struct m_arg *) malloc(sizeof(struct m_arg)*MACLEVEL)))
                    298:         fatal("cmdini: no memory for m_arg");
                    299: #endif /* COMMENT */
                    300: #endif /* DCMDBUF */
                    301: 
                    302: #ifndef NOSPL
                    303:     if (macini() < 0) fatal("Can't allocate macro buffers!");
                    304: #endif /* NOSPL */
                    305: 
                    306: #ifdef AMIGA
                    307:     if (tlevel < 0)    
                    308:       concb(escape);
                    309: #endif /* AMIGA */
                    310: 
                    311: #ifndef NOSPL
                    312:     cmdlvl = 0;                                /* Start at command level 0 */
                    313:     cmdstk[cmdlvl].src = CMD_KB;
                    314:     cmdstk[cmdlvl].lvl = 0;
                    315: #endif /* NOSPL */
                    316: 
                    317:     tlevel = -1;                       /* Take file level = keyboard */
                    318: #ifdef MAC 
                    319:     cmsetp("Mac-Kermit>");             /* Set default prompt */
                    320: #else
                    321:     cmsetp("C-Kermit>");               /* Set default prompt */
                    322: #endif /* MAC */
                    323: 
                    324: #ifndef NOSPL
                    325:     initmac();                         /* Initialize macro table */
                    326: /* Add one-line macros */
                    327:     addmac("ibm-linemode",m_ibm);      /* Add built-in macros. */
                    328:     addmac("fatal",m_fat);             /* FATAL macro. */
                    329: /* Add multiline macros */
                    330:     addmmac("_forx",for_def);          /* FOR macro. */
                    331:     addmmac("_xif",xif_def);           /* XIF macro. */
                    332:     addmmac("_while",whil_def);                /* WHILE macro. */
                    333: /* Fill in command line argument vector */
                    334:     sprintf(vnambuf,"\\&@[%d]",xargs);         /* Command line argument vector */
                    335:     y = arraynam(vnambuf,&x,&z);       /* goes in array \&@[] */
                    336:     if (y > -1) {
                    337:        dclarray((char)x,z);            /* Declare the array */
                    338:        for (i = 0; i < xargs; i++) {   /* Fill it */
                    339:            sprintf(vnambuf,"\\&@[%d]",i);
                    340:            addmac(vnambuf,xargv[i]);
                    341:        }
                    342:     }
                    343:     *vnambuf = NUL;
                    344: #endif /* NOSPL */
                    345: 
                    346: /* If skipping init file ('-Y' on Kermit command line), return now. */
                    347: 
                    348:     if (noinit) return;
                    349: 
                    350: /* Look for init file in home or current directory. */
                    351: /* (NOTE - should really use zkermini for this!)    */
                    352:     homdir = zhome();                  /* (===OS2 change===) */
                    353: #ifdef OS2
                    354: /*
                    355:   The -y init file must be fully specified or in the current directory.
                    356:   KERMRC is looked for via INIT, PATH and DPATH in that order.  Finally, our
                    357:   own executable file path is taken and the .EXE suffix is replaced by .INI
                    358:   and this is tried as initialization file.
                    359: */
                    360:     if (rcflag) {
                    361:        strcpy(line, kermrc);
                    362:     } else {
                    363:        _searchenv(kermrc,"INIT",line);
                    364:        if (line[0] == 0)
                    365:          _searchenv(kermrc,"PATH",line);
                    366:        if (line[0] == 0)
                    367:          _searchenv(kermrc,"DPATH",line);
                    368:        if (line[0] == 0) {
                    369:            extern char *_pgmptr;
                    370:            lp = strrchr(_pgmptr, '.');
                    371:            strncpy(line, _pgmptr, lp - _pgmptr);
                    372:            strcpy(line + (lp - _pgmptr), ".ini");
                    373:        }
                    374:     }
                    375:     if ((tfile[0] = fopen(line,"r")) != NULL) {
                    376:         tlevel = 0;
                    377: #ifndef NOSPL
                    378:        cmdlvl++;
                    379:        cmdstk[cmdlvl].src = CMD_TF;
                    380:        cmdstk[cmdlvl].lvl = tlevel;
                    381:        ifcmd[cmdlvl] = 0;
                    382:        iftest[cmdlvl] = 0;
                    383:        count[cmdlvl] = 0;
                    384: #endif /* NOSPL */
                    385:         debug(F110,"init file",line,0);
                    386:     } else {
                    387:         debug(F100,"no init file","",0);
                    388:     }
                    389: #else /* not OS2 */
                    390:     lp = line;
                    391:     lp[0] = '\0';
                    392: #ifdef VMS
                    393:     zkermini(line,LINBUFSIZ,kermrc);
                    394: #else /* not VMS */
                    395:     if (rcflag) {                      /* If init file name from cmd line */
                    396:        strcpy(lp,kermrc);              /* use it */
                    397:     } else {                           /* otherwise */
                    398:        if (homdir) {                   /* look in home directory for it */
                    399:            strcpy(lp,homdir);
                    400:            if (lp[0] == '/') strcat(lp,"/");
                    401:        }
                    402:        strcat(lp,kermrc);              /* and use the default name */
                    403:     }
                    404: #endif /* VMS */
                    405: 
                    406: #ifdef AMIGA
                    407:     reqoff();                          /* disable requestors */
                    408: #endif /* AMIGA */
                    409: 
                    410:     debug(F110,"ini file is",line,0);
                    411:     if ((tfile[0] = fopen(line,"r")) != NULL) {
                    412:        tlevel = 0;
                    413: #ifndef NOSPL
                    414:        cmdlvl++;
                    415:        ifcmd[cmdlvl] = 0;
                    416:        iftest[cmdlvl] = 0;
                    417:        count[cmdlvl] = 0;
                    418:        debug(F101,"open ok","",cmdlvl);
                    419:        cmdstk[cmdlvl].src = CMD_TF;
                    420:        cmdstk[cmdlvl].lvl = tlevel;
                    421: #endif /* NOSPL */
                    422:        debug(F110,"init file",line,0);
                    423:     }
                    424:     if (homdir && (tlevel < 0)) {
                    425:        strcpy(lp,kermrc);
                    426:        if ((tfile[0] = fopen(line,"r")) != NULL) {
                    427:            tlevel = 0;
                    428: #ifndef NOSPL
                    429:            cmdlvl++;
                    430:            cmdstk[cmdlvl].src = CMD_TF;
                    431:            cmdstk[cmdlvl].lvl = tlevel;
                    432:            ifcmd[cmdlvl] = 0;
                    433:            iftest[cmdlvl] = 0;
                    434:            count[cmdlvl] = 0;
                    435: #endif /* NOSPL */
                    436:        }
                    437:     }
                    438: #endif /* OS2 */
                    439: #ifdef AMIGA
                    440:     reqpop();                          /* Restore requestors */
                    441: #endif /* AMIGA */
                    442: }
                    443: 
                    444: /*  P A R S E R  --  Top-level interactive command parser.  */
                    445:  
                    446: /*
                    447:   Call with:
                    448:     m = 0 for normal behavior: keep parsing and executing commands
                    449:           until an action command is parsed, then return with a
                    450:           Kermit start-state as the value of this function.
                    451:     m = 1 to parse only one command, can also be used to call parser()
                    452:           recursively.
                    453:     m = 2 to read but do not execute one command.
                    454:   In all cases, parser() returns:
                    455:     0     if no Kermit protocol action required
                    456:     > 0   with a Kermit protocol start-state.
                    457:     < 0   upon error.
                    458: */
                    459: int
                    460: parser(m) int m; {
                    461:     int y, xx, yy, zz;                 /* Workers */
                    462:     char ic;                           /* Interruption character */
                    463:     int icn;                           /* Interruption character counter */
                    464: #ifndef NOSPL
                    465:     int inlevel;                       /* Level we were called at */
                    466:     int pp;                            /* Paren nesting level */
                    467:     int kp;                            /* Bracket nesting level */
                    468: #endif /* NOSPL */
                    469:     char *cbp;                         /* Command buffer pointer */
                    470:     int cbn;                           /* Command buffer length */
                    471: #ifdef MAC
                    472:     extern char *lfiles;               /* fake extern cast */
                    473: #endif /* MAC */
                    474: 
                    475: #ifdef AMIGA
                    476:     reqres();                  /* restore AmigaDOS requestors */
                    477: #endif /* AMIGA */
                    478: 
                    479:     what = W_COMMAND;          /* Now we're parsing commands. */
                    480: #ifndef NOSPL
                    481:     if (cmdlvl == 0)           /* If at top (interactive) level, */
                    482: #else
                    483:     if (tlevel < 0)
                    484: #endif /* NOSPL */
                    485:       concb((char)escape);     /* put console in cbreak mode. */
                    486: 
                    487: #ifndef NOSPL
                    488:     ifcmd[0] = 0;              /* Command-level related variables */
                    489:     iftest[0] = 0;             /* initialize variables at top level */
                    490:     count[0] = 0;              /* of stack... */
                    491:     inlevel = maclvl;          /* Current macro level */
                    492:     debug(F101,"&parser entry maclvl","",maclvl);
                    493:     debug(F101,"&parser entry inlevel","",inlevel);
                    494: #endif /* NOSPL */
                    495: 
                    496: /*
                    497:  sstate becomes nonzero when a command has been parsed that requires some
                    498:  action from the protocol module.  Any non-protocol actions, such as local
                    499:  directory listing or terminal emulation, are invoked directly from below.
                    500: */
                    501:     if (local && pflag)                        /* Just returned from connect? */
                    502:       printf("\n");
                    503:     sstate = 0;                                /* Start with no start state. */
                    504: #ifndef NOFRILLS
                    505:     rmailf = rprintf = 0;              /* MAIL and PRINT modifiers for SEND */
                    506:     *optbuf = NUL;                     /* MAIL and PRINT options */
                    507: #endif /* NOFRILLS */
                    508:     while (sstate == 0) {              /* Parse cmds until action requested */
                    509:        debug(F100,"top of parse loop","",0);
                    510: 
                    511:     /* Take requested action if there was an error in the previous command */
                    512: 
                    513: #ifndef MAC
                    514:        conint(trap,stptrap);           /* In case we were just fg'd */
                    515:        bgchk();                        /* Check background status */
                    516: #endif /* MAC */
                    517: 
                    518: #ifndef NOSPL                          /* In case we just reached top level */
                    519:        if (cmdlvl == 0) concb((char)escape);
                    520: #else
                    521:        if (tlevel < 0) concb((char)escape);
                    522: #endif /* NOSPL */
                    523: 
                    524: #ifndef NOSPL
                    525:        if (success == 0) {
                    526:            if (cmdstk[cmdlvl].src == CMD_TF && terror) {
                    527:                printf("Command error: take file terminated.");
                    528:                popclvl();
                    529:                if (cmdlvl == 0) return(0);
                    530:            }
                    531:            if (cmdstk[cmdlvl].src == CMD_MD && merror) {
                    532:                printf("Command error: macro terminated.");
                    533:                popclvl();
                    534:                if (m && (maclvl < inlevel))
                    535:                  return((int) sstate);
                    536:            }
                    537:        }
                    538: 
                    539:        nulcmd = (m == 2);
                    540: #endif /* NOSPL */
                    541: 
                    542: #ifdef MAC
                    543:        if ((tlevel == -1) && lfiles)  /* Check for take initiated by menu. */
                    544:            startlfile();
                    545: #endif /* MAC */
                    546: 
                    547:         /* If in TAKE file, check for EOF */
                    548: 
                    549: #ifndef NOSPL
                    550: #ifdef MAC
                    551:        if
                    552: #else
                    553:        while
                    554: #endif /* MAC */
                    555:          ((cmdstk[cmdlvl].src == CMD_TF)  /* If end of take file */
                    556:               && (tlevel > -1)
                    557:               && feof(tfile[tlevel])) {
                    558:            popclvl();                  /* pop command level */
                    559:            cmini(ckxech);              /* and clear the cmd buffer. */
                    560:            if (cmdlvl == 0)            /* Just popped out of all cmd files? */
                    561:              return(0);                /* End of init file or whatever. */
                    562:        }
                    563: #ifdef MAC
                    564:        miniparser(1);
                    565:        if (sstate == 'a') {            /* if cmd-. cancel */
                    566:            debug(F100, "parser: cancel take due to sstate", "", sstate);
                    567:            sstate = '\0';
                    568:            dostop();
                    569:            return(0);                  /* End of init file or whatever. */
                    570:        }
                    571: #endif /*  MAC */
                    572: 
                    573: #else /* NOSPL */
                    574:        if ((tlevel > -1) && feof(tfile[tlevel])) { /* If end of take */
                    575:            popclvl();                  /* Pop up one level. */
                    576:            cmini(ckxech);              /* and clear the cmd buffer. */
                    577:            if (tlevel < 0)             /* Just popped out of cmd files? */
                    578:              return(0);                /* End of init file or whatever. */
                    579:        }
                    580: #endif /* NOSPL */
                    581: 
                    582: #ifndef NOSPL
                    583:         /* If macro, check for interruption and then get next command */
                    584: 
                    585:         if (cmdstk[cmdlvl].src == CMD_MD) { /* Executing a macro? */
                    586:            debug(F100,"parser macro","",0);
                    587:            if (icn = conchk()) {       /* Yes */
                    588:                while (icn--) {         /* User typed something */
                    589:                    ic = coninc(0);
                    590:                    if (ic == CR) {     /* Carriage return? */
                    591:                        printf(" Interrupted...\n");
                    592:                        dostop();
                    593:                    } else {
                    594:                        putchar(BEL);
                    595:                    }
                    596:                }               
                    597:            }
                    598:            debug(F101,"parser maclvl","",maclvl);
                    599:            maclvl = cmdstk[cmdlvl].lvl; /* No interrupt, get current level */
                    600:            cbp = cmdbuf;               /* Copy next cmd to command buffer. */
                    601:            *cbp = NUL;
                    602:            if (*savbuf) {              /* In case then-part of 'if' command */
                    603:                strcpy(cbp,savbuf);     /* was saved, restore it. */
                    604:                *savbuf = '\0';
                    605:            } else {                    /* Else get next cmd from macro def */
                    606:                debug(F111,"macro maclvl", macp[maclvl], maclvl);
                    607:                kp = pp = 0;
                    608:                
                    609:                for (y = 0;             /* copy next macro part */
                    610:                     *macp[maclvl] && y < CMDBL;
                    611:                     y++, cbp++, macp[maclvl]++) {
                    612: 
                    613:                    /* Allow braces around macro def to prevent */
                    614:                     /* commas from being turned to end-of-lines */
                    615:                     /* and also treat any commas within parens  */
                    616:                     /* as text so that multiple-argument functions */
                    617:                     /* won't cause the command to break prematurely. */
                    618: 
                    619:                    *cbp = *macp[maclvl];  /* Get next character */
                    620: 
                    621:                    if (*cbp == '{') kp++; /* Count braces */
                    622:                    if (*cbp == '}') kp--;
                    623:                    if (*cbp == '(') pp++; /* Count parentheses. */
                    624:                    if (*cbp == ')') pp--;
                    625:                    if (*cbp == ',' && pp <= 0 && kp <= 0) {
                    626:                        macp[maclvl]++;
                    627:                        kp = pp = 0;
                    628:                        break;
                    629:                    }
                    630:                }                       /* Reached end. */
                    631:                if (*cmdbuf == NUL) {   /* If nothing was copied, */
                    632:                    popclvl();          /* pop command level. */
                    633:                    debug(F101,"macro level popped","",maclvl);
                    634:                    if (m && (maclvl < inlevel))
                    635:                      return((int) sstate);
                    636:                    else if (!m) continue;
                    637:                } else {                /* otherwise, tack CR onto end */
                    638:                    *cbp++ = CR;        /* NOTE: NOT '\r' !!! */
                    639:                    *cbp = '\0';
                    640:                    if (mecho && pflag)
                    641:                      printf("%s\n",cmdbuf);
                    642:                    debug(F110,"cmdbuf",cmdbuf,0);
                    643:                }
                    644:            }
                    645: 
                    646:         /* If TAKE file, get next line */    
                    647: 
                    648:        } else if (cmdstk[cmdlvl].src == CMD_TF)
                    649: #else
                    650:        if (tlevel > -1)  
                    651: #endif /* NOSPL */
                    652:          {
                    653:            debug(F101,"tlevel","",tlevel);
                    654:            cbp = cmdbuf;               /* Get the next line. */
                    655:            cbn = CMDBL;
                    656:  
                    657: /* Loop to get next command line and all continuation lines from take file. */
                    658:  
                    659: again:
                    660: #ifndef NOSPL
                    661:            if (*savbuf) {              /* In case then-part of 'if' command */
                    662:                strcpy(line,savbuf);    /* was saved, restore it. */
                    663:                *savbuf = '\0';
                    664:            } else
                    665: #endif /* NOSPL */
                    666:              if (fgets(line,cbn,tfile[tlevel]) == NULL) continue;
                    667:            if (icn = conchk()) {
                    668:                while (icn--) {         /* User typed something... */
                    669:                    ic = coninc(0);     /* Look for carriage return */
                    670:                    if (ic == CR) {
                    671:                        printf(" Interrupted...\n");
                    672:                        dostop();
                    673:                    } else putchar(BEL); /* Ignore anything else */
                    674:                }               
                    675:            }
                    676:            lp = line;                  /* Got a line, copy it. */
                    677:            debug(F110,"from TAKE file",line,0);
                    678:            {                           /* Trim trailing whitespace */
                    679:                char c; int i, j;
                    680:                j = (int)strlen(line) - 1; /* Position of line terminator */
                    681:                c = line[j];            /* Value of line terminator */
                    682:                for (i = j - 1; i > -1; i--)
                    683:                  if (line[i] != SP && line[i] != HT) break;
                    684:                line[i+1] = c;          /* Move after last nonblank char */
                    685:                line[i+2] = NUL;        /* Terminate */
                    686:            }
                    687:            while (*cbp++ = *lp++) {
                    688:                if (--cbn < 2) {
                    689:                    printf("?Command too long, maximum length: %d.\n",CMDBL);
                    690:                    return(dostop());
                    691:                }
                    692:            }
                    693:            if (*(cbp - 3) == CMDQ || *(cbp - 3) == '-') { /* Continued? */
                    694:                cbp -= 3;               /* If so, back up pointer, */
                    695:                goto again;             /* go back, get next line. */
                    696:            }
                    697:            untab(cmdbuf);              /* Convert tabs to spaces */
                    698:            if (techo && pflag)         /* "take echo on" */
                    699:              printf("%s",cmdbuf);
                    700: 
                    701:         /* If interactive, get next command from user. */
                    702: 
                    703:        } else {                        /* User types it in. */
                    704:            if (pflag) prompt(xxstring);
                    705:            cmini(ckxech);
                    706:        }
                    707: 
                    708:         /* Now know where next command is coming from. Parse and execute it. */
                    709: 
                    710:        repars = 1;                     /* 1 = command needs parsing */
                    711:        displa = 0;                     /* Assume no file transfer display */
                    712: 
                    713:        while (repars) {                /* Parse this cmd until entered. */
                    714:            debug(F101,"parser top of while loop","",0);
                    715:            cmres();                    /* Reset buffer pointers. */
                    716:            xx = cmkey2(cmdtab,ncmd,"Command","",toktab,xxstring);
                    717:            debug(F101,"top-level cmkey2","",xx);
                    718:            if (xx == -5) {
                    719:                yy = chktok(toktab);
                    720:                debug(F101,"top-level cmkey token","",yy);
                    721:                ungword();
                    722:                switch (yy) {
                    723:                  case '!': xx = XXSHE; break;
                    724:                  case '#': xx = XXCOM; break;
                    725:                  case ';': xx = XXCOM; break;
                    726: #ifndef NOSPL
                    727:                  case ':': xx = XXLBL; break;
                    728: #endif /* NOSPL */
                    729:                   case '@': xx = XXSHE; break;
                    730:                  default: 
                    731:                    printf("\n?Invalid - %s\n",cmdbuf);
                    732:                    xx = -2;
                    733:                }
                    734:            }
                    735: 
                    736: #ifndef NOSPL
                    737:             /* Special handling for IF..ELSE */
                    738: 
                    739:            if (ifcmd[cmdlvl])          /* Count stmts after IF */
                    740:              ifcmd[cmdlvl]++;
                    741:            if (ifcmd[cmdlvl] > 2 && xx != XXELS && xx != XXCOM)
                    742:              ifcmd[cmdlvl] = 0;
                    743: 
                    744:            /* Execute the command and take action based on return code. */
                    745: 
                    746:            if (nulcmd) {               /* Ignoring this command? */
                    747:                xx = XXCOM;             /* Make this command a comment. */
                    748:            }
                    749: #endif /* NOSPL */
                    750: 
                    751:            zz = docmd(xx);     /* Parse rest of command & execute. */
                    752:            debug(F101,"docmd returns","",zz);
                    753: #ifdef MAC
                    754:            if (tlevel > -1) {
                    755:                if (sstate == 'a') {    /* if cmd-. cancel */
                    756:                    debug(F110, "parser: cancel take, sstate:", "a", 0);
                    757:                    sstate = '\0';
                    758:                    dostop();
                    759:                    return(0);          /* End of init file or whatever. */
                    760:                }
                    761:            }
                    762: #endif /* MAC */
                    763:            switch (zz) {
                    764:                case -4:                /* EOF (e.g. on redirected stdin) */
                    765:                    doexit(GOOD_EXIT,xitsta); /* ...exit successfully */
                    766:                case -1:                /* Reparse needed */
                    767:                    repars = 1;         /* Just set reparse flag and  */
                    768:                    continue;
                    769:                case -6:                /* Invalid command given w/no args */
                    770:                case -2:                /* Invalid command given w/args */
                    771: #ifndef NOSPL
                    772:                    /* This is going to be really ugly... */
                    773:                    yy = mlook(mactab,atmbuf,nmac); /* Look in macro table */
                    774:                    if (yy > -1) {                  /* If it's there */
                    775:                        if (zz == -2) {             /* insert "do" */
                    776:                            char *mp;
                    777:                            mp = malloc((int)strlen(cmdbuf) + 5);
                    778:                            if (!mp) {
                    779:                                printf("?malloc error 1\n");
                    780:                                return(-2);
                    781:                            }
                    782:                            sprintf(mp,"do %s ",cmdbuf);
                    783:                            strcpy(cmdbuf,mp);
                    784:                            free(mp);
                    785:                        } else sprintf(cmdbuf,"do %s %c",atmbuf, CR);
                    786:                        if (ifcmd[cmdlvl] == 2) /* This one doesn't count! */
                    787:                          ifcmd[cmdlvl]--;
                    788:                        debug(F111,"stuff cmdbuf",cmdbuf,zz);
                    789:                        repars = 1;     /* go for reparse */
                    790:                        continue;
                    791:                    } else {
                    792:                        char *p;
                    793:                        int n;
                    794:                        p = cmdbuf;
                    795:                        lp = line;     
                    796:                        n = LINBUFSIZ;
                    797:                        if (cmflgs == 0) printf("\n");
                    798:                        if (xxstring(p,&lp,&n) > -1) 
                    799:                          printf("?Invalid: %s\n",line);
                    800:                        else
                    801:                          printf("?Invalid: %s\n",cmdbuf);
                    802:                    } /* (fall thru...) */
                    803: #else
                    804:                    printf("?Invalid: %s\n",cmdbuf);
                    805: #endif /* NOSPL */
                    806: 
                    807:                case -9:                /* Bad, error message already done */
                    808:                    success = 0;
                    809:                    debug(F110,"top-level cmkey failed",cmdbuf,0);
                    810:                    if (pflag == 0)     /* if background, terminate */
                    811:                      fatal("Kermit command error in background execution");
                    812:                    cmini(ckxech);      /* (fall thru) */
                    813: 
                    814:                case -3:                /* Empty command OK at top level */
                    815:                    repars = 0;         /* Don't need to reparse. */
                    816:                    continue;           /* Go back and get another command. */
                    817: 
                    818:                default:                /* Command was successful. */
                    819: #ifndef NOSPL
                    820:                    debug(F101,"parser preparing to continue","",maclvl);
                    821: #endif /* NOSPL */
                    822:                    repars = 0;         /* Don't need to reparse. */
                    823:                    continue;           /* Go back and get another command. */
                    824:                }
                    825:        }
                    826: #ifndef NOSPL
                    827:        debug(F101,"parser breaks out of while loop","",maclvl);
                    828:        if (m && (maclvl < inlevel))  return((int) sstate);
                    829: #endif /* NOSPL */
                    830:     }
                    831: 
                    832: /* Got an action command, return start state. */
                    833:  
                    834: #ifdef COMMENT
                    835:     /* This is done in ckcpro.w instead, no need to do it twice. */
                    836:     /* Interrupts off only if remote */
                    837:     if (!local) connoi();
                    838: #endif /* COMMENT */
                    839:     return((int) sstate);
                    840: }
                    841: 
                    842: #ifndef NOSPL
                    843: /* OUTPUT command */
                    844: 
                    845: int
                    846: #ifdef CK_ANSIC
                    847: xxout(char c)
                    848: #else
                    849: xxout(c) char c; 
                    850: #endif /* CK_ANSIC */
                    851: /* xxout */ {                  /* Function to output a character. */
                    852:     debug(F101,"xxout","",c);
                    853:     if (local)                         /* If in local mode */
                    854:       return(ttoc(c));                 /* then to the external line */
                    855:     else return(conoc(c));             /* otherwise to the console. */
                    856: }
                    857: 
                    858: /* Returns 0 on failure, 1 on success */
                    859: 
                    860: int
                    861: dooutput(s) char *s; {
                    862:     int x, y, quote;
                    863: 
                    864:     if (local) {                       /* Condition external line */
                    865:        y = ttvt(speed,flow);
                    866:        if (y < 0) return(0);
                    867:     }
                    868:     quote = 0;                         /* Initialize backslash (\) quote */
                    869: 
                    870: #ifdef COMMENT
                    871: /* This is done automatically in ttopen() now... */
                    872: #ifdef NETCONN
                    873:     if (network && ttnproto == NP_TELNET) /* If telnet connection, */
                    874:       if (!tn_init++) tn_ini();           /* initialize it if necessary */
                    875: #endif /* NETCONN */
                    876: #endif /* COMMENT */
                    877:     while (x = *s++) {                 /* Loop through the string */
                    878:        y = 0;                          /* Error code, 0 = no error. */
                    879:        if (x == CMDQ) {                /* Look for \b or \B in string */
                    880:             quote = 1;                 /* Got \ */
                    881:            continue;                   /* Get next character */
                    882:        } else if (quote) {             /* This character is quoted */
                    883:            quote = 0;                  /* Turn off quote flag */
                    884:            if (x == 'b' || x == 'B') { /* If \b or \B */
                    885:                debug(F100,"OUTPUT BREAK","",0);
                    886:                ttsndb();               /* send BREAK signal */
                    887:                continue;               /* and not the b or B */
                    888: #ifdef UNIX
                    889:            } else if (x == 'l' || x == 'L') {  /* If \l or \L */
                    890:                debug(F100,"OUTPUT Long BREAK","",0);
                    891:                ttsndlb();              /* send Long BREAK signal */
                    892:                continue;               /* and not the l or L */
                    893: #endif /* UNIX */
                    894:            } else {                    /* if \ not followed by b or B */
                    895:                y = xxout(dopar(CMDQ)); /* output the backslash. */
                    896:            }
                    897:        }
                    898:        y = xxout(dopar((char)x));      /* Output this character */
                    899:        if (y < 0) {
                    900:            printf("output error.\n");
                    901:            return(0);
                    902:        }
                    903:        if (seslog && duplex)
                    904:          if (zchout(ZSFILE,(char)x) < 0) seslog = 0;
                    905:     }
                    906:     return(1);
                    907: }
                    908: #endif /* NOSPL */
                    909: 
                    910: 
                    911: /* Display version herald and initial prompt */
                    912: 
                    913: VOID
                    914: herald() {
                    915:     int x = 0;
                    916:     if (bgset > 0 || (bgset != 0 && backgrd != 0)) x = 1;
                    917:     debug(F101,"herald","",backgrd);
                    918:     if (x == 0)
                    919:       printf("%s,%s\nType ? or HELP for help\n",versio,ckxsys);
                    920: }
                    921: #ifndef NOSPL
                    922: /*  M L O O K  --  Lookup the macro name in the macro table  */
                    923:  
                    924: /*
                    925:  Call this way:  v = mlook(table,word,n);
                    926:  
                    927:    table - a 'struct mtab' table.
                    928:    word  - the target string to look up in the table.
                    929:    n     - the number of elements in the table.
                    930:  
                    931:  The keyword table must be arranged in ascending alphabetical order, and
                    932:  all letters must be lowercase.
                    933:  
                    934:  Returns the table index, 0 or greater, if the name was found, or:
                    935:  
                    936:   -3 if nothing to look up (target was null),
                    937:   -2 if ambiguous,
                    938:   -1 if not found.
                    939:  
                    940:  A match is successful if the target matches a keyword exactly, or if
                    941:  the target is a prefix of exactly one keyword.  It is ambiguous if the
                    942:  target matches two or more keywords from the table.
                    943: */
                    944: int
                    945: mlook(table,cmd,n) struct mtab table[]; char *cmd; int n; {
                    946:  
                    947:     int i, v, cmdlen;
                    948:  
                    949: /* Lowercase & get length of target, if it's null return code -3. */
                    950:  
                    951:     if ((((cmdlen = lower(cmd))) == 0) || (n < 1)) return(-3);
                    952:  
                    953: /* Not null, look it up */
                    954:  
                    955:     for (i = 0; i < n-1; i++) {
                    956:         if (!strcmp(table[i].kwd,cmd) ||
                    957:            ((v = !strncmp(table[i].kwd,cmd,cmdlen)) &&
                    958:              strncmp(table[i+1].kwd,cmd,cmdlen))) {
                    959:                 return(i);
                    960:              }
                    961:         if (v) return(-2);
                    962:     }   
                    963:  
                    964: /* Last (or only) element */
                    965:  
                    966:     if (!strncmp(table[n-1].kwd,cmd,cmdlen)) {
                    967:         return(n-1);
                    968:     } else return(-1);
                    969: }
                    970: 
                    971: /* mxlook is like mlook, but an exact full-length match is required */
                    972: 
                    973: int
                    974: mxlook(table,cmd,n) char *cmd; struct mtab table[]; int n; {
                    975:     int i, cmdlen;
                    976:     if ((((cmdlen = lower(cmd))) == 0) || (n < 1)) return(-3);
                    977:     for (i = 0; i < n; i++)
                    978:       if (((int)strlen(table[i].kwd) == cmdlen) &&
                    979:          (!strncmp(table[i].kwd,cmd,cmdlen))) return(i);
                    980:     return(-1);
                    981: }
                    982: 
                    983: /*
                    984:   This routine is for the benefit of those compilers that can't handle
                    985:   long string constants or continued lines within them.  Long predefined
                    986:   macros like FOR, WHILE, and XIF have their contents broken up into
                    987:   arrays of string pointers.  This routine concatenates them back into a
                    988:   single string again, and then calls the real addmac() routine to enter
                    989:   the definition into the macro table.
                    990: */
                    991: int
                    992: addmmac(nam,s) char *nam, *s[]; {      /* Add a multiline macro definition */
                    993:     int i, x, y; char *p;
                    994:     x = 0;                             /* Length counter */
                    995:     for (i = 0; (y = (int)strlen(s[i])) > 0; i++) { /* Add up total length */
                    996:        debug(F111,"addmmac line",s[i],y);      
                    997:        x += y;
                    998:     }
                    999:     debug(F101,"addmmac lines","",i);
                   1000:     debug(F101,"addmmac loop exit","",y);
                   1001:     debug(F111,"addmmac length",nam,x);
                   1002:     if (x < 0) return(-1);
                   1003: 
                   1004:     p = malloc(x+1);                   /* Allocate space for all of it. */
                   1005:     if (!p) {
                   1006:        printf("?addmmac malloc error: %s\n",nam);
                   1007:        debug(F110,"addmmac malloc error",nam,0);
                   1008:        return(-1);
                   1009:     }
                   1010:     *p = '\0';                         /* Start off with null string. */
                   1011:     for (i = 0; *s[i]; i++)            /* Concatenate them all together. */
                   1012:       strcat(p,s[i]);
                   1013:     y = (int)strlen(p);                        /* Final precaution. */
                   1014:     debug(F111,"addmmac constructed string",p,y);
                   1015:     if (y == x) {
                   1016:        y = addmac(nam,p);              /* Add result to the macro table. */
                   1017:     } else {
                   1018:        debug(F100,"addmmac length mismatch","",0);
                   1019:        printf("\n!addmmac internal error!\n");
                   1020:        y = -1;
                   1021:     }
                   1022:     free(p);                           /* Free the temporary copy. */
                   1023:     return(y); 
                   1024: }
                   1025: 
                   1026: /* Here is the real addmac routine. */
                   1027: 
                   1028: int
                   1029: addmac(nam,def) char *nam, *def; {     /* Add a macro to the macro table */
                   1030:     int i, x, y, z, namlen, deflen;
                   1031:     char *p, c;
                   1032: 
                   1033:     if (!nam) return(-1);
                   1034:     namlen = (int)strlen(nam);         /* Get argument lengths */
                   1035:     debug(F111,"addmac nam",nam,namlen);
                   1036:     if (!def) {                                /* Watch out for null pointer */
                   1037:        deflen = 0;
                   1038:        debug(F111,"addmac def","(null pointer)",deflen);
                   1039:     } else {
                   1040:        deflen = (int)strlen(def);
                   1041:        debug(F111,"addmac def",def,deflen);
                   1042:     }
                   1043:     if (deflen < 0) return(-1);                /* strlen() failure, fail. */
                   1044:     if (namlen < 1) return(-1);                /* No name given, fail. */
                   1045: 
                   1046:     if (*nam == CMDQ) nam++;           /* Backslash quote? */
                   1047:     if (*nam == '%') {                 /* Yes, if it's a variable name, */
                   1048:        delmac(nam);                    /* Delete any old value. */
                   1049:        if (!(c = *(nam + 1))) return(-1); /* Variable name letter or digit */
                   1050:        if (deflen < 1) {               /* Null definition */
                   1051:            p = NULL;                   /* Better not malloc or strcpy! */
                   1052:        } else {                        /* A substantial definition */
                   1053:            p = malloc(deflen + 1);     /* Allocate space for it */
                   1054:            if (!p) {
                   1055:                printf("?addmac malloc error 2\n");
                   1056:                return(-1);
                   1057:            } else strcpy(p,def);       /* Copy definition into new space */
                   1058:        }
                   1059: 
                   1060:        /* Now p points to the definition, or is a null pointer */
                   1061: 
                   1062:        if (p)
                   1063:          debug(F110,"addmac p",p,0);
                   1064:        else
                   1065:          debug(F110,"addmac p","(null pointer)",0);
                   1066: 
                   1067:        if (c >= '0' && c <= '9') {     /* Digit variable */
                   1068:            if (maclvl < 0) {           /* Are we calling or in a macro? */
                   1069:                g_var[c] = p;           /* No, it's a global "top level" one */
                   1070:                debug(F101,"addmac numeric global maclvl","",maclvl);
                   1071:            } else {                    /* Yes, it's a macro argument */
                   1072:                m_arg[maclvl][c - '0'] = p;
                   1073:                debug(F101,"addmac macro arg maclvl","",maclvl);
                   1074:            }
                   1075:        } else {                        /* It's a global variable */
                   1076:            if (c < 33 || c > GVARS) return(-1);
                   1077:            if (isupper(c)) c = tolower(c);
                   1078:            g_var[c] = p;               /* Put pointer in global-var table */
                   1079:            debug(F100,"addmac global","",0);
                   1080:        }
                   1081:        return(0);
                   1082:     } else if (*nam == '&') {          /* An array reference? */
                   1083:        char **q;
                   1084:        if ((y = arraynam(nam,&x,&z)) < 0) /* If syntax is bad */
                   1085:          return(-1);                   /* return -1. */
                   1086:        if (chkarray(x,z) < 0)          /* If array not declared or */
                   1087:          return(-2);                   /* subscript out of range, ret -2 */
                   1088:        delmac(nam);                    /* Delete any current definition. */
                   1089:        x -= 96;                        /* Convert name letter to index. */
                   1090:        if ((q = a_ptr[x]) == NULL)     /* If array not declared, */
                   1091:          return(-3);                   /* return -3. */
                   1092:        if (deflen > 0) {
                   1093:            if ((p = malloc(deflen+1)) == NULL) { /* Allocate space */
                   1094:                printf("addmac macro error 7: %s\n",nam);
                   1095:                return(-4);             /* for new def, return -4 on fail. */
                   1096:            }
                   1097:            strcpy(p,def);              /* Copy definition into new space. */
                   1098:        } else p = NULL;
                   1099:        q[z] = p;                       /* Store pointer to it. */
                   1100:        return(0);                      /* Done. */
                   1101:     } else debug(F110,"addmac macro def",nam,0);
                   1102: 
                   1103: /* Not a macro argument or a variable, so it's a macro definition */
                   1104: 
                   1105:     lower(nam);                                /* Lowercase the name */
                   1106:     delmac(nam);                       /* if it's already there, delete it. */
                   1107:     debug(F111,"addmac table size",nam,nmac);
                   1108:     for (y = 0;                                /* Find the alphabetical slot */
                   1109:         y < MAC_MAX && mactab[y].kwd != NULL && strcmp(nam,mactab[y].kwd) > 0;
                   1110:         y++) ;
                   1111:     if (y == MAC_MAX) {                        /* No more room. */
                   1112:        debug(F101,"addmac table overflow","",y);
                   1113:        return(-1);
                   1114:     } else debug(F111,"addmac position",nam,y);
                   1115:     if (mactab[y].kwd != NULL) {       /* Must insert */
                   1116:        for (i = nmac; i > y; i--) {    /* Move the rest down one slot */
                   1117:            mactab[i].kwd = mactab[i-1].kwd;
                   1118:            mactab[i].mval = mactab[i-1].mval;
                   1119:            mactab[i].flgs = mactab[i-1].flgs;
                   1120:        }
                   1121:     }
                   1122:     p = malloc(namlen + 1);            /* Allocate space for name */
                   1123:     if (!p) {
                   1124:        printf("?addmac malloc error 3: %s\n",nam);
                   1125:        return(-1);
                   1126:     }
                   1127:     strcpy(p,nam);                     /* Copy name into new space */
                   1128:     mactab[y].kwd = p;                 /* Add pointer to table */
                   1129: 
                   1130:     if (deflen > 0) {                  /* Same deal for definition */
                   1131:        p = malloc(deflen + 1);         /* but watch out for null pointer */
                   1132:        if (p == NULL) {
                   1133:            printf("?addmac malloc error 5: %s\n", nam);
                   1134:            free(mactab[y].kwd);
                   1135:            mactab[y].kwd = NULL;
                   1136:            return(-1);
                   1137:        } else strcpy(p,def);           /* Copy the definition */
                   1138:     } else p = NULL;
                   1139:     mactab[y].mval = p;
                   1140:     mactab[y].flgs = 0;
                   1141:     nmac++;                            /* Count this macro */
                   1142:     return(y);
                   1143: }
                   1144: 
                   1145: int
                   1146: delmac(nam) char *nam; {               /* Delete the named macro */
                   1147:     int i, x, z;
                   1148:     char *p, c;
                   1149: 
                   1150:     if (!nam) return(0);               /* Watch out for null pointer */
                   1151:     debug(F110,"delmac nam",nam,0);
                   1152:     if (*nam == CMDQ) nam++;
                   1153:     if (*nam == '%') {                 /* If it's a variable name */
                   1154:        if (!(c = *(nam+1))) return(0); /* Get variable name letter or digit */
                   1155:        p = (char *)0;                  /* Initialize value pointer */
                   1156:        if (maclvl > -1 && c >= '0' && c <= '9') { /* Digit? */
                   1157:            p = m_arg[maclvl][c - '0']; /* Get pointer from macro-arg table */
                   1158:            m_arg[maclvl][c - '0'] = NULL; /* Zero the table pointer */
                   1159:        } else {                        /* It's a global variable */
                   1160:            if (c < 33 || c > GVARS) return(0);
                   1161:            p = g_var[c];               /* Get pointer from global-var table */
                   1162:            g_var[c] = NULL;            /* Zero the table entry */
                   1163:        }
                   1164:        if (p) {
                   1165:            debug(F110,"delmac def",p,0);
                   1166:            free(p);                    /* Free the storage */
                   1167:        } else debug(F110,"delmac def","(null pointer)",0);
                   1168:        return(0);
                   1169:     }
                   1170:            
                   1171:     if (*nam == '&') {                 /* An array reference? */
                   1172:        char **q;
                   1173:        if (arraynam(nam,&x,&z) < 0)    /* If syntax is bad */
                   1174:          return(-1);                   /* return -1. */
                   1175:        x -= 96;                        /* Convert name to number. */
                   1176:        if ((q = a_ptr[x]) == NULL)     /* If array not declared, */
                   1177:          return(-2);                   /* return -2. */
                   1178:        if (z > a_dim[x])               /* If subscript out of range, */
                   1179:          return(-3);                   /* return -3. */
                   1180:        if (q[z]) {                     /* If there is an old value, */
                   1181:            debug(F110,"delman def",q[z],0);
                   1182:            free(q[z]);                 /* delete it. */
                   1183:            q[z] = NULL;
                   1184:        } else debug(F110,"delmac def","(null pointer)",0);
                   1185:     }
                   1186: 
                   1187:    /* Not a variable or an array, so it must be a macro. */
                   1188: 
                   1189:     if ((x = mlook(mactab,nam,nmac)) < 0) return(x); /* Look it up */
                   1190: 
                   1191:     if (mactab[x].kwd)                 /* Free the storage for the name */
                   1192:       free(mactab[x].kwd);
                   1193:     if (mactab[x].mval)                        /* and for the definition */
                   1194:       free(mactab[x].mval);
                   1195: 
                   1196:     for (i = x; i < nmac; i++) {       /* Now move up the others. */
                   1197:        mactab[i].kwd = mactab[i+1].kwd;
                   1198:        mactab[i].mval = mactab[i+1].mval;
                   1199:        mactab[i].flgs = mactab[i+1].flgs;
                   1200:     }
                   1201:     nmac--;                            /* One less macro */
                   1202:     mactab[nmac].kwd = NULL;           /* Delete last item from table */
                   1203:     mactab[nmac].mval = NULL;
                   1204:     mactab[nmac].flgs = 0;
                   1205:     return(0);
                   1206: }
                   1207: 
                   1208: VOID
                   1209: initmac() {                            /* Init macro & variable tables */
                   1210:     int i, j;
                   1211: 
                   1212:     nmac = 0;                          /* No macros */
                   1213:     for (i = 0; i < MAC_MAX; i++) {    /* Initialize the macro table */
                   1214:        mactab[i].kwd = NULL;
                   1215:        mactab[i].mval = NULL;
                   1216:        mactab[i].flgs = 0;
                   1217:     }
                   1218:     for (i = 0; i < MACLEVEL; i++) {   /* Init the macro argument tables */
                   1219:        mrval[i] = NULL;
                   1220:        for (j = 0; j < 10; j++) {
                   1221:            m_arg[i][j] = NULL;
                   1222:        }
                   1223:     }
                   1224:     for (i = 0; i < GVARS; i++) {      /* And the global variables table */
                   1225:        g_var[i] = NULL;
                   1226:     }
                   1227:     for (i = 0; i < 26; i++) {         /* And the table of arrays */
                   1228:        a_ptr[i] = (char **) NULL;      /* Null pointer for each */
                   1229:        a_dim[i] = 0;                   /* and a dimension of zero */
                   1230:     }
                   1231: }
                   1232: 
                   1233: int
                   1234: popclvl() {                            /* Pop command level, return cmdlvl */
                   1235:     if (cmdlvl < 1) {                  /* If we're already at top level */
                   1236:        cmdlvl = 0;                     /* just make sure all the */
                   1237:        tlevel = -1;                    /* stack pointers are set right */
                   1238:        maclvl = -1;                    /* and return */
                   1239:     } else if (cmdstk[cmdlvl].src == CMD_TF) { /* Reading from TAKE file? */
                   1240:        if (tlevel > -1) {              /* Yes, */
                   1241:            fclose(tfile[tlevel--]);    /* close it and pop take level */
                   1242:            cmdlvl--;                   /* pop command level */
                   1243:        } else tlevel = -1;
                   1244:     } else if (cmdstk[cmdlvl].src == CMD_MD) { /* In a macro? */
                   1245:        if (maclvl > -1) {              /* Yes, */
                   1246:            macp[maclvl] = "";          /* set macro pointer to null string */
                   1247:            *cmdbuf = '\0';             /* clear the command buffer */
                   1248:            if (mrval[maclvl+1]) {      /* Free any deeper return values. */
                   1249:                free(mrval[maclvl+1]);
                   1250:                mrval[maclvl+1] = NULL;
                   1251:            }
                   1252:            maclvl--;                   /* pop macro level */
                   1253:            cmdlvl--;                   /* and command level */
                   1254:        } else maclvl = -1;
                   1255:     }
                   1256:     if (cmdlvl < 1) {                  /* If back at top level */
                   1257: #ifndef MAC
                   1258:        conint(trap,stptrap);           /* Fix interrupts */
                   1259:        bgchk();                        /* Check background status */
                   1260:        concb((char)escape);            /* Go into cbreak mode */
                   1261: #endif /* MAC */
                   1262:     }
                   1263:     return(cmdlvl < 1 ? 0 : cmdlvl);   /* Return command level */
                   1264: }
                   1265: #else /* No script programming language */
                   1266: int popclvl() {                                /* Just close current take file. */
                   1267:     if (tlevel > -1)                   /* if any... */
                   1268:       fclose(tfile[tlevel--]);
                   1269:     if (tlevel == -1) {                        /* And if back at top level */
                   1270:        conint(trap,stptrap);           /* check and set interrupts */
                   1271:         bgchk();                       /* and background status */
                   1272:         concb((char)escape);           /* and go back into cbreak mode. */
                   1273:     }
                   1274:     return(tlevel + 1);
                   1275: }
                   1276: #endif /* NOSPL */
                   1277: 
                   1278: /* STOP - get back to C-Kermit prompt, no matter where from. */
                   1279: 
                   1280: int
                   1281: dostop() {
                   1282:     while ( popclvl() )  ;     /* Pop all macros & take files */
                   1283: #ifndef NOSPL
                   1284:     while (cmpop() > -1) ;     /* And all recursive cmd pkg invocations */
                   1285: #endif /* NOSPL */
                   1286:     cmini(ckxech);             /* Clear the command buffer. */
                   1287:     return(0);
                   1288: }
                   1289: 
                   1290: 
                   1291: /* Close the given log */
                   1292: 
                   1293: int
                   1294: doclslog(x) int x; {
                   1295:     int y;
                   1296:     switch (x) {
                   1297: #ifdef DEBUG
                   1298:        case LOGD:
                   1299:            if (deblog == 0) {
                   1300:                printf("?Debugging log wasn't open\n");
                   1301:                return(0);
                   1302:            }
                   1303:            *debfil = '\0';
                   1304:            deblog = 0;
                   1305:            return(zclose(ZDFILE));
                   1306: #endif /* DEBUG */
                   1307: 
                   1308:        case LOGP:
                   1309:            if (pktlog == 0) {
                   1310:                printf("?Packet log wasn't open\n");
                   1311:                return(0);
                   1312:            }
                   1313:            *pktfil = '\0';
                   1314:            pktlog = 0;
                   1315:            return(zclose(ZPFILE));
                   1316:  
                   1317:        case LOGS:
                   1318:            if (seslog == 0) {
                   1319:                printf("?Session log wasn't open\n");
                   1320:                return(0);
                   1321:            }
                   1322:            *sesfil = '\0';
                   1323:            seslog = 0;
                   1324:            return(zclose(ZSFILE));
                   1325:  
                   1326: #ifdef TLOG
                   1327:        case LOGT:
                   1328:            if (tralog == 0) {
                   1329:                printf("?Transaction log wasn't open\n");
                   1330:                return(0);
                   1331:            }
                   1332:            *trafil = '\0';
                   1333:            tralog = 0;
                   1334:            return(zclose(ZTFILE));
                   1335: #endif /* TLOG */
                   1336:  
                   1337: #ifndef NOSPL
                   1338:           case LOGW:
                   1339:          case LOGR:
                   1340:            y = (x == LOGR) ? ZRFILE : ZWFILE;
                   1341:            if (chkfn(y) < 1) {
                   1342:                if (x == LOGW)
                   1343:                  printf("?No file to close\n");
                   1344:                return(0);
                   1345:            }
                   1346:            y = zclose(y);
                   1347:            return((x == LOGR) ? 1 : y);
                   1348: #endif /* NOSPL */
                   1349: 
                   1350:        default:
                   1351:            printf("\n?Unexpected log designator - %ld\n", x);
                   1352:            return(0);
                   1353:        }
                   1354: }
                   1355: 
                   1356: #ifndef NOSERVER
                   1357: #ifndef NOFRILLS
                   1358: static char *nm[] = { "disabled", "enabled" };
                   1359: #endif /* NOFRILLS */
                   1360: #endif /* NOSERVER */
                   1361: 
                   1362: static int slc = 0;                    /* Screen line count */
                   1363: 
                   1364: #ifndef NOFRILLS
                   1365: #define xxdiff(v,sys) strncmp(v,sys,strlen(sys))
                   1366: VOID
                   1367: shover() {
                   1368:     printf("\nVersions:\n %s\n Numeric: %ld",versio,vernum);
                   1369:     if (verwho) printf("-%d",verwho);
                   1370:     printf(xxdiff(ckxv,ckxsys) ? "\n %s for%s\n" : "\n %s\n",ckxv,ckxsys);
                   1371:     printf(xxdiff(ckzv,ckzsys) ? " %s for%s\n" : " %s\n",ckzv,ckzsys);
                   1372:     printf(" %s\n",protv);
                   1373:     printf(" %s\n",fnsv);
                   1374:     printf(" %s\n %s\n",cmdv,userv);
                   1375: #ifndef NOCSETS
                   1376:     printf(" %s\n",xlav);
                   1377: #endif /* NOCSETS */
                   1378: #ifndef MAC
                   1379:     printf(" %s\n",connv);
                   1380: #endif /* MAC */
                   1381: #ifndef NODIAL
                   1382:     printf(" %s\n",dialv);
                   1383: #endif /* NODIAL */
                   1384: #ifndef NOSCRIPT
                   1385:     printf(" %s\n",loginv);
                   1386: #endif /* NOSCRIPT */
                   1387: #ifdef NETCONN
                   1388:     printf(" %s\n",cknetv);
                   1389: #endif /* NETCONN */
                   1390: 
                   1391:     printf("\nSpecial features:\n");
                   1392: #ifdef NETCONN
                   1393:     printf(" Network support (type SHOW NET for further info)\n");
                   1394: #endif /* NETCONN */
                   1395: 
                   1396: #ifdef KANJI
                   1397:     printf(" Kanji character-set translation\n");
                   1398: #endif /* KANJI */
                   1399: 
                   1400:     printf("\nFeatures not included:\n");
                   1401: #ifdef NOSERVER
                   1402:     printf(" No server mode\n");
                   1403: #endif /* NOSERVER */
                   1404: #ifdef NODEBUG
                   1405:     printf(" No debugging\n");
                   1406: #endif /* NODEBUG */
                   1407: #ifdef NOTLOG
                   1408:     printf(" No transaction log\n");
                   1409: #endif /* NOTLOG */
                   1410: #ifdef NOHELP
                   1411:     printf(" No built-in help\n");
                   1412: #endif /* NOHELP */
                   1413: #ifndef NETCONN
                   1414:     printf(" No network support\n");
                   1415: #endif /* NETCONN */
                   1416: #ifdef NOMSEND
                   1417:     printf(" No MSEND command\n");
                   1418: #endif /* NOMSEND */
                   1419: #ifdef NODIAL
                   1420:     printf(" No DIAL command\n");
                   1421: #endif /* NODIAL */
                   1422: #ifdef NOXMIT
                   1423:     printf(" No TRANSMIT command\n");
                   1424: #endif /* NOXMIT */
                   1425: #ifdef NOSCRIPT
                   1426:     printf(" No SCRIPT command\n");
                   1427: #endif /* NOSCRIPT */
                   1428: #ifdef NOSPL
                   1429:     printf(" No script programming features\n");
                   1430: #endif /* NOSPL */
                   1431: #ifdef NOCSETS
                   1432:     printf(" No character-set translation\n");
                   1433: #else
                   1434: #ifdef NOCYRIL
                   1435:     printf(" No Cyrillic character-set translation\n");
                   1436: #endif /* NOCYRIL */
                   1437: #ifndef KANJI
                   1438:     printf(" No Kanji character-set translation\n");
                   1439: #endif /* KANJI */
                   1440: #endif /* NOCSETS */
                   1441: #ifdef NOCMDL
                   1442:     printf(" No command-line arguments\n");
                   1443: #endif /* NOCMDL */
                   1444: #ifdef NOFRILLS
                   1445:     printf(" No frills\n");
                   1446: #endif /* NOFRILLS */
                   1447: #ifdef NOPUSH
                   1448:     printf(" No escape to system\n");
                   1449: #endif /* NOPUSH */
                   1450: #ifdef NOJC
                   1451:     printf(" No UNIX job control\n");
                   1452: #endif /* NOJC */
                   1453: #ifdef NOSETKEY
                   1454:     printf(" No SET KEY command\n");
                   1455: #endif /* NOSETKEY */
                   1456: #ifdef NOESCSEQ
                   1457:     printf(" No ANSI escape sequence recognition\n");
                   1458: #endif /* NOESCSEQ */
                   1459: #ifndef PARSENSE
                   1460:     printf(" No automatic parity detection\n");
                   1461: #endif /* PARSENSE */
                   1462: /*
                   1463:   Print all of Kermit's compile-time options, as well as C preprocessor
                   1464:   predefined symbols that might affect us...
                   1465: */
                   1466:     printf("\nCompiler options:\n");
                   1467: #ifdef DEBUG
                   1468: #ifdef IFDEBUG
                   1469:     prtopt(" IFDEBUG");
                   1470: #else
                   1471:     prtopt(" DEBUG");
                   1472: #endif /* IFDEBUG */
                   1473: #endif /* DEBUG */
                   1474: #ifdef TLOG
                   1475:     prtopt(" TLOG");
                   1476: #endif /* TLOG */
                   1477: #ifdef DYNAMIC
                   1478:     prtopt(" DYNAMIC");
                   1479: #endif /* IFDEBUG */
                   1480: #ifdef UNIX
                   1481:     prtopt(" UNIX");
                   1482: #endif /* UNIX */
                   1483: #ifdef VMS
                   1484:     prtopt(" VMS");
                   1485: #endif /* VMS */
                   1486: #ifdef vms
                   1487:     prtopt(" vms");
                   1488: #endif /* vms */
                   1489: #ifdef VMSSHARE
                   1490:     prtopt(" VMSSHARE");
                   1491: #endif /* VMSSHARE */
                   1492: #ifdef datageneral
                   1493:     prtopt(" datageneral");
                   1494: #endif /* datageneral */
                   1495: #ifdef apollo
                   1496:     prtopt(" apollo");
                   1497: #endif /* apollo */
                   1498: #ifdef aegis
                   1499:     prtopt(" aegis");
                   1500: #endif /* aegis */
                   1501: #ifdef A986
                   1502:     prtopt(" A986");
                   1503: #endif /* A986 */
                   1504: #ifdef AMIGA
                   1505:     prtopt(" AMIGA");
                   1506: #endif /* AMIGA */
                   1507: #ifdef MAC
                   1508:     prtopt(" MAC");
                   1509: #endif /* MAC */
                   1510: #ifdef AUX
                   1511:     prtopt(" AUX");
                   1512: #endif /* AUX */
                   1513: #ifdef OS2
                   1514:     prtopt(" OS2");
                   1515: #endif /* OS2 */
                   1516: #ifdef OS9
                   1517:     prtopt(" OS9");
                   1518: #endif /* OS9 */
                   1519: #ifdef MSDOS
                   1520:     prtopt(" MSDOS");
                   1521: #endif /* MSDOS */
                   1522: #ifdef DIRENT
                   1523:     prtopt(" DIRENT");
                   1524: #endif /* DIRENT */
                   1525: #ifdef SDIRENT
                   1526:     prtopt(" SDIRENT");
                   1527: #endif /* SDIRENT */
                   1528: #ifdef NDIR
                   1529:     prtopt(" NDIR");
                   1530: #endif /* NDIR */
                   1531: #ifdef XNDIR
                   1532:     prtopt(" XNDIR");
                   1533: #endif /* XNDIR */
                   1534: #ifdef MATCHDOT
                   1535:     prtopt(" MATCHDOT");
                   1536: #endif /* MATCHDOT */
                   1537: #ifdef SAVEDUID
                   1538:     prtopt(" SAVEDUID");
                   1539: #endif /* SAVEDUID */
                   1540: #ifdef NOCCTRAP
                   1541:     prtopt(" NOCCTRAP");
                   1542: #endif /* NOCCTRAP */
                   1543: #ifdef SUNX25
                   1544:     prtopt(" SUNX25");
                   1545: #endif /* SUNX25 */
                   1546: #ifdef ATT7300
                   1547:     prtopt(" ATT7300");
                   1548: #endif /* ATT7300 */
                   1549: #ifdef ATT6300
                   1550:     prtopt(" ATT6300");
                   1551: #endif /* ATT6300 */
                   1552: #ifdef HDBUUCP
                   1553:     prtopt(" HDBUUCP");
                   1554: #endif /* HDBUUCP */
                   1555: #ifdef NOUUCP
                   1556:     prtopt(" NOUUCP");
                   1557: #endif /* NOUUCP */
                   1558: #ifdef LONGFN
                   1559:     prtopt(" LONGFN");
                   1560: #endif /* LONGFN */
                   1561: #ifdef RDCHK
                   1562:     prtopt(" RDCHK");
                   1563: #endif /* RDCHK */
                   1564: #ifdef NAP
                   1565:     prtopt(" NAP");
                   1566: #endif /* NAP */
                   1567: #ifdef EXCELAN
                   1568:     prtopt(" EXCELAN");
                   1569: #endif /* EXCELAN */
                   1570: #ifdef PARAMH
                   1571:     prtopt(" PARAMH");
                   1572: #endif /* PARAMH */
                   1573: #ifdef INTERLAN
                   1574:     prtopt(" INTERLAN");
                   1575: #endif /* INTERLAN */
                   1576: #ifdef NOFILEH
                   1577:     prtopt(" NOFILEH");
                   1578: #endif /* NOFILEH */
                   1579: #ifdef NOSYSIOCTLH
                   1580:     prtopt(" NOSYSIOCTLH");
                   1581: #endif /* NOSYSIOCTLH */
                   1582: #ifdef DCLPOPEN
                   1583:     prtopt(" DCLPOPEN");
                   1584: #endif /* DCLPOPEN */
                   1585: #ifdef NOPOPEN
                   1586:     prtopt(" NOPOPEN");
                   1587: #endif /* NOPOPEN */
                   1588: #ifdef NOPARTIAL
                   1589:     prtopt(" NOPARTIAL");
                   1590: #endif /* NOPARTIAL */
                   1591: #ifdef NOSETREU
                   1592:     prtopt(" NOSETREU");
                   1593: #endif /* NOSETREU */
                   1594: #ifdef _POSIX_SOURCE
                   1595:     prtopt(" _POSIX_SOURCE");
                   1596: #endif /* _POSIX_SOURCE */
                   1597: #ifdef LCKDIR
                   1598:     prtopt(" LCKDIR");
                   1599: #endif /* LCKDIR */
                   1600: #ifdef ACUCNTRL
                   1601:     prtopt(" ACUCNTRL");
                   1602: #endif /* ACUCNTRL */
                   1603: #ifdef BSD4
                   1604:     prtopt(" BSD4");
                   1605: #endif /* BSD4 */
                   1606: #ifdef BSD41
                   1607:     prtopt(" BSD41");
                   1608: #endif /* BSD41 */
                   1609: #ifdef BSD43
                   1610:     prtopt(" BSD43");
                   1611: #endif /* BSD43 */
                   1612: #ifdef BSD29
                   1613:     prtopt(" BSD29");
                   1614: #endif /* BSD29 */
                   1615: #ifdef V7
                   1616:     prtopt(" V7");
                   1617: #endif /* V7 */
                   1618: #ifdef AIX370
                   1619:     prtopt(" AIX370");
                   1620: #endif /* AIX370 */
                   1621: #ifdef RTAIX
                   1622:     prtopt(" RTAIX");
                   1623: #endif /* RTAIX */
                   1624: #ifdef HPUX
                   1625:     prtopt(" HPUX");
                   1626: #endif /* HPUX */
                   1627: #ifdef HPUXPRE65
                   1628:     prtopt(" HPUXPRE65");
                   1629: #endif /* HPUXPRE65 */
                   1630: #ifdef DGUX
                   1631:     prtopt(" DGUX");
                   1632: #endif /* DGUX */
                   1633: #ifdef DGUX540
                   1634:     prtopt(" DGUX540");
                   1635: #endif /* DGUX540 */
                   1636: #ifdef sony_news
                   1637:     prtopt(" sony_news");
                   1638: #endif /* sony_news */
                   1639: #ifdef CIE
                   1640:     prtopt(" CIE");
                   1641: #endif /* CIE */
                   1642: #ifdef XENIX
                   1643:     prtopt(" XENIX");
                   1644: #endif /* XENIX */
                   1645: #ifdef SCO_XENIX
                   1646:     prtopt(" SCO_XENIX");
                   1647: #endif /* SCO_XENIX */
                   1648: #ifdef ISIII
                   1649:     prtopt(" ISIII");
                   1650: #endif /* ISIII */
                   1651: #ifdef I386IX
                   1652:     prtopt(" I386IX");
                   1653: #endif /* I386IX */
                   1654: #ifdef RTU
                   1655:     prtopt(" RTU");
                   1656: #endif /* RTU */
                   1657: #ifdef PROVX1
                   1658:     prtopt(" PROVX1");
                   1659: #endif /* PROVX1 */
                   1660: #ifdef TOWER1
                   1661:     prtopt(" TOWER1");
                   1662: #endif /* TOWER1 */
                   1663: #ifdef ZILOG
                   1664:     prtopt(" ZILOG");
                   1665: #endif /* ZILOG */
                   1666: #ifdef TRS16
                   1667:     prtopt(" TRS16");
                   1668: #endif /* TRS16 */
                   1669: #ifdef MINIX
                   1670:     prtopt(" MINIX");
                   1671: #endif /* MINIX */
                   1672: #ifdef C70
                   1673:     prtopt(" C70");
                   1674: #endif /* C70 */
                   1675: #ifdef AIXPS2
                   1676:     prtopt(" AIXPS2");
                   1677: #endif /* AIXPS2 */
                   1678: #ifdef AIXRS
                   1679:     prtopt(" AIXRS");
                   1680: #endif /* AIXRS */
                   1681: #ifdef UTSV
                   1682:     prtopt(" UTSV");
                   1683: #endif /* UTSV */
                   1684: #ifdef ATTSV
                   1685:     prtopt(" ATTSV");
                   1686: #endif /* ATTSV */
                   1687: #ifdef SVR3
                   1688:     prtopt(" SVR3");
                   1689: #endif /* SVR3 */
                   1690: #ifdef SVR4
                   1691:     prtopt(" SVR4");
                   1692: #endif /* SVR4 */
                   1693: #ifdef POSIX
                   1694:     prtopt(" POSIX");
                   1695: #endif /* POSIX */
                   1696: #ifdef SUNOS4
                   1697:     prtopt(" SUNOS4");
                   1698: #endif /* SUNOS4 */
                   1699: #ifdef SUN4S5
                   1700:     prtopt(" SUN4S5");
                   1701: #endif /* SUN4S5 */
                   1702: #ifdef ENCORE
                   1703:     prtopt(" ENCORE");
                   1704: #endif /* ENCORE */
                   1705: #ifdef ultrix
                   1706:     prtopt(" ultrix");
                   1707: #endif
                   1708: #ifdef sxaE50
                   1709:     prtopt(" sxaE50");
                   1710: #endif
                   1711: #ifdef mips
                   1712:     prtopt(" mips");
                   1713: #endif
                   1714: #ifdef MIPS
                   1715:     prtopt(" MIPS");
                   1716: #endif
                   1717: #ifdef vax
                   1718:     prtopt(" vax");
                   1719: #endif
                   1720: #ifdef VAX
                   1721:     prtopt(" VAX");
                   1722: #endif
                   1723: #ifdef sun
                   1724:     prtopt(" sun");
                   1725: #endif
                   1726: #ifdef sun3
                   1727:     prtopt(" sun3");
                   1728: #endif
                   1729: #ifdef sun386
                   1730:     prtopt(" sun386");
                   1731: #endif
                   1732: #ifdef _SUN
                   1733:     prtopt(" _SUN");
                   1734: #endif
                   1735: #ifdef sun4
                   1736:     prtopt(" sun4");
                   1737: #endif
                   1738: #ifdef sparc
                   1739:     prtopt(" sparc");
                   1740: #endif
                   1741: #ifdef NEXT
                   1742:     prtopt(" NEXT");
                   1743: #endif
                   1744: #ifdef NeXT
                   1745:     prtopt(" NeXT");
                   1746: #endif
                   1747: #ifdef sgi
                   1748:     prtopt(" sgi");
                   1749: #endif
                   1750: #ifdef M_SYS5
                   1751:     prtopt(" M_SYS5");
                   1752: #endif
                   1753: #ifdef __SYSTEM_FIVE
                   1754:     prtopt(" __SYSTEM_FIVE");
                   1755: #endif
                   1756: #ifdef sysV
                   1757:     prtopt(" sysV");
                   1758: #endif
                   1759: #ifdef M_XENIX                         /* SCO Xenix V and UNIX/386 */
                   1760:     prtopt(" M_XENIX");
                   1761: #endif 
                   1762: #ifdef M_UNIX
                   1763:     prtopt(" M_UNIX");
                   1764: #endif
                   1765: #ifdef M_I386
                   1766:     prtopt(" M_I386");
                   1767: #endif
                   1768: #ifdef i386
                   1769:     prtopt(" i386");
                   1770: #endif
                   1771: #ifdef i286
                   1772:     prtopt(" i286");
                   1773: #endif
                   1774: #ifdef M_I286
                   1775:     prtopt(" M_I286");
                   1776: #endif
                   1777: #ifdef mc68000
                   1778:     prtopt(" mc68000");
                   1779: #endif
                   1780: #ifdef mc68010
                   1781:     prtopt(" mc68010");
                   1782: #endif
                   1783: #ifdef mc68020
                   1784:     prtopt(" mc68020");
                   1785: #endif
                   1786: #ifdef mc68030
                   1787:     prtopt(" mc68030");
                   1788: #endif
                   1789: #ifdef mc68040
                   1790:     prtopt(" mc68040");
                   1791: #endif
                   1792: #ifdef M_68000
                   1793:     prtopt(" M_68000");
                   1794: #endif
                   1795: #ifdef M_68010
                   1796:     prtopt(" M_68010");
                   1797: #endif
                   1798: #ifdef M_68020
                   1799:     prtopt(" M_68020");
                   1800: #endif
                   1801: #ifdef M_68030
                   1802:     prtopt(" M_68030");
                   1803: #endif
                   1804: #ifdef M_68040
                   1805:     prtopt(" M_68040");
                   1806: #endif
                   1807: #ifdef m68k
                   1808:     prtopt(" m68k");
                   1809: #endif
                   1810: #ifdef m88k
                   1811:     prtopt(" m88k");
                   1812: #endif
                   1813: #ifdef pdp11
                   1814:     prtopt(" pdp11");
                   1815: #endif
                   1816: #ifdef iAPX
                   1817:     prtopt(" iAPX");
                   1818: #endif
                   1819: #ifdef __hp9000s800
                   1820:     prtopt(" __hp9000s800");
                   1821: #endif
                   1822: #ifdef __hp9000s500
                   1823:     prtopt(" __hp9000s500");
                   1824: #endif
                   1825: #ifdef __hp9000s300
                   1826:     prtopt(" __hp9000s300");
                   1827: #endif
                   1828: #ifdef __hp9000s200
                   1829:     prtopt(" __hp9000s200");
                   1830: #endif
                   1831: #ifdef AIX
                   1832:     prtopt(" AIX");
                   1833: #endif
                   1834: #ifdef _AIXFS
                   1835:     prtopt(" _AIXFS");
                   1836: #endif
                   1837: #ifdef u370
                   1838:     prtopt(" u370");
                   1839: #endif
                   1840: #ifdef u3b
                   1841:     prtopt(" u3b");
                   1842: #endif
                   1843: #ifdef u3b2
                   1844:     prtopt(" u3b2");
                   1845: #endif
                   1846: #ifdef multimax
                   1847:     prtopt(" multimax");
                   1848: #endif
                   1849: #ifdef balance
                   1850:     prtopt(" balance");
                   1851: #endif
                   1852: #ifdef ibmrt
                   1853:     prtopt(" ibmrt");
                   1854: #endif
                   1855: #ifdef _IBMRT
                   1856:     prtopt(" _IBMRT");
                   1857: #endif
                   1858: #ifdef ibmrs6000
                   1859:     prtopt(" ibmrs6000");
                   1860: #endif
                   1861: #ifdef _AIX
                   1862:     prtopt(" _AIX");
                   1863: #endif /* _AIX */
                   1864: #ifdef _IBMR2
                   1865:     prtopt(" _IBMR2");
                   1866: #endif
                   1867: #ifdef __STRICT_BSD__
                   1868:     prtopt(" __STRICT_BSD__");
                   1869: #endif
                   1870: #ifdef __STRICT_ANSI__
                   1871:     prtopt(" __STRICT_ANSI__");
                   1872: #endif
                   1873: #ifdef _ANSI_C_SOURCE
                   1874:     prtopt(" _ANSI_C_SOURCE");
                   1875: #endif
                   1876: #ifdef __STDC__
                   1877:     prtopt(" __STDC__");
                   1878: #endif
                   1879: #ifdef __GNUC__                                /* gcc in ansi mode */
                   1880:     prtopt(" __GNUC__");
                   1881: #endif
                   1882: #ifdef GNUC                            /* gcc in traditional mode */
                   1883:     prtopt(" GNUC");
                   1884: #endif
                   1885: #ifdef CK_ANSIC
                   1886:     prtopt(" CK_ANSIC");
                   1887: #endif
                   1888: #ifdef CK_ANSILIBS
                   1889:     prtopt(" CK_ANSILIBS");
                   1890: #endif
                   1891: #ifdef _XOPEN_SOURCE
                   1892:     prtopt(" _XOPEN_SOURCE");
                   1893: #endif
                   1894: #ifdef _ALL_SOURCE
                   1895:     prtopt(" _ALL_SOURCE");
                   1896: #endif
                   1897: #ifdef _SC_JOB_CONTROL
                   1898:     prtopt(" _SC_JOB_CONTROL");
                   1899: #endif
                   1900: #ifdef _POSIX_JOB_CONTROL
                   1901:     prtopt(" _POSIX_JOB_CONTROL");
                   1902: #endif
                   1903: #ifdef _BSD
                   1904:     prtopt(" _BSD");
                   1905: #endif
                   1906: #ifdef TERMIOX
                   1907:     prtopt(" TERMIOX");
                   1908: #endif /* TERMIOX */
                   1909: #ifdef STERMIOX
                   1910:     prtopt(" STERMIOX");
                   1911: #endif /* STERMIOX */
                   1912:     prtopt((char *)0);
                   1913:     printf("\n\n");
                   1914: }
                   1915: #endif /* NOFRILLS */
                   1916: 
                   1917: #ifdef VMS
                   1918: int
                   1919: sholbl() {
                   1920:     printf("VMS Labeled File Features:\n");
                   1921:     printf(" acl %s (ACL info %s)\n",
                   1922:           lf_opts & LBL_ACL ? "on " : "off",
                   1923:           lf_opts & LBL_ACL ? "preserved" : "discarded");
                   1924:     printf(" backup-date %s (backup date/time %s)\n",
                   1925:           lf_opts & LBL_BCK ? "on " : "off",
                   1926:           lf_opts & LBL_BCK ? "preserved" : "discarded");
                   1927:     printf(" name %s (original filename %s)\n",
                   1928:           lf_opts & LBL_NAM ? "on " : "off",
                   1929:           lf_opts & LBL_NAM ? "preserved" : "discarded");
                   1930:     printf(" owner %s (original file owner id %s)\n",
                   1931:           lf_opts & LBL_OWN ? "on " : "off",
                   1932:           lf_opts & LBL_OWN ? "preserved" : "discarded");
                   1933:     printf(" path %s (original file's disk:[directory] %s)\n",
                   1934:           lf_opts & LBL_PTH ? "on " : "off",
                   1935:           lf_opts & LBL_PTH ? "preserved" : "discarded");
                   1936: }
                   1937: #endif /* VMS */
                   1938: 
                   1939: #ifndef NOSHOW
                   1940: int
                   1941: doshow(x) int x; {
                   1942:     int y;
                   1943:     char *s;
                   1944: 
                   1945: #ifndef NOSETKEY
                   1946:     if (x == SHKEY) {                  /* SHOW KEY */
                   1947:        int c;
                   1948:        KEY ch;
                   1949:        CHAR *s;
                   1950: 
                   1951:        if ((y = cmcfm()) < 0) return(y);           
                   1952: #ifdef MAC
                   1953:        printf("Not implemented\n");
                   1954:        return(0);
                   1955: #else /* Not MAC */
                   1956:        printf(" Press key: ");
                   1957:        conbin((char)escape);           /* Put terminal in binary mode */
                   1958:        c = congks(0);                  /* Get character or scan code */
                   1959:        concb((char)escape);            /* Restore terminal to cbreak mode */
                   1960:        if (c < 0) {                    /* Check for error */
                   1961:            printf("?Error reading key\n");
                   1962:            return(0);
                   1963:        }
                   1964: #ifndef OS2
                   1965: /*
                   1966:   Do NOT mask when it can be a raw scan code, perhaps > 255
                   1967: */
                   1968:        c &= cmdmsk;                    /* Apply command mask */
                   1969: #endif /* OS2 */
                   1970:        printf("\n Key code \\%d => ",c);
                   1971:         if (macrotab[c]) {             /* See if there's a macro */
                   1972:            printf("String: ");         /* If so, display its definition */
                   1973:             s = macrotab[c];
                   1974:            while (ch = *s++)
                   1975:              if (ch < 32 || ch == 127
                   1976: /*
                   1977:   Systems whose native character sets have graphic characters in C1...
                   1978: */
                   1979: #ifndef NEXT                           /* NeXT */
                   1980: #ifndef AUX                            /* Macintosh */
                   1981: #ifndef XENIX                          /* IBM PC */
                   1982: #ifndef OS2                            /* IBM PC */
                   1983:                  || (ch > 127 && ch < 160)
                   1984: #endif /* OS2 */
                   1985: #endif /* XENIX */
                   1986: #endif /* AUX */
                   1987: #endif /* NEXT */
                   1988:                  )
                   1989:                 printf("\\{%d}",ch);   /* Display control characters */
                   1990:              else putchar((char) ch);  /* in backslash notation */
                   1991:            printf("\n");
                   1992:         } else {                       /* No macro, show single character */
                   1993:            printf("Character: ");
                   1994:            ch = keymap[c];
                   1995:            if (ch < 32 || ch == 127 || ch > 255
                   1996: #ifndef NEXT
                   1997: #ifndef AUX
                   1998: #ifndef XENIX
                   1999: #ifndef OS2
                   2000:                  || (ch > 127 && ch < 160)
                   2001: #endif /* OS2 */
                   2002: #endif /* XENIX */
                   2003: #endif /* AUX */
                   2004: #endif /* NEXT */
                   2005:                )
                   2006:              printf("\\%d",(unsigned int) ch);
                   2007:            else printf("%c \\%d",ch,(unsigned int) ch);
                   2008:        }
                   2009:        if (ch == (KEY) c)
                   2010:          printf(" (self, no translation)\n");
                   2011:        else printf("\n");
                   2012:        return(1);
                   2013: #endif /* MAC */
                   2014:     }
                   2015: #endif /* NOSETKEY */
                   2016: 
                   2017: #ifndef NOSPL
                   2018:     if (x == SHMAC) {                  /* SHOW MACRO */
                   2019:        x = cmfld("Macro name, or carriage return to see them all","",&s,
                   2020:                  NULL);
                   2021:        if (x == -3)                    /* This means they want see all */
                   2022:          *line = '\0';
                   2023:        else if (x < 0)                 /* Otherwise negative = parse error */
                   2024:          return(x);
                   2025:        else                            /* 0 or greater */
                   2026:          strcpy(line,s);               /* means they typed something */
                   2027:        if ((y = cmcfm()) < 0) return(y); /* Get confirmation */
                   2028:        if (*line) {
                   2029:            slc = 0;                    /* Initial SHO MAC line number */
                   2030:            x = mlook(mactab,s,nmac);   /* Look up what they typed */
                   2031:            switch (x) {
                   2032:              case -3:                  /* Nothing to look up */
                   2033:                return(0);
                   2034:              case -1:                  /* Not found */
                   2035:                printf("%s - not found\n",s);
                   2036:                return(0);
                   2037:              case -2:                  /* Ambiguous, matches more than one */
                   2038:                y = (int)strlen(line);
                   2039:                for (x = 0; x < nmac; x++)
                   2040:                  if (!strncmp(mactab[x].kwd,line,y))
                   2041:                    if (shomac(mactab[x].kwd,mactab[x].mval) < 0) break;
                   2042:                return(1);
                   2043:              default:                  /* Matches one exactly */
                   2044:                shomac(mactab[x].kwd,mactab[x].mval);
                   2045:                return(1);
                   2046:            }
                   2047:        } else {                        /* They want to see them all */
                   2048:            printf("Macros:\n");
                   2049:            slc = 1;
                   2050:            for (y = 0; y < nmac; y++)
                   2051:              if (shomac(mactab[y].kwd,mactab[y].mval) < 0) break;
                   2052:            return(1);
                   2053:        }
                   2054:     }
                   2055: #endif /* NOSPL */
                   2056: 
                   2057: /*
                   2058:   Other SHOW commands only have two fields.  Get command confirmation here,
                   2059:   then handle with big switch() statement.
                   2060: */
                   2061:     if ((y = cmcfm()) < 0) return(y);
                   2062:     switch (x) {
                   2063: 
                   2064: #ifdef SUNX25
                   2065:         case SHPAD:
                   2066:             shopad();
                   2067:             break;
                   2068: #endif /* SUNX25 */
                   2069: 
                   2070: #ifdef NETCONN
                   2071:        case SHNET:
                   2072:            shonet();
                   2073:            break;
                   2074: #endif /* NETCONN */
                   2075: 
                   2076:        case SHPAR:
                   2077:            shopar();
                   2078:            break;
                   2079:  
                   2080:         case SHATT:
                   2081:            shoatt();
                   2082:            break;
                   2083:  
                   2084: #ifndef NOSPL
                   2085:        case SHCOU:
                   2086:            printf(" %d\n",count[cmdlvl]);
                   2087:            break;
                   2088: #endif /* NOSPL */
                   2089: 
                   2090: #ifndef NOSERVER
                   2091:         case SHSER:                    /* Show Server */
                   2092: #ifndef NOFRILLS
                   2093:            printf("Function           Status:\n");
                   2094:            printf(" GET                %s\n",nm[en_get]);
                   2095:            printf(" SEND               %s\n",nm[en_sen]);          
                   2096:            printf(" REMOTE CD/CWD      %s\n",nm[en_cwd]);
                   2097:            printf(" REMOTE DELETE      %s\n",nm[en_del]);
                   2098:            printf(" REMOTE DIRECTORY   %s\n",nm[en_dir]);
                   2099:            printf(" REMOTE HOST        %s\n",nm[en_hos]);          
                   2100:            printf(" REMOTE SET         %s\n",nm[en_set]);          
                   2101:            printf(" REMOTE SPACE       %s\n",nm[en_spa]);          
                   2102:            printf(" REMOTE TYPE        %s\n",nm[en_typ]);          
                   2103:            printf(" REMOTE WHO         %s\n",nm[en_who]);
                   2104:            printf(" BYE                %s\n",nm[en_bye]);
                   2105:             printf(" FINISH             %s\n",nm[en_fin]);
                   2106: #endif /* NOFRILLS */
                   2107:            printf("Server timeout: %d\n",srvtim);
                   2108:            printf("Server display: %s\n\n", srvdis ? "on" : "off");
                   2109:            break;
                   2110: #endif /* NOSERVER */
                   2111: 
                   2112:         case SHSTA:                    /* Status of last command */
                   2113:            if (success) printf(" SUCCESS\n"); else printf(" FAILURE\n");
                   2114:            break;
                   2115: 
                   2116: #ifdef MAC
                   2117:        case SHSTK: {                   /* Stack for MAC debugging */
                   2118:            long sp;
                   2119: 
                   2120:            sp = -1;
                   2121:            loadA0 ((char *)&sp);       /* set destination address */
                   2122:            SPtoaA0();                  /* move SP to destination */
                   2123:            printf("Stack at 0x%x\n", sp);
                   2124:            show_queue();               /* more debugging */
                   2125:            break; 
                   2126:        }
                   2127: #endif /* MAC */
                   2128: 
                   2129:        case SHTER:
                   2130: #ifdef OS2PM
                   2131:            printf(" Terminal type: %s\n",
                   2132:                   (Term_mode == VT100) ? "VT100" : "Tektronix");
                   2133: #endif /* OS2PM */
                   2134:            printf(" Command bytesize:  %d bits\n",
                   2135:                   (cmdmsk == 0377) ? 8 : 7);
                   2136:            printf(" Terminal bytesize: %d bits\n",
                   2137:                   (cmask == 0377) ? 8 : 7);
                   2138:            printf(" Terminal locking-shift: %s\n", sosi ? "on" : "off");
                   2139:            printf(" Terminal newline-mode:  %s\n", tnlm ? "on" : "off");
                   2140: #ifndef NOCSETS
                   2141:            printf(" Terminal character set");
                   2142:            if (tcsl == tcsr) {
                   2143:                printf(": transparent\n");
                   2144:            } else {
                   2145:                s = "unknown";
                   2146:                for (y = 0; y <= nfilc; y++)
                   2147:                  if (fcstab[y].kwval == tcsr) {
                   2148:                      s = fcstab[y].kwd;
                   2149:                      break;
                   2150:                  }
                   2151:                printf("s: remote: %s, local: ",s);
                   2152:                s = "unknown";
                   2153:                for (y = 0; y <= nfilc; y++)
                   2154:                  if (fcstab[y].kwval == tcsl) {
                   2155:                      s = fcstab[y].kwd;
                   2156:                      break;
                   2157:                  }
                   2158:                printf("%s",s);
                   2159:                if (tcsr != tcsl)
                   2160:                  printf(" (via %s)",
                   2161: #ifdef CYRILLIC
                   2162:                        (language == L_RUSSIAN) ? "latin-cyrillic" : "latin1"
                   2163: #else
                   2164:                        "latin1"
                   2165: #endif /* CYRILLIC */
                   2166:                );
                   2167:                printf("\n");
                   2168:            }
                   2169: #endif /* NOCSETS */
                   2170: #ifdef UNIX
                   2171:            printf(" Suspend: %s\n", suspend ? "on" : "off");
                   2172: #endif /* UNIX */
                   2173:            break;
                   2174: 
                   2175: #ifndef NOFRILLS
                   2176:        case SHVER:
                   2177:            shover();
                   2178:            break;
                   2179: #endif /* NOFRILLS */
                   2180:  
                   2181: #ifndef NOSPL
                   2182:        case SHBUI:                     /* Built-in variables */
                   2183:            for (y = 0; y < nvars; y++)
                   2184:              printf(" \\v(%s) = %s\n",vartab[y].kwd,nvlook(vartab[y].kwd));
                   2185:             break;
                   2186: 
                   2187:        case SHFUN:                     /* Functions */
                   2188:            for (y = 0; y < nfuncs; y++)
                   2189:              printf(" \\f%s()\n",fnctab[y].kwd);
                   2190:            break;
                   2191: 
                   2192:         case SHVAR:                    /* Global variables */
                   2193:            x = 0;                      /* Variable count */
                   2194:            slc = 1;                    /* Screen line count for "more?" */
                   2195:            for (y = 33; y < GVARS; y++)
                   2196:              if (g_var[y]) {
                   2197:                  if (x++ == 0) printf("Global variables:\n");
                   2198:                  sprintf(line," \\%%%c",y);
                   2199:                  if (shomac(line,g_var[y]) < 0) break;
                   2200:              }
                   2201:            if (!x) printf(" No variables defined\n");
                   2202:            break;
                   2203: 
                   2204:         case SHARG:                    /* Args */
                   2205:            if (maclvl > -1) {
                   2206:                printf("Macro arguments at level %d\n",maclvl);
                   2207:                for (y = 0; y < 10; y++)
                   2208:                  if (m_arg[maclvl][y])
                   2209:                    printf(" \\%%%d = %s\n",y,m_arg[maclvl][y]);
                   2210:            } else {
                   2211:                printf(" No macro arguments at top level\n");
                   2212:            }
                   2213:            break;
                   2214: 
                   2215:         case SHARR:                    /* Arrays */
                   2216:            x = 0;
                   2217:            for (y = 0; y < 27; y++)
                   2218:              if (a_ptr[y]) {
                   2219:                  if (x == 0) printf("Declared arrays:\n");
                   2220:                  x = 1;
                   2221:                  printf(" \\&%c[%d]\n",(y == 0) ? 64 : y + 96, a_dim[y]);
                   2222:              }
                   2223:            if (!x) printf(" No arrays declared\n");
                   2224:            break;
                   2225: #endif /* NOSPL */
                   2226: 
                   2227:        case SHPRO:                     /* Protocol parameters */
                   2228:            shoparp();
                   2229:            printf("\n");
                   2230:            break;
                   2231: 
                   2232:        case SHCOM:                     /* Communication parameters */
                   2233:            printf("\n");
                   2234:            shoparc();
                   2235: #ifndef NODIAL
                   2236:            printf("\n");
                   2237: #ifdef NETCONN
                   2238:            if (!network)
                   2239: #endif /* NETCONN */
                   2240:              shodial();
                   2241: #endif /* NODIAL */
                   2242:            printf("\n");
                   2243:            shomdm();
                   2244:            printf("\n");
                   2245:            break;
                   2246: 
                   2247:        case SHFIL:                     /* File parameters */
                   2248:            shoparf();
                   2249:            printf("\n");
                   2250:            break;
                   2251: 
                   2252: #ifndef NOCSETS
                   2253:        case SHLNG:                     /* Languages */
                   2254:            shoparl();
                   2255:            break;
                   2256: #endif /* NOCSETS */
                   2257: 
                   2258: #ifndef NOSPL
                   2259:        case SHSCR:                     /* Scripts */
                   2260:            printf(" Take  echo:     %s\n", techo  ? "On" : "Off");
                   2261:            printf(" Take  error:    %s\n", terror ? "On" : "Off");
                   2262:            printf(" Macro Echo:     %s\n", mecho  ? "On" : "Off");
                   2263:            printf(" Macro Error:    %s\n", merror ? "On" : "Off");
                   2264:            printf(" Input Case:     %s\n", incase ? "Observe" : "Ignore");
                   2265:            printf(" Input Echo:     %s\n", inecho ? "On" : "Off");
                   2266:            printf(" Input Timeout:  %s\n", intime ? "Quit" : "Proceed");
                   2267: #ifndef NOSCRIPT
                   2268:            printf(" Script echo:    %s\n", secho  ? "On" : "Off");
                   2269: #endif /* NOSCRIPT */
                   2270:            break;
                   2271: #endif /* NOSPL */
                   2272: 
                   2273: #ifndef NOXMIT
                   2274:          case SHXMI:
                   2275:            printf(" File type: %s\n", binary ? "binary" : "text");
                   2276:             printf(" Transmit EOF: ");
                   2277:            if (*xmitbuf == NUL) {
                   2278:                printf("none\n");
                   2279:            } else {
                   2280:                char *p;
                   2281:                p = xmitbuf;
                   2282:                while (*p) {
                   2283:                    if (*p < SP)
                   2284:                      printf("^%c",ctl(*p));
                   2285:                    else
                   2286:                      printf("%c",*p);
                   2287:                    p++;
                   2288:                }
                   2289:                printf("\n");
                   2290:            }
                   2291:            if (xmitf)
                   2292:              printf(" Transmit Fill: %d (fill character for blank lines)\n",
                   2293:                   xmitf);
                   2294:            else printf(" Transmit Fill: none\n");
                   2295:            printf(" Transmit Linefeed: %s\n",
                   2296:                   xmitl ? "on (send linefeeds too)" : "off");
                   2297:            if (xmitp) 
                   2298:              printf(" Transmit Prompt: %d (host line end character)\n",xmitp);
                   2299:            else printf(" Transmit Prompt: none\n");
                   2300:            printf(" Transmit Echo: %s\n",
                   2301:                   xmitx ? "on" : "off");
                   2302:            printf(" Transmit Locking-Shift: %s\n",xmits ? "on" : "off");
                   2303:            printf(" Transmit Pause: %d milliseconds\n", xmitw);
                   2304:            break;
                   2305: #endif /* NOXMIT */
                   2306: 
                   2307:          case SHMOD:                   /* SHOW MODEM */
                   2308:            shmdmlin();
                   2309:            shomdm();
                   2310:            break;
                   2311: 
                   2312: #ifndef MAC
                   2313:           case SHDFLT:
                   2314:            zsyscmd(PWDCMD);
                   2315:             break;
                   2316: #endif /* MAC */
                   2317: 
                   2318:           case SHESC:
                   2319:            printf(" Escape character: %d (^%c)\n",escape,ctl(escape));
                   2320:            break;
                   2321: 
                   2322: #ifndef NODIAL
                   2323:          case SHDIA:
                   2324:            shmdmlin();
                   2325:            doshodial();
                   2326:            if (local
                   2327: #ifdef NETCONN
                   2328:                && !network
                   2329: #endif /* NETCONN */
                   2330:                ) {
                   2331:                printf("%s modem signals:\n",ttname);
                   2332:                shomdm();
                   2333:            }
                   2334:            break;
                   2335: #endif /* NODIAL */
                   2336: 
                   2337: #ifdef VMS
                   2338:        case SHLBL:
                   2339:            sholbl();
                   2340:            break;
                   2341: #endif /* VMS */           
                   2342: 
                   2343:        default:
                   2344:            printf("\nNothing to show...\n");
                   2345:            return(-2);
                   2346:     }
                   2347:     return(success = 1);
                   2348: }
                   2349: 
                   2350: VOID
                   2351: shmdmlin() {                           /* Briefly show modem & line */
                   2352:     int i;
                   2353:     if (local
                   2354: #ifdef NETCONN
                   2355:  && !network
                   2356: #endif /* NETCONN */
                   2357:        )
                   2358:       printf("Line: %s, modem: ",ttname);
                   2359:     else
                   2360:       printf(" Communication device not yet selected with SET LINE\nModem: ");
                   2361:     if (
                   2362: #ifdef NETCONN
                   2363:        !network
                   2364: #else
                   2365:        1
                   2366: #endif /* NETCONN */
                   2367:        ) {
                   2368: #ifndef NODIAL
                   2369:        for (i = 0; i < nmdm; i++) {
                   2370:            if (mdmtab[i].kwval == mdmtyp) {
                   2371:                printf("%s\n",mdmtab[i].kwd);
                   2372:                break;
                   2373:            }
                   2374:        }
                   2375: #else
                   2376:        printf("(disabled)\n");
                   2377: #endif /* NODIAL */
                   2378:     }
                   2379: }
                   2380: 
                   2381: #ifndef NOSPL
                   2382: #define SCRNLEN 21
                   2383: #define SCRNWID 79
                   2384: int                                    /* SHO MACROS */
                   2385: shomac(s1, s2) char *s1, *s2; {
                   2386:     int x, n, pp;
                   2387:     pp = 0;
                   2388: 
                   2389:     if (!s1)
                   2390:       return(0);
                   2391:     else
                   2392:       printf("%s = ",s1);              /* Print macro name */
                   2393:     n = (int)strlen(s1) + 3;
                   2394:     if (!s2) s2 = "(null definition)";
                   2395:     while (x = *s2++) {                        /* Loop thru definition */
                   2396:        if (x == '(') pp++;             /* Treat commas within parens */
                   2397:        if (x == ')') pp--;             /* as ordinary text */
                   2398:        if (pp < 0) pp = 0;             /* Outside parens, */
                   2399:        if (x == ',' && pp == 0) {      /* comma becomes comma-dash-NL. */
                   2400:            putchar(',');
                   2401:            x = '\n';
                   2402:        }
                   2403:        putchar(x);
                   2404:        if (x == '\n') {
                   2405:            n = 0;
                   2406:            slc++;
                   2407:        } else if (++n > SCRNWID) {
                   2408:            putchar(NL);
                   2409:            n = 0;
                   2410:            slc++;
                   2411:        }
                   2412:        if (slc > SCRNLEN) {
                   2413:            if (!askmore()) return(-1);
                   2414:            n = 0;
                   2415:            slc = 0;
                   2416:        }
                   2417:     }
                   2418:     putchar(NL);
                   2419:     if (++slc > SCRNLEN) {
                   2420:        if (!askmore()) return(-1);
                   2421:        slc = 0;
                   2422:     }
                   2423:     return(0);
                   2424: }
                   2425: #endif /* NOSPL */
                   2426: 
                   2427: int
                   2428: shoatt() {
                   2429:     printf("Attributes: %s\n", atcapr ? "On" : "Off");
                   2430:     if (!atcapr) return(0);
                   2431:     printf(" Blocksize: %s\n", atblki ? "On" : "Off");
                   2432:     printf(" Date: %s\n", atdati ? "On" : "Off");
                   2433:     printf(" Disposition: %s\n", atdisi ? "On" : "Off");
                   2434:     printf(" Encoding (Character Set): %s\n", atenci ? "On" : "Off");
                   2435:     printf(" Length: %s\n", atleni ? "On" : "Off");
                   2436:     printf(" Type (text/binary): %s\n", attypi ? "On" : "Off");
                   2437:     printf(" System ID: %s\n", atsidi ? "On" : "Off");
                   2438:     printf(" System Info: %s\n", atsysi ? "On" : "Off");
                   2439:     return(0);
                   2440: }
                   2441: #endif /* NOSHOW */
                   2442: 
                   2443: #ifndef NOSPL
                   2444: /* Evaluate an arithmetic expression. */
                   2445: /* Code adapted from ev, by Howie Kaye of Columbia U & others. */
                   2446: 
                   2447: static int xerror;
                   2448: static char *cp;
                   2449: static long tokval;
                   2450: static char curtok;
                   2451: static long expval;
                   2452: 
                   2453: #define LONGBITS (8*sizeof (long))
                   2454: #define NUMBER 'N'
                   2455: #define EOT 'E'
                   2456: 
                   2457: /*
                   2458:  Replacement for strchr() and index(), neither of which seem to be universal.
                   2459: */
                   2460: 
                   2461: static char *
                   2462: #ifdef CK_ANSIC
                   2463: windex(char * s, char c)
                   2464: #else
                   2465: windex(s,c) char *s, c;
                   2466: #endif /* CK_ANSIC */
                   2467: /* windex */ {
                   2468:     while (*s != NUL && *s != c) s++;
                   2469:     if (*s == c) return(s); else return(NULL);
                   2470: }
                   2471: 
                   2472: /*
                   2473:  g e t t o k
                   2474: 
                   2475:  Returns the next token.  If token is a NUMBER, sets tokval appropriately.
                   2476: */
                   2477: static char
                   2478: gettok() {
                   2479:     while (isspace(*cp)) cp++ ;
                   2480:     switch(*cp) {
                   2481:       case '$':                                /* ??? */
                   2482:       case '+':                                /* Add */
                   2483:       case '-':                                /* Subtract or Negate */
                   2484:       case '@':                                /* Greatest Common Divisor */
                   2485:       case '*':                                /* Multiply */
                   2486:       case '/':                                /* Divide */
                   2487:       case '%':                                /* Modulus */
                   2488:       case '<':                                /* Left shift */
                   2489:       case '>':                                /* Right shift */
                   2490:       case '&':                                /* And */
                   2491:       case '|':                                /* Or */
                   2492:       case '#':                                /* Exclusive Or */
                   2493:       case '~':                                /* Not */
                   2494:       case '^':                                /* Exponent */
                   2495:       case '!':                                /* Factorial */
                   2496:       case '(':                                /* Parens for grouping */
                   2497:       case ')': return(*cp++);         /* operator, just return it */
                   2498:       case '\n':
                   2499:       case '\0': return(EOT);          /* end of line, return that */
                   2500:     }
                   2501:     if (isxdigit(*cp)) {               /* digit, must be a number */
                   2502:        char tbuf[80],*tp;              /* buffer to accumulate number */
                   2503:        int radix = 10;                 /* default radix */
                   2504:        for (tp=tbuf; isxdigit(*cp); cp++)
                   2505:          *tp++ = isupper(*cp) ? tolower(*cp) : *cp;
                   2506:        *tp = '\0';                     /* end number */
                   2507:        switch(isupper(*cp) ? tolower(*cp) : *cp) { /* examine break char */
                   2508:          case 'h':
                   2509:          case 'x': radix = 16; cp++; break; /* if radix signifier... */
                   2510:          case 'o':
                   2511:          case 'q': radix = 8; cp++; break;
                   2512:          case 't': radix = 2; cp++; break;
                   2513:        }
                   2514:        for (tp=tbuf,tokval=0; *tp != '\0'; tp++)  {
                   2515:            int dig;
                   2516:            dig = *tp - '0';            /* convert number */
                   2517:            if (dig > 10) dig -= 'a'-'0'-10;
                   2518:            if (dig >= radix) {
                   2519:                xerror = 1;
                   2520:                if (cmdlvl == 0)
                   2521:                  printf("invalid digit '%c' in number\n",*tp);
                   2522:                return(NUMBER);
                   2523:            }
                   2524:            tokval = radix*tokval + dig;
                   2525:        }
                   2526:        return(NUMBER);
                   2527:     }
                   2528:     if (cmdlvl == 0)
                   2529:       printf("Invalid character '%c' in input\n",*cp);
                   2530:     xerror = 1;
                   2531:     cp++;
                   2532:     return(gettok());
                   2533: }
                   2534: 
                   2535: static long
                   2536: expon(x,y) long x,y; {
                   2537:     long result = 1;
                   2538:     int sign = 1;
                   2539:     if (y < 0) return(0);
                   2540:     if (x < 0) {
                   2541:        x = -x;
                   2542:        if (y & 1) sign = -1;
                   2543:     }
                   2544:     while (y != 0) {
                   2545:        if (y & 1) result *= x;
                   2546:        y >>= 1;
                   2547:        if (y != 0) x *= x;
                   2548:   }
                   2549:   return(result * sign);
                   2550: }
                   2551: 
                   2552: /*
                   2553:  * factor ::= simple | simple ^ factor
                   2554:  *
                   2555:  */
                   2556: _PROTOTYP( static VOID simple, (void) );
                   2557: 
                   2558: static VOID
                   2559: factor() {
                   2560:     long oldval;
                   2561:     simple();
                   2562:     if (curtok == '^') {
                   2563:        oldval = expval;
                   2564:        curtok = gettok();
                   2565:        factor();
                   2566:        expval = expon(oldval,expval);
                   2567:     }
                   2568: }
                   2569: 
                   2570: /*
                   2571:  * termp ::= NULL | {*,/,%,&} factor termp
                   2572:  *
                   2573:  */
                   2574: static VOID
                   2575: termp() {
                   2576:     while (curtok == '*' || curtok == '/' || curtok == '%' || curtok == '&') {
                   2577:        long oldval;
                   2578:        char op;
                   2579:        op = curtok;
                   2580:        curtok = gettok();              /* skip past operator */
                   2581:        oldval = expval;
                   2582:        factor();
                   2583:        switch(op) {
                   2584:          case '*': expval = oldval * expval; break;
                   2585:          case '/': expval = oldval / expval; break;
                   2586:          case '%': expval = oldval % expval; break;
                   2587:          case '&': expval = oldval & expval; break;
                   2588:        }
                   2589:     }
                   2590: }
                   2591: 
                   2592: static long
                   2593: fact(x) long x; {                      /* factorial */
                   2594:     long result = 1;
                   2595:     while (x > 1)
                   2596:       result *= x--;
                   2597:     return(result);
                   2598: }
                   2599: 
                   2600: /*
                   2601:  * term ::= factor termp
                   2602:  *
                   2603:  */
                   2604: static VOID
                   2605: term() {
                   2606:     factor();
                   2607:     termp();
                   2608: }
                   2609: 
                   2610: static long
                   2611: gcd(x,y) long x,y; {
                   2612:     int nshift = 0;
                   2613:     if (x < 0) x = -x;
                   2614:     if (y < 0) y = -y;                 /* validate arguments */
                   2615:     if (x == 0 || y == 0) return(x + y);    /* this is bogus */
                   2616:     
                   2617:     while (!((x & 1) | (y & 1))) {     /* get rid of powers of 2 */
                   2618:        nshift++;
                   2619:        x >>= 1;
                   2620:        y >>= 1;
                   2621:     }
                   2622:     while (x != 1 && y != 1 && x != 0 && y != 0) {
                   2623:        while (!(x & 1)) x >>= 1;       /* eliminate unnecessary */
                   2624:        while (!(y & 1)) y >>= 1;       /* powers of 2 */
                   2625:        if (x < y) {                    /* force x to be larger */
                   2626:            long t;
                   2627:            t = x;
                   2628:            x = y;
                   2629:            y = t;
                   2630:        }
                   2631:        x -= y;
                   2632:     }
                   2633:     if (x == 0 || y == 0) return((x + y) << nshift); /* gcd is non-zero one */
                   2634:     else return((long) 1 << nshift);   /* else gcd is 1 */
                   2635: }
                   2636: 
                   2637: /*
                   2638:  * exprp ::= NULL | {+,-,|,...} term exprp
                   2639:  *
                   2640:  */
                   2641: static VOID
                   2642: exprp() {
                   2643:     while (windex("+-|<>#@",curtok) != NULL) {
                   2644:        long oldval;
                   2645:        char op;
                   2646:        op = curtok;
                   2647:        curtok = gettok();              /* skip past operator */
                   2648:        oldval = expval;
                   2649:        term();
                   2650:        switch(op) {
                   2651:          case '+' : expval = oldval + expval; break;
                   2652:          case '-' : expval = oldval - expval; break;
                   2653:          case '|' : expval = oldval | expval; break;
                   2654:          case '#' : expval = oldval ^ expval; break;
                   2655:          case '@' : expval = gcd(oldval,expval); break;
                   2656:          case '<' : expval = oldval << expval; break;
                   2657:          case '>' : expval = oldval >> expval; break;
                   2658:        }
                   2659:     }
                   2660: }
                   2661: 
                   2662: /*
                   2663:  * expr ::= term exprp
                   2664:  *
                   2665:  */
                   2666: static VOID
                   2667: expr() {
                   2668:     term();
                   2669:     exprp();
                   2670: }
                   2671: 
                   2672: static long
                   2673: xparse() {
                   2674:     curtok = gettok();
                   2675:     expr();
                   2676: #ifdef COMMENT
                   2677:     if (curtok == '$') {
                   2678:        curtok = gettok();
                   2679:        if (curtok != NUMBER) {
                   2680:            if (cmdlvl == 0) printf("illegal radix\n");
                   2681:            return(0);
                   2682:        }
                   2683:        curtok = gettok();
                   2684:     }
                   2685: #endif /* COMMENT */
                   2686:     if (curtok != EOT) {
                   2687:        if (cmdlvl == 0)
                   2688:          printf("extra characters after expression\n");
                   2689:        xerror = 1;
                   2690:     }
                   2691:     return(expval);
                   2692: }
                   2693: 
                   2694: char *
                   2695: evala(s) char *s; {
                   2696:     char *p;                           /* Return pointer */
                   2697:     long v;                            /* Numeric value */
                   2698: 
                   2699:     xerror = 0;                                /* Start out with no error */
                   2700:     cp = s;                            /* Make the argument global */
                   2701:     v = xparse();                      /* Parse the string */
                   2702:     p = numbuf;                                /* Convert long number to string */
                   2703:     sprintf(p,"%ld",v);
                   2704:     return(xerror ? "" : p);           /* Return empty string on error */
                   2705: }
                   2706: 
                   2707: /*
                   2708:  * simplest ::= NUMBER | ( expr )
                   2709:  *
                   2710:  */
                   2711: static VOID
                   2712: simplest() {
                   2713:     if (curtok == NUMBER) expval = tokval;
                   2714:     else if (curtok == '(') {
                   2715:        curtok = gettok();              /* skip over paren */
                   2716:        expr();
                   2717:        if (curtok != ')') {
                   2718:            if (cmdlvl == 0) printf("missing right parenthesis\n");
                   2719:            xerror = 1;
                   2720:        }
                   2721:     }
                   2722:     else {
                   2723:        if (cmdlvl == 0) printf("operator unexpected\n");
                   2724:        xerror = 1;
                   2725:     }
                   2726:     curtok = gettok();
                   2727: }
                   2728: 
                   2729: /*
                   2730:  * simpler ::= simplest | simplest !
                   2731:  *
                   2732:  */
                   2733: static VOID
                   2734: simpler() {
                   2735:     simplest();
                   2736:     if (curtok == '!') {
                   2737:        curtok = gettok();
                   2738:        expval = fact(expval);
                   2739:     }
                   2740: }
                   2741: 
                   2742: /*
                   2743:  * simple ::= {-,~} simpler | simpler
                   2744:  *
                   2745:  */
                   2746: 
                   2747: static VOID
                   2748: simple() {
                   2749:     if (curtok == '-' || curtok == '~') {
                   2750:        int op = curtok;
                   2751:        curtok = gettok();              /* skip over - sign */
                   2752:        simpler();                      /* parse the factor again */
                   2753:        expval = op == '-' ? -expval : ~expval;
                   2754:     } else simpler();
                   2755: }
                   2756: #endif /* NOSPL */
                   2757: 
                   2758: #ifndef NOSPL
                   2759: /*  D C L A R R A Y  --  Declare an array  */
                   2760: 
                   2761: int                                    /* Declare an array of size n */
                   2762: #ifdef CK_ANSIC
                   2763: dclarray(char a, int n)
                   2764: #else
                   2765: dclarray(a,n) char a; int n;
                   2766: #endif /* CK_ANSIC */
                   2767: /* dclarray */ {
                   2768:     char **p; int i, n2;
                   2769: 
                   2770:     if (a > 63 && a < 96) a += 32;     /* Convert to lowercase */
                   2771:     if (a < 96 || a > 122) return(-1); /* Verify name */
                   2772:     a -= 96;                           /* Convert name to number */
                   2773:     if ((p = a_ptr[a]) != NULL) {      /* Delete old array of same name */
                   2774:        n2 = a_dim[a];
                   2775:        for (i = 0; i <= n2; i++)       /* First delete its elements */
                   2776:          if (p[i]) free(p[i]);
                   2777:        free(a_ptr[a]);                 /* Then the element list */
                   2778:        a_ptr[a] = (char **) NULL;      /* Remove pointer to element list */
                   2779:        a_dim[a] = 0;                   /* Set dimension at zero. */
                   2780:     }
                   2781:     if (n == 0) return(0);             /* If dimension 0, just deallocate. */
                   2782: 
                   2783:     p = (char **) malloc((n+1) * sizeof(char **)); /* Allocate for new array */
                   2784:     if (p == NULL) return(-1);         /* Check */
                   2785:     a_ptr[a] = p;                      /* Save pointer to member list */
                   2786:     a_dim[a] = n;                      /* Save dimension */
                   2787:     for (i = 0; i <= n; i++)           /* Initialize members to null */
                   2788:       p[i] = NULL;
                   2789:     return(0);
                   2790: }
                   2791: 
                   2792: /*  A R R A Y N A M  --  Parse an array name  */
                   2793: 
                   2794: /*
                   2795:   Call with pointer to string that starts with the array reference.
                   2796:   String may begin with either \& or just &.
                   2797:   On success,
                   2798:     Returns letter ID (always lowercase) in argument c,
                   2799:       which can also be accent grave (` = 96; '@' is converted to grave);
                   2800:     Dimension or subscript in argument n;
                   2801:     IMPORTANT: These arguments must be provided by the caller as addresses
                   2802:     of ints (not chars), for example:
                   2803:       char *s; int x, y;
                   2804:       arraynam(s,&x,&y);
                   2805:   On failure, returns a negative number, with args n and c set to zero.
                   2806: */
                   2807: int
                   2808: arraynam(ss,c,n) char *ss; int *c; int *n; {
                   2809:     int i, y, pp;
                   2810:     char x;
                   2811:     char *s, *p, *sx, *vnp;
                   2812:     char vnbuf[VNAML+1];               /* On stack to allow for */
                   2813:     char ssbuf[VNAML+1];               /* recursive calls... */
                   2814:     char sxbuf[VNAML+1];
                   2815: 
                   2816:     *c = *n = 0;                       /* Initialize return values */
                   2817:     strncpy(vnbuf,ss,VNAML);
                   2818:     vnp = vnbuf;
                   2819:     if (vnbuf[0] == CMDQ && vnbuf[1] == '&') vnp++;
                   2820:     if (*vnp != '&') {
                   2821:        printf("?Not an array - %s\n",vnbuf);
                   2822:        return(-9);
                   2823:     }
                   2824:     x = *(vnp + 1);                    /* Fold case of array name */
                   2825:     /* We don't use isupper & tolower here on purpose because these */
                   2826:     /* would produce undesired effects with accented letters. */
                   2827:     if (x > 63 && x < 91) x  = *(vnp +1) = x + 32;
                   2828:     if ((x < 96) || (x > 122) || (*(vnp+2) != '[')) {
                   2829:        printf("?Invalid format for array name - %s\n",vnbuf);
                   2830:        return(-9);
                   2831:     }
                   2832:     *c = x;                            /* Return the array name */
                   2833:     s = vnp+3;                         /* Get dimension */
                   2834:     p = ssbuf;    
                   2835:     pp = 1;                            /* Bracket counter */
                   2836:     for (i = 0; i < VNAML && *s != NUL; i++) { /* Copy up to ] */
                   2837:        if (*s == '[') pp++;
                   2838:        if (*s == ']' && --pp == 0) break;
                   2839:        *p++ = *s++;
                   2840:     }
                   2841:     if (*s != ']') {
                   2842:        printf("?No closing bracket on array dimension - %s\n",vnbuf);
                   2843:        return(-9);
                   2844:     }
                   2845:     *p = NUL;                          /* Terminate subscript with null */
                   2846:     p = ssbuf;                         /* Point to beginning of subscript */
                   2847:     sx = sxbuf;                                /* Where to put expanded subscript */
                   2848:     y = VNAML-1;
                   2849:     xxstring(p,&sx,&y);                        /* Convert variables, etc. */
                   2850:     if (!chknum(sxbuf)) {              /* Make sure it's all digits */
                   2851:        printf("?Array dimension or subscript must be numeric - %s\n",sxbuf);
                   2852:        return(-9);
                   2853:     }
                   2854:     if ((y = atoi(sxbuf)) < 0) {
                   2855:         if (cmflgs == 0) printf("\n");
                   2856:         printf("?Array dimension or subscript must be positive or zero - %s\n",
                   2857:               sxbuf);
                   2858:        return(-9);
                   2859:     }
                   2860:     *n = y;                            /* Return the subscript or dimension */
                   2861:     return(0);
                   2862: }
                   2863: 
                   2864: int
                   2865: chkarray(a,i) int a, i; {              /* Check if array is declared */
                   2866:     int x;                             /* and if subscript is in range */
                   2867:     if (a == 64) a = 96;               /* Convert atsign to grave accent */
                   2868:     x = a - 96;                                /* Values must be in range 96-122 */
                   2869:     if (x < 0 || x > 26) return(-2);   /* Not in range */
                   2870:     if (a_ptr[x] == NULL) return(-1);  /* Not declared */
                   2871:     if (i > a_dim[x]) return(-2);      /* Declared but out of range. */
                   2872:     return(a_dim[x]);                  /* All ok, return dimension */
                   2873: }
                   2874: 
                   2875: char *
                   2876: arrayval(a,i) int a, i; {              /* Return value of \&a[i] */
                   2877:     int x; char **p;                   /* (possibly NULL) */
                   2878: 
                   2879:     if (a == 64) a = 96;               /* Convert atsign to grave accent */
                   2880:     x = a - 96;                                /* Values must be in range 96-122 */
                   2881:     if (x < 0 || x > 26) return(NULL); /* Not in range */
                   2882:     if ((p = a_ptr[x]) == NULL)                /* Array not declared */
                   2883:       return(NULL);
                   2884:     if (i > a_dim[x])                  /* Subscript out of range. */
                   2885:       return(NULL);
                   2886:     return(p[i]);                      /* All ok, return pointer to value. */
                   2887: }
                   2888: #endif /* NOSPL */
                   2889: 
                   2890: #ifndef NOSPL
                   2891: /*  P A R S E V A R  --  Parse a variable name or array reference.  */
                   2892: /*
                   2893:  Call with:
                   2894:    s  = pointer to candidate variable name or array reference.
                   2895:    *c = address of integer in which to return variable ID.
                   2896:    *i = address of integer in which to return array subscript.
                   2897:  Returns:
                   2898:    -2:  syntax error in variable name or array reference.
                   2899:     1:  successful parse of a simple variable, with ID in c.
                   2900:     2:  successful parse of an array reference, w/ID in c and subscript in i.
                   2901: */
                   2902: int
                   2903: parsevar(s,c,i) char *s; int *c, *i; {
                   2904:     char *p;
                   2905:     int x,y,z;
                   2906: 
                   2907:     p = s;
                   2908:     if (*s == CMDQ) s++;               /* Point after backslash */
                   2909: 
                   2910:     if (*s != '%' && *s != '&') {      /* Make sure it's % or & */
                   2911:        printf("?Not a variable name - %s\n",p);
                   2912:        return(-9);
                   2913:     }
                   2914:     if ((int)strlen(s) < 2) {
                   2915:        printf("?Incomplete variable name - %s\n",p);
                   2916:        return(-9);
                   2917:     }
                   2918:     if (*s == '%' && *(s+2) != '\0') {
                   2919:        printf("?Only one character after '%%' in variable name, please\n");
                   2920:        return(-9);
                   2921:     }
                   2922:     if (*s == '&' && *(s+2) != '[') {
                   2923:        printf("?Array subscript expected - %s\n",p);
                   2924:        return(-9);
                   2925:     }
                   2926:     if (*s == '%') {                   /* Simple variable. */
                   2927:        y = *(s+1);                     /* Get variable ID letter/char */
                   2928:        if (isupper(y)) y -= ('a'-'A'); /* Convert upper to lower case */
                   2929:        *c = y;                         /* Set the return values. */
                   2930:        *i = -1;                        /* No array subscript. */
                   2931:        return(1);                      /* Return 1 = simple variable */
                   2932:     }
                   2933:     if (*s == '&') {                   /* Array reference. */
                   2934:        if (arraynam(s,&x,&z) < 0) { /* Go parse it. */
                   2935:            printf("?Invalid array reference - %s\n",p);
                   2936:            return(-9);
                   2937:        }
                   2938:        if (chkarray(x,z) < 0) {        /* Check if declared, etc. */
                   2939:            printf("?Array not declared or subscript out of range\n");
                   2940:            return(-9);
                   2941:        }
                   2942:        *c = x;                         /* Return array letter */
                   2943:        *i = z;                         /* and subscript. */
                   2944:        return(2);
                   2945:     }    
                   2946:     return(-2);                                /* None of the above. */
                   2947: }
                   2948: 
                   2949: #define VALN 20
                   2950: 
                   2951: /* Get the numeric value of a variable */
                   2952: /*
                   2953:   Call with pointer to variable name, pointer to int for return value.
                   2954:   Returns:
                   2955:     0 on success with second arg containing the value.
                   2956:    -1 on failure (bad variable syntax, variable not defined or not numeric).
                   2957: */
                   2958: int
                   2959: varval(s,v) char *s; int *v; {
                   2960:     char valbuf[VALN+1];               /* s is pointer to variable name */
                   2961:     char *p;
                   2962:     int y;
                   2963: 
                   2964:     p = valbuf;                                /* Expand variable into valbuf. */
                   2965:     y = VALN;
                   2966:     if (xxstring(s,&p,&y) < 0) return(-1);
                   2967:     p = valbuf;                                /* Make sure value is numeric */
                   2968:     if (!chknum(p)) return(-1);
                   2969:     *v = atoi(p);                      /* Convert numeric string to int */
                   2970:     return(0);    
                   2971: }
                   2972: 
                   2973: /* Increment or decrement a variable */
                   2974: /* Returns -1 on failure, 0 on success, with 4th argument set to result */
                   2975: 
                   2976: int
                   2977: incvar(s,x,z,r) char *s; int x, z, *r; { /* Increment a numeric variable */
                   2978:     char valbuf[VALN+1];               /* s is pointer to variable name */
                   2979:                                        /* x is amount to increment by */
                   2980:     int n;                             /* z != 0 means add */
                   2981:                                        /* z = 0 means subtract */
                   2982: 
                   2983:     if (varval(s,&n) < 0)              /* Convert numeric string to int */
                   2984:       return(-1);
                   2985:     if (z)                             /* Increment it by the given amount */
                   2986:       n += x;
                   2987:     else                               /* or decrement as requested. */
                   2988:       n -= x;
                   2989:     sprintf(valbuf,"%d",n);            /* Convert back to numeric string */
                   2990:     addmac(s,valbuf);                  /* Replace old variable */
                   2991:     *r = n;                            /* Return the integer value */
                   2992:     return(0);
                   2993: }
                   2994: #endif /* NOSPL */
                   2995: 
                   2996: /* Functions moved here from ckuusr.c to even out the module sizes... */
                   2997: 
                   2998: #ifndef NOSPL
                   2999: /* D O D O  --  Do a macro */
                   3000: 
                   3001: /*
                   3002:   Call with x = macro table index, s = pointer to arguments.
                   3003:   Returns 0 on failure, 1 on success.
                   3004: */
                   3005: 
                   3006: int
                   3007: dodo(x,s) int x; char *s; {
                   3008:     char *p;
                   3009:     int b, y, z;
                   3010: 
                   3011:     debug(F101,"dodo maclvl","",maclvl);
                   3012:     if (++maclvl > MACLEVEL) {         /* Make sure we have storage */
                   3013:         debug(F101,"dodo maclvl too deep","",maclvl);
                   3014:        --maclvl;
                   3015:        printf("Macros nested too deeply\n");
                   3016:        return(0);
                   3017:     }
                   3018:     macp[maclvl] = mactab[x].mval;     /* Point to the macro body */ 
                   3019:     macx[maclvl] = mactab[x].mval;     /* Remember where the beginning is */
                   3020:     debug(F111,"do macro",macp[maclvl],maclvl);
                   3021: 
                   3022:     cmdlvl++;                          /* Entering a new command level */
                   3023:     if (cmdlvl > CMDSTKL) {            /* Too many macros + TAKE files? */
                   3024:         debug(F101,"dodo cmdlvl too deep","",cmdlvl);
                   3025:        cmdlvl--;
                   3026:        printf("?TAKE files and DO commands nested too deeply\n");
                   3027:        return(0);
                   3028:     }
                   3029: #ifdef VMS
                   3030:     conres();                          /* So Ctrl-C, etc, will work. */
                   3031: #endif
                   3032:     ifcmd[cmdlvl] = 0;
                   3033:     iftest[cmdlvl] = 0;
                   3034:     count[cmdlvl] = 0;
                   3035:     cmdstk[cmdlvl].src = CMD_MD;       /* Say we're in a macro */
                   3036:     cmdstk[cmdlvl].lvl = maclvl;       /* and remember the macro level */
                   3037:     mrval[maclvl] = NULL;              /* Initialize return value */
                   3038: 
                   3039:     debug(F110,"do macro",mactab[x].kwd,0);
                   3040: 
                   3041: /* Clear old %0..%9 arguments */
                   3042: 
                   3043:     addmac("%0",mactab[x].kwd);                /* Define %0 = name of macro */
                   3044:     varnam[0] = '%';
                   3045:     varnam[2] = '\0';
                   3046:     for (y = 1; y < 10; y++) {         /* Clear args %1..%9 */
                   3047:        varnam[1] = y + '0';
                   3048:        delmac(varnam);
                   3049:     }  
                   3050: 
                   3051: /* Assign the new args one word per arg, allowing braces to group words */
                   3052: 
                   3053:     p = s;                             /* Pointer to beginning of arg */
                   3054:     b = 0;                             /* Flag for outer brace removal */
                   3055:     x = 0;                             /* Flag for in-word */
                   3056:     y = 0;                             /* Brace nesting level */
                   3057:     z = 0;                             /* Argument counter, 0 thru 9 */
                   3058: 
                   3059:     while (1) {                                /* Go thru argument list */
                   3060:        if (!s || (*s == '\0')) {       /* No more characters? */
                   3061:            if (x != 0) {
                   3062:                if (z == 9) break;      /* Only go up to 9. */
                   3063:                z++;                    /* Count it. */
                   3064:                varnam[1] = z + '0';    /* Assign last argument */
                   3065:                addmac(varnam,p);
                   3066:                break;                  /* And get out. */
                   3067:            } else break;
                   3068:        } 
                   3069:        if (x == 0 && *s == ' ') {      /* Eat leading blanks */
                   3070:            s++;
                   3071:            continue;
                   3072:        } else if (*s == '{') {         /* An opening brace */
                   3073:            if (x == 0 && y == 0) {     /* If leading brace */
                   3074:                p = s+1;                /* point past it */
                   3075:                b = 1;                  /* and flag that we did this */
                   3076:            }
                   3077:            x = 1;                      /* Flag that we're in a word */
                   3078:            y++;                        /* Count the brace. */
                   3079:        } else if (*s == '}') {         /* A closing brace. */
                   3080:            y--;                        /* Count it. */
                   3081:            if (y == 0 && b != 0) {     /* If it matches the leading brace */
                   3082:                *s = ' ';               /* change it to a space */
                   3083:                b = 0;                  /* and we're not in braces any more */
                   3084:            } else if (y < 0) x = 1;    /* otherwise just start a new word. */
                   3085:        } else if (*s != ' ') {         /* Nonspace means we're in a word */
                   3086:            if (x == 0) p = s;          /* Mark the beginning */
                   3087:            x = 1;                      /* Set in-word flag */
                   3088:        }
                   3089:        /* If we're not inside a braced quantity, and we are in a word, and */
                   3090:        /* we have hit a space, then we have an argument to assign. */
                   3091:        if ((y < 1) && (x != 0) && (*s == ' ')) { 
                   3092:            *s = '\0';                  /* terminate the arg with null */
                   3093:            x = 0;                      /* say we're not in a word any more */
                   3094:            y = 0;                      /* start braces off clean again */
                   3095:            if (z == 9) break;          /* Only go up to 9. */
                   3096:            z++;                        /* count this arg */
                   3097:            varnam[1] = z + '0';        /* compute its name */
                   3098:            addmac(varnam,p);           /* add it to the macro table */
                   3099:            p = s+1;
                   3100:        }
                   3101:        s++;                            /* Point past this character */
                   3102:     }
                   3103:     if ((z == 0) && (y > 1)) {         /* Extra closing brace(s) at end */
                   3104:        z++;
                   3105:        varnam[1] = z + '0';            /* compute its name */
                   3106:        addmac(varnam,p);               /* Add rest of line to last arg */
                   3107:     }
                   3108:     macargc[maclvl] = z + 1;           /* For ARGC variable */
                   3109:     return(1);                         /* DO command succeeded */
                   3110: }
                   3111: 
                   3112: /* Insert "literal" quote around each comma-separated command to prevent */
                   3113: /* its premature expansion.  Only do this if object command is surrounded */
                   3114: /* by braces. */
                   3115: 
                   3116: static char* flit = "\\flit(";
                   3117: 
                   3118: int
                   3119: litcmd(src,dest) char **src, **dest; {
                   3120:     int bc = 0, pp = 0;
                   3121:     char *s, *lp, *ss;
                   3122: 
                   3123:     s = *src;
                   3124:     lp = *dest;
                   3125: 
                   3126:     while (*s == SP) s++;              /* strip extra leading spaces */
                   3127:     if (*s == '{') {
                   3128: 
                   3129:         pp = 0;                                /* paren counter */
                   3130:        bc = 1;                         /* count leading brace */
                   3131:        *lp++ = *s++;                   /* copy it */
                   3132:        while (*s == SP) s++;           /* strip interior leading spaces */
                   3133:        ss = flit;                      /* point to "\flit(" */
                   3134:        while (*lp++ = *ss++) ;         /* copy it */
                   3135:        lp--;                           /* back up over null */
                   3136:        while (*s) {                    /* go thru rest of text */
                   3137:            ss = flit;                  /* point back to start of "\flit(" */
                   3138:            if (*s == '{') bc++;        /* count brackets */
                   3139:            if (*s == '(') pp++;        /* and parens */
                   3140:            if (*s == ')') pp--;
                   3141:            if (*s == '}') {            /* Closing brace. */
                   3142:                if (--bc == 0) {        /* Final one? */
                   3143:                    *lp++ = ')';        /* Add closing paren for "\flit()" */
                   3144:                    *lp++ = *s++;
                   3145:                    break;
                   3146:                }
                   3147:            }
                   3148:            if (*s == ',' && pp == 0) { /* comma not inside of parens */
                   3149:                *lp++ = ')';            /* closing ) of \flit( */
                   3150:                *lp++ = ',';            /* insert the comma */
                   3151:                while (*lp++ = *ss++) ; /* start new "\flit(" */
                   3152:                lp--;                   /* back up over null */
                   3153:                s++;                    /* skip over comma in source string */
                   3154:                while (*s++ == SP);     /* eat leading spaces again. */
                   3155:                s--;                    /* back up over nonspace */
                   3156:                continue;
                   3157:            }
                   3158:             *lp++ = *s++;              /* Copy anything but comma here. */
                   3159:         }
                   3160:        *lp = NUL;
                   3161:     } else {                           /* No brackets around, */
                   3162:        while (*lp++ = *s++) ;          /* just copy. */
                   3163:        lp--;
                   3164:     }
                   3165:     *src = s;
                   3166:     *dest = lp;
                   3167:     if (bc) return(-1);
                   3168:     else return(0);
                   3169: }
                   3170: #endif /* NOSPL */
                   3171: 
                   3172: int
                   3173: docd() {                               /* Do the CD command */
                   3174:     int x;
                   3175:     char *s;
                   3176: 
                   3177: #ifdef AMIGA
                   3178:     if ((x = cmtxt("Name of local directory, or carriage return","",&s,
                   3179:                   xxstring)) < 0)
                   3180:        return(x);
                   3181:     /* if no name, just print directory name */
                   3182:     if (*s) {
                   3183:        if (chdir(s)) {
                   3184:            cwdf = success = 0;
                   3185:            perror(s);
                   3186:        }
                   3187:        success = cwdf = 1;
                   3188:     }
                   3189:     if (getcwd(line, LINBUFSIZ) == NULL)
                   3190:       printf("Current directory name not available.\n");
                   3191:     else
                   3192:       if (pflag && 
                   3193: #ifndef NOSPL
                   3194:          cmdlvl == 0
                   3195: #else
                   3196:          tlevel < 0
                   3197: #endif /* NOSPL */
                   3198:          ) printf("%s\n", line);
                   3199: #else
                   3200:     if ((x = cmdir("Name of local directory, or carriage return",homdir,&s,
                   3201:                   xxstring)) < 0 )
                   3202:       return(x);
                   3203:     if (x == 2) {
                   3204:        printf("?Wildcards not allowed in directory name\n");
                   3205:        return(-9);
                   3206:     }
                   3207: #ifdef OS2
                   3208:     if ( s!=NUL ) {
                   3209:        if ((int)strlen(s)>=2 && s[1]==':') {   /* Disk specifier */
                   3210:            if (zchdsk(*s)) {                   /* Change disk successful */
                   3211:                if ( (int)strlen(s)>=3 & ( s[2]==CMDQ || isalnum(s[2]) ) ) {
                   3212:                    if (chdir(s)) perror(s);
                   3213:                }
                   3214:            } else {
                   3215:                cwdf = success = 0;
                   3216:                perror(s);
                   3217:            }
                   3218:        } else if (chdir(s)) {
                   3219:            cwdf = success = 0;
                   3220:            perror(s);
                   3221:        }
                   3222:     }
                   3223:     printf("%s\n", zgtdir());
                   3224:     success = cwdf = 1;
                   3225: #else /* Not OS2 */
                   3226:     if (! zchdir(s)) {
                   3227:        cwdf = 0;
                   3228:        perror(s);
                   3229:     } else cwdf = 1;
                   3230: #ifndef MAC
                   3231:     zsyscmd(PWDCMD);                   /* assume this works... */
                   3232: #endif /* MAC */
                   3233: #endif /* OS2 */
                   3234: #endif /* AMIGA */
                   3235:     return(cwdf);
                   3236: }
                   3237: 
                   3238: VOID
                   3239: fixcmd() {                     /* Fix command parser after interruption */
                   3240:     dostop();                  /* Back to top level (also calls conint()). */
                   3241:     bgchk();                   /* Check background status */
                   3242:     if (*psave) {              /* If old prompt saved, */
                   3243:        cmsetp(psave);          /* restore it. */
                   3244:        *psave = NUL;
                   3245:     }
                   3246:     success = 0;               /* Tell parser last command failed */
                   3247: }
                   3248: 
                   3249: VOID
                   3250: prtopt(s) char *s; {                   /* Print an option */
                   3251:     static int x = 0;                  /* (used by SHOW VER) */
                   3252:     int y;                             /* Does word wrap. */
                   3253:     if (!s) { x = 0; return; }         /* Call with null pointer to */
                   3254:     y = (int)strlen(s);                        /* reset horizontal position. */
                   3255:     x += y;
                   3256:     if (x > 79) {
                   3257:        printf("\n%s",s);
                   3258:        x = y;
                   3259:     } else printf("%s",s);
                   3260: }
                   3261: 
                   3262: #endif /* NOICP */

unix.superglobalmegacorp.com

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