Annotation of coherent/a/usr/bob/korn/c_test.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * test(1); version 7-like  --  author Erik Baalbergen
                      3:  * modified by Eric Gisin to be used as built-in.
                      4:  * modified by Arnold Robbins to add SVR3 compatibility
                      5:  * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket).
                      6:  */
                      7: 
                      8: static char *RCSid = "$Header: c_test.c,v 3.1 88/11/03 09:14:43 egisin Exp $";
                      9: 
                     10: #include <stddef.h>
                     11: #include <stdlib.h>
                     12: #include <string.h>
                     13: #include <signal.h>
                     14: #include <errno.h>
                     15: #include <setjmp.h>
                     16: #include <sys/types.h>
                     17: #include <sys/stat.h>
                     18: #include "sh.h"
                     19: 
                     20: /* test(1) accepts the following grammar:
                     21:        expr    ::= bexpr | bexpr "-o" expr ;
                     22:        bexpr   ::= primary | primary "-a" bexpr ;
                     23:        primary ::= unary-operator operand
                     24:                | operand binary-operator operand
                     25:                | operand
                     26:                | "(" expr ")"
                     27:                | "!" expr
                     28:                ;
                     29:        unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"|
                     30:                "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S";
                     31: 
                     32:        binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"|
                     33:                        "-nt"|"-ot"|"-ef";
                     34:        operand ::= <any legal UNIX file name>
                     35: */
                     36: 
                     37: #define EOI    0
                     38: #define FILRD  1
                     39: #define FILWR  2
                     40: #define FILREG 3
                     41: #define FILID  4
                     42: #define FILGZ  5
                     43: #define FILTT  6
                     44: #define STZER  7
                     45: #define STNZE  8
                     46: #define STEQL  9
                     47: #define STNEQ  10
                     48: #define INTEQ  11
                     49: #define INTNE  12
                     50: #define INTGE  13
                     51: #define INTGT  14
                     52: #define INTLE  15
                     53: #define INTLT  16
                     54: #define UNEGN  17
                     55: #define BAND   18
                     56: #define BOR    19
                     57: #define LPAREN 20
                     58: #define RPAREN 21
                     59: #define OPERAND        22
                     60: #define FILEX  23
                     61: #define FILCDEV        24
                     62: #define FILBDEV        25
                     63: #define FILFIFO        26
                     64: #define FILSETU        27
                     65: #define FILSETG        28
                     66: #define FILSTCK        29
                     67: #define FILSYM 30
                     68: #define FILNT  31
                     69: #define FILOT  32
                     70: #define FILEQ  33
                     71: #define FILSOCK        34
                     72: #define        FILUID  35
                     73: #define        FILGID  36
                     74: #define        OPTION  37
                     75: 
                     76: #define UNOP   1
                     77: #define BINOP  2
                     78: #define BUNOP  3
                     79: #define BBINOP 4
                     80: #define PAREN  5
                     81: 
                     82: struct t_op {
                     83:        char *op_text;
                     84:        short op_num, op_type;
                     85: } Const ops [] = {
                     86:        {"-r",  FILRD,  UNOP},
                     87:        {"-w",  FILWR,  UNOP},
                     88:        {"-x",  FILEX,  UNOP},
                     89:        {"-f",  FILREG, UNOP},
                     90:        {"-d",  FILID,  UNOP},
                     91:        {"-c",  FILCDEV,UNOP},
                     92:        {"-b",  FILBDEV,UNOP},
                     93:        {"-p",  FILFIFO,UNOP},
                     94:        {"-u",  FILSETU,UNOP},
                     95:        {"-g",  FILSETG,UNOP},
                     96:        {"-k",  FILSTCK,UNOP},
                     97:        {"-s",  FILGZ,  UNOP},
                     98:        {"-t",  FILTT,  UNOP},
                     99:        {"-z",  STZER,  UNOP},
                    100:        {"-n",  STNZE,  UNOP},
                    101: #if 0                          /* conficts with binary -o */
                    102:        {"-o",  OPTION, UNOP},
                    103: #endif
                    104:        {"-U",  FILUID, UNOP},
                    105:        {"-G",  FILGID, UNOP},
                    106:        {"-L",  FILSYM, UNOP},
                    107:        {"-S",  FILSOCK,UNOP},
                    108:        {"=",   STEQL,  BINOP},
                    109:        {"!=",  STNEQ,  BINOP},
                    110:        {"-eq", INTEQ,  BINOP},
                    111:        {"-ne", INTNE,  BINOP},
                    112:        {"-ge", INTGE,  BINOP},
                    113:        {"-gt", INTGT,  BINOP},
                    114:        {"-le", INTLE,  BINOP},
                    115:        {"-lt", INTLT,  BINOP},
                    116:        {"-nt", FILNT,  BINOP},
                    117:        {"-ot", FILOT,  BINOP},
                    118:        {"-ef", FILEQ,  BINOP},
                    119:        {"!",   UNEGN,  BUNOP},
                    120:        {"-a",  BAND,   BBINOP},
                    121:        {"-o",  BOR,    BBINOP},
                    122:        {"(",   LPAREN, PAREN},
                    123:        {")",   RPAREN, PAREN},
                    124:        {0,     0,      0}
                    125: };
                    126: 
                    127: char **t_wp;
                    128: struct t_op Const *t_wp_op;
                    129: 
                    130: int
                    131: c_test(wp)
                    132:        char **wp;
                    133: {
                    134:        t_wp = wp+1;
                    135:        if (strcmp(wp[0], "[") == 0) {
                    136:                while (*wp != NULL)
                    137:                        wp++;
                    138:                if (strcmp(*--wp, "]") != 0)
                    139:                        errorf("[: missing ]\n");
                    140:                *wp = NULL;
                    141:        }
                    142: #if 0
                    143:        if (*t_wp == NULL)
                    144:                mypr("*t_wp == NULL\n");
                    145:        else if (!expr(t_lex(*t_wp)))
                    146:                mypr("expr returned 0\n");
                    147: #endif
                    148:        return *t_wp == NULL || !expr(t_lex(*t_wp));
                    149: }
                    150: 
                    151: static
                    152: syntax()
                    153: {
                    154:        errorf("test: syntax error\n");
                    155: }
                    156: 
                    157: expr(n)
                    158: {
                    159:        int res;
                    160: 
                    161:        if (n == EOI)
                    162:                syntax();
                    163:        res = bexpr(n);
                    164:        if (t_lex(*++t_wp) == BOR)
                    165:                return expr(t_lex(*++t_wp)) || res;
                    166:        t_wp--;
                    167:        return res;
                    168: }
                    169: 
                    170: bexpr(n)
                    171: {
                    172:        int res;
                    173: 
                    174:        if (n == EOI)
                    175:                syntax();
                    176:        res = primary(n);
                    177:        if (t_lex(*++t_wp) == BAND)
                    178:                return bexpr(t_lex(*++t_wp)) && res;
                    179:        t_wp--;
                    180:        return res;
                    181: }
                    182: 
                    183: primary(n)
                    184:        int n;                  /* token */
                    185: {
                    186:        register char *opnd1, *opnd2;
                    187:        int res;
                    188: 
                    189:        if (n == EOI)
                    190:                syntax();
                    191:        if (n == UNEGN)
                    192:                return !expr(t_lex(*++t_wp));
                    193:        if (n == LPAREN) {
                    194:                res = expr(t_lex(*++t_wp));
                    195:                if (t_lex(*++t_wp) != RPAREN)
                    196:                        syntax();
                    197:                return res;
                    198:        }
                    199:        if (n == OPERAND) {
                    200:                opnd1 = *t_wp;
                    201:                (void) t_lex(*++t_wp);
                    202:                if (t_wp_op && t_wp_op->op_type == BINOP) {
                    203:                        struct t_op Const *op = t_wp_op;
                    204: 
                    205:                        if ((opnd2 = *++t_wp) == (char *)0)
                    206:                                syntax();
                    207:                        
                    208:                        switch (op->op_num) {
                    209:                        case STEQL:
                    210:                                return strcmp(opnd1, opnd2) == 0;
                    211:                        case STNEQ:
                    212:                                return strcmp(opnd1, opnd2) != 0;
                    213:                        case INTEQ:
                    214:                                return evaluate(opnd1) == evaluate(opnd2);
                    215:                        case INTNE:
                    216:                                return evaluate(opnd1) != evaluate(opnd2);
                    217:                        case INTGE:
                    218:                                return evaluate(opnd1) >= evaluate(opnd2);
                    219:                        case INTGT:
                    220:                                return evaluate(opnd1) > evaluate(opnd2);
                    221:                        case INTLE:
                    222:                                return evaluate(opnd1) <= evaluate(opnd2);
                    223:                        case INTLT:
                    224:                                return evaluate(opnd1) < evaluate(opnd2);
                    225:                        case FILNT:
                    226:                                return newerf (opnd1, opnd2);
                    227:                        case FILOT:
                    228:                                return olderf (opnd1, opnd2);
                    229:                        case FILEQ:
                    230:                                return equalf (opnd1, opnd2);
                    231:                        }
                    232:                }
                    233:                t_wp--;
                    234:                return strlen(opnd1) > 0;
                    235:        }
                    236:        if (t_wp_op->op_type == UNOP) {
                    237:                /* unary expression */
                    238:                if (*++t_wp == NULL && n != FILTT)
                    239:                        syntax();
                    240:                switch (n) {
                    241:                  case OPTION:
                    242:                        return flag[option(*t_wp)];
                    243:                  case STZER:
                    244:                        return strlen(*t_wp) == 0;
                    245:                  case STNZE:
                    246:                        return strlen(*t_wp) != 0;
                    247:                  case FILTT:
                    248:                        if (!digit(**t_wp))
                    249:                                return filstat("0", n);
                    250:                  default:      /* all other FIL* */
                    251:                        return filstat(*t_wp, n);
                    252:                }
                    253:        }
                    254:        syntax();
                    255: }
                    256: 
                    257: filstat(nm, mode)
                    258:        char *nm;
                    259: {
                    260:        struct stat s;
                    261:        
                    262:        switch (mode) {
                    263:        case FILRD:
                    264:                return access(nm, 4) == 0;
                    265:        case FILWR:
                    266:                return access(nm, 2) == 0;
                    267:        case FILEX:
                    268:                return access(nm, 1) == 0;
                    269:        case FILREG:
                    270:                return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFREG;
                    271:        case FILID:
                    272:                return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFDIR;
                    273:        case FILCDEV:
                    274:                return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFCHR;
                    275:        case FILBDEV:
                    276:                return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFBLK;
                    277:        case FILFIFO:
                    278: #ifdef S_IFIFO
                    279:                return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFIFO;
                    280: #else
                    281:                return 0;
                    282: #endif
                    283:        case FILSETU:
                    284:                return stat(nm, &s) == 0 && (s.st_mode & S_ISUID) == S_ISUID;
                    285:        case FILSETG:
                    286:                return stat(nm, &s) == 0 && (s.st_mode & S_ISGID) == S_ISGID;
                    287:        case FILSTCK:
                    288:                return stat(nm, &s) == 0 && (s.st_mode & S_ISVTX) == S_ISVTX;
                    289:        case FILGZ:
                    290:                return stat(nm, &s) == 0 && s.st_size > 0L;
                    291:        case FILTT:
                    292:                return isatty(getn(nm));
                    293:          case FILUID:
                    294:                return stat(nm, &s) == 0 && s.st_uid == geteuid();
                    295:          case FILGID:
                    296:                return stat(nm, &s) == 0 && s.st_gid == getegid();
                    297: #ifdef S_IFLNK
                    298:        case FILSYM:
                    299:                return lstat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFLNK;
                    300: #endif
                    301: #ifdef S_IFSOCK
                    302:        case FILSOCK:
                    303:                return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFSOCK;
                    304: #endif
                    305:          default:
                    306:                return 1;
                    307:        }
                    308: }
                    309: 
                    310: int
                    311: t_lex(s)
                    312:        register char *s;
                    313: {
                    314:        register struct t_op Const *op = ops;
                    315: 
                    316:        if (s == 0)
                    317:                return EOI;
                    318:        while (op->op_text) {
                    319:                if (strcmp(s, op->op_text) == 0) {
                    320:                        t_wp_op = op;
                    321:                        return op->op_num;
                    322:                }
                    323:                op++;
                    324:        }
                    325:        t_wp_op = (struct t_op *)0;
                    326:        return OPERAND;
                    327: }
                    328: 
                    329: newerf (f1, f2)
                    330: char *f1, *f2;
                    331: {
                    332:        struct stat b1, b2;
                    333: 
                    334:        return (stat (f1, &b1) == 0 &&
                    335:                stat (f2, &b2) == 0 &&
                    336:                b1.st_mtime > b2.st_mtime);
                    337: }
                    338: 
                    339: olderf (f1, f2)
                    340: char *f1, *f2;
                    341: {
                    342:        struct stat b1, b2;
                    343: 
                    344:        return (stat (f1, &b1) == 0 &&
                    345:                stat (f2, &b2) == 0 &&
                    346:                b1.st_mtime < b2.st_mtime);
                    347: }
                    348: 
                    349: equalf (f1, f2)
                    350: char *f1, *f2;
                    351: {
                    352:        struct stat b1, b2;
                    353: 
                    354:        return (stat (f1, &b1) == 0 &&
                    355:                stat (f2, &b2) == 0 &&
                    356:                b1.st_dev == b2.st_dev &&
                    357:                b1.st_ino == b2.st_ino);
                    358: }
                    359: 

unix.superglobalmegacorp.com

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