Annotation of coherent/b/bin/sh_B4_420/eval.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * sh/eval.c
                      3:  * Bourne shell.
                      4:  * Evaluation of parameter substitution, command substitution,
                      5:  * blank interpretation, and file name generation.
                      6:  */
                      7: 
                      8: #include "sh.h"
                      9: 
                     10: char   *arcp;          /* character position in argument */
                     11: int    argf = 1;       /* First character of argument flag */
                     12: int    argg = 0;       /* Glob seek, escape quoted glob chars */
                     13: int    argq = 0;       /* Quotation flag, no blanks or glob */
                     14: 
                     15: /*
                     16:  * Evaluate a string.
                     17:  */
                     18: eval(cp, f)
                     19: char *cp;
                     20: {
                     21:        register int m, c;
                     22: 
                     23:        strp = strt;
                     24:        arcp = cp;
                     25:        argf = 1;
                     26:        if (f==EHERE) {
                     27:                m = MHERE;
                     28:                argq = 2;
                     29:        } else if (f==EWORD) {
                     30:                m = MNQUO;
                     31:                argq = 2;
                     32:        } else {
                     33:                m = MNQUO;
                     34:                argq = 0;
                     35:        }
                     36:        argg = (f==EARGS || f==EPATT);
                     37: 
                     38:        while ((c = *arcp++) != '\0') {
                     39:                if (!class(c, m)) {
                     40:                        add_char(c);
                     41:                        continue;
                     42:                }
                     43:                switch (c) {
                     44:                case '"':       /* m == MNQUO || m == MDQUO */
                     45:                        m = ((argq ^= 1) & 1) ? MDQUO : MNQUO;
                     46:                        /*
                     47:                         * POSIX.2 says: If there are no positional
                     48:                         * parameters, the expansion of $@ shall generate
                     49:                         * zero fields, even when double-quoted.
                     50:                         */
                     51: #if 1
                     52:                        if (m == MDQUO && strcmp (arcp, "\"") == 0)
                     53:                                argf = 0;
                     54: #else
                     55:                        if (m==MDQUO && strcmp(arcp, "$@\"")!=0)
                     56:                                argf = 0;
                     57: #endif
                     58:                        continue;
                     59:                case '\'':      /* m == MNQUO */
                     60:                        while ((c = *arcp++) != '\'')
                     61:                                add_quoted(c);
                     62:                        argf = 0;
                     63:                        continue;
                     64:                case '\\':      /* m == MDQUO || m == MNQUO */
                     65:                        c = *arcp++;
                     66:                        if (m != MNQUO && ! class(c, m)) {
                     67:                                add_char('\\');
                     68:                                add_char(c);
                     69:                        } else
                     70:                                add_quoted(c);
                     71:                        argf = 0;
                     72:                        continue;
                     73:                case '$':       /* m == MNQUO || m = MDQUO */
                     74:                        variable();
                     75:                        continue;
                     76:                case '`':       /* m == MNQUO || m = MDQUO */
                     77:                        graves (m);
                     78:                        continue;
                     79:                default:
                     80:                        add_char(c);
                     81:                        continue;
                     82:                }
                     83:        }
                     84:        if (f==EARGS)
                     85:                end_arg();
                     86:        else
                     87:                *strp++ = '\0';
                     88: }
                     89: 
                     90: /*
                     91:  * Read the name of a shell variable and perform the appropriate substitution.
                     92:  * Doesn't check for end of buffer.
                     93:  */
                     94: variable()
                     95: {
                     96:        VAR *vp;
                     97:        int s;
                     98:        char *wp, *sav;
                     99:        register int c, count, quote;
                    100:        register char *cp, *pp;
                    101: 
                    102:        cp = strp;
                    103:        s = '\0';
                    104:        c = *arcp++;
                    105:        if (class(c, MSVAR)) {
                    106:                special(c);
                    107:                return;
                    108:        } else if (class(c, MRVAR)) {
                    109:                while (class(c, MRVAR)) {
                    110:                        *cp++ = c;
                    111:                        c = *arcp++;
                    112:                }
                    113:                --arcp;
                    114:        } else if (c != '{') {
                    115:                /* Not a legal variable name, put it back. */
                    116:                add_char('$');
                    117:                add_char(c);
                    118:                return;
                    119:        } else {
                    120:                /* c == '{' */
                    121:                if (index("#?$!-@*0123456789", arcp[0]) != NULL && arcp[1] == '}') {
                    122:                        /* Allow specials of the form "${?}" etc. */
                    123:                        special(arcp[0]);
                    124:                        arcp += 2;
                    125:                        return;
                    126:                }
                    127:                while (index("}-=?+", c = *arcp++) == NULL)
                    128:                        *cp++ = c;
                    129:                if (c != '}') {
                    130:                        /* ${VAR [-=?+] token} */
                    131:                        s = c;
                    132:                        if (cp[-1] == ':')
                    133:                                --cp;           /* allow e.g. ${VAR:=foo} */
                    134:                        *cp++ = '=';
                    135:                        wp = cp;
                    136:                        if ((quote = *arcp) == '"' || quote =='\'')
                    137:                                ++arcp;
                    138:                        else
                    139:                                quote = 0;
                    140:                        for (count = 1; ; ) {
                    141:                                c = *arcp++;
                    142:                                if (c == '}' && count-- == 1)
                    143:                                        break;
                    144:                                else if (c == '$' && quote != '\'') {
                    145: /*
                    146:  * steve 6/24/92
                    147:  * This truly sleazy hack handles e.g. "${V1-$V2}", oy.
                    148:  * It doesn't do it very well, paying no attention to quotes (for example).
                    149:  * The recursive call to variable() should be straightforward but is not,
                    150:  * the hacky way this module uses globals like strp requires the save/restore.
                    151:  */
                    152:                                        sav = strp;
                    153:                                        strp = cp;
                    154:                                        variable();
                    155:                                        cp = strp;
                    156:                                        strp = sav;
                    157:                                        continue;
                    158:                                } else if (c == '{')
                    159:                                        ++count;
                    160:                                else if (quote != 0 && c == quote) {
                    161:                                        quote = 0;
                    162:                                        continue;
                    163:                                }
                    164:                                *cp++ = c;
                    165:                        }
                    166:                }
                    167:        }
                    168:        *cp++ = '\0';
                    169:        if (class((c = *strp), MDIGI)) {
                    170:                if ((c -= '1') >= sargc)
                    171:                        pp = NULL;
                    172:                else
                    173:                        pp = sargp[c];
                    174:        } else if (namevar(strp) == 0) {
                    175:                eillvar(strp);
                    176:                return;
                    177:        } else {
                    178:                pp = NULL;
                    179:                if ((vp=findvar(strp)) != NULL) {
                    180:                        pp = convvar(vp);
                    181:                        if (*pp == '\0')
                    182:                                pp = NULL;      /* regard value "" as not set */
                    183:                }
                    184:        }
                    185:        switch (s) {
                    186:        case '\0':
                    187:                if (uflag!=0 && pp==NULL)
                    188:                        enotdef(strp);
                    189:                break;
                    190:        case '-':
                    191:                if (pp == NULL)
                    192:                        pp = wp;
                    193:                break;
                    194:        case '=':
                    195:                if (pp == NULL) {
                    196:                        pp = wp;
                    197:                        if (class(*strp, MDIGI)) {
                    198:                                printe("Illegal substitution");
                    199:                                return;
                    200:                        }
                    201:                        setsvar(strp);
                    202:                }
                    203:                break;
                    204:        case '?':
                    205:                if (pp != NULL)
                    206:                        break;
                    207:                if (*wp != '\0')
                    208:                        prints("%s\n", wp);
                    209:                else {
                    210:                        *--wp = '\0';
                    211:                        enotdef(strp);
                    212:                }
                    213:                reset(RUABORT);
                    214:                NOTREACHED;
                    215:        case '+':
                    216:                if (pp != NULL)
                    217:                        pp = wp;
                    218:                break;
                    219:        }
                    220:        if (pp != NULL)
                    221:                while ((c = *pp++) != '\0')
                    222:                        add_char(c);
                    223:        argf &= ~ argq;
                    224: }
                    225: 
                    226: /*
                    227:  * Return the value of the special shell variables.
                    228:  * No check for end of buffer.
                    229:  */
                    230: special(n)
                    231: register int n;
                    232: {
                    233:        register char *sp;
                    234:        register int flag;
                    235: 
                    236:        sp = strp;
                    237:        switch (n) {
                    238:        case '#':
                    239:                n = sargc;
                    240:                goto maked;
                    241:        case '?':
                    242:                n = slret;
                    243:                goto maked;
                    244:        case '$':
                    245:                n = shpid;
                    246:                goto maked;
                    247:        case '!':
                    248:                n = sback;
                    249:                goto maked;
                    250:        maked:
                    251:                sprintf(sp, "%d", n);
                    252:                break;
                    253:        case '-':
                    254:                for (sp = &eflag; sp <= &xflag; sp += 1)
                    255:                        if (*sp)
                    256:                                add_char(*sp);
                    257:                argf &= ~ argq;
                    258:                return;
                    259:        case '@':
                    260:        case '*':
                    261:                flag = (argq == 1 && n == '@');
                    262:                for (n = 0; n < sargc; n++) {
                    263:                        if (n) {
                    264:                                argq ^= flag;
                    265:                                add_char(' ');
                    266:                                argq ^= flag;
                    267:                        }
                    268:                        sp = sargp[n];
                    269:                        while (*sp)
                    270:                                add_char(*sp++);
                    271:                        /*
                    272:                         * Make sure that arguments like "" get handled
                    273:                         * properly when expanding "$@"
                    274:                         */
                    275:                        if (flag)
                    276:                                argf &= ~ argq;
                    277:                }
                    278:                return;
                    279:        case '0':
                    280:                sp = sarg0;
                    281:                break;
                    282:        default:
                    283:                if ((n-='1') >= sargc) {
                    284:                        if (uflag)
                    285:                                printe("Unset parameter: %c", n+'1');
                    286:                        argf &= ~ argq;
                    287:                        return;
                    288:                }
                    289:                sp = sargp[n];
                    290:                break;
                    291:        }
                    292:        while (*sp)
                    293:                add_char(*sp++);
                    294:        argf &= ~ argq;
                    295: }
                    296: 
                    297: /*
                    298:  * Read and evaluate a command found between graves.
                    299:  *
                    300:  * NB : The code below relating to saving/restoring the global variable
                    301:  * "argf" has been removed; it was not clear what the intended effect was,
                    302:  * but it caused expansions into single words (eg, "echo `pwd`") to vanish
                    303:  * and caused the word-break algorithm to perform in an unintuitive (and
                    304:  * incorrect according to POSIX.2) manner.
                    305:  *
                    306:  * NB : Backslash-quoting inside graves was not supported properly before,
                    307:  * and I'm not sure that I've got it right. The idea is that before passing
                    308:  * things off to session (), we process the appropriate backslash-escapes.
                    309:  * What consists of an "appropriate" escape depends on whether the graves
                    310:  * appeared within a double-quoted section (in which case we recognise the
                    311:  * specials appropriate to that) or not (in which case we recognised the
                    312:  * characters $`\ as specials. We also process '$'-expansions in graves now,
                    313:  * but not globs.
                    314:  *
                    315:  * Since we are removing some bashslashes here, we should be building into
                    316:  * a temporary buffer. We append our work onto the global "strp" buffer and
                    317:  * cut it back once we have finished.
                    318:  */
                    319: graves (quotemode)
                    320: int            quotemode;
                    321: {
                    322:        int pipev[2], f, oslret;
                    323:        int oargf;
                    324:        char          * ostrp;
                    325:        register FILE *fp;
                    326:        register int c;
                    327:        register int nnl;
                    328:        char *cmdp;
                    329: 
                    330:        oargf = argf;
                    331:        ostrp = strp;
                    332:        oslret = slret;
                    333: 
                    334:        cmdp = strp;
                    335:        while ((c = *arcp++) != '`') {
                    336:                if (c != '\\') {
                    337:                        add_arg (c);
                    338:                        continue;
                    339:                }
                    340:                c = * arcp ++;
                    341: 
                    342:                if (! (quotemode == MDQUO && class (c, MDQUO)) &&
                    343:                    (c != '$' && c != '\\' && c != '`'))
                    344:                        add_arg ('\\');
                    345:                add_arg (c);
                    346:        }
                    347:        * strp = 0;
                    348: 
                    349:        if ((f = pipeline(pipev)) == 0) {
                    350:                slret = oslret;         /* in case grave command uses $? */
                    351:                dup2(pipev[1], 1);
                    352:                close(pipev[0]);
                    353:                close(pipev[1]);
                    354:                exit(session(SARGS, cmdp));
                    355:                NOTREACHED;
                    356:        }
                    357: 
                    358:        close(pipev[1]);
                    359:        if ((fp=fdopen(pipev[0], "r")) == NULL) {
                    360:                close(pipev[0]);
                    361:                ecantfdop();
                    362:                return;
                    363:        }
                    364:        strp = ostrp;
                    365:        argf = oargf;
                    366:        nnl = 0;
                    367:        while ((c=getc(fp)) != EOF) {
                    368:                if ( ! recover(IEVAL)) {
                    369: #ifdef VERBOSE
                    370:                        if (xflag) prints("Interrupt in eval\n");
                    371: #endif
                    372:                        errflag++;
                    373:                        break;
                    374:                }
                    375:                if (c=='\n')
                    376:                        ++nnl;
                    377:                else {
                    378:                        while (nnl) {
                    379:                                nnl--;
                    380:                                add_char('\n');
                    381:                        }
                    382:                        add_char(c);
                    383:                }
                    384:        }
                    385: 
                    386:        /*
                    387:         * If we expanded to something, we have an arg. If we are in double-
                    388:         * quotes, we have an arg. Otherwise, we have an arg if we had an arg
                    389:         * before.
                    390:         */
                    391: 
                    392:        if (argf)
                    393:                argf = argq ? 0 : oargf;
                    394: 
                    395:        fclose(fp);
                    396:        waitc(f);
                    397: }
                    398: 
                    399: /*
                    400:  * Add a character to the current argument.
                    401:  * If no quotation is set, pick off blanks and globs.
                    402:  */
                    403: add_char(c)
                    404: register int c;
                    405: {
                    406:        if (argq==0) {
                    407:                if (index(vifs, c) != NULL) {
                    408:                        end_arg();
                    409:                        return;
                    410:                }
                    411:                if (argg && class(c, MGLOB)) {
                    412:                        add_arg(c);
                    413:                        return;
                    414:                }
                    415:        }
                    416:        add_quoted(c);
                    417: }
                    418: 
                    419: /*
                    420:  * Add a quoted character to the current argument.
                    421:  * if argg is set, then glob characters are quoted with a \,
                    422:  * as well as \ itself.
                    423:  */
                    424: add_quoted(c) register int c;
                    425: {
                    426:        if (argg && (class(c, MGLOB) || c == '\\'))
                    427:                add_arg('\\');
                    428:        add_arg(c);
                    429: }
                    430: 
                    431: /*
                    432:  * Add a character to the current argument
                    433:  * and check for end of buffer.
                    434:  */
                    435: add_arg(c) register int c;
                    436: {
                    437:        if (strp >= &strt[STRSIZE])     /* Should do more */
                    438:                etoolong();
                    439:        else
                    440:                *strp++ = c;
                    441:        argf = 0;
                    442: }
                    443: 
                    444: /*
                    445:  * Terminate the current argument if it is non-empty.
                    446:  * If argg is set, then glob the argument to expand globs
                    447:  * or to simply remove any quotes.
                    448:  */
                    449: end_arg()
                    450: {
                    451:        if (argf != 0)
                    452:                return;
                    453:        *strp++ = '\0';
                    454:        if (argg)
                    455:                glob1(duplstr(strt, 0));
                    456:        else {
                    457:                nargv = addargl(nargv, duplstr(strt, 0));
                    458:                nargc += 1;
                    459:        }
                    460:        strp = strt;
                    461:        argf = 1;
                    462:        return;
                    463: }
                    464: 
                    465: /*
                    466:  * Evaluate a here document.
                    467:  * Unevaluated document is on u2, put the evaluated document there, too.
                    468:  */
                    469: evalhere(u2)
                    470: {
                    471:        register int u1;
                    472:        register FILE *f2;
                    473:        char buf[128];
                    474:        char *tmp;
                    475: 
                    476:        tmp = shtmp();
                    477:        if ((u1=creat(tmp, 0666))<0) {
                    478:                ecantmake(tmp);
                    479:                return -1;
                    480:        }
                    481:        if ((f2=fdopen(u2, "r"))==NULL) {
                    482:                ecantfdop();
                    483:                close(u1);
                    484:                close(u2);
                    485:                return -1;
                    486:        }
                    487:        while (fgets(buf, 128, f2) != NULL) {
                    488:                eval(buf, EHERE);
                    489:                write(u1, strt, strp-1-strt);
                    490:        }
                    491:        close(u1);
                    492:        fclose(f2);
                    493:        if ((u2 = open(tmp, 0))<0) {
                    494:                ecantopen(tmp);
                    495:                u2 = -1;
                    496:        }
                    497:        unlink(tmp);
                    498:        return u2;
                    499: }
                    500: 
                    501: /* end of sh/eval.c */

unix.superglobalmegacorp.com

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