summary refs log tree commit diff
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);
+}