mirror of
git://git.code.sf.net/p/zsh/code
synced 2024-11-19 13:33:52 +01:00
227 lines
5.2 KiB
C
227 lines
5.2 KiB
C
|
/*
|
||
|
* 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);
|
||
|
}
|