summaryrefslogtreecommitdiff
path: root/Src/cond.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/cond.c')
-rw-r--r--Src/cond.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/Src/cond.c b/Src/cond.c
new file mode 100644
index 000000000..79886a720
--- /dev/null
+++ b/Src/cond.c
@@ -0,0 +1,226 @@
+/*
+ * cond.c - evaluate conditional expressions
+ *
+ * This file is part of zsh, the Z shell.
+ *
+ * Copyright (c) 1992-1997 Paul Falstad
+ * All rights reserved.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and to distribute modified versions of this software for any
+ * purpose, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ *
+ * In no event shall Paul Falstad or the Zsh Development Group be liable
+ * to any party for direct, indirect, special, incidental, or consequential
+ * damages arising out of the use of this software and its documentation,
+ * even if Paul Falstad and the Zsh Development Group have been advised of
+ * the possibility of such damage.
+ *
+ * Paul Falstad and the Zsh Development Group specifically disclaim any
+ * warranties, including, but not limited to, the implied warranties of
+ * merchantability and fitness for a particular purpose. The software
+ * provided hereunder is on an "as is" basis, and Paul Falstad and the
+ * Zsh Development Group have no obligation to provide maintenance,
+ * support, updates, enhancements, or modifications.
+ *
+ */
+
+#include "zsh.mdh"
+#include "cond.pro"
+
+/**/
+int
+evalcond(Cond c)
+{
+ struct stat *st;
+
+ switch (c->type) {
+ case COND_NOT:
+ return !evalcond(c->left);
+ case COND_AND:
+ return evalcond(c->left) && evalcond(c->right);
+ case COND_OR:
+ return evalcond(c->left) || evalcond(c->right);
+ }
+ singsub((char **)&c->left);
+ untokenize(c->left);
+ if (c->right) {
+ singsub((char **)&c->right);
+ if (c->type != COND_STREQ && c->type != COND_STRNEQ)
+ untokenize(c->right);
+ }
+ switch (c->type) {
+ case COND_STREQ:
+ return matchpat(c->left, c->right);
+ case COND_STRNEQ:
+ return !matchpat(c->left, c->right);
+ case COND_STRLT:
+ return strcmp(c->left, c->right) < 0;
+ case COND_STRGTR:
+ return strcmp(c->left, c->right) > 0;
+ case 'e':
+ case 'a':
+ return (doaccess(c->left, F_OK));
+ case 'b':
+ return (S_ISBLK(dostat(c->left)));
+ case 'c':
+ return (S_ISCHR(dostat(c->left)));
+ case 'd':
+ return (S_ISDIR(dostat(c->left)));
+ case 'f':
+ return (S_ISREG(dostat(c->left)));
+ case 'g':
+ return (!!(dostat(c->left) & S_ISGID));
+ case 'k':
+ return (!!(dostat(c->left) & S_ISVTX));
+ case 'n':
+ return (!!strlen(c->left));
+ case 'o':
+ return (optison(c->left));
+ case 'p':
+ return (S_ISFIFO(dostat(c->left)));
+ case 'r':
+ return (doaccess(c->left, R_OK));
+ case 's':
+ return ((st = getstat(c->left)) && !!(st->st_size));
+ case 'S':
+ return (S_ISSOCK(dostat(c->left)));
+ case 'u':
+ return (!!(dostat(c->left) & S_ISUID));
+ case 'w':
+ return (doaccess(c->left, W_OK));
+ case 'x':
+ if (privasserted()) {
+ mode_t mode = dostat(c->left);
+ return (mode & S_IXUGO) || S_ISDIR(mode);
+ }
+ return doaccess(c->left, X_OK);
+ case 'z':
+ return (!strlen(c->left));
+ case 'h':
+ case 'L':
+ return (S_ISLNK(dolstat(c->left)));
+ case 'O':
+ return ((st = getstat(c->left)) && st->st_uid == geteuid());
+ case 'G':
+ return ((st = getstat(c->left)) && st->st_gid == getegid());
+ case 'N':
+ return ((st = getstat(c->left)) && st->st_atime <= st->st_mtime);
+ case 't':
+ return isatty(matheval(c->left));
+ case COND_EQ:
+ return matheval(c->left) == matheval(c->right);
+ case COND_NE:
+ return matheval(c->left) != matheval(c->right);
+ case COND_LT:
+ return matheval(c->left) < matheval(c->right);
+ case COND_GT:
+ return matheval(c->left) > matheval(c->right);
+ case COND_LE:
+ return matheval(c->left) <= matheval(c->right);
+ case COND_GE:
+ return matheval(c->left) >= matheval(c->right);
+ case COND_NT:
+ case COND_OT:
+ {
+ time_t a;
+
+ if (!(st = getstat(c->left)))
+ return 0;
+ a = st->st_mtime;
+ if (!(st = getstat(c->right)))
+ return 0;
+ return (c->type == COND_NT) ? a > st->st_mtime : a < st->st_mtime;
+ }
+ case COND_EF:
+ {
+ dev_t d;
+ ino_t i;
+
+ if (!(st = getstat(c->left)))
+ return 0;
+ d = st->st_dev;
+ i = st->st_ino;
+ if (!(st = getstat(c->right)))
+ return 0;
+ return d == st->st_dev && i == st->st_ino;
+ }
+ default:
+ zerr("bad cond structure", NULL, 0);
+ }
+ return 0;
+}
+
+
+/**/
+static int
+doaccess(char *s, int c)
+{
+ return !access(unmeta(s), c);
+}
+
+
+static struct stat st;
+
+/**/
+static struct stat *
+getstat(char *s)
+{
+/* /dev/fd/n refers to the open file descriptor n. We always use fstat *
+ * in this case since on Solaris /dev/fd/n is a device special file */
+ if (!strncmp(s, "/dev/fd/", 8)) {
+ if (fstat(atoi(s + 8), &st))
+ return NULL;
+ return &st;
+ }
+
+ if (stat(unmeta(s), &st))
+ return NULL;
+ return &st;
+}
+
+
+/**/
+static mode_t
+dostat(char *s)
+{
+ struct stat *statp;
+
+ if (!(statp = getstat(s)))
+ return 0;
+ return statp->st_mode;
+}
+
+
+/* pem@aaii.oz; needed since dostat now uses "stat" */
+
+/**/
+static mode_t
+dolstat(char *s)
+{
+ if (lstat(unmeta(s), &st) < 0)
+ return 0;
+ return st.st_mode;
+}
+
+
+/**/
+static int
+optison(char *s)
+{
+ int i;
+
+ if (strlen(s) == 1)
+ i = optlookupc(*s);
+ else
+ i = optlookup(s);
+ if (!i) {
+ zerr("no such option: %s", s, 0);
+ return 0;
+ } else if(i < 0)
+ return unset(-i);
+ else
+ return isset(i);
+}