diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/test.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/test.c')
-rwxr-xr-x | sys/src/cmd/test.c | 408 |
1 files changed, 408 insertions, 0 deletions
diff --git a/sys/src/cmd/test.c b/sys/src/cmd/test.c new file mode 100755 index 000000000..42318075d --- /dev/null +++ b/sys/src/cmd/test.c @@ -0,0 +1,408 @@ +/* + * POSIX standard + * test expression + * [ expression ] + * + * Plan 9 additions: + * -A file exists and is append-only + * -L file exists and is exclusive-use + * -T file exists and is temporary + */ + +#include <u.h> +#include <libc.h> + +#define EQ(a,b) ((tmp=a)==0?0:(strcmp(tmp,b)==0)) + +int ap; +int ac; +char **av; +char *tmp; + +void synbad(char *, char *); +int fsizep(char *); +int isdir(char *); +int isreg(char *); +int isatty(int); +int isint(char *, int *); +int isolder(char *, char *); +int isolderthan(char *, char *); +int isnewerthan(char *, char *); +int hasmode(char *, ulong); +int tio(char *, int); +int e(void), e1(void), e2(void), e3(void); +char *nxtarg(int); + +void +main(int argc, char *argv[]) +{ + int r; + char *c; + + ac = argc; av = argv; ap = 1; + if(EQ(argv[0],"[")) { + if(!EQ(argv[--ac],"]")) + synbad("] missing",""); + } + argv[ac] = 0; + if (ac<=1) + exits("usage"); + r = e(); + /* + * nice idea but short-circuit -o and -a operators may have + * not consumed their right-hand sides. + */ + if(0 && (c = nxtarg(1)) != nil) + synbad("unexpected operator/operand: ", c); + exits(r?0:"false"); +} + +char * +nxtarg(int mt) +{ + if(ap>=ac){ + if(mt){ + ap++; + return(0); + } + synbad("argument expected",""); + } + return(av[ap++]); +} + +int +nxtintarg(int *pans) +{ + if(ap<ac && isint(av[ap], pans)){ + ap++; + return 1; + } + return 0; +} + +int +e(void) +{ + int p1; + + p1 = e1(); + if (EQ(nxtarg(1), "-o")) + return(p1 || e()); + ap--; + return(p1); +} + +int +e1(void) +{ + int p1; + + p1 = e2(); + if (EQ(nxtarg(1), "-a")) + return (p1 && e1()); + ap--; + return(p1); +} + +int +e2(void) +{ + if (EQ(nxtarg(0), "!")) + return(!e2()); + ap--; + return(e3()); +} + +int +e3(void) +{ + int p1, int1, int2; + char *a, *p2; + + a = nxtarg(0); + if(EQ(a, "(")) { + p1 = e(); + if(!EQ(nxtarg(0), ")")) + synbad(") expected",""); + return(p1); + } + + if(EQ(a, "-A")) + return(hasmode(nxtarg(0), DMAPPEND)); + + if(EQ(a, "-L")) + return(hasmode(nxtarg(0), DMEXCL)); + + if(EQ(a, "-T")) + return(hasmode(nxtarg(0), DMTMP)); + + if(EQ(a, "-f")) + return(isreg(nxtarg(0))); + + if(EQ(a, "-d")) + return(isdir(nxtarg(0))); + + if(EQ(a, "-r")) + return(tio(nxtarg(0), 4)); + + if(EQ(a, "-w")) + return(tio(nxtarg(0), 2)); + + if(EQ(a, "-x")) + return(tio(nxtarg(0), 1)); + + if(EQ(a, "-e")) + return(tio(nxtarg(0), 0)); + + if(EQ(a, "-c")) + return(0); + + if(EQ(a, "-b")) + return(0); + + if(EQ(a, "-u")) + return(0); + + if(EQ(a, "-g")) + return(0); + + if(EQ(a, "-s")) + return(fsizep(nxtarg(0))); + + if(EQ(a, "-t")) + if(ap>=ac) + return(isatty(1)); + else if(nxtintarg(&int1)) + return(isatty(int1)); + else + synbad("not a valid file descriptor number ", ""); + + if(EQ(a, "-n")) + return(!EQ(nxtarg(0), "")); + if(EQ(a, "-z")) + return(EQ(nxtarg(0), "")); + + p2 = nxtarg(1); + if (p2==0) + return(!EQ(a,"")); + if(EQ(p2, "=")) + return(EQ(nxtarg(0), a)); + + if(EQ(p2, "!=")) + return(!EQ(nxtarg(0), a)); + + if(EQ(p2, "-older")) + return(isolder(nxtarg(0), a)); + + if(EQ(p2, "-ot")) + return(isolderthan(nxtarg(0), a)); + + if(EQ(p2, "-nt")) + return(isnewerthan(nxtarg(0), a)); + + if(!isint(a, &int1)) + synbad("unexpected operator/operand: ", p2); + + if(nxtintarg(&int2)){ + if(EQ(p2, "-eq")) + return(int1==int2); + if(EQ(p2, "-ne")) + return(int1!=int2); + if(EQ(p2, "-gt")) + return(int1>int2); + if(EQ(p2, "-lt")) + return(int1<int2); + if(EQ(p2, "-ge")) + return(int1>=int2); + if(EQ(p2, "-le")) + return(int1<=int2); + } + + synbad("unknown operator ",p2); + return 0; /* to shut ken up */ +} + +int +tio(char *a, int f) +{ + return access (a, f) >= 0; +} + +/* + * note that the name strings pointed to by Dir members are + * allocated with the Dir itself (by the same call to malloc), + * but are not included in sizeof(Dir), so copying a Dir won't + * copy the strings it points to. + */ + +int +hasmode(char *f, ulong m) +{ + int r; + Dir *dir; + + dir = dirstat(f); + if (dir == nil) + return 0; + r = (dir->mode & m) != 0; + free(dir); + return r; +} + +int +isdir(char *f) +{ + return hasmode(f, DMDIR); +} + +int +isreg(char *f) +{ + int r; + Dir *dir; + + dir = dirstat(f); + if (dir == nil) + return 0; + r = (dir->mode & DMDIR) == 0; + free(dir); + return r; +} + +int +isatty(int fd) +{ + int r; + Dir *d1, *d2; + + d1 = dirfstat(fd); + d2 = dirstat("/dev/cons"); + if (d1 == nil || d2 == nil) + r = 0; + else + r = d1->type == d2->type && d1->dev == d2->dev && + d1->qid.path == d2->qid.path; + free(d1); + free(d2); + return r; +} + +int +fsizep(char *f) +{ + int r; + Dir *dir; + + dir = dirstat(f); + if (dir == nil) + return 0; + r = dir->length > 0; + free(dir); + return r; +} + +void +synbad(char *s1, char *s2) +{ + int len; + + write(2, "test: ", 6); + if ((len = strlen(s1)) != 0) + write(2, s1, len); + if ((len = strlen(s2)) != 0) + write(2, s2, len); + write(2, "\n", 1); + exits("bad syntax"); +} + +int +isint(char *s, int *pans) +{ + char *ep; + + *pans = strtol(s, &ep, 0); + return (*ep == 0); +} + +int +isolder(char *pin, char *f) +{ + int r; + ulong n, m; + char *p = pin; + Dir *dir; + + dir = dirstat(f); + if (dir == nil) + return 0; + + /* parse time */ + n = 0; + while(*p){ + m = strtoul(p, &p, 0); + switch(*p){ + case 0: + n = m; + break; + case 'y': + m *= 12; + /* fall through */ + case 'M': + m *= 30; + /* fall through */ + case 'd': + m *= 24; + /* fall through */ + case 'h': + m *= 60; + /* fall through */ + case 'm': + m *= 60; + /* fall through */ + case 's': + n += m; + p++; + break; + default: + synbad("bad time syntax, ", pin); + } + } + + r = dir->mtime + n < time(0); + free(dir); + return r; +} + +int +isolderthan(char *a, char *b) +{ + int r; + Dir *ad, *bd; + + ad = dirstat(a); + bd = dirstat(b); + if (ad == nil || bd == nil) + r = 0; + else + r = ad->mtime > bd->mtime; + free(ad); + free(bd); + return r; +} + +int +isnewerthan(char *a, char *b) +{ + int r; + Dir *ad, *bd; + + ad = dirstat(a); + bd = dirstat(b); + if (ad == nil || bd == nil) + r = 0; + else + r = ad->mtime < bd->mtime; + free(ad); + free(bd); + return r; +} |