aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/test.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2003-11-23 18:04:47 +0000
committerrsc <devnull@localhost>2003-11-23 18:04:47 +0000
commitbc7cb1a15a67c859c8c71c4b52bb35fe9425a63d (patch)
tree8ca0fe4e2418e6aa18dc74a236c577a719f6c6ed /src/cmd/test.c
parentf08fdedcee12c06e3ce9ac9bec363915978e8289 (diff)
downloadplan9port-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.c303
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);
+}