summaryrefslogtreecommitdiff
path: root/sys/src/cmd/test.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/test.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/test.c')
-rwxr-xr-xsys/src/cmd/test.c408
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;
+}