Annotation of 43BSDTahoe/new/kermit/ckucmd.c, revision 1.1

1.1     ! root        1: char *cmdv = "Unix cmd package V1A(021), 19 Jun 85";
        !             2: 
        !             3: /*  C K U C M D  --  Interactive command package for Unix  */
        !             4: /*
        !             5:  Modelled after the DECSYSTEM-20 command parser (the COMND JSYS)
        !             6: 
        !             7:  Features:
        !             8:  . parses and verifies keywords, text strings, numbers, and other data
        !             9:  . displays appropriate menu or help message when user types "?"
        !            10:  . does keyword and filename completion when user types ESC
        !            11:  . accepts any unique abbreviation for a keyword
        !            12:  . allows keywords to have attributes, like "invisible"
        !            13:  . can supply defaults for fields omitted by user
        !            14:  . provides command line editing (character, word, and line deletion)
        !            15:  . accepts input from keyboard, command files, or redirected stdin
        !            16:  . allows for full or half duplex operation, character or line input
        !            17:  . settable prompt, protected from deletion
        !            18: 
        !            19:  Functions:
        !            20:   cmsetp - Set prompt (cmprom is prompt string, cmerrp is error msg prefix)
        !            21:   cmsavp - Save current prompt
        !            22:   prompt - Issue prompt 
        !            23:   cmini  - Clear the command buffer (before parsing a new command)
        !            24:   cmres  - Reset command buffer pointers (before reparsing)
        !            25:   cmkey  - Parse a keyword
        !            26:   cmnum  - Parse a number
        !            27:   cmifi  - Parse an input file name
        !            28:   cmofi  - Parse an output file name
        !            29:   cmfld  - Parse an arbitrary field
        !            30:   cmtxt  - Parse a text string
        !            31:   cmcfm  - Parse command confirmation (end of line)
        !            32:   stripq - Strip out backslash quotes from a string.
        !            33: 
        !            34:  Return codes:
        !            35:   -3: no input provided when required
        !            36:   -2: input was invalid
        !            37:   -1: reparse required (user deleted into a preceding field)
        !            38:    0 or greater: success
        !            39:   See individual functions for greater detail.
        !            40: 
        !            41:  Before using these routines, the caller should #include ckucmd.h, and
        !            42:  set the program's prompt by calling cmsetp().  If the file parsing
        !            43:  functions cmifi and cmofi are to be used, this module must be linked
        !            44:  with a ck?fio file system support module for the appropriate system,
        !            45:  e.g. ckufio for Unix.  If the caller puts the terminal in
        !            46:  character wakeup ("cbreak") mode with no echo, then these functions will
        !            47:  provide line editing -- character, word, and line deletion, as well as
        !            48:  keyword and filename completion upon ESC and help strings, keyword, or
        !            49:  file menus upon '?'.  If the caller puts the terminal into character
        !            50:  wakeup/noecho mode, care should be taken to restore it before exit from
        !            51:  or interruption of the program.  If the character wakeup mode is not
        !            52:  set, the system's own line editor may be used.
        !            53: 
        !            54:  Author: Frank da Cruz (SY.FDC@CU20B),
        !            55:  Columbia University Center for Computing Activities, January 1985.
        !            56:  Copyright (C) 1985, Trustees of Columbia University in the City of New York.
        !            57:  Permission is granted to any individual or institution to use, copy, or
        !            58:  redistribute this software so long as it is not sold for profit, provided this
        !            59:  copyright notice is retained. 
        !            60: */
        !            61: 
        !            62: /* Includes */
        !            63: 
        !            64: #include <stdio.h>                     /* Standard C I/O package */
        !            65: #include <ctype.h>                     /* Character types */
        !            66: #include "ckucmd.h"                    /* Command parsing definitions */
        !            67: #include "ckcdeb.h"                    /* Formats for debug() */
        !            68: 
        !            69: /* Local variables */
        !            70: 
        !            71: int psetf = 0,                         /* Flag that prompt has been set */
        !            72:     cc = 0,                            /* Character count */
        !            73:     dpx = 0;                           /* Duplex (0 = full) */
        !            74: 
        !            75: int hw = HLPLW,                                /* Help line width */
        !            76:     hc = HLPCW,                                /* Help line column width */
        !            77:     hh,                                        /* Current help column number */
        !            78:     hx;                                        /* Current help line position */
        !            79: 
        !            80: #define PROML 60                       /* Maximum length for prompt */
        !            81: 
        !            82: char cmprom[PROML+1];                  /* Program's prompt */
        !            83: char *dfprom = "Command? ";            /* Default prompt */
        !            84: 
        !            85: char cmerrp[PROML+1];                  /* Program's error message prefix */
        !            86: 
        !            87: int cmflgs;                            /* Command flags */
        !            88: 
        !            89: char cmdbuf[CMDBL+4];                  /* Command buffer */
        !            90: char hlpbuf[HLPBL+4];                  /* Help string buffer */
        !            91: char atmbuf[ATMBL+4];                  /* Atom buffer */
        !            92: char filbuf[ATMBL+4];                  /* File name buffer */
        !            93: 
        !            94: /* Command buffer pointers */
        !            95: 
        !            96: static char *bp,                       /* Current command buffer position */
        !            97:     *pp,                               /* Start of current field */
        !            98:     *np;                               /* Start of next field */
        !            99: 
        !           100: long zchki();                          /* From ck?fio.c. */
        !           101: 
        !           102: 
        !           103: /*  C M S E T P  --  Set the program prompt.  */
        !           104: 
        !           105: cmsetp(s) char *s; {
        !           106:     char *sx, *sy, *strncpy();
        !           107:     psetf = 1;                         /* Flag that prompt has been set. */
        !           108:     strncpy(cmprom,s,PROML - 1);       /* Copy the string. */
        !           109:     cmprom[PROML] = NUL;               /* Ensure null terminator. */
        !           110:     sx = cmprom; sy = cmerrp;          /* Also use as error message prefix. */
        !           111:     while (*sy++ = *sx++) ;            /* Copy. */
        !           112:     sy -= 2; if (*sy == '>') *sy = NUL;        /* Delete any final '>'. */
        !           113: }
        !           114: /*  C M S A V P  --  Save a copy of the current prompt.  */
        !           115: 
        !           116: cmsavp(s,n) int n; char s[]; {
        !           117:     extern char        *strncpy();                                     /* +1   */
        !           118:     strncpy(s,cmprom,n-1);
        !           119:     s[n] = NUL;
        !           120: }
        !           121: 
        !           122: /*  P R O M P T  --  Issue the program prompt.  */
        !           123: 
        !           124: prompt() {
        !           125:     if (psetf == 0) cmsetp(dfprom);    /* If no prompt set, set default. */
        !           126:     printf("\r%s",cmprom);             /* Print the prompt. */
        !           127: }
        !           128: 
        !           129: 
        !           130: /*  C M R E S  --  Reset pointers to beginning of command buffer.  */
        !           131: 
        !           132: cmres() {  
        !           133:     cc = 0;                            /* Reset character counter. */
        !           134:     pp = np = bp = cmdbuf;             /* Point to command buffer. */
        !           135:     cmflgs = -5;                       /* Parse not yet started. */
        !           136: }
        !           137: 
        !           138: 
        !           139: /*  C M I N I  --  Clear the command and atom buffers, reset pointers.  */
        !           140: 
        !           141: /*
        !           142: The argument specifies who is to echo the user's typein --
        !           143:   1 means the cmd package echoes
        !           144:   0 somebody else (system, front end, terminal) echoes
        !           145: */
        !           146: cmini(d) int d; {
        !           147:     for (bp = cmdbuf; bp < cmdbuf+CMDBL; bp++) *bp = NUL;
        !           148:     *atmbuf = NUL;
        !           149:     dpx = d;
        !           150:     cmres();
        !           151: }
        !           152: 
        !           153: stripq(s) char *s; {                   /* Function to strip '\' quotes */
        !           154:     char *t;
        !           155:     while (*s) {
        !           156:        if (*s == '\\') {
        !           157:            for (t = s; *t != '\0'; t++) *t = *(t+1);
        !           158:        }
        !           159:        s++;
        !           160:     }
        !           161: }
        !           162: 
        !           163: 
        !           164: /*  C M N U M  --  Parse a number in the indicated radix  */
        !           165: 
        !           166: /*  For now, only works for positive numbers in base 10.  */
        !           167: 
        !           168: /*
        !           169:  Returns
        !           170:    -3 if no input present when required,
        !           171:    -2 if user typed an illegal number,
        !           172:    -1 if reparse needed,
        !           173:     0 otherwise, with n set to number that was parsed
        !           174: */
        !           175: cmnum(xhlp,xdef,radix,n) char *xhlp, *xdef; int radix, *n; {
        !           176:     int x; char *s;
        !           177: 
        !           178:     if (radix != 10) {                 /* Just do base 10 for now */
        !           179:        printf("cmnum: illegal radix - %d\n",radix);
        !           180:        return(-1);
        !           181:     }
        !           182: 
        !           183:     x = cmfld(xhlp,xdef,&s);
        !           184:     debug(F101,"cmnum: cmfld","",x);
        !           185:     if (x < 0) return(x);    /* Parse a field */
        !           186: 
        !           187:     if (digits(atmbuf)) {              /* Convert to number */
        !           188:        *n = atoi(atmbuf);
        !           189:        return(x);
        !           190:     } else {
        !           191:        printf("\n?not a number - %s\n",s);
        !           192:        return(-2);     
        !           193:     }
        !           194: }
        !           195: 
        !           196: 
        !           197: /*  C M O F I  --  Parse the name of an output file  */
        !           198: 
        !           199: /*
        !           200:  Depends on the external function zchko(); if zchko() not available, use
        !           201:  cmfld() to parse output file names.
        !           202: 
        !           203:  Returns
        !           204:    -3 if no input present when required,
        !           205:    -2 if permission would be denied to create the file,
        !           206:    -1 if reparse needed,
        !           207:     0 or 1 otherwise, with xp pointing to name.
        !           208: */
        !           209: cmofi(xhlp,xdef,xp) char *xhlp, *xdef, **xp; {
        !           210:     int x; char *s;
        !           211: 
        !           212:     if (*xhlp == NUL) xhlp = "Output file";
        !           213:     *xp = "";
        !           214: 
        !           215:     if ((x = cmfld(xhlp,xdef,&s)) < 0) return(x);
        !           216: 
        !           217:     if (chkwld(s)) {
        !           218:        printf("\n?Wildcards not allowed - %s\n",s);
        !           219:        return(-2);
        !           220:     }
        !           221:     if (zchko(s) < 0) {
        !           222:        printf("\n?Write permission denied - %s\n",s);
        !           223:        return(-2);
        !           224:     } else {
        !           225:        *xp = s;
        !           226:        return(x);
        !           227:     }
        !           228: }
        !           229: 
        !           230: 
        !           231: /*  C M I F I  --  Parse the name of an existing file  */
        !           232: 
        !           233: /*
        !           234:  This function depends on the external functions:
        !           235:    zchki()  - Check if input file exists and is readable.
        !           236:    zxpand() - Expand a wild file specification into a list.
        !           237:    znext()  - Return next file name from list.
        !           238:  If these functions aren't available, then use cmfld() to parse filenames.
        !           239: */
        !           240: /*
        !           241:  Returns
        !           242:    -4 EOF
        !           243:    -3 if no input present when required,
        !           244:    -2 if file does not exist or is not readable,
        !           245:    -1 if reparse needed,
        !           246:     0 or 1 otherwise, with:
        !           247:        xp pointing to name,
        !           248:        wild = 1 if name contains '*' or '?', 0 otherwise.
        !           249: */
        !           250: cmifi(xhlp,xdef,xp,wild) char *xhlp, *xdef, **xp; int *wild; {
        !           251:     int i, x, xc; long y; char *sp;
        !           252: 
        !           253:     cc = xc = 0;                       /* Initialize counts & pointers */
        !           254:     *xp = "";
        !           255:     if ((x = cmflgs) != 1) {           /* Already confirmed? */
        !           256:        x = getwd();                    /* No, get a word */
        !           257:     } else {
        !           258:        cc = setatm(xdef);              /* If so, use default, if any. */
        !           259:     }
        !           260:     *xp = atmbuf;                      /* Point to result. */
        !           261:     *wild = chkwld(*xp);
        !           262: 
        !           263:     while (1) {
        !           264:        xc += cc;                       /* Count the characters. */
        !           265:        debug(F111,"cmifi: getwd",atmbuf,xc);
        !           266:        switch (x) {
        !           267:            case -4:                    /* EOF */
        !           268:            case -2:                    /* Out of space. */
        !           269:            case -1:                    /* Reparse needed */
        !           270:                return(x);
        !           271: 
        !           272: /* cont'd... */
        !           273: 
        !           274: 
        !           275: /* ...cmifi(), cont'd */
        !           276: 
        !           277: 
        !           278:            case 0:                     /* SP or NL */
        !           279:            case 1:
        !           280:                if (xc == 0) *xp = xdef;    /* If no input, return default. */
        !           281:                else *xp = atmbuf;
        !           282:                if (**xp == NUL) return(-3); /* If field empty, return -3. */
        !           283:                
        !           284:                /* If filespec is wild, see if there are any matches */
        !           285: 
        !           286:                *wild = chkwld(*xp);
        !           287:                debug(F101," *wild","",*wild);
        !           288:                if (*wild != 0) {
        !           289:                    y = zxpand(*xp);
        !           290:                    if (y == 0) {
        !           291:                        printf("\n?No files match - %s\n",*xp);
        !           292:                        return(-2);
        !           293:                    } else if (y < 0) {
        !           294:                        printf("\n?Too many files match - %s\n",*xp);
        !           295:                        return(-2);
        !           296:                    } else return(x);
        !           297:                }
        !           298: 
        !           299:                /* If not wild, see if it exists and is readable. */
        !           300: 
        !           301:                y = zchki(*xp);
        !           302:                if (y == -3) {
        !           303:                    printf("\n?Read permission denied - %s\n",*xp);
        !           304:                    return(-2);
        !           305:                } else if (y == -2) {
        !           306:                    printf("\n?File not readable - %s\n",*xp);
        !           307:                    return(-2);
        !           308:                } else if (y < 0) {
        !           309:                    printf("\n?File not found - %s\n",*xp);
        !           310:                    return(-2);
        !           311:                }
        !           312:                return(x);
        !           313: /* cont'd... */
        !           314: 
        !           315: 
        !           316: /* ...cmifi(), cont'd */
        !           317: 
        !           318: 
        !           319:            case 2:                     /* ESC */
        !           320:                if (xc == 0) {
        !           321:                    if (*xdef != '\0') {
        !           322:                        printf("%s ",xdef); /* If at beginning of field, */
        !           323:                        addbuf(xdef);   /* supply default. */
        !           324:                        cc = setatm(xdef);
        !           325:                    } else {            /* No default */
        !           326:                        putchar(BEL);
        !           327:                    }
        !           328:                    break;
        !           329:                } 
        !           330:                if (*wild = chkwld(*xp)) {  /* No completion if wild */
        !           331:                    putchar(BEL);
        !           332:                    break;
        !           333:                }
        !           334:                sp = atmbuf + cc;
        !           335:                *sp++ = '*';
        !           336:                *sp-- = '\0';
        !           337:                y = zxpand(atmbuf);     /* Add * and expand list. */
        !           338:                *sp = '\0';             /* Remove *. */
        !           339: 
        !           340:                if (y == 0) {
        !           341:                    printf("\n?No files match - %s\n",atmbuf);
        !           342:                    return(-2);
        !           343:                } else if (y < 0) {
        !           344:                    printf("\n?Too many files match - %s\n",atmbuf);
        !           345:                    return(-2);
        !           346:                } else if (y > 1) {     /* Not unique, just beep. */
        !           347:                    putchar(BEL);
        !           348:                } else {                /* Unique, complete it.  */
        !           349:                    znext(filbuf);      /* Get whole name of file. */
        !           350:                    sp = filbuf + cc;   /* Point past what user typed. */
        !           351:                    printf("%s ",sp);   /* Complete the name. */
        !           352:                    addbuf(sp);         /* Add the characters to cmdbuf. */
        !           353:                    setatm(pp);         /* And to atmbuf. */
        !           354:                    *xp = atmbuf;       /* Return pointer to atmbuf. */
        !           355:                    return(cmflgs = 0);
        !           356:                }
        !           357:                break;
        !           358: 
        !           359: /* cont'd... */
        !           360: 
        !           361: 
        !           362: /* ...cmifi(), cont'd */
        !           363: 
        !           364: 
        !           365:            case 3:                     /* Question mark */
        !           366:                if (*xhlp == NUL)
        !           367:                    printf(" Input file specification");
        !           368:                else
        !           369:                    printf(" %s",xhlp);
        !           370:                if (xc > 0) {
        !           371:                    sp = atmbuf + cc;   /* Insert * at end */
        !           372:                    *sp++ = '*';
        !           373:                    *sp-- = '\0';
        !           374:                    y = zxpand(atmbuf);
        !           375:                    *sp = '\0';
        !           376:                    if (y == 0) {                   
        !           377:                        printf("\n?No files match - %s\n",atmbuf);
        !           378:                        return(-2);
        !           379:                    } else if (y < 0) {
        !           380:                        printf("\n?Too many file match - %s\n",atmbuf);
        !           381:                        return(-2);
        !           382:                    } else {
        !           383:                        printf(", one of the following:\n");
        !           384:                        clrhlp();
        !           385:                        for (i = 0; i < y; i++) {
        !           386:                            znext(filbuf);
        !           387:                            addhlp(filbuf);
        !           388:                        }
        !           389:                        dmphlp();
        !           390:                    }
        !           391:                } else printf("\n");
        !           392:                printf("%s%s",cmprom,cmdbuf);
        !           393:                break;
        !           394:        }
        !           395:     x = getwd();
        !           396:     }
        !           397: }
        !           398: 
        !           399: 
        !           400: 
        !           401: /*  C H K W L D  --  Check for wildcard characters '*' or '?'  */
        !           402: 
        !           403: chkwld(s) char *s; {
        !           404: 
        !           405:     for ( ; *s != '\0'; s++) {
        !           406:        if ((*s == '*') || (*s == '?'))
        !           407:            return(1);
        !           408:     }
        !           409:     return(0);
        !           410: }
        !           411: 
        !           412: 
        !           413: /*  C M F L D  --  Parse an arbitrary field  */
        !           414: /*
        !           415:  Returns
        !           416:    -3 if no input present when required,
        !           417:    -2 if field too big for buffer,
        !           418:    -1 if reparse needed,
        !           419:     0 otherwise, xp pointing to string result.
        !           420: */
        !           421: cmfld(xhlp,xdef,xp) char *xhlp, *xdef, **xp; {
        !           422:     int x, xc;
        !           423: 
        !           424:     cc = xc = 0;                       /* Initialize counts & pointers */
        !           425:     *xp = "";
        !           426:     if ((x = cmflgs) != 1) {           /* Already confirmed? */
        !           427:        x = getwd();                    /* No, get a word */
        !           428:     } else {
        !           429:        cc = setatm(xdef);              /* If so, use default, if any. */
        !           430:     }
        !           431:     *xp = atmbuf;                      /* Point to result. */
        !           432: 
        !           433:     while (1) {
        !           434:        xc += cc;                       /* Count the characters. */
        !           435:        debug(F111,"cmfld: getwd",atmbuf,xc);
        !           436:        debug(F101," x","",x);
        !           437:        switch (x) {
        !           438:            case -4:                    /* EOF */
        !           439:            case -2:                    /* Out of space. */
        !           440:            case -1:                    /* Reparse needed */
        !           441:                return(x);
        !           442:            case 0:                     /* SP or NL */
        !           443:            case 1:
        !           444:                if (xc == 0) *xp = xdef;    /* If no input, return default. */
        !           445:                else *xp = atmbuf;
        !           446:                if (**xp == NUL) x = -3;    /* If field empty, return -3. */
        !           447:                return(x);
        !           448:            case 2:                     /* ESC */
        !           449:                if (xc == 0) {
        !           450:                    printf("%s ",xdef); /* If at beginning of field, */
        !           451:                    addbuf(xdef);       /* supply default. */
        !           452:                    cc = setatm(xdef);  /* Return as if whole field */
        !           453:                    return(0);          /* typed, followed by space. */
        !           454:                } else {
        !           455:                    putchar(BEL);       /* Beep if already into field. */
        !           456:                }                   
        !           457:                break;
        !           458:            case 3:                     /* Question mark */
        !           459:                if (*xhlp == NUL)
        !           460:                    printf(" Please complete this field");
        !           461:                else
        !           462:                    printf(" %s",xhlp);
        !           463:                printf("\n%s%s",cmprom,cmdbuf);
        !           464:                break;
        !           465:        }
        !           466:     x = getwd();
        !           467:     }
        !           468: }
        !           469: 
        !           470: 
        !           471: /*  C M T X T  --  Get a text string, including confirmation  */
        !           472: 
        !           473: /*
        !           474:   Print help message 'xhlp' if ? typed, supply default 'xdef' if null
        !           475:   string typed.  Returns
        !           476: 
        !           477:    -1 if reparse needed or buffer overflows.
        !           478:     1 otherwise.
        !           479: 
        !           480:   with cmflgs set to return code, and xp pointing to result string.
        !           481: */
        !           482: 
        !           483: cmtxt(xhlp,xdef,xp) char *xhlp; char *xdef; char **xp; {
        !           484: 
        !           485:     int x;
        !           486:     static int xc;
        !           487: 
        !           488:     debug(F101,"cmtxt, cmflgs","",cmflgs);
        !           489:     cc = 0;                            /* Start atmbuf counter off at 0 */
        !           490:     if (cmflgs == -1) {                        /* If reparsing, */
        !           491:        xc = strlen(*xp);               /* get back the total text length, */
        !           492:     } else {                           /* otherwise, */
        !           493:        *xp = "";                       /* start fresh. */
        !           494:        xc = 0;
        !           495:     }
        !           496:     *atmbuf = NUL;                     /* And empty atom buffer. */
        !           497:     if ((x = cmflgs) != 1) {
        !           498:        x = getwd();                    /* Get first word. */
        !           499:        *xp = pp;                       /* Save pointer to it. */
        !           500:     }
        !           501:     while (1) {
        !           502:        xc += cc;                       /* Char count for all words. */
        !           503:        debug(F111,"cmtxt: getwd",atmbuf,xc);
        !           504:        debug(F101," x","",x);
        !           505:        switch (x) {
        !           506:            case -4:                    /* EOF */
        !           507:            case -2:                    /* Overflow */
        !           508:            case -1:                    /* Deletion */
        !           509:                return(x);
        !           510:            case 0:                     /* Space */
        !           511:                xc++;                   /* Just count it */
        !           512:                break;
        !           513:            case 1:                     /* CR or LF */
        !           514:                if (xc == 0) *xp = xdef;
        !           515:                return(x);
        !           516:            case 2:                     /* ESC */
        !           517:                if (xc == 0) {
        !           518:                    printf("%s ",xdef);
        !           519:                    cc = addbuf(xdef);
        !           520:                } else {
        !           521:                    putchar(BEL);
        !           522:                }
        !           523:                break;
        !           524:            case 3:                     /* Question Mark */
        !           525:                if (*xhlp == NUL)
        !           526:                    printf(" Text string");
        !           527:                else
        !           528:                    printf(" %s",xhlp);
        !           529:                printf("\n%s%s",cmprom,cmdbuf);
        !           530:                break;
        !           531:             default:
        !           532:                printf("\n?Unexpected return code from getwd() - %d\n",x);
        !           533:                return(-2);
        !           534:         }
        !           535:        x = getwd();
        !           536:     }
        !           537: }
        !           538: 
        !           539: 
        !           540: /*  C M K E Y  --  Parse a keyword  */
        !           541: 
        !           542: /*
        !           543:  Call with:
        !           544:    table    --  keyword table, in 'struct keytab' format;
        !           545:    n        --  number of entries in table;
        !           546:    xhlp     --  pointer to help string;
        !           547:    xdef     --  pointer to default keyword;
        !           548: 
        !           549:  Returns:
        !           550:    -3       --  no input supplied and no default available
        !           551:    -2       --  input doesn't uniquely match a keyword in the table
        !           552:    -1       --  user deleted too much, command reparse required
        !           553:     n >= 0  --  value associated with keyword
        !           554: */
        !           555: 
        !           556: cmkey(table,n,xhlp,xdef) struct keytab table[]; int n; char *xhlp, *xdef; {
        !           557:     int i, y, z, zz, xc;
        !           558:     char *xp;
        !           559: 
        !           560:     xc = cc = 0;                       /* Clear character counters. */
        !           561: 
        !           562:     if ((zz = cmflgs) == 1)            /* Command already entered? */
        !           563:        setatm(xdef);
        !           564:     else zz = getwd(); 
        !           565: 
        !           566: debug(F101,"cmkey: table length","",n);
        !           567: debug(F101," cmflgs","",cmflgs);
        !           568: debug(F101," zz","",zz);
        !           569: while (1) {
        !           570:     xc += cc;
        !           571:     debug(F111,"cmkey: getwd",atmbuf,xc);
        !           572: 
        !           573:     switch(zz) {
        !           574:        case -4:                        /* EOF */
        !           575:        case -2:                        /* Buffer overflow */
        !           576:        case -1:                        /* Or user did some deleting. */
        !           577:            return(zz);
        !           578: 
        !           579:        case 0:                         /* User terminated word with space */
        !           580:        case 1:                         /* or newline */
        !           581:            if (cc == 0) setatm(xdef);
        !           582:            y = lookup(table,atmbuf,n,&z);
        !           583:            switch (y) {
        !           584:                case -2:
        !           585:                    printf("\n?Ambiguous - %s\n",atmbuf);
        !           586:                    return(cmflgs = -2);
        !           587:                case -1:
        !           588:                    printf("\n?Invalid - %s\n",atmbuf);
        !           589:                    return(cmflgs = -2);
        !           590:                default:
        !           591:                    break;
        !           592:            }
        !           593:            return(y);
        !           594: 
        !           595: /* cont'd... */
        !           596: 
        !           597: 
        !           598: /* ...cmkey(), cont'd */
        !           599: 
        !           600:        case 2:                         /* User terminated word with ESC */
        !           601:            if (cc == 0) {
        !           602:                if (*xdef != NUL) {     /* Nothing in atmbuf */
        !           603:                    printf("%s ",xdef); /* Supply default if any */
        !           604:                    addbuf(xdef);
        !           605:                    cc = setatm(xdef);
        !           606:                    debug(F111,"cmkey: default",atmbuf,cc);
        !           607:                } else {
        !           608:                    putchar(BEL);       /* No default, just beep */
        !           609:                    break;
        !           610:                }
        !           611:            }
        !           612:            y = lookup(table,atmbuf,n,&z); /* Something in atmbuf */
        !           613:            debug(F111,"cmkey: esc",atmbuf,y);
        !           614:            if (y == -2) {
        !           615:                putchar(BEL);
        !           616:                break;
        !           617:            }
        !           618:            if (y == -1) {
        !           619:                printf("\n?Invalid - %s\n",atmbuf);
        !           620:                return(cmflgs = -2);
        !           621:            }
        !           622:            xp = table[z].kwd + cc;
        !           623:            printf("%s ",xp);
        !           624:            addbuf(xp);
        !           625:            debug(F110,"cmkey: addbuf",cmdbuf,0);
        !           626:            return(y);
        !           627: 
        !           628: /* cont'd... */
        !           629: 
        !           630: 
        !           631: /* ...cmkey(), cont'd */
        !           632: 
        !           633:        case 3:                         /* User terminated word with "?" */
        !           634:            y = lookup(table,atmbuf,n,&z);
        !           635:            if (y > -1) {
        !           636:                printf(" %s\n%s%s",table[z].kwd,cmprom,cmdbuf);
        !           637:                break;
        !           638:            } else if (y == -1) {
        !           639:                printf("\n?Invalid\n");
        !           640:                return(cmflgs = -2);
        !           641:            }
        !           642: 
        !           643:            if (*xhlp == NUL)
        !           644:                printf(" One of the following:\n");
        !           645:            else
        !           646:                printf(" %s, one of the following:\n",xhlp);
        !           647: 
        !           648:            clrhlp();
        !           649:            for (i = 0; i < n; i++) {   
        !           650:                if (!strncmp(table[i].kwd,atmbuf,cc)
        !           651:                        && !test(table[i].flgs,CM_INV))
        !           652:                    addhlp(table[i].kwd);
        !           653:            }
        !           654:            dmphlp();
        !           655:            printf("%s%s", cmprom, cmdbuf);
        !           656:            break;
        !           657: 
        !           658:        default:            
        !           659:            printf("\n%d - Unexpected return code from getwd\n",zz);
        !           660:            return(cmflgs = -2);
        !           661:         }
        !           662:        zz = getwd();
        !           663:     }
        !           664: }
        !           665: 
        !           666: 
        !           667: /*  C M C F M  --  Parse command confirmation (end of line)  */
        !           668: 
        !           669: /*
        !           670:  Returns
        !           671:    -2: User typed anything but whitespace or newline
        !           672:    -1: Reparse needed
        !           673:     0: Confirmation was received
        !           674: */
        !           675: 
        !           676: cmcfm() {
        !           677:     int x, xc;
        !           678: 
        !           679:     debug(F101,"cmcfm: cmflgs","",cmflgs);
        !           680: 
        !           681:     xc = cc = 0;
        !           682:     if (cmflgs == 1) return(0);
        !           683: 
        !           684:     while (1) {
        !           685:        x = getwd();
        !           686:        xc += cc;
        !           687:        debug(F111,"cmcfm: getwd",atmbuf,xc);
        !           688:         switch (x) {
        !           689:            case -4:                    /* EOF */
        !           690:            case -2:
        !           691:            case -1:
        !           692:                return(x);
        !           693: 
        !           694:            case 0:                     /* Space */
        !           695:                continue;
        !           696:            case 1:                     /* End of line */
        !           697:                if (xc > 0) {
        !           698:                    printf("?Not confirmed - %s\n",atmbuf);
        !           699:                    return(-2);
        !           700:                } else return(0);                   
        !           701:            case 2:
        !           702:                putchar(BEL);
        !           703:                continue;
        !           704: 
        !           705:             case 3:
        !           706:                if (xc > 0) {
        !           707:                    printf("\n?Not confirmed - %s\n",atmbuf);
        !           708:                    return(-2);
        !           709:                }
        !           710:                printf("\n Type a carriage return to confirm the command\n");
        !           711:                printf("%s%s",cmprom,cmdbuf);
        !           712:                continue;
        !           713:        }
        !           714:     }
        !           715: }
        !           716: 
        !           717: 
        !           718: /* Keyword help routines */
        !           719: 
        !           720: 
        !           721: /*  C L R H L P -- Initialize/Clear the help line buffer  */
        !           722: 
        !           723: clrhlp() {                             /* Clear the help buffer */
        !           724:     hlpbuf[0] = NUL;
        !           725:     hh = hx = 0;
        !           726: }
        !           727: 
        !           728: 
        !           729: /*  A D D H L P  --  Add a string to the help line buffer  */
        !           730: 
        !           731: addhlp(s) char *s; {                   /* Add a word to the help buffer */
        !           732:     int j;
        !           733: 
        !           734:     hh++;                              /* Count this column */
        !           735: 
        !           736:     for (j = 0; (j < hc) && (*s != NUL); j++) { /* Fill the column */
        !           737:        hlpbuf[hx++] = *s++;
        !           738:     }
        !           739:     if (*s != NUL)                     /* Still some chars left in string? */
        !           740:        hlpbuf[hx-1] = '+';             /* Mark as too long for column. */
        !           741: 
        !           742:     if (hh < (hw / hc))        {               /* Pad col with spaces if necessary */
        !           743:        for (; j < hc; j++) {
        !           744:            hlpbuf[hx++] = SP;
        !           745:         }
        !           746:     } else {                           /* If last column, */
        !           747:        hlpbuf[hx++] = NUL;             /* no spaces. */
        !           748:        dmphlp();                       /* Print it. */
        !           749:        return;
        !           750:     }
        !           751: }
        !           752: 
        !           753: 
        !           754: /*  D M P H L P  --  Dump the help line buffer  */
        !           755: 
        !           756: dmphlp() {                             /* Print the help buffer */
        !           757:     hlpbuf[hx++] = NUL;
        !           758:     printf(" %s\n",hlpbuf);
        !           759:     clrhlp();
        !           760: }
        !           761: 
        !           762: 
        !           763: /*  L O O K U P  --  Lookup the string in the given array of strings  */
        !           764: 
        !           765: /*
        !           766:  Call this way:  v = lookup(table,word,n,&x);
        !           767: 
        !           768:    table - a 'struct keytab' table.
        !           769:    word  - the target string to look up in the table.
        !           770:    n     - the number of elements in the table.
        !           771:    x     - address of an integer for returning the table array index.
        !           772: 
        !           773:  The keyword table must be arranged in ascending alphabetical order, and
        !           774:  all letters must be lowercase.
        !           775: 
        !           776:  Returns the keyword's associated value ( zero or greater ) if found,
        !           777:  with the variable x set to the array index, or:
        !           778: 
        !           779:   -3 if nothing to look up (target was null),
        !           780:   -2 if ambiguous,
        !           781:   -1 if not found.
        !           782: 
        !           783:  A match is successful if the target matches a keyword exactly, or if
        !           784:  the target is a prefix of exactly one keyword.  It is ambiguous if the
        !           785:  target matches two or more keywords from the table.
        !           786: */
        !           787: 
        !           788: lookup(table,cmd,n,x) char *cmd; struct keytab table[]; int n, *x; {
        !           789: 
        !           790:     int i, v, cmdlen;
        !           791: 
        !           792: /* Lowercase & get length of target, if it's null return code -3. */
        !           793: 
        !           794:     if ((((cmdlen = lower(cmd))) == 0) || (n < 1)) return(-3);
        !           795: 
        !           796: /* Not null, look it up */
        !           797: 
        !           798:     for (i = 0; i < n-1; i++) {
        !           799:        if (!strcmp(table[i].kwd,cmd) ||
        !           800:            ((v = !strncmp(table[i].kwd,cmd,cmdlen)) &&
        !           801:              strncmp(table[i+1].kwd,cmd,cmdlen))) {
        !           802:                *x = i;
        !           803:                return(table[i].val);
        !           804:             }
        !           805:        if (v) return(-2);
        !           806:     }  
        !           807: 
        !           808: /* Last (or only) element */
        !           809: 
        !           810:     if (!strncmp(table[n-1].kwd,cmd,cmdlen)) {
        !           811:        *x = n-1;
        !           812:        return(table[n-1].val);
        !           813:     } else return(-1);
        !           814: }
        !           815: 
        !           816: 
        !           817: /*  G E T W D  --  Gets a "word" from the command input stream  */
        !           818: 
        !           819: /*
        !           820: Usage: retcode = getwd();
        !           821: 
        !           822: Returns:
        !           823:  -4 if end of file (e.g. pipe broken)
        !           824:  -2 if command buffer overflows
        !           825:  -1 if user did some deleting
        !           826:   0 if word terminates with SP or tab
        !           827:   1 if ... CR
        !           828:   2 if ... ESC
        !           829:   3 if ... ?
        !           830: 
        !           831: With:
        !           832:   pp pointing to beginning of word in buffer
        !           833:   bp pointing to after current position
        !           834:   atmbuf containing a copy of the word
        !           835:   cc containing the number of characters in the word copied to atmbuf
        !           836: */
        !           837: getwd() {
        !           838: 
        !           839:     int c;                             /* Current char */
        !           840:     static int inword = 0;             /* Flag for start of word found */
        !           841:     int quote = 0;                     /* Flag for quote character */
        !           842:     int echof = 0;                     /* Flag for whether to echo */
        !           843:     int ignore = 0;
        !           844: 
        !           845:     pp = np;                           /* Start of current field */
        !           846:     debug(F101,"getwd: cmdbuf","",(int) cmdbuf);
        !           847:     debug(F101," bp","",(int) bp);
        !           848:     debug(F101," pp","",(int) pp);
        !           849:     debug(F110," cmdbuf",cmdbuf,0);
        !           850: 
        !           851:     while (bp < cmdbuf+CMDBL) {                /* Loop */
        !           852: 
        !           853:        ignore = echof = 0;             /* Flag for whether to echo */
        !           854: 
        !           855:        if ((c = *bp) == NUL) {         /* Get next character */
        !           856:            if (dpx) echof = 1;         /* from reparse buffer */
        !           857:            c = getchar();              /* or from tty. */
        !           858:            if (c == EOF) return(-4);
        !           859:        } else ignore = 1;
        !           860: 
        !           861:        if (quote == 0) {
        !           862: 
        !           863:            if (!ignore && (c == '\\')) { /* Quote character */
        !           864:               quote = 1;
        !           865:               continue;
        !           866:            }
        !           867:            if (c == FF) {              /* Formfeed. */
        !           868:                c = NL;                 /* Replace with newline */
        !           869:                system("clear");        /* and clear the screen. */
        !           870:            }
        !           871: 
        !           872:            if (c == HT) c = SP;        /* Substitute space for tab. */
        !           873: 
        !           874: /* cont'd... */
        !           875: 
        !           876: 
        !           877: /* ...getwd(), cont'd */
        !           878: 
        !           879:            if (c == SP) {              /* If space */
        !           880:                *bp++ = c;              /* deposit it in buffer. */
        !           881:                if (echof) putchar(c);  /* echo it. */
        !           882:                if (inword == 0) {      /* If leading, gobble it. */
        !           883:                    pp++;
        !           884:                    continue;
        !           885:                } else {                /* If terminating, return. */
        !           886:                    np = bp;
        !           887:                    setatm(pp);
        !           888:                    inword = 0;
        !           889:                    return(cmflgs = 0);
        !           890:                }
        !           891:            }
        !           892:            if (c == NL || c == CR) {   /* CR, LF */
        !           893:                *bp = NUL;              /* End the string */
        !           894:                if (echof) {            /* If echoing, */
        !           895:                    putchar(c);         /* echo the typein */
        !           896: #ifdef aegis
        !           897:                    if (c == CR) putchar(NL);
        !           898: #endif
        !           899:                }
        !           900:                np = bp;                /* Where to start next field. */
        !           901:                setatm(pp);             /* Copy this field to atom buffer. */
        !           902:                inword = 0;
        !           903:                return(cmflgs = 1);
        !           904:            }
        !           905:            if (!ignore && (c == '?')) { /* Question mark */
        !           906:                putchar(c);
        !           907:                *bp = NUL;
        !           908:                setatm(pp);
        !           909:                return(cmflgs = 3);
        !           910:            }
        !           911:            if (c == ESC) {             /* ESC */
        !           912:                *bp = NUL;
        !           913:                setatm(pp);
        !           914:                return(cmflgs = 2);
        !           915:            }
        !           916:            if (c == BS || c == RUB) {  /* Character deletion */
        !           917:                if (bp > cmdbuf) {      /* If still in buffer... */
        !           918:                    printf("\b \b");    /* erase character from screen, */
        !           919:                    bp--;               /* point behind it, */
        !           920:                    if (*bp == SP) inword = 0; /* Flag if current field gone */
        !           921:                    *bp = NUL;          /* Erase character from buffer. */
        !           922:                } else {                /* Otherwise, */
        !           923:                    putchar(BEL);       /* beep, */
        !           924:                    cmres();            /* and start parsing a new command. */
        !           925:                }
        !           926:                if (pp < bp) continue;
        !           927:                else return(cmflgs = -1);
        !           928:            }
        !           929:            if (c == LDEL) {            /* ^U, line deletion */
        !           930:                while ((bp--) > cmdbuf) {
        !           931:                    printf("\b \b");
        !           932:                    *bp = NUL;
        !           933:                }
        !           934:                cmres();                /* Restart the command. */
        !           935:                inword = 0;
        !           936:                return(cmflgs = -1);
        !           937:            }
        !           938: 
        !           939: /* cont'd... */
        !           940: 
        !           941: 
        !           942: /* ...getwd(), cont'd */
        !           943: 
        !           944:            if (c == WDEL) {            /* ^W, word deletion */
        !           945:                if (bp <= cmdbuf) {     /* Beep if nothing to delete */
        !           946:                    putchar(BEL);
        !           947:                    cmres();
        !           948:                    return(cmflgs = -1);
        !           949:                }
        !           950:                bp--;
        !           951:                for ( ; (bp >= cmdbuf) && (*bp == SP) ; bp--) {
        !           952:                    printf("\b \b");
        !           953:                    *bp = NUL;
        !           954:                }
        !           955:                for ( ; (bp >= cmdbuf) && (*bp != SP) ; bp--) {
        !           956:                    printf("\b \b");
        !           957:                    *bp = NUL;
        !           958:                }
        !           959:                bp++;
        !           960:                inword = 0;
        !           961:                return(cmflgs = -1);
        !           962:            }
        !           963:            if (c == RDIS) {            /* ^R, redisplay */
        !           964:                *bp = NUL;
        !           965:                printf("\n%s%s",cmprom,cmdbuf);
        !           966:                continue;
        !           967:            }
        !           968:        }
        !           969:        if (echof) putchar(c);          /* If tty input, echo. */
        !           970:        inword = 1;                     /* Flag we're in a word. */
        !           971:        if (quote == 0 || c != NL) *bp++ = c;   /* And deposit it. */
        !           972:        quote = 0;                      /* Turn off quote. */
        !           973:     }                                  /* end of big while */
        !           974:     putchar(BEL);                      /* Get here if... */
        !           975:     printf("\n?Buffer full\n");
        !           976:     return(cmflgs = -2);
        !           977: }
        !           978: 
        !           979: 
        !           980: /* Utility functions */
        !           981: 
        !           982: /* A D D B U F  -- Add the string pointed to by cp to the command buffer  */
        !           983: 
        !           984: addbuf(cp) char *cp; {
        !           985:     int len = 0;
        !           986:     while ((*cp != NUL) && (bp < cmdbuf+CMDBL)) {
        !           987:        *bp++ = *cp++;                  /* Copy and */
        !           988:        len++;                          /* count the characters. */
        !           989:     }  
        !           990:     *bp++ = SP;                                /* Put a space at the end */
        !           991:     *bp = NUL;                         /* Terminate with a null */
        !           992:     np = bp;                           /* Update the next-field pointer */
        !           993:     return(len);                       /* Return the length */
        !           994: }
        !           995: 
        !           996: /*  S E T A T M  --  Deposit a string in the atom buffer  */
        !           997: 
        !           998: setatm(cp) char *cp; {
        !           999:     char *ap;
        !          1000:     cc = 0;
        !          1001:     ap = atmbuf;
        !          1002:     *ap = NUL;
        !          1003:     while (*cp == SP) cp++;
        !          1004:     while ((*cp != SP) && (*cp != NL) && (*cp != NUL) && (*cp != CR)) {
        !          1005:        *ap++ = *cp++;
        !          1006:        cc++;
        !          1007:     }
        !          1008:     *ap++ = NUL;
        !          1009:     return(cc);                                /* Return length */
        !          1010: }
        !          1011: 
        !          1012: /*  D I G I T S  -- Verify that all the characters in line are digits  */
        !          1013: 
        !          1014: digits(s) char *s; {
        !          1015:     while (*s) {
        !          1016:         if (!isdigit(*s)) return(0);
        !          1017:         s++;
        !          1018:     }
        !          1019:     return(1);
        !          1020: }
        !          1021: 
        !          1022: /*  L O W E R  --  Lowercase a string  */
        !          1023: 
        !          1024: lower(s) char *s; {
        !          1025:     int n = 0;
        !          1026:     while (*s) {
        !          1027:        if (isupper(*s)) *s = tolower(*s);
        !          1028:        s++, n++;
        !          1029:     }
        !          1030:     return(n);
        !          1031: }
        !          1032: 
        !          1033: /*  T E S T  --  Bit test  */
        !          1034: 
        !          1035: test(x,m) int x, m; { /*  Returns 1 if any bits from m are on in x, else 0  */
        !          1036:     return((x & m) ? 1 : 0);
        !          1037: }

unix.superglobalmegacorp.com

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