diff options
author | rsc <devnull@localhost> | 2003-11-23 18:04:47 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2003-11-23 18:04:47 +0000 |
commit | bc7cb1a15a67c859c8c71c4b52bb35fe9425a63d (patch) | |
tree | 8ca0fe4e2418e6aa18dc74a236c577a719f6c6ed /src/cmd/test.c | |
parent | f08fdedcee12c06e3ce9ac9bec363915978e8289 (diff) | |
download | plan9port-bc7cb1a15a67c859c8c71c4b52bb35fe9425a63d.tar.gz plan9port-bc7cb1a15a67c859c8c71c4b52bb35fe9425a63d.tar.bz2 plan9port-bc7cb1a15a67c859c8c71c4b52bb35fe9425a63d.zip |
new utilities.
the .C files compile but are renamed to avoid building automatically.
Diffstat (limited to 'src/cmd/test.c')
-rw-r--r-- | src/cmd/test.c | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/src/cmd/test.c b/src/cmd/test.c new file mode 100644 index 00000000..0282f198 --- /dev/null +++ b/src/cmd/test.c @@ -0,0 +1,303 @@ +/* + * POSIX standard + * test expression + * [ expression ] + * + * Plan 9 additions: + * -A file exists and is append-only + * -L file exists and is exclusive-use + */ + +#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 hasmode(char *, ulong); +int tio(char *, int); +int e(void), e1(void), e2(void), e3(void); + +void +main(int argc, char *argv[]) +{ + + ac = argc; av = argv; ap = 1; + if(EQ(argv[0],"[")) { + if(!EQ(argv[--ac],"]")) + synbad("] missing",""); + } + argv[ac] = 0; + if (ac<=1) exits("usage"); + exits(e()?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; + char *a; + char *p2; + int int1, int2; + + 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, "-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 || !nxtintarg(&int1)) + return(isatty(1)); + else + return(isatty(int1)); + + 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(!isint(a, &int1)) + return(!EQ(a,"")); + + 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; +} + +/* copy to local memory; clear names for safety */ +int +localstat(char *f, Dir *dir) +{ + Dir *d; + + d = dirstat(f); + if(d == 0) + return(-1); + *dir = *d; + dir->name = 0; + dir->uid = 0; + dir->gid = 0; + dir->muid = 0; + return 0; +} + +/* copy to local memory; clear names for safety */ +int +localfstat(int f, Dir *dir) +{ + Dir *d; + + d = dirfstat(f); + if(d == 0) + return(-1); + *dir = *d; + dir->name = 0; + dir->uid = 0; + dir->gid = 0; + dir->muid = 0; + return 0; +} + +int +hasmode(char *f, ulong m) +{ + Dir dir; + + if(localstat(f,&dir)<0) + return(0); + return(dir.mode&m); +} + +int +isdir(char *f) +{ + Dir dir; + + if(localstat(f,&dir)<0) + return(0); + return(dir.mode&DMDIR); +} + +int +isreg(char *f) +{ + Dir dir; + + if(localstat(f,&dir)<0) + return(0); + return(!(dir.mode&DMDIR)); +} + +int +isatty(int fd) +{ + Dir d1, d2; + + if(localfstat(fd, &d1) < 0) + return 0; + if(localstat("/dev/cons", &d2) < 0) + return 0; + return d1.type==d2.type && d1.dev==d2.dev && d1.qid.path==d2.qid.path; +} + +int +fsizep(char *f) +{ + Dir dir; + + if(localstat(f,&dir)<0) + return(0); + return(dir.length>0); +} + +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); +} |