URI:
       ttest.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       ttest.c (5813B)
       ---
            1 /*
            2  * POSIX standard
            3  *        test expression
            4  *        [ expression ]
            5  *
            6  * Plan 9 additions:
            7  *        -A file exists and is append-only
            8  *        -L file exists and is exclusive-use
            9  *        -T file exists and is temporary
           10  */
           11 
           12 #include <u.h>
           13 #include <libc.h>
           14 
           15 #define isatty plan9_isatty
           16 
           17 #define EQ(a,b)        ((tmp=a)==0?0:(strcmp(tmp,b)==0))
           18 
           19 int        ap;
           20 int        ac;
           21 char        **av;
           22 char        *tmp;
           23 
           24 void        synbad(char *, char *);
           25 int        fsizep(char *);
           26 int        isdir(char *);
           27 int        isreg(char *);
           28 int        isatty(int);
           29 int        isint(char *, int *);
           30 int        isolder(char *, char *);
           31 int        isolderthan(char *, char *);
           32 int        isnewerthan(char *, char *);
           33 int        hasmode(char *, ulong);
           34 int        tio(char *, int);
           35 int        e(void), e1(void), e2(void), e3(void);
           36 char        *nxtarg(int);
           37 
           38 void
           39 main(int argc, char *argv[])
           40 {
           41         int r;
           42         char *c;
           43 
           44         ac = argc; av = argv; ap = 1;
           45         if(EQ(argv[0],"[")) {
           46                 if(!EQ(argv[--ac],"]"))
           47                         synbad("] missing","");
           48         }
           49         argv[ac] = 0;
           50         if (ac<=1)
           51                 exits("usage");
           52         r = e();
           53         /*
           54          * nice idea but short-circuit -o and -a operators may have
           55          * not consumed their right-hand sides.
           56          */
           57         if(0 && (c = nxtarg(1)) != nil)
           58                 synbad("unexpected operator/operand: ", c);
           59         exits(r?0:"false");
           60 }
           61 
           62 char *
           63 nxtarg(int mt)
           64 {
           65         if(ap>=ac){
           66                 if(mt){
           67                         ap++;
           68                         return(0);
           69                 }
           70                 synbad("argument expected","");
           71         }
           72         return(av[ap++]);
           73 }
           74 
           75 int
           76 nxtintarg(int *pans)
           77 {
           78         if(ap<ac && isint(av[ap], pans)){
           79                 ap++;
           80                 return 1;
           81         }
           82         return 0;
           83 }
           84 
           85 int
           86 e(void)
           87 {
           88         int p1;
           89 
           90         p1 = e1();
           91         if (EQ(nxtarg(1), "-o"))
           92                 return(p1 || e());
           93         ap--;
           94         return(p1);
           95 }
           96 
           97 int
           98 e1(void)
           99 {
          100         int p1;
          101 
          102         p1 = e2();
          103         if (EQ(nxtarg(1), "-a"))
          104                 return (p1 && e1());
          105         ap--;
          106         return(p1);
          107 }
          108 
          109 int
          110 e2(void)
          111 {
          112         if (EQ(nxtarg(0), "!"))
          113                 return(!e2());
          114         ap--;
          115         return(e3());
          116 }
          117 
          118 int
          119 e3(void)
          120 {
          121         int p1, int1, int2;
          122         char *a, *p2;
          123 
          124         a = nxtarg(0);
          125         if(EQ(a, "(")) {
          126                 p1 = e();
          127                 if(!EQ(nxtarg(0), ")"))
          128                         synbad(") expected","");
          129                 return(p1);
          130         }
          131 
          132         if(EQ(a, "-A"))
          133                 return(hasmode(nxtarg(0), DMAPPEND));
          134 
          135         if(EQ(a, "-L"))
          136                 return(hasmode(nxtarg(0), DMEXCL));
          137 
          138         if(EQ(a, "-T"))
          139                 return(hasmode(nxtarg(0), DMTMP));
          140 
          141         if(EQ(a, "-f"))
          142                 return(isreg(nxtarg(0)));
          143 
          144         if(EQ(a, "-d"))
          145                 return(isdir(nxtarg(0)));
          146 
          147         if(EQ(a, "-r"))
          148                 return(tio(nxtarg(0), 4));
          149 
          150         if(EQ(a, "-w"))
          151                 return(tio(nxtarg(0), 2));
          152 
          153         if(EQ(a, "-x"))
          154                 return(tio(nxtarg(0), 1));
          155 
          156         if(EQ(a, "-e"))
          157                 return(tio(nxtarg(0), 0));
          158 
          159         if(EQ(a, "-c"))
          160                 return(0);
          161 
          162         if(EQ(a, "-b"))
          163                 return(0);
          164 
          165         if(EQ(a, "-u"))
          166                 return(0);
          167 
          168         if(EQ(a, "-g"))
          169                 return(0);
          170 
          171         if(EQ(a, "-s"))
          172                 return(fsizep(nxtarg(0)));
          173 
          174         if(EQ(a, "-t"))
          175                 if(ap>=ac)
          176                         return(isatty(1));
          177                 else if(nxtintarg(&int1))
          178                         return(isatty(int1));
          179                 else
          180                         synbad("not a valid file descriptor number ", "");
          181 
          182         if(EQ(a, "-n"))
          183                 return(!EQ(nxtarg(0), ""));
          184         if(EQ(a, "-z"))
          185                 return(EQ(nxtarg(0), ""));
          186 
          187         p2 = nxtarg(1);
          188         if (p2==0)
          189                 return(!EQ(a,""));
          190         if(EQ(p2, "="))
          191                 return(EQ(nxtarg(0), a));
          192 
          193         if(EQ(p2, "!="))
          194                 return(!EQ(nxtarg(0), a));
          195 
          196         if(EQ(p2, "-older"))
          197                 return(isolder(nxtarg(0), a));
          198 
          199         if(EQ(p2, "-ot"))
          200                 return(isolderthan(nxtarg(0), a));
          201 
          202         if(EQ(p2, "-nt"))
          203                 return(isnewerthan(nxtarg(0), a));
          204 
          205         if(!isint(a, &int1))
          206                 synbad("unexpected operator/operand: ", p2);
          207 
          208         if(nxtintarg(&int2)){
          209                 if(EQ(p2, "-eq"))
          210                         return(int1==int2);
          211                 if(EQ(p2, "-ne"))
          212                         return(int1!=int2);
          213                 if(EQ(p2, "-gt"))
          214                         return(int1>int2);
          215                 if(EQ(p2, "-lt"))
          216                         return(int1<int2);
          217                 if(EQ(p2, "-ge"))
          218                         return(int1>=int2);
          219                 if(EQ(p2, "-le"))
          220                         return(int1<=int2);
          221         }
          222 
          223         synbad("unknown operator ",p2);
          224         return 0;                /* to shut ken up */
          225 }
          226 
          227 int
          228 tio(char *a, int f)
          229 {
          230         return access (a, f) >= 0;
          231 }
          232 
          233 /*
          234  * note that the name strings pointed to by Dir members are
          235  * allocated with the Dir itself (by the same call to malloc),
          236  * but are not included in sizeof(Dir), so copying a Dir won't
          237  * copy the strings it points to.
          238  */
          239 
          240 int
          241 hasmode(char *f, ulong m)
          242 {
          243         int r;
          244         Dir *dir;
          245 
          246         dir = dirstat(f);
          247         if (dir == nil)
          248                 return 0;
          249         r = (dir->mode & m) != 0;
          250         free(dir);
          251         return r;
          252 }
          253 
          254 int
          255 isdir(char *f)
          256 {
          257         return hasmode(f, DMDIR);
          258 }
          259 
          260 int
          261 isreg(char *f)
          262 {
          263         int r;
          264         Dir *dir;
          265 
          266         dir = dirstat(f);
          267         if (dir == nil)
          268                 return 0;
          269         r = (dir->mode & DMDIR) == 0;
          270         free(dir);
          271         return r;
          272 }
          273 
          274 int
          275 isatty(int fd)
          276 {
          277         int r;
          278         Dir *d1, *d2;
          279 
          280         d1 = dirfstat(fd);
          281         d2 = dirstat("/dev/cons");
          282         if (d1 == nil || d2 == nil)
          283                 r = 0;
          284         else
          285                 r = d1->type == d2->type && d1->dev == d2->dev &&
          286                         d1->qid.path == d2->qid.path;
          287         free(d1);
          288         free(d2);
          289         return r;
          290 }
          291 
          292 int
          293 fsizep(char *f)
          294 {
          295         int r;
          296         Dir *dir;
          297 
          298         dir = dirstat(f);
          299         if (dir == nil)
          300                 return 0;
          301         r = dir->length > 0;
          302         free(dir);
          303         return r;
          304 }
          305 
          306 void
          307 synbad(char *s1, char *s2)
          308 {
          309         int len;
          310 
          311         write(2, "test: ", 6);
          312         if ((len = strlen(s1)) != 0)
          313                 write(2, s1, len);
          314         if ((len = strlen(s2)) != 0)
          315                 write(2, s2, len);
          316         write(2, "\n", 1);
          317         exits("bad syntax");
          318 }
          319 
          320 int
          321 isint(char *s, int *pans)
          322 {
          323         char *ep;
          324 
          325         *pans = strtol(s, &ep, 0);
          326         return (*ep == 0);
          327 }
          328 
          329 int
          330 isolder(char *pin, char *f)
          331 {
          332         int r;
          333         ulong n, m;
          334         char *p = pin;
          335         Dir *dir;
          336 
          337         dir = dirstat(f);
          338         if (dir == nil)
          339                 return 0;
          340 
          341         /* parse time */
          342         n = 0;
          343         while(*p){
          344                 m = strtoul(p, &p, 0);
          345                 switch(*p){
          346                 case 0:
          347                         n = m;
          348                         break;
          349                 case 'y':
          350                         m *= 12;
          351                         /* fall through */
          352                 case 'M':
          353                         m *= 30;
          354                         /* fall through */
          355                 case 'd':
          356                         m *= 24;
          357                         /* fall through */
          358                 case 'h':
          359                         m *= 60;
          360                         /* fall through */
          361                 case 'm':
          362                         m *= 60;
          363                         /* fall through */
          364                 case 's':
          365                         n += m;
          366                         p++;
          367                         break;
          368                 default:
          369                         synbad("bad time syntax, ", pin);
          370                 }
          371         }
          372 
          373         r = dir->mtime + n < time(0);
          374         free(dir);
          375         return r;
          376 }
          377 
          378 int
          379 isolderthan(char *a, char *b)
          380 {
          381         int r;
          382         Dir *ad, *bd;
          383 
          384         ad = dirstat(a);
          385         bd = dirstat(b);
          386         if (ad == nil || bd == nil)
          387                 r = 0;
          388         else
          389                 r = ad->mtime > bd->mtime;
          390         free(ad);
          391         free(bd);
          392         return r;
          393 }
          394 
          395 int
          396 isnewerthan(char *a, char *b)
          397 {
          398         int r;
          399         Dir *ad, *bd;
          400 
          401         ad = dirstat(a);
          402         bd = dirstat(b);
          403         if (ad == nil || bd == nil)
          404                 r = 0;
          405         else
          406                 r = ad->mtime < bd->mtime;
          407         free(ad);
          408         free(bd);
          409         return r;
          410 }