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

unix.superglobalmegacorp.com

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