Blob
1 /*2 * POSIX standard3 * test expression4 * [ expression ]5 *6 * Plan 9 additions:7 * -A file exists and is append-only8 * -L file exists and is exclusive-use9 */11 #include <u.h>12 #include <libc.h>13 #define EQ(a,b) ((tmp=a)==0?0:(strcmp(tmp,b)==0))15 int ap;16 int ac;17 char **av;18 char *tmp;20 void synbad(char *, char *);21 int fsizep(char *);22 int isdir(char *);23 int isreg(char *);24 int isatty(int);25 int isint(char *, int *);26 int hasmode(char *, ulong);27 int tio(char *, int);28 int e(void), e1(void), e2(void), e3(void);30 void31 main(int argc, char *argv[])32 {34 ac = argc; av = argv; ap = 1;35 if(EQ(argv[0],"[")) {36 if(!EQ(argv[--ac],"]"))37 synbad("] missing","");38 }39 argv[ac] = 0;40 if (ac<=1) exits("usage");41 exits(e()?0:"false");42 }44 char *45 nxtarg(int mt)46 {47 if(ap>=ac){48 if(mt){49 ap++;50 return(0);51 }52 synbad("argument expected","");53 }54 return(av[ap++]);55 }57 int58 nxtintarg(int *pans)59 {60 if(ap<ac && isint(av[ap], pans)){61 ap++;62 return 1;63 }64 return 0;65 }67 int68 e(void) {69 int p1;71 p1 = e1();72 if (EQ(nxtarg(1), "-o")) return(p1 || e());73 ap--;74 return(p1);75 }77 int78 e1(void) {79 int p1;81 p1 = e2();82 if (EQ(nxtarg(1), "-a")) return (p1 && e1());83 ap--;84 return(p1);85 }87 int88 e2(void) {89 if (EQ(nxtarg(0), "!"))90 return(!e2());91 ap--;92 return(e3());93 }95 int96 e3(void) {97 int p1;98 char *a;99 char *p2;100 int int1, int2;102 a = nxtarg(0);103 if(EQ(a, "(")) {104 p1 = e();105 if(!EQ(nxtarg(0), ")")) synbad(") expected","");106 return(p1);107 }109 if(EQ(a, "-A"))110 return(hasmode(nxtarg(0), DMAPPEND));112 if(EQ(a, "-L"))113 return(hasmode(nxtarg(0), DMEXCL));115 if(EQ(a, "-f"))116 return(isreg(nxtarg(0)));118 if(EQ(a, "-d"))119 return(isdir(nxtarg(0)));121 if(EQ(a, "-r"))122 return(tio(nxtarg(0), 4));124 if(EQ(a, "-w"))125 return(tio(nxtarg(0), 2));127 if(EQ(a, "-x"))128 return(tio(nxtarg(0), 1));130 if(EQ(a, "-e"))131 return(tio(nxtarg(0), 0));133 if(EQ(a, "-c"))134 return(0);136 if(EQ(a, "-b"))137 return(0);139 if(EQ(a, "-u"))140 return(0);142 if(EQ(a, "-g"))143 return(0);145 if(EQ(a, "-s"))146 return(fsizep(nxtarg(0)));148 if(EQ(a, "-t"))149 if(ap>=ac || !nxtintarg(&int1))150 return(isatty(1));151 else152 return(isatty(int1));154 if(EQ(a, "-n"))155 return(!EQ(nxtarg(0), ""));156 if(EQ(a, "-z"))157 return(EQ(nxtarg(0), ""));159 p2 = nxtarg(1);160 if (p2==0)161 return(!EQ(a,""));162 if(EQ(p2, "="))163 return(EQ(nxtarg(0), a));165 if(EQ(p2, "!="))166 return(!EQ(nxtarg(0), a));168 if(!isint(a, &int1))169 return(!EQ(a,""));171 if(nxtintarg(&int2)){172 if(EQ(p2, "-eq"))173 return(int1==int2);174 if(EQ(p2, "-ne"))175 return(int1!=int2);176 if(EQ(p2, "-gt"))177 return(int1>int2);178 if(EQ(p2, "-lt"))179 return(int1<int2);180 if(EQ(p2, "-ge"))181 return(int1>=int2);182 if(EQ(p2, "-le"))183 return(int1<=int2);184 }186 synbad("unknown operator ",p2);187 return 0; /* to shut ken up */188 }190 int191 tio(char *a, int f)192 {193 return access (a, f) >= 0;194 }196 /* copy to local memory; clear names for safety */197 int198 localstat(char *f, Dir *dir)199 {200 Dir *d;202 d = dirstat(f);203 if(d == 0)204 return(-1);205 *dir = *d;206 dir->name = 0;207 dir->uid = 0;208 dir->gid = 0;209 dir->muid = 0;210 return 0;211 }213 /* copy to local memory; clear names for safety */214 int215 localfstat(int f, Dir *dir)216 {217 Dir *d;219 d = dirfstat(f);220 if(d == 0)221 return(-1);222 *dir = *d;223 dir->name = 0;224 dir->uid = 0;225 dir->gid = 0;226 dir->muid = 0;227 return 0;228 }230 int231 hasmode(char *f, ulong m)232 {233 Dir dir;235 if(localstat(f,&dir)<0)236 return(0);237 return(dir.mode&m);238 }240 int241 isdir(char *f)242 {243 Dir dir;245 if(localstat(f,&dir)<0)246 return(0);247 return(dir.mode&DMDIR);248 }250 int251 isreg(char *f)252 {253 Dir dir;255 if(localstat(f,&dir)<0)256 return(0);257 return(!(dir.mode&DMDIR));258 }260 int261 isatty(int fd)262 {263 Dir d1, d2;265 if(localfstat(fd, &d1) < 0)266 return 0;267 if(localstat("/dev/cons", &d2) < 0)268 return 0;269 return d1.type==d2.type && d1.dev==d2.dev && d1.qid.path==d2.qid.path;270 }272 int273 fsizep(char *f)274 {275 Dir dir;277 if(localstat(f,&dir)<0)278 return(0);279 return(dir.length>0);280 }282 void283 synbad(char *s1, char *s2)284 {285 int len;287 write(2, "test: ", 6);288 if ((len = strlen(s1)) != 0)289 write(2, s1, len);290 if ((len = strlen(s2)) != 0)291 write(2, s2, len);292 write(2, "\n", 1);293 exits("bad syntax");294 }296 int297 isint(char *s, int *pans)298 {299 char *ep;301 *pans = strtol(s, &ep, 0);302 return (*ep == 0);303 }