home *** CD-ROM | disk | FTP | other *** search
- /* pred.c -- execute the expression tree.
- Copyright (C) 1987, 1990, 1991 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #include <stdio.h>
- #include <fnmatch.h>
- #include <sys/types.h>
- #include <sys/stat.h>
-
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif
-
- #include <pwd.h>
- #include <grp.h>
-
- #ifndef _POSIX_VERSION
- struct passwd *getpwuid ();
- struct group *getgrgid ();
- #endif
- #include "defs.h"
- #include "modetype.h"
-
- #include "wait.h"
-
- #if defined(DIRENT) || defined(_POSIX_VERSION)
- #include <dirent.h>
- #define NLENGTH(direct) (strlen((direct)->d_name))
- #else /* not (DIRENT or _POSIX_VERSION) */
- #define dirent direct
- #define NLENGTH(direct) ((direct)->d_namlen)
- #ifdef SYSNDIR
- #include <sys/ndir.h>
- #endif /* SYSNDIR */
- #ifdef SYSDIR
- #include <sys/dir.h>
- #endif /* SYSDIR */
- #ifdef NDIR
- #include <ndir.h>
- #endif /* NDIR */
- #endif /* DIRENT or _POSIX_VERSION */
-
- #ifdef VOID_CLOSEDIR
- /* Fake a return value. */
- #define CLOSEDIR(d) (closedir (d), 0)
- #else
- #define CLOSEDIR(d) closedir (d)
- #endif
-
- #ifndef S_IFLNK
- #define lstat stat
- #endif
-
- /* Extract or fake data from a `struct stat'.
- ST_NBLOCKS: Number of 512-byte blocks in the file
- (including indirect blocks). */
- #ifdef _POSIX_SOURCE
- #define ST_NBLOCKS(statp) (((statp)->st_size + 512 - 1) / 512)
- #else /* !_POSIX_SOURCE */
- #ifndef HAVE_ST_BLOCKS
- #define ST_NBLOCKS(statp) (st_blocks ((statp)->st_size))
- #else /* HAVE_ST_BLOCKS */
- #if defined(hpux) || defined(__hpux__)
- /* HP-UX, perhaps uniquely, counts st_blocks in 1024-byte units.
- This loses when mixing HP-UX and 4BSD filesystems, though. */
- #define ST_NBLOCKS(statp) ((statp)->st_blocks * 2)
- #else /* !hpux */
- #define ST_NBLOCKS(statp) ((statp)->st_blocks)
- #endif /* !hpux */
- #endif /* HAVE_ST_BLOCKS */
- #endif /* !_POSIX_SOURCE */
-
- boolean pred_amin ();
- boolean pred_and ();
- boolean pred_anewer ();
- boolean pred_atime ();
- boolean pred_close ();
- boolean pred_cmin ();
- boolean pred_cnewer ();
- boolean pred_comma ();
- boolean pred_ctime ();
- /* no pred_daystart */
- /* no pred_depth */
- boolean pred_empty ();
- boolean pred_exec ();
- boolean pred_false ();
- boolean pred_fprint ();
- boolean pred_fprint0 ();
- boolean pred_fprintf ();
- boolean pred_fstype ();
- boolean pred_gid ();
- boolean pred_group ();
- boolean pred_ilname ();
- boolean pred_iname ();
- boolean pred_inum ();
- boolean pred_ipath ();
- /* no pred_iregex */
- boolean pred_links ();
- boolean pred_lname ();
- boolean pred_ls ();
- boolean pred_mmin ();
- boolean pred_mtime ();
- boolean pred_name ();
- boolean pred_negate ();
- boolean pred_newer ();
- /* no pred_noleaf */
- boolean pred_nogroup ();
- boolean pred_nouser ();
- boolean pred_ok ();
- boolean pred_open ();
- boolean pred_or ();
- boolean pred_path ();
- boolean pred_perm ();
- boolean pred_print ();
- boolean pred_print0 ();
- /* no pred_printf */
- boolean pred_prune ();
- boolean pred_regex ();
- boolean pred_size ();
- boolean pred_true ();
- boolean pred_type ();
- boolean pred_uid ();
- boolean pred_used ();
- boolean pred_user ();
- /* no pred_version */
- /* no pred_xdev */
- boolean pred_xtype ();
-
- int lstat ();
- int stat ();
-
- boolean launch ();
- char *basename ();
- char *format_date ();
- char *filesystem_type ();
- char *stpcpy ();
- void list_file ();
-
- static boolean insert_lname ();
-
- #ifdef DEBUG
- struct pred_assoc
- {
- PFB pred_func;
- char *pred_name;
- };
-
- struct pred_assoc pred_table[] =
- {
- {pred_amin, "amin "},
- {pred_and, "and "},
- {pred_anewer, "anewer "},
- {pred_atime, "atime "},
- {pred_close, ") "},
- {pred_amin, "cmin "},
- {pred_cnewer, "cnewer "},
- {pred_comma, ", "},
- {pred_ctime, "ctime "},
- {pred_empty, "empty "},
- {pred_exec, "exec "},
- {pred_false, "false "},
- {pred_fprint, "fprint "},
- {pred_fprint0, "fprint0 "},
- {pred_fprintf, "fprintf "},
- {pred_fstype, "fstype "},
- {pred_gid, "gid "},
- {pred_group, "group "},
- {pred_ilname, "ilname "},
- {pred_iname, "iname "},
- {pred_inum, "inum "},
- {pred_ipath, "ipath "},
- {pred_links, "links "},
- {pred_lname, "lname "},
- {pred_ls, "ls "},
- {pred_amin, "mmin "},
- {pred_mtime, "mtime "},
- {pred_name, "name "},
- {pred_negate, "not "},
- {pred_newer, "newer "},
- {pred_nogroup, "nogroup "},
- {pred_nouser, "nouser "},
- {pred_ok, "ok "},
- {pred_open, "( "},
- {pred_or, "or "},
- {pred_path, "path "},
- {pred_perm, "perm "},
- {pred_print, "print "},
- {pred_print0, "print0 "},
- {pred_prune, "prune "},
- {pred_regex, "regex "},
- {pred_size, "size "},
- {pred_true, "true "},
- {pred_type, "type "},
- {pred_uid, "uid "},
- {pred_used, "used "},
- {pred_user, "user "},
- {pred_xtype, "xtype "},
- {0, "none "}
- };
-
- struct op_assoc
- {
- short type;
- char *type_name;
- };
-
- struct op_assoc type_table[] =
- {
- {NO_TYPE, "no "},
- {VICTIM_TYPE, "victim "},
- {UNI_OP, "uni_op "},
- {BI_OP, "bi_op "},
- {OPEN_PAREN, "open_paren "},
- {CLOSE_PAREN, "close_paren "},
- {-1, "unknown "}
- };
-
- struct prec_assoc
- {
- short prec;
- char *prec_name;
- };
-
- struct prec_assoc prec_table[] =
- {
- {NO_PREC, "no "},
- {COMMA_PREC, "comma "},
- {OR_PREC, "or "},
- {AND_PREC, "and "},
- {NEGATE_PREC, "negate "},
- {MAX_PREC, "max "},
- {-1, "unknown "}
- };
- #endif /* DEBUG */
-
- /* Predicate processing routines.
-
- PATHNAME is the full pathname of the file being checked.
- *STAT_BUF contains information about PATHNAME.
- *PRED_PTR contains information for applying the predicate.
-
- Return true if the file passes this predicate, false if not. */
-
- boolean
- pred_amin (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- switch (pred_ptr->args.info.kind)
- {
- case COMP_GT:
- if (stat_buf->st_atime > (time_t) pred_ptr->args.info.l_val)
- return (true);
- break;
- case COMP_LT:
- if (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val)
- return (true);
- break;
- case COMP_EQ:
- if ((stat_buf->st_atime >= (time_t) pred_ptr->args.info.l_val)
- && (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val + 60))
- return (true);
- break;
- }
- return (false);
- }
-
- boolean
- pred_and (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- if (pred_ptr->pred_left == NULL
- || (*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
- pred_ptr->pred_left))
- {
- /* Check whether we need a stat here. */
- if (pred_ptr->need_stat)
- {
- if (!have_stat && (*xstat) (pathname, stat_buf) != 0)
- {
- fflush (stdout);
- error (0, errno, "%s", pathname);
- exit_status = 1;
- return (false);
- }
- have_stat = true;
- }
- return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
- pred_ptr->pred_right));
- }
- else
- return (false);
- }
-
- boolean
- pred_anewer (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- if (stat_buf->st_atime > pred_ptr->args.time)
- return (true);
- return (false);
- }
-
- boolean
- pred_atime (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- switch (pred_ptr->args.info.kind)
- {
- case COMP_GT:
- if (stat_buf->st_atime > (time_t) pred_ptr->args.info.l_val)
- return (true);
- break;
- case COMP_LT:
- if (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val)
- return (true);
- break;
- case COMP_EQ:
- if ((stat_buf->st_atime >= (time_t) pred_ptr->args.info.l_val)
- && (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val
- + DAYSECS))
- return (true);
- break;
- }
- return (false);
- }
-
- boolean
- pred_close (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- return (true);
- }
-
- boolean
- pred_cmin (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- switch (pred_ptr->args.info.kind)
- {
- case COMP_GT:
- if (stat_buf->st_ctime > (time_t) pred_ptr->args.info.l_val)
- return (true);
- break;
- case COMP_LT:
- if (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val)
- return (true);
- break;
- case COMP_EQ:
- if ((stat_buf->st_ctime >= (time_t) pred_ptr->args.info.l_val)
- && (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val + 60))
- return (true);
- break;
- }
- return (false);
- }
-
- boolean
- pred_cnewer (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- if (stat_buf->st_ctime > pred_ptr->args.time)
- return (true);
- return (false);
- }
-
- boolean
- pred_comma (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- if (pred_ptr->pred_left != NULL)
- (*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
- pred_ptr->pred_left);
- /* Check whether we need a stat here. */
- if (pred_ptr->need_stat)
- {
- if (!have_stat && (*xstat) (pathname, stat_buf) != 0)
- {
- fflush (stdout);
- error (0, errno, "%s", pathname);
- exit_status = 1;
- return (false);
- }
- have_stat = true;
- }
- return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
- pred_ptr->pred_right));
- }
-
- boolean
- pred_ctime (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- switch (pred_ptr->args.info.kind)
- {
- case COMP_GT:
- if (stat_buf->st_ctime > (time_t) pred_ptr->args.info.l_val)
- return (true);
- break;
- case COMP_LT:
- if (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val)
- return (true);
- break;
- case COMP_EQ:
- if ((stat_buf->st_ctime >= (time_t) pred_ptr->args.info.l_val)
- && (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val
- + DAYSECS))
- return (true);
- break;
- }
- return (false);
- }
-
- boolean
- pred_empty (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- if (S_ISDIR (stat_buf->st_mode))
- {
- DIR *d;
- struct dirent *dp;
- boolean empty = true;
-
- errno = 0;
- d = opendir (pathname);
- if (d == NULL)
- {
- fflush (stdout);
- error (0, errno, "%s", pathname);
- exit_status = 1;
- return (false);
- }
- for (dp = readdir (d); dp; dp = readdir (d))
- {
- if (dp->d_name[0] != '.'
- || (dp->d_name[1] != '\0'
- && (dp->d_name[1] != '.' || dp->d_name[2] != '\0')))
- {
- empty = false;
- break;
- }
- }
- if (CLOSEDIR (d))
- {
- fflush (stdout);
- error (0, errno, "%s", pathname);
- exit_status = 1;
- return (false);
- }
- return (empty);
- }
- else if (S_ISREG (stat_buf->st_mode))
- return (stat_buf->st_size == 0);
- else
- return (false);
- }
-
- boolean
- pred_exec (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- int i;
- int path_pos;
- struct exec_val *execp; /* Pointer for efficiency. */
-
- execp = &pred_ptr->args.exec_vec;
-
- /* Replace "{}" with the real path in each affected arg. */
- for (path_pos = 0; execp->paths[path_pos].offset >= 0; path_pos++)
- {
- register char *from, *to;
-
- i = execp->paths[path_pos].offset;
- execp->vec[i] =
- xmalloc (strlen (execp->paths[path_pos].origarg) + 1
- + (strlen (pathname) - 2) * execp->paths[path_pos].count);
- for (from = execp->paths[path_pos].origarg, to = execp->vec[i]; *from; )
- if (from[0] == '{' && from[1] == '}')
- {
- to = stpcpy (to, pathname);
- from += 2;
- }
- else
- *to++ = *from++;
- *to = *from; /* Copy null. */
- }
-
- i = launch (pred_ptr);
-
- /* Free the temporary args. */
- for (path_pos = 0; execp->paths[path_pos].offset >= 0; path_pos++)
- free (execp->vec[execp->paths[path_pos].offset]);
-
- return (i);
- }
-
- boolean
- pred_false (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- return (false);
- }
-
- boolean
- pred_fprint (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- fputs (pathname, pred_ptr->args.stream);
- putc ('\n', pred_ptr->args.stream);
- return (true);
- }
-
- boolean
- pred_fprint0 (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- fputs (pathname, pred_ptr->args.stream);
- putc (0, pred_ptr->args.stream);
- return (true);
- }
-
- boolean
- pred_fprintf (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- FILE *fp = pred_ptr->args.printf_vec.stream;
- struct segment *segment;
- char *cp;
-
- for (segment = pred_ptr->args.printf_vec.segment; segment;
- segment = segment->next)
- {
- if (segment->kind & 0xff00) /* Component of date. */
- {
- time_t t;
-
- switch (segment->kind & 0xff)
- {
- case 'A':
- t = stat_buf->st_atime;
- break;
- case 'C':
- t = stat_buf->st_ctime;
- break;
- case 'T':
- t = stat_buf->st_mtime;
- break;
- }
- fprintf (fp, segment->text,
- format_date (t, (segment->kind >> 8) & 0xff));
- continue;
- }
-
- switch (segment->kind)
- {
- case KIND_PLAIN: /* Plain text string (no % conversion). */
- fwrite (segment->text, 1, segment->text_len, fp);
- break;
- case KIND_STOP: /* Terminate argument (no newline). */
- fwrite (segment->text, 1, segment->text_len, fp);
- return (true);
- case 'a': /* atime in `ctime' format. */
- cp = ctime (&stat_buf->st_atime);
- cp[24] = '\0';
- fprintf (fp, segment->text, cp);
- break;
- case 'b': /* size in 512-byte blocks */
- fprintf (fp, segment->text, ST_NBLOCKS (stat_buf));
- break;
- case 'c': /* ctime in `ctime' format */
- cp = ctime (&stat_buf->st_ctime);
- cp[24] = '\0';
- fprintf (fp, segment->text, cp);
- break;
- case 'd': /* depth in search tree */
- fprintf (fp, segment->text, curdepth);
- break;
- case 'f': /* basename of path */
- cp = rindex (pathname, '/');
- if (cp)
- cp++;
- else
- cp = pathname;
- fprintf (fp, segment->text, cp);
- break;
- case 'F': /* filesystem type */
- fprintf (fp, segment->text, filesystem_type (pathname, stat_buf));
- break;
- case 'g': /* group name */
- {
- struct group *g;
-
- g = getgrgid (stat_buf->st_gid);
- if (g)
- {
- segment->text[segment->text_len] = 's';
- fprintf (fp, segment->text, g->gr_name);
- break;
- }
- /* else fallthru */
- }
- case 'G': /* GID number */
- segment->text[segment->text_len] = 'u';
- fprintf (fp, segment->text, stat_buf->st_gid);
- break;
- case 'h': /* leading directories part of path */
- {
- char cc;
-
- cp = rindex (pathname, '/');
- if (cp == NULL) /* No leading directories. */
- break;
- cc = *cp;
- *cp = '\0';
- fprintf (fp, segment->text, pathname);
- *cp = cc;
- break;
- }
- case 'H': /* ARGV element file was found under */
- {
- char cc = pathname[path_length];
-
- pathname[path_length] = '\0';
- fprintf (fp, segment->text, pathname);
- pathname[path_length] = cc;
- break;
- }
- case 'i': /* inode number */
- fprintf (fp, segment->text, stat_buf->st_ino);
- break;
- case 'k': /* size in 1K blocks */
- fprintf (fp, segment->text, (ST_NBLOCKS (stat_buf) + 1) / 2);
- break;
- case 'l': /* object of symlink */
- #ifdef S_ISLNK
- {
- int linklen;
- char *linkname;
-
- if (!S_ISLNK (stat_buf->st_mode))
- break;
- #ifdef _AIX
- #define LINK_BUF PATH_MAX
- #else
- #define LINK_BUF stat_buf->st_size
- #endif
- linkname = (char *) xmalloc (LINK_BUF + 1);
- linklen = readlink (pathname, linkname, LINK_BUF);
- if (linklen < 0)
- {
- fflush (stdout);
- error (0, "%s", pathname);
- exit_status = 1;
- free (linkname);
- break;
- }
- linkname[linklen] = '\0';
- fprintf (fp, segment->text, linkname);
- free (linkname);
- }
- #endif /* S_ISLNK */
- break;
- case 'm': /* mode as octal number (perms only) */
- fprintf (fp, segment->text, stat_buf->st_mode & 07777);
- break;
- case 'n': /* number of links */
- fprintf (fp, segment->text, stat_buf->st_nlink);
- break;
- case 'p': /* pathname */
- fprintf (fp, segment->text, pathname);
- break;
- case 'P': /* pathname with ARGV element stripped */
- if (curdepth)
- {
- cp = pathname + path_length;
- if (*cp == '/')
- /* Move past the slash between the ARGV element
- and the rest of the pathname. But if the ARGV element
- ends in a slash, we didn't add another, so we've
- already skipped past it. */
- cp++;
- fprintf (fp, segment->text, cp);
- }
- break;
- case 's': /* size in bytes */
- fprintf (fp, segment->text, stat_buf->st_size);
- break;
- case 't': /* mtime in `ctime' format */
- cp = ctime (&stat_buf->st_mtime);
- cp[24] = '\0';
- fprintf (fp, segment->text, cp);
- break;
- case 'u': /* user name */
- {
- struct passwd *p;
-
- p = getpwuid (stat_buf->st_uid);
- if (p)
- {
- segment->text[segment->text_len] = 's';
- fprintf (fp, segment->text, p->pw_name);
- break;
- }
- /* else fallthru */
- }
- case 'U': /* UID number */
- segment->text[segment->text_len] = 'u';
- fprintf (fp, segment->text, stat_buf->st_uid);
- break;
- }
- }
- return (true);
- }
-
- boolean
- pred_fstype (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- if (strcmp (filesystem_type (pathname, stat_buf), pred_ptr->args.str) == 0)
- return (true);
- return (false);
- }
-
- boolean
- pred_gid (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- switch (pred_ptr->args.info.kind)
- {
- case COMP_GT:
- if (stat_buf->st_gid > pred_ptr->args.info.l_val)
- return (true);
- break;
- case COMP_LT:
- if (stat_buf->st_gid < pred_ptr->args.info.l_val)
- return (true);
- break;
- case COMP_EQ:
- if (stat_buf->st_gid == pred_ptr->args.info.l_val)
- return (true);
- break;
- }
- return (false);
- }
-
- boolean
- pred_group (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- if (pred_ptr->args.gid == stat_buf->st_gid)
- return (true);
- else
- return (false);
- }
-
- boolean
- pred_ilname (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- return insert_lname (pathname, stat_buf, pred_ptr, true);
- }
-
- boolean
- pred_iname (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- char *base;
-
- base = basename (pathname);
- if (fnmatch (pred_ptr->args.str, base, FNM_PERIOD | FNM_CASEFOLD) == 0)
- return (true);
- return (false);
- }
-
- boolean
- pred_inum (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- switch (pred_ptr->args.info.kind)
- {
- case COMP_GT:
- if (stat_buf->st_ino > pred_ptr->args.info.l_val)
- return (true);
- break;
- case COMP_LT:
- if (stat_buf->st_ino < pred_ptr->args.info.l_val)
- return (true);
- break;
- case COMP_EQ:
- if (stat_buf->st_ino == pred_ptr->args.info.l_val)
- return (true);
- break;
- }
- return (false);
- }
-
- boolean
- pred_ipath (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- if (fnmatch (pred_ptr->args.str, pathname, FNM_CASEFOLD) == 0)
- return (true);
- return (false);
- }
-
- boolean
- pred_links (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- switch (pred_ptr->args.info.kind)
- {
- case COMP_GT:
- if (stat_buf->st_nlink > pred_ptr->args.info.l_val)
- return (true);
- break;
- case COMP_LT:
- if (stat_buf->st_nlink < pred_ptr->args.info.l_val)
- return (true);
- break;
- case COMP_EQ:
- if (stat_buf->st_nlink == pred_ptr->args.info.l_val)
- return (true);
- break;
- }
- return (false);
- }
-
- boolean
- pred_lname (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- return insert_lname (pathname, stat_buf, pred_ptr, false);
- }
-
- static boolean
- insert_lname (pathname, stat_buf, pred_ptr, ignore_case)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- boolean ignore_case;
- {
- boolean ret = false;
- #ifdef S_ISLNK
- int linklen;
- char *linkname;
-
- if (S_ISLNK (stat_buf->st_mode))
- {
- linkname = (char *) xmalloc (LINK_BUF + 1);
- linklen = readlink (pathname, linkname, LINK_BUF);
- if (linklen < 0)
- {
- fflush (stdout);
- error (0, "can't read link %s", pathname);
- }
- else
- {
- linkname[linklen] = '\0';
- if (fnmatch (pred_ptr->args.str, linkname,
- ignore_case ? FNM_CASEFOLD : 0) == 0)
- ret = true;
- }
- free (linkname);
- }
- #endif /* S_ISLNK */
- return (ret);
- }
-
- boolean
- pred_ls (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- list_file (pathname, stat_buf);
- return (true);
- }
-
- boolean
- pred_mmin (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- switch (pred_ptr->args.info.kind)
- {
- case COMP_GT:
- if (stat_buf->st_mtime > (time_t) pred_ptr->args.info.l_val)
- return (true);
- break;
- case COMP_LT:
- if (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val)
- return (true);
- break;
- case COMP_EQ:
- if ((stat_buf->st_mtime >= (time_t) pred_ptr->args.info.l_val)
- && (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val + 60))
- return (true);
- break;
- }
- return (false);
- }
-
- boolean
- pred_mtime (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- switch (pred_ptr->args.info.kind)
- {
- case COMP_GT:
- if (stat_buf->st_mtime > (time_t) pred_ptr->args.info.l_val)
- return (true);
- break;
- case COMP_LT:
- if (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val)
- return (true);
- break;
- case COMP_EQ:
- if ((stat_buf->st_mtime >= (time_t) pred_ptr->args.info.l_val)
- && (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val
- + DAYSECS))
- return (true);
- break;
- }
- return (false);
- }
-
- boolean
- pred_name (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- char *base;
-
- base = basename (pathname);
- if (fnmatch (pred_ptr->args.str, base, FNM_PERIOD) == 0)
- return (true);
- return (false);
- }
-
- boolean
- pred_negate (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- /* Check whether we need a stat here. */
- if (pred_ptr->need_stat)
- {
- if (!have_stat && (*xstat) (pathname, stat_buf) != 0)
- {
- fflush (stdout);
- error (0, errno, "%s", pathname);
- exit_status = 1;
- return (false);
- }
- have_stat = true;
- }
- return (!(*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
- pred_ptr->pred_right));
- }
-
- boolean
- pred_newer (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- if (stat_buf->st_mtime > pred_ptr->args.time)
- return (true);
- return (false);
- }
-
- boolean
- pred_nogroup (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- #ifdef CACHE_IDS
- extern char *gid_unused;
-
- return gid_unused[(unsigned) stat_buf->st_gid];
- #else
- return getgrgid (stat_buf->st_gid) == NULL;
- #endif
- }
-
- boolean
- pred_nouser (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- #ifdef CACHE_IDS
- extern char *uid_unused;
-
- return uid_unused[(unsigned) stat_buf->st_uid];
- #else
- return getpwuid (stat_buf->st_uid) == NULL;
- #endif
- }
-
- boolean
- pred_ok (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- int i, yes;
-
- fflush (stdout);
- fprintf (stderr, "< %s ... %s > ? ",
- pred_ptr->args.exec_vec.vec[0], pathname);
- fflush (stderr);
- i = getchar ();
- yes = (i == 'y' || i == 'Y');
- while (i != EOF && i != '\n')
- i = getchar ();
- if (!yes)
- return (false);
- return pred_exec (pathname, stat_buf, pred_ptr);
- }
-
- boolean
- pred_open (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- return (true);
- }
-
- boolean
- pred_or (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- if (pred_ptr->pred_left == NULL
- || !(*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
- pred_ptr->pred_left))
- {
- /* Check whether we need a stat here. */
- if (pred_ptr->need_stat)
- {
- if (!have_stat && (*xstat) (pathname, stat_buf) != 0)
- {
- fflush (stdout);
- error (0, errno, "%s", pathname);
- exit_status = 1;
- return (false);
- }
- have_stat = true;
- }
- return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
- pred_ptr->pred_right));
- }
- else
- return (true);
- }
-
- boolean
- pred_path (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- if (fnmatch (pred_ptr->args.str, pathname, 0) == 0)
- return (true);
- return (false);
- }
-
- boolean
- pred_perm (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- if (pred_ptr->args.perm & 010000)
- {
- /* Magic flag set in parse_perm:
- true if at least the given bits are set. */
- if ((stat_buf->st_mode & 07777 & pred_ptr->args.perm)
- == (pred_ptr->args.perm & 07777))
- return (true);
- }
- else if (pred_ptr->args.perm & 020000)
- {
- /* Magic flag set in parse_perm:
- true if any of the given bits are set. */
- if ((stat_buf->st_mode & 07777) & pred_ptr->args.perm)
- return (true);
- }
- else
- {
- /* True if exactly the given bits are set. */
- if ((stat_buf->st_mode & 07777) == pred_ptr->args.perm)
- return (true);
- }
- return (false);
- }
-
- boolean
- pred_print (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- puts (pathname);
- return (true);
- }
-
- boolean
- pred_print0 (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- fputs (pathname, stdout);
- putc (0, stdout);
- return (true);
- }
-
- boolean
- pred_prune (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- stop_at_current_level = true;
- return (do_dir_first); /* This is what SunOS find seems to do. */
- }
-
- boolean
- pred_regex (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- if (re_match (pred_ptr->args.regex, pathname, strlen (pathname), 0,
- (struct re_registers *) NULL) != -1)
- return (true);
- return (false);
- }
-
- boolean
- pred_size (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- unsigned long f_val;
-
- f_val = (stat_buf->st_size + pred_ptr->args.size.blocksize - 1)
- / pred_ptr->args.size.blocksize;
- switch (pred_ptr->args.size.kind)
- {
- case COMP_GT:
- if (f_val > pred_ptr->args.size.size)
- return (true);
- break;
- case COMP_LT:
- if (f_val < pred_ptr->args.size.size)
- return (true);
- break;
- case COMP_EQ:
- if (f_val == pred_ptr->args.size.size)
- return (true);
- break;
- }
- return (false);
- }
-
- boolean
- pred_true (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- return (true);
- }
-
- boolean
- pred_type (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- unsigned long mode = stat_buf->st_mode;
- unsigned long type = pred_ptr->args.type;
-
- #ifndef S_IFMT
- /* POSIX system; check `mode' the slow way. */
- if ((S_ISBLK (mode) && type == S_IFBLK)
- || (S_ISCHR (mode) && type == S_IFCHR)
- || (S_ISDIR (mode) && type == S_IFDIR)
- || (S_ISREG (mode) && type == S_IFREG)
- #ifdef S_IFLNK
- || (S_ISLNK (mode) && type == S_IFLNK)
- #endif
- #ifdef S_IFIFO
- || (S_ISFIFO (mode) && type == S_IFIFO)
- #endif
- #ifdef S_IFSOCK
- || (S_ISSOCK (mode) && type == S_IFSOCK)
- #endif
- )
- #else /* S_IFMT */
- /* Unix system; check `mode' the fast way. */
- if ((mode & S_IFMT) == type)
- #endif /* S_IFMT */
- return (true);
- else
- return (false);
- }
-
- boolean
- pred_uid (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- switch (pred_ptr->args.info.kind)
- {
- case COMP_GT:
- if (stat_buf->st_uid > pred_ptr->args.info.l_val)
- return (true);
- break;
- case COMP_LT:
- if (stat_buf->st_uid < pred_ptr->args.info.l_val)
- return (true);
- break;
- case COMP_EQ:
- if (stat_buf->st_uid == pred_ptr->args.info.l_val)
- return (true);
- break;
- }
- return (false);
- }
-
- boolean
- pred_used (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- time_t delta;
-
- delta = stat_buf->st_atime - stat_buf->st_ctime; /* Use difftime? */
- switch (pred_ptr->args.info.kind)
- {
- case COMP_GT:
- if (delta > (time_t) pred_ptr->args.info.l_val)
- return (true);
- break;
- case COMP_LT:
- if (delta < (time_t) pred_ptr->args.info.l_val)
- return (true);
- break;
- case COMP_EQ:
- if ((delta >= (time_t) pred_ptr->args.info.l_val)
- && (delta < (time_t) pred_ptr->args.info.l_val + DAYSECS))
- return (true);
- break;
- }
- return (false);
- }
-
- boolean
- pred_user (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- if (pred_ptr->args.uid == stat_buf->st_uid)
- return (true);
- else
- return (false);
- }
-
- boolean
- pred_xtype (pathname, stat_buf, pred_ptr)
- char *pathname;
- struct stat *stat_buf;
- struct predicate *pred_ptr;
- {
- struct stat sbuf;
- int (*ystat) ();
-
- ystat = xstat == lstat ? stat : lstat;
- if ((*ystat) (pathname, &sbuf) != 0)
- {
- if (ystat == stat && errno == ENOENT)
- /* Mimic behavior of ls -lL. */
- return (pred_type (pathname, stat_buf, pred_ptr));
- fflush (stdout);
- error (0, errno, "%s", pathname);
- exit_status = 1;
- return (false);
- }
- return (pred_type (pathname, &sbuf, pred_ptr));
- }
-
- /* 1) fork to get a child; parent remembers the child pid
- 2) child execs the command requested
- 3) parent waits for child; checks for proper pid of child
-
- Possible returns:
-
- ret errno status(h) status(l)
-
- pid x signal# 0177 stopped
- pid x exit arg 0 term by _exit
- pid x 0 signal # term by signal
- -1 EINTR parent got signal
- -1 other some other kind of error
-
- Return true only if the pid matches, status(l) is
- zero, and the exit arg (status high) is 0.
- Otherwise return false, possibly printing an error message. */
-
- boolean
- launch (pred_ptr)
- struct predicate *pred_ptr;
- {
- int status, wait_ret, child_pid;
- struct exec_val *execp; /* Pointer for efficiency. */
-
- execp = &pred_ptr->args.exec_vec;
-
- /* Make sure output of command doesn't get mixed with find output. */
- fflush (stdout);
- fflush (stderr);
-
- child_pid = vfork ();
- if (child_pid == -1)
- error (1, errno, "cannot fork");
- if (child_pid == 0)
- {
- /* We be the child. */
- execvp (execp->vec[0], execp->vec);
- error (0, errno, "%s", execp->vec[0]);
- _exit (1);
- }
-
- wait_ret = wait (&status);
- if (wait_ret == -1)
- {
- fflush (stdout);
- error (0, errno, "error waiting for %s", execp->vec[0]);
- exit_status = 1;
- return (false);
- }
- if (wait_ret != child_pid)
- {
- fflush (stdout);
- error (0, 0, "wait got pid %d, expected pid %d", wait_ret, child_pid);
- exit_status = 1;
- return (false);
- }
- if (WIFSTOPPED (status))
- {
- fflush (stdout);
- error (0, 0, "%s stopped by signal %d",
- execp->vec[0], WSTOPSIG (status));
- exit_status = 1;
- return (false);
- }
- if (WIFSIGNALED (status))
- {
- fflush (stdout);
- error (0, 0, "%s terminated by signal %d",
- execp->vec[0], WTERMSIG (status));
- exit_status = 1;
- return (false);
- }
- return (!WEXITSTATUS (status));
- }
-
- /* Return a static string formatting the time WHEN according to the
- strftime format character KIND. */
-
- char *
- format_date (when, kind)
- time_t when;
- int kind;
- {
- static char fmt[3];
- static char buf[64]; /* More than enough space. */
-
- if (kind == '@')
- {
- sprintf (buf, "%ld", when);
- return (buf);
- }
- else
- {
- fmt[0] = '%';
- fmt[1] = kind;
- fmt[2] = '\0';
- if (strftime (buf, sizeof (buf), fmt, localtime (&when)))
- return (buf);
- }
- return "";
- }
-
- #ifdef DEBUG
- /* Return a pointer to the string representation of
- the predicate function PRED_FUNC. */
-
- char *
- find_pred_name (pred_func)
- PFB pred_func;
- {
- int i;
-
- for (i = 0; pred_table[i].pred_func != 0; i++)
- if (pred_table[i].pred_func == pred_func)
- break;
- return (pred_table[i].pred_name);
- }
-
- char *
- type_name (type)
- short type;
- {
- int i;
-
- for (i = 0; type_table[i].type != (short) -1; i++)
- if (type_table[i].type == type)
- break;
- return (type_table[i].type_name);
- }
-
- char *
- prec_name (prec)
- short prec;
- {
- int i;
-
- for (i = 0; prec_table[i].prec != (short) -1; i++)
- if (prec_table[i].prec == prec)
- break;
- return (prec_table[i].prec_name);
- }
-
- /* Walk the expression tree NODE to stdout.
- INDENT is the number of levels to indent the left margin. */
-
- void
- print_tree (node, indent)
- struct predicate *node;
- int indent;
- {
- int i;
-
- if (node == NULL)
- return;
- for (i = 0; i < indent; i++)
- printf (" ");
- printf ("pred = %s type = %s prec = %s addr = %x\n",
- find_pred_name (node->pred_func),
- type_name (node->p_type), prec_name (node->p_prec), node);
- for (i = 0; i < indent; i++)
- printf (" ");
- printf ("left:\n");
- print_tree (node->pred_left, indent + 1);
- for (i = 0; i < indent; i++)
- printf (" ");
- printf ("right:\n");
- print_tree (node->pred_right, indent + 1);
- }
-
- /* Copy STR into BUF and trim blanks from the end of BUF.
- Return BUF. */
-
- char *
- blank_rtrim (str, buf)
- char *str;
- char *buf;
- {
- int i;
-
- if (str == NULL)
- return (NULL);
- strcpy (buf, str);
- i = strlen (buf) - 1;
- while ((i >= 0) && ((buf[i] == ' ') || buf[i] == '\t'))
- i--;
- buf[++i] = '\0';
- return (buf);
- }
-
- /* Print out the predicate list starting at NODE. */
-
- void
- print_list (node)
- struct predicate *node;
- {
- struct predicate *cur;
- char name[256];
-
- cur = node;
- while (cur != NULL)
- {
- printf ("%s ", blank_rtrim (find_pred_name (cur->pred_func), name));
- cur = cur->pred_next;
- }
- printf ("\n");
- }
- #endif /* DEBUG */
-