upgraded description
[findutils.git] / find / pred.c
blob9c8c682852cee0ba22cb9f0b9df2f6d1678d0b1b
1 /* pred.c -- execute the expression tree.
2 Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
18 #include <config.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <stdio.h>
22 #include <fnmatch.h>
23 #include <signal.h>
24 #include <pwd.h>
25 #include <grp.h>
26 #include "defs.h"
27 #include "modetype.h"
28 #include "wait.h"
30 #if !defined(SIGCHLD) && defined(SIGCLD)
31 #define SIGCHLD SIGCLD
32 #endif
34 #ifndef _POSIX_VERSION
35 struct passwd *getpwuid ();
36 struct group *getgrgid ();
37 #endif
39 #if HAVE_DIRENT_H
40 # include <dirent.h>
41 # define NAMLEN(dirent) strlen((dirent)->d_name)
42 #else
43 # define dirent direct
44 # define NAMLEN(dirent) (dirent)->d_namlen
45 # if HAVE_SYS_NDIR_H
46 # include <sys/ndir.h>
47 # endif
48 # if HAVE_SYS_DIR_H
49 # include <sys/dir.h>
50 # endif
51 # if HAVE_NDIR_H
52 # include <ndir.h>
53 # endif
54 #endif
56 #ifdef CLOSEDIR_VOID
57 /* Fake a return value. */
58 #define CLOSEDIR(d) (closedir (d), 0)
59 #else
60 #define CLOSEDIR(d) closedir (d)
61 #endif
63 #ifndef S_IFLNK
64 #define lstat stat
65 #endif
67 /* Extract or fake data from a `struct stat'.
68 ST_NBLOCKS: Number of 512-byte blocks in the file
69 (including indirect blocks).
70 HP-UX, perhaps uniquely, counts st_blocks in 1024-byte units.
71 This workaround loses when mixing HP-UX and 4BSD filesystems, though. */
72 #ifdef _POSIX_SOURCE
73 # define ST_NBLOCKS(statp) (((statp)->st_size + 512 - 1) / 512)
74 #else
75 # ifndef HAVE_ST_BLOCKS
76 # define ST_NBLOCKS(statp) (st_blocks ((statp)->st_size))
77 # else
78 # if defined(hpux) || defined(__hpux__)
79 # define ST_NBLOCKS(statp) ((statp)->st_blocks * 2)
80 # else
81 # define ST_NBLOCKS(statp) ((statp)->st_blocks)
82 # endif
83 # endif
84 #endif
86 int lstat ();
87 int stat ();
89 static boolean insert_lname P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr, boolean ignore_case));
90 static boolean launch P_((struct predicate *pred_ptr));
91 static char *format_date P_((time_t when, int kind));
93 #ifdef DEBUG
94 struct pred_assoc
96 PFB pred_func;
97 char *pred_name;
100 struct pred_assoc pred_table[] =
102 {pred_amin, "amin "},
103 {pred_and, "and "},
104 {pred_anewer, "anewer "},
105 {pred_atime, "atime "},
106 {pred_close, ") "},
107 {pred_amin, "cmin "},
108 {pred_cnewer, "cnewer "},
109 {pred_comma, ", "},
110 {pred_ctime, "ctime "},
111 {pred_empty, "empty "},
112 {pred_exec, "exec "},
113 {pred_false, "false "},
114 {pred_fprint, "fprint "},
115 {pred_fprint0, "fprint0 "},
116 {pred_fprintf, "fprintf "},
117 {pred_fstype, "fstype "},
118 {pred_gid, "gid "},
119 {pred_group, "group "},
120 {pred_ilname, "ilname "},
121 {pred_iname, "iname "},
122 {pred_inum, "inum "},
123 {pred_ipath, "ipath "},
124 {pred_links, "links "},
125 {pred_lname, "lname "},
126 {pred_ls, "ls "},
127 {pred_amin, "mmin "},
128 {pred_mtime, "mtime "},
129 {pred_name, "name "},
130 {pred_negate, "not "},
131 {pred_newer, "newer "},
132 {pred_nogroup, "nogroup "},
133 {pred_nouser, "nouser "},
134 {pred_ok, "ok "},
135 {pred_open, "( "},
136 {pred_or, "or "},
137 {pred_path, "path "},
138 {pred_perm, "perm "},
139 {pred_print, "print "},
140 {pred_print0, "print0 "},
141 {pred_prune, "prune "},
142 {pred_regex, "regex "},
143 {pred_size, "size "},
144 {pred_true, "true "},
145 {pred_type, "type "},
146 {pred_uid, "uid "},
147 {pred_used, "used "},
148 {pred_user, "user "},
149 {pred_xtype, "xtype "},
150 {0, "none "}
153 struct op_assoc
155 short type;
156 char *type_name;
159 struct op_assoc type_table[] =
161 {NO_TYPE, "no "},
162 {PRIMARY_TYPE, "primary "},
163 {UNI_OP, "uni_op "},
164 {BI_OP, "bi_op "},
165 {OPEN_PAREN, "open_paren "},
166 {CLOSE_PAREN, "close_paren "},
167 {-1, "unknown "}
170 struct prec_assoc
172 short prec;
173 char *prec_name;
176 struct prec_assoc prec_table[] =
178 {NO_PREC, "no "},
179 {COMMA_PREC, "comma "},
180 {OR_PREC, "or "},
181 {AND_PREC, "and "},
182 {NEGATE_PREC, "negate "},
183 {MAX_PREC, "max "},
184 {-1, "unknown "}
186 #endif /* DEBUG */
188 /* Predicate processing routines.
190 PATHNAME is the full pathname of the file being checked.
191 *STAT_BUF contains information about PATHNAME.
192 *PRED_PTR contains information for applying the predicate.
194 Return true if the file passes this predicate, false if not. */
196 boolean
197 pred_amin (pathname, stat_buf, pred_ptr)
198 char *pathname;
199 struct stat *stat_buf;
200 struct predicate *pred_ptr;
202 switch (pred_ptr->args.info.kind)
204 case COMP_GT:
205 if (stat_buf->st_atime > (time_t) pred_ptr->args.info.l_val)
206 return (true);
207 break;
208 case COMP_LT:
209 if (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val)
210 return (true);
211 break;
212 case COMP_EQ:
213 if ((stat_buf->st_atime >= (time_t) pred_ptr->args.info.l_val)
214 && (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val + 60))
215 return (true);
216 break;
218 return (false);
221 boolean
222 pred_and (pathname, stat_buf, pred_ptr)
223 char *pathname;
224 struct stat *stat_buf;
225 struct predicate *pred_ptr;
227 if (pred_ptr->pred_left == NULL
228 || (*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
229 pred_ptr->pred_left))
231 /* Check whether we need a stat here. */
232 if (pred_ptr->need_stat)
234 if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
236 error (0, errno, "%s", pathname);
237 exit_status = 1;
238 return (false);
240 have_stat = true;
242 return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
243 pred_ptr->pred_right));
245 else
246 return (false);
249 boolean
250 pred_anewer (pathname, stat_buf, pred_ptr)
251 char *pathname;
252 struct stat *stat_buf;
253 struct predicate *pred_ptr;
255 if (stat_buf->st_atime > pred_ptr->args.time)
256 return (true);
257 return (false);
260 boolean
261 pred_atime (pathname, stat_buf, pred_ptr)
262 char *pathname;
263 struct stat *stat_buf;
264 struct predicate *pred_ptr;
266 switch (pred_ptr->args.info.kind)
268 case COMP_GT:
269 if (stat_buf->st_atime > (time_t) pred_ptr->args.info.l_val)
270 return (true);
271 break;
272 case COMP_LT:
273 if (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val)
274 return (true);
275 break;
276 case COMP_EQ:
277 if ((stat_buf->st_atime >= (time_t) pred_ptr->args.info.l_val)
278 && (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val
279 + DAYSECS))
280 return (true);
281 break;
283 return (false);
286 boolean
287 pred_close (pathname, stat_buf, pred_ptr)
288 char *pathname;
289 struct stat *stat_buf;
290 struct predicate *pred_ptr;
292 return (true);
295 boolean
296 pred_cmin (pathname, stat_buf, pred_ptr)
297 char *pathname;
298 struct stat *stat_buf;
299 struct predicate *pred_ptr;
301 switch (pred_ptr->args.info.kind)
303 case COMP_GT:
304 if (stat_buf->st_ctime > (time_t) pred_ptr->args.info.l_val)
305 return (true);
306 break;
307 case COMP_LT:
308 if (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val)
309 return (true);
310 break;
311 case COMP_EQ:
312 if ((stat_buf->st_ctime >= (time_t) pred_ptr->args.info.l_val)
313 && (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val + 60))
314 return (true);
315 break;
317 return (false);
320 boolean
321 pred_cnewer (pathname, stat_buf, pred_ptr)
322 char *pathname;
323 struct stat *stat_buf;
324 struct predicate *pred_ptr;
326 if (stat_buf->st_ctime > pred_ptr->args.time)
327 return (true);
328 return (false);
331 boolean
332 pred_comma (pathname, stat_buf, pred_ptr)
333 char *pathname;
334 struct stat *stat_buf;
335 struct predicate *pred_ptr;
337 if (pred_ptr->pred_left != NULL)
338 (*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
339 pred_ptr->pred_left);
340 /* Check whether we need a stat here. */
341 if (pred_ptr->need_stat)
343 if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
345 error (0, errno, "%s", pathname);
346 exit_status = 1;
347 return (false);
349 have_stat = true;
351 return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
352 pred_ptr->pred_right));
355 boolean
356 pred_ctime (pathname, stat_buf, pred_ptr)
357 char *pathname;
358 struct stat *stat_buf;
359 struct predicate *pred_ptr;
361 switch (pred_ptr->args.info.kind)
363 case COMP_GT:
364 if (stat_buf->st_ctime > (time_t) pred_ptr->args.info.l_val)
365 return (true);
366 break;
367 case COMP_LT:
368 if (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val)
369 return (true);
370 break;
371 case COMP_EQ:
372 if ((stat_buf->st_ctime >= (time_t) pred_ptr->args.info.l_val)
373 && (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val
374 + DAYSECS))
375 return (true);
376 break;
378 return (false);
381 boolean
382 pred_empty (pathname, stat_buf, pred_ptr)
383 char *pathname;
384 struct stat *stat_buf;
385 struct predicate *pred_ptr;
387 if (S_ISDIR (stat_buf->st_mode))
389 DIR *d;
390 struct dirent *dp;
391 boolean empty = true;
393 errno = 0;
394 d = opendir (rel_pathname);
395 if (d == NULL)
397 error (0, errno, "%s", pathname);
398 exit_status = 1;
399 return (false);
401 for (dp = readdir (d); dp; dp = readdir (d))
403 if (dp->d_name[0] != '.'
404 || (dp->d_name[1] != '\0'
405 && (dp->d_name[1] != '.' || dp->d_name[2] != '\0')))
407 empty = false;
408 break;
411 if (CLOSEDIR (d))
413 error (0, errno, "%s", pathname);
414 exit_status = 1;
415 return (false);
417 return (empty);
419 else if (S_ISREG (stat_buf->st_mode))
420 return (stat_buf->st_size == 0);
421 else
422 return (false);
425 boolean
426 pred_exec (pathname, stat_buf, pred_ptr)
427 char *pathname;
428 struct stat *stat_buf;
429 struct predicate *pred_ptr;
431 int i;
432 int path_pos;
433 struct exec_val *execp; /* Pointer for efficiency. */
435 execp = &pred_ptr->args.exec_vec;
437 /* Replace "{}" with the real path in each affected arg. */
438 for (path_pos = 0; execp->paths[path_pos].offset >= 0; path_pos++)
440 register char *from, *to;
442 i = execp->paths[path_pos].offset;
443 execp->vec[i] =
444 xmalloc (strlen (execp->paths[path_pos].origarg) + 1
445 + (strlen (pathname) - 2) * execp->paths[path_pos].count);
446 for (from = execp->paths[path_pos].origarg, to = execp->vec[i]; *from; )
447 if (from[0] == '{' && from[1] == '}')
449 to = stpcpy (to, pathname);
450 from += 2;
452 else
453 *to++ = *from++;
454 *to = *from; /* Copy null. */
457 i = launch (pred_ptr);
459 /* Free the temporary args. */
460 for (path_pos = 0; execp->paths[path_pos].offset >= 0; path_pos++)
461 free (execp->vec[execp->paths[path_pos].offset]);
463 return (i);
466 boolean
467 pred_false (pathname, stat_buf, pred_ptr)
468 char *pathname;
469 struct stat *stat_buf;
470 struct predicate *pred_ptr;
472 return (false);
475 boolean
476 pred_fls (pathname, stat_buf, pred_ptr)
477 char *pathname;
478 struct stat *stat_buf;
479 struct predicate *pred_ptr;
481 list_file (pathname, rel_pathname, stat_buf, pred_ptr->args.stream);
482 return (true);
485 boolean
486 pred_fprint (pathname, stat_buf, pred_ptr)
487 char *pathname;
488 struct stat *stat_buf;
489 struct predicate *pred_ptr;
491 fputs (pathname, pred_ptr->args.stream);
492 putc ('\n', pred_ptr->args.stream);
493 return (true);
496 boolean
497 pred_fprint0 (pathname, stat_buf, pred_ptr)
498 char *pathname;
499 struct stat *stat_buf;
500 struct predicate *pred_ptr;
502 fputs (pathname, pred_ptr->args.stream);
503 putc (0, pred_ptr->args.stream);
504 return (true);
507 boolean
508 pred_fprintf (pathname, stat_buf, pred_ptr)
509 char *pathname;
510 struct stat *stat_buf;
511 struct predicate *pred_ptr;
513 FILE *fp = pred_ptr->args.printf_vec.stream;
514 struct segment *segment;
515 char *cp;
517 for (segment = pred_ptr->args.printf_vec.segment; segment;
518 segment = segment->next)
520 if (segment->kind & 0xff00) /* Component of date. */
522 time_t t;
524 switch (segment->kind & 0xff)
526 case 'A':
527 t = stat_buf->st_atime;
528 break;
529 case 'C':
530 t = stat_buf->st_ctime;
531 break;
532 case 'T':
533 t = stat_buf->st_mtime;
534 break;
535 default:
536 abort ();
538 fprintf (fp, segment->text,
539 format_date (t, (segment->kind >> 8) & 0xff));
540 continue;
543 switch (segment->kind)
545 case KIND_PLAIN: /* Plain text string (no % conversion). */
546 fwrite (segment->text, 1, segment->text_len, fp);
547 break;
548 case KIND_STOP: /* Terminate argument and flush output. */
549 fwrite (segment->text, 1, segment->text_len, fp);
550 fflush (fp);
551 return (true);
552 case 'a': /* atime in `ctime' format. */
553 cp = ctime (&stat_buf->st_atime);
554 cp[24] = '\0';
555 fprintf (fp, segment->text, cp);
556 break;
557 case 'b': /* size in 512-byte blocks */
558 fprintf (fp, segment->text, ST_NBLOCKS (stat_buf));
559 break;
560 case 'c': /* ctime in `ctime' format */
561 cp = ctime (&stat_buf->st_ctime);
562 cp[24] = '\0';
563 fprintf (fp, segment->text, cp);
564 break;
565 case 'd': /* depth in search tree */
566 fprintf (fp, segment->text, curdepth);
567 break;
568 case 'f': /* basename of path */
569 cp = strrchr (pathname, '/');
570 if (cp)
571 cp++;
572 else
573 cp = pathname;
574 fprintf (fp, segment->text, cp);
575 break;
576 case 'F': /* filesystem type */
577 fprintf (fp, segment->text,
578 filesystem_type (pathname, rel_pathname, stat_buf));
579 break;
580 case 'g': /* group name */
582 struct group *g;
584 g = getgrgid (stat_buf->st_gid);
585 if (g)
587 segment->text[segment->text_len] = 's';
588 fprintf (fp, segment->text, g->gr_name);
589 break;
591 /* else fallthru */
593 case 'G': /* GID number */
594 segment->text[segment->text_len] = 'u';
595 fprintf (fp, segment->text, stat_buf->st_gid);
596 break;
597 case 'h': /* leading directories part of path */
599 char cc;
601 cp = strrchr (pathname, '/');
602 if (cp == NULL) /* No leading directories. */
603 break;
604 cc = *cp;
605 *cp = '\0';
606 fprintf (fp, segment->text, pathname);
607 *cp = cc;
608 break;
610 case 'H': /* ARGV element file was found under */
612 char cc = pathname[path_length];
614 pathname[path_length] = '\0';
615 fprintf (fp, segment->text, pathname);
616 pathname[path_length] = cc;
617 break;
619 case 'i': /* inode number */
620 fprintf (fp, segment->text, stat_buf->st_ino);
621 break;
622 case 'k': /* size in 1K blocks */
623 fprintf (fp, segment->text, (ST_NBLOCKS (stat_buf) + 1) / 2);
624 break;
625 case 'l': /* object of symlink */
626 #ifdef S_ISLNK
628 char *linkname = 0;
630 if (S_ISLNK (stat_buf->st_mode))
632 linkname = get_link_name (pathname, rel_pathname);
633 if (linkname == 0)
634 exit_status = 1;
636 if (linkname)
638 fprintf (fp, segment->text, linkname);
639 free (linkname);
641 else
642 fprintf (fp, segment->text, "");
644 #endif /* S_ISLNK */
645 break;
646 case 'm': /* mode as octal number (perms only) */
647 fprintf (fp, segment->text, stat_buf->st_mode & 07777);
648 break;
649 case 'n': /* number of links */
650 fprintf (fp, segment->text, stat_buf->st_nlink);
651 break;
652 case 'p': /* pathname */
653 fprintf (fp, segment->text, pathname);
654 break;
655 case 'P': /* pathname with ARGV element stripped */
656 if (curdepth)
658 cp = pathname + path_length;
659 if (*cp == '/')
660 /* Move past the slash between the ARGV element
661 and the rest of the pathname. But if the ARGV element
662 ends in a slash, we didn't add another, so we've
663 already skipped past it. */
664 cp++;
666 else
667 cp = "";
668 fprintf (fp, segment->text, cp);
669 break;
670 case 's': /* size in bytes */
671 fprintf (fp, segment->text, stat_buf->st_size);
672 break;
673 case 't': /* mtime in `ctime' format */
674 cp = ctime (&stat_buf->st_mtime);
675 cp[24] = '\0';
676 fprintf (fp, segment->text, cp);
677 break;
678 case 'u': /* user name */
680 struct passwd *p;
682 p = getpwuid (stat_buf->st_uid);
683 if (p)
685 segment->text[segment->text_len] = 's';
686 fprintf (fp, segment->text, p->pw_name);
687 break;
689 /* else fallthru */
691 case 'U': /* UID number */
692 segment->text[segment->text_len] = 'u';
693 fprintf (fp, segment->text, stat_buf->st_uid);
694 break;
697 return (true);
700 boolean
701 pred_fstype (pathname, stat_buf, pred_ptr)
702 char *pathname;
703 struct stat *stat_buf;
704 struct predicate *pred_ptr;
706 if (strcmp (filesystem_type (pathname, rel_pathname, stat_buf),
707 pred_ptr->args.str) == 0)
708 return (true);
709 return (false);
712 boolean
713 pred_gid (pathname, stat_buf, pred_ptr)
714 char *pathname;
715 struct stat *stat_buf;
716 struct predicate *pred_ptr;
718 switch (pred_ptr->args.info.kind)
720 case COMP_GT:
721 if (stat_buf->st_gid > pred_ptr->args.info.l_val)
722 return (true);
723 break;
724 case COMP_LT:
725 if (stat_buf->st_gid < pred_ptr->args.info.l_val)
726 return (true);
727 break;
728 case COMP_EQ:
729 if (stat_buf->st_gid == pred_ptr->args.info.l_val)
730 return (true);
731 break;
733 return (false);
736 boolean
737 pred_group (pathname, stat_buf, pred_ptr)
738 char *pathname;
739 struct stat *stat_buf;
740 struct predicate *pred_ptr;
742 if (pred_ptr->args.gid == stat_buf->st_gid)
743 return (true);
744 else
745 return (false);
748 boolean
749 pred_ilname (pathname, stat_buf, pred_ptr)
750 char *pathname;
751 struct stat *stat_buf;
752 struct predicate *pred_ptr;
754 return insert_lname (pathname, stat_buf, pred_ptr, true);
757 boolean
758 pred_iname (pathname, stat_buf, pred_ptr)
759 char *pathname;
760 struct stat *stat_buf;
761 struct predicate *pred_ptr;
763 char *base;
765 base = basename (pathname);
766 if (fnmatch (pred_ptr->args.str, base, FNM_PERIOD | FNM_CASEFOLD) == 0)
767 return (true);
768 return (false);
771 boolean
772 pred_inum (pathname, stat_buf, pred_ptr)
773 char *pathname;
774 struct stat *stat_buf;
775 struct predicate *pred_ptr;
777 switch (pred_ptr->args.info.kind)
779 case COMP_GT:
780 if (stat_buf->st_ino > pred_ptr->args.info.l_val)
781 return (true);
782 break;
783 case COMP_LT:
784 if (stat_buf->st_ino < pred_ptr->args.info.l_val)
785 return (true);
786 break;
787 case COMP_EQ:
788 if (stat_buf->st_ino == pred_ptr->args.info.l_val)
789 return (true);
790 break;
792 return (false);
795 boolean
796 pred_ipath (pathname, stat_buf, pred_ptr)
797 char *pathname;
798 struct stat *stat_buf;
799 struct predicate *pred_ptr;
801 if (fnmatch (pred_ptr->args.str, pathname, FNM_CASEFOLD) == 0)
802 return (true);
803 return (false);
806 boolean
807 pred_links (pathname, stat_buf, pred_ptr)
808 char *pathname;
809 struct stat *stat_buf;
810 struct predicate *pred_ptr;
812 switch (pred_ptr->args.info.kind)
814 case COMP_GT:
815 if (stat_buf->st_nlink > pred_ptr->args.info.l_val)
816 return (true);
817 break;
818 case COMP_LT:
819 if (stat_buf->st_nlink < pred_ptr->args.info.l_val)
820 return (true);
821 break;
822 case COMP_EQ:
823 if (stat_buf->st_nlink == pred_ptr->args.info.l_val)
824 return (true);
825 break;
827 return (false);
830 boolean
831 pred_lname (pathname, stat_buf, pred_ptr)
832 char *pathname;
833 struct stat *stat_buf;
834 struct predicate *pred_ptr;
836 return insert_lname (pathname, stat_buf, pred_ptr, false);
839 static boolean
840 insert_lname (pathname, stat_buf, pred_ptr, ignore_case)
841 char *pathname;
842 struct stat *stat_buf;
843 struct predicate *pred_ptr;
844 boolean ignore_case;
846 boolean ret = false;
847 #ifdef S_ISLNK
848 if (S_ISLNK (stat_buf->st_mode))
850 char *linkname = get_link_name (pathname, rel_pathname);
851 if (linkname)
853 if (fnmatch (pred_ptr->args.str, linkname,
854 ignore_case ? FNM_CASEFOLD : 0) == 0)
855 ret = true;
856 free (linkname);
859 #endif /* S_ISLNK */
860 return (ret);
863 boolean
864 pred_ls (pathname, stat_buf, pred_ptr)
865 char *pathname;
866 struct stat *stat_buf;
867 struct predicate *pred_ptr;
869 list_file (pathname, rel_pathname, stat_buf, stdout);
870 return (true);
873 boolean
874 pred_mmin (pathname, stat_buf, pred_ptr)
875 char *pathname;
876 struct stat *stat_buf;
877 struct predicate *pred_ptr;
879 switch (pred_ptr->args.info.kind)
881 case COMP_GT:
882 if (stat_buf->st_mtime > (time_t) pred_ptr->args.info.l_val)
883 return (true);
884 break;
885 case COMP_LT:
886 if (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val)
887 return (true);
888 break;
889 case COMP_EQ:
890 if ((stat_buf->st_mtime >= (time_t) pred_ptr->args.info.l_val)
891 && (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val + 60))
892 return (true);
893 break;
895 return (false);
898 boolean
899 pred_mtime (pathname, stat_buf, pred_ptr)
900 char *pathname;
901 struct stat *stat_buf;
902 struct predicate *pred_ptr;
904 switch (pred_ptr->args.info.kind)
906 case COMP_GT:
907 if (stat_buf->st_mtime > (time_t) pred_ptr->args.info.l_val)
908 return (true);
909 break;
910 case COMP_LT:
911 if (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val)
912 return (true);
913 break;
914 case COMP_EQ:
915 if ((stat_buf->st_mtime >= (time_t) pred_ptr->args.info.l_val)
916 && (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val
917 + DAYSECS))
918 return (true);
919 break;
921 return (false);
924 boolean
925 pred_name (pathname, stat_buf, pred_ptr)
926 char *pathname;
927 struct stat *stat_buf;
928 struct predicate *pred_ptr;
930 char *base;
932 base = basename (pathname);
933 if (fnmatch (pred_ptr->args.str, base, FNM_PERIOD) == 0)
934 return (true);
935 return (false);
938 boolean
939 pred_negate (pathname, stat_buf, pred_ptr)
940 char *pathname;
941 struct stat *stat_buf;
942 struct predicate *pred_ptr;
944 /* Check whether we need a stat here. */
945 if (pred_ptr->need_stat)
947 if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
949 error (0, errno, "%s", pathname);
950 exit_status = 1;
951 return (false);
953 have_stat = true;
955 return (!(*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
956 pred_ptr->pred_right));
959 boolean
960 pred_newer (pathname, stat_buf, pred_ptr)
961 char *pathname;
962 struct stat *stat_buf;
963 struct predicate *pred_ptr;
965 if (stat_buf->st_mtime > pred_ptr->args.time)
966 return (true);
967 return (false);
970 boolean
971 pred_nogroup (pathname, stat_buf, pred_ptr)
972 char *pathname;
973 struct stat *stat_buf;
974 struct predicate *pred_ptr;
976 #ifdef CACHE_IDS
977 extern char *gid_unused;
979 return gid_unused[(unsigned) stat_buf->st_gid];
980 #else
981 return getgrgid (stat_buf->st_gid) == NULL;
982 #endif
985 boolean
986 pred_nouser (pathname, stat_buf, pred_ptr)
987 char *pathname;
988 struct stat *stat_buf;
989 struct predicate *pred_ptr;
991 #ifdef CACHE_IDS
992 extern char *uid_unused;
994 return uid_unused[(unsigned) stat_buf->st_uid];
995 #else
996 return getpwuid (stat_buf->st_uid) == NULL;
997 #endif
1000 boolean
1001 pred_ok (pathname, stat_buf, pred_ptr)
1002 char *pathname;
1003 struct stat *stat_buf;
1004 struct predicate *pred_ptr;
1006 int i, yes;
1008 fflush (stdout);
1009 fprintf (stderr, "< %s ... %s > ? ",
1010 pred_ptr->args.exec_vec.vec[0], pathname);
1011 fflush (stderr);
1012 i = getchar ();
1013 yes = (i == 'y' || i == 'Y');
1014 while (i != EOF && i != '\n')
1015 i = getchar ();
1016 if (!yes)
1017 return (false);
1018 return pred_exec (pathname, stat_buf, pred_ptr);
1021 boolean
1022 pred_open (pathname, stat_buf, pred_ptr)
1023 char *pathname;
1024 struct stat *stat_buf;
1025 struct predicate *pred_ptr;
1027 return (true);
1030 boolean
1031 pred_or (pathname, stat_buf, pred_ptr)
1032 char *pathname;
1033 struct stat *stat_buf;
1034 struct predicate *pred_ptr;
1036 if (pred_ptr->pred_left == NULL
1037 || !(*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
1038 pred_ptr->pred_left))
1040 /* Check whether we need a stat here. */
1041 if (pred_ptr->need_stat)
1043 if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
1045 error (0, errno, "%s", pathname);
1046 exit_status = 1;
1047 return (false);
1049 have_stat = true;
1051 return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
1052 pred_ptr->pred_right));
1054 else
1055 return (true);
1058 boolean
1059 pred_path (pathname, stat_buf, pred_ptr)
1060 char *pathname;
1061 struct stat *stat_buf;
1062 struct predicate *pred_ptr;
1064 if (fnmatch (pred_ptr->args.str, pathname, 0) == 0)
1065 return (true);
1066 return (false);
1069 boolean
1070 pred_perm (pathname, stat_buf, pred_ptr)
1071 char *pathname;
1072 struct stat *stat_buf;
1073 struct predicate *pred_ptr;
1075 if (pred_ptr->args.perm & 010000)
1077 /* Magic flag set in parse_perm:
1078 true if at least the given bits are set. */
1079 if ((stat_buf->st_mode & 07777 & pred_ptr->args.perm)
1080 == (pred_ptr->args.perm & 07777))
1081 return (true);
1083 else if (pred_ptr->args.perm & 020000)
1085 /* Magic flag set in parse_perm:
1086 true if any of the given bits are set. */
1087 if ((stat_buf->st_mode & 07777) & pred_ptr->args.perm)
1088 return (true);
1090 else
1092 /* True if exactly the given bits are set. */
1093 if ((stat_buf->st_mode & 07777) == pred_ptr->args.perm)
1094 return (true);
1096 return (false);
1099 boolean
1100 pred_print (pathname, stat_buf, pred_ptr)
1101 char *pathname;
1102 struct stat *stat_buf;
1103 struct predicate *pred_ptr;
1105 puts (pathname);
1106 return (true);
1109 boolean
1110 pred_print0 (pathname, stat_buf, pred_ptr)
1111 char *pathname;
1112 struct stat *stat_buf;
1113 struct predicate *pred_ptr;
1115 fputs (pathname, stdout);
1116 putc (0, stdout);
1117 return (true);
1120 boolean
1121 pred_prune (pathname, stat_buf, pred_ptr)
1122 char *pathname;
1123 struct stat *stat_buf;
1124 struct predicate *pred_ptr;
1126 stop_at_current_level = true;
1127 return (do_dir_first); /* This is what SunOS find seems to do. */
1130 boolean
1131 pred_regex (pathname, stat_buf, pred_ptr)
1132 char *pathname;
1133 struct stat *stat_buf;
1134 struct predicate *pred_ptr;
1136 int len = strlen (pathname);
1137 if (re_match (pred_ptr->args.regex, pathname, len, 0,
1138 (struct re_registers *) NULL) == len)
1139 return (true);
1140 return (false);
1143 boolean
1144 pred_size (pathname, stat_buf, pred_ptr)
1145 char *pathname;
1146 struct stat *stat_buf;
1147 struct predicate *pred_ptr;
1149 unsigned long f_val;
1151 f_val = (stat_buf->st_size + pred_ptr->args.size.blocksize - 1)
1152 / pred_ptr->args.size.blocksize;
1153 switch (pred_ptr->args.size.kind)
1155 case COMP_GT:
1156 if (f_val > pred_ptr->args.size.size)
1157 return (true);
1158 break;
1159 case COMP_LT:
1160 if (f_val < pred_ptr->args.size.size)
1161 return (true);
1162 break;
1163 case COMP_EQ:
1164 if (f_val == pred_ptr->args.size.size)
1165 return (true);
1166 break;
1168 return (false);
1171 boolean
1172 pred_true (pathname, stat_buf, pred_ptr)
1173 char *pathname;
1174 struct stat *stat_buf;
1175 struct predicate *pred_ptr;
1177 return (true);
1180 boolean
1181 pred_type (pathname, stat_buf, pred_ptr)
1182 char *pathname;
1183 struct stat *stat_buf;
1184 struct predicate *pred_ptr;
1186 unsigned long mode = stat_buf->st_mode;
1187 unsigned long type = pred_ptr->args.type;
1189 #ifndef S_IFMT
1190 /* POSIX system; check `mode' the slow way. */
1191 if ((S_ISBLK (mode) && type == S_IFBLK)
1192 || (S_ISCHR (mode) && type == S_IFCHR)
1193 || (S_ISDIR (mode) && type == S_IFDIR)
1194 || (S_ISREG (mode) && type == S_IFREG)
1195 #ifdef S_IFLNK
1196 || (S_ISLNK (mode) && type == S_IFLNK)
1197 #endif
1198 #ifdef S_IFIFO
1199 || (S_ISFIFO (mode) && type == S_IFIFO)
1200 #endif
1201 #ifdef S_IFSOCK
1202 || (S_ISSOCK (mode) && type == S_IFSOCK)
1203 #endif
1205 #else /* S_IFMT */
1206 /* Unix system; check `mode' the fast way. */
1207 if ((mode & S_IFMT) == type)
1208 #endif /* S_IFMT */
1209 return (true);
1210 else
1211 return (false);
1214 boolean
1215 pred_uid (pathname, stat_buf, pred_ptr)
1216 char *pathname;
1217 struct stat *stat_buf;
1218 struct predicate *pred_ptr;
1220 switch (pred_ptr->args.info.kind)
1222 case COMP_GT:
1223 if (stat_buf->st_uid > pred_ptr->args.info.l_val)
1224 return (true);
1225 break;
1226 case COMP_LT:
1227 if (stat_buf->st_uid < pred_ptr->args.info.l_val)
1228 return (true);
1229 break;
1230 case COMP_EQ:
1231 if (stat_buf->st_uid == pred_ptr->args.info.l_val)
1232 return (true);
1233 break;
1235 return (false);
1238 boolean
1239 pred_used (pathname, stat_buf, pred_ptr)
1240 char *pathname;
1241 struct stat *stat_buf;
1242 struct predicate *pred_ptr;
1244 time_t delta;
1246 delta = stat_buf->st_atime - stat_buf->st_ctime; /* Use difftime? */
1247 switch (pred_ptr->args.info.kind)
1249 case COMP_GT:
1250 if (delta > (time_t) pred_ptr->args.info.l_val)
1251 return (true);
1252 break;
1253 case COMP_LT:
1254 if (delta < (time_t) pred_ptr->args.info.l_val)
1255 return (true);
1256 break;
1257 case COMP_EQ:
1258 if ((delta >= (time_t) pred_ptr->args.info.l_val)
1259 && (delta < (time_t) pred_ptr->args.info.l_val + DAYSECS))
1260 return (true);
1261 break;
1263 return (false);
1266 boolean
1267 pred_user (pathname, stat_buf, pred_ptr)
1268 char *pathname;
1269 struct stat *stat_buf;
1270 struct predicate *pred_ptr;
1272 if (pred_ptr->args.uid == stat_buf->st_uid)
1273 return (true);
1274 else
1275 return (false);
1278 boolean
1279 pred_xtype (pathname, stat_buf, pred_ptr)
1280 char *pathname;
1281 struct stat *stat_buf;
1282 struct predicate *pred_ptr;
1284 struct stat sbuf;
1285 int (*ystat) ();
1287 ystat = xstat == lstat ? stat : lstat;
1288 if ((*ystat) (rel_pathname, &sbuf) != 0)
1290 if (ystat == stat && errno == ENOENT)
1291 /* Mimic behavior of ls -lL. */
1292 return (pred_type (pathname, stat_buf, pred_ptr));
1293 error (0, errno, "%s", pathname);
1294 exit_status = 1;
1295 return (false);
1297 return (pred_type (pathname, &sbuf, pred_ptr));
1300 /* 1) fork to get a child; parent remembers the child pid
1301 2) child execs the command requested
1302 3) parent waits for child; checks for proper pid of child
1304 Possible returns:
1306 ret errno status(h) status(l)
1308 pid x signal# 0177 stopped
1309 pid x exit arg 0 term by _exit
1310 pid x 0 signal # term by signal
1311 -1 EINTR parent got signal
1312 -1 other some other kind of error
1314 Return true only if the pid matches, status(l) is
1315 zero, and the exit arg (status high) is 0.
1316 Otherwise return false, possibly printing an error message. */
1318 static boolean
1319 launch (pred_ptr)
1320 struct predicate *pred_ptr;
1322 int status;
1323 pid_t wait_ret, child_pid;
1324 struct exec_val *execp; /* Pointer for efficiency. */
1325 static int first_time = 1;
1327 execp = &pred_ptr->args.exec_vec;
1329 /* Make sure output of command doesn't get mixed with find output. */
1330 fflush (stdout);
1331 fflush (stderr);
1333 /* Make sure to listen for the kids. */
1334 if (first_time)
1336 first_time = 0;
1337 signal (SIGCHLD, SIG_DFL);
1340 child_pid = fork ();
1341 if (child_pid == -1)
1342 error (1, errno, "cannot fork");
1343 if (child_pid == 0)
1345 /* We be the child. */
1346 #ifndef HAVE_FCHDIR
1347 if (chdir (starting_dir) < 0)
1349 error (0, errno, "%s", starting_dir);
1350 _exit (1);
1352 #else
1353 if (fchdir (starting_desc) < 0)
1355 error (0, errno, "cannot return to starting directory");
1356 _exit (1);
1358 #endif
1359 execvp (execp->vec[0], execp->vec);
1360 error (0, errno, "%s", execp->vec[0]);
1361 _exit (1);
1364 wait_ret = wait (&status);
1365 if (wait_ret == -1)
1367 error (0, errno, "error waiting for %s", execp->vec[0]);
1368 exit_status = 1;
1369 return (false);
1371 if (wait_ret != child_pid)
1373 error (0, 0, "wait got pid %d, expected pid %d", wait_ret, child_pid);
1374 exit_status = 1;
1375 return (false);
1377 if (WIFSTOPPED (status))
1379 error (0, 0, "%s stopped by signal %d",
1380 execp->vec[0], WSTOPSIG (status));
1381 exit_status = 1;
1382 return (false);
1384 if (WIFSIGNALED (status))
1386 error (0, 0, "%s terminated by signal %d",
1387 execp->vec[0], WTERMSIG (status));
1388 exit_status = 1;
1389 return (false);
1391 return (!WEXITSTATUS (status));
1394 /* Return a static string formatting the time WHEN according to the
1395 strftime format character KIND. */
1397 static char *
1398 format_date (when, kind)
1399 time_t when;
1400 int kind;
1402 static char fmt[3];
1403 static char buf[64]; /* More than enough space. */
1405 if (kind == '@')
1407 sprintf (buf, "%ld", when);
1408 return (buf);
1410 else
1412 fmt[0] = '%';
1413 fmt[1] = kind;
1414 fmt[2] = '\0';
1415 if (strftime (buf, sizeof (buf), fmt, localtime (&when)))
1416 return (buf);
1418 return "";
1421 #ifdef DEBUG
1422 /* Return a pointer to the string representation of
1423 the predicate function PRED_FUNC. */
1425 char *
1426 find_pred_name (pred_func)
1427 PFB pred_func;
1429 int i;
1431 for (i = 0; pred_table[i].pred_func != 0; i++)
1432 if (pred_table[i].pred_func == pred_func)
1433 break;
1434 return (pred_table[i].pred_name);
1437 static char *
1438 type_name (type)
1439 short type;
1441 int i;
1443 for (i = 0; type_table[i].type != (short) -1; i++)
1444 if (type_table[i].type == type)
1445 break;
1446 return (type_table[i].type_name);
1449 static char *
1450 prec_name (prec)
1451 short prec;
1453 int i;
1455 for (i = 0; prec_table[i].prec != (short) -1; i++)
1456 if (prec_table[i].prec == prec)
1457 break;
1458 return (prec_table[i].prec_name);
1461 /* Walk the expression tree NODE to stdout.
1462 INDENT is the number of levels to indent the left margin. */
1464 void
1465 print_tree (node, indent)
1466 struct predicate *node;
1467 int indent;
1469 int i;
1471 if (node == NULL)
1472 return;
1473 for (i = 0; i < indent; i++)
1474 printf (" ");
1475 printf ("pred = %s type = %s prec = %s addr = %x\n",
1476 find_pred_name (node->pred_func),
1477 type_name (node->p_type), prec_name (node->p_prec), node);
1478 for (i = 0; i < indent; i++)
1479 printf (" ");
1480 printf ("left:\n");
1481 print_tree (node->pred_left, indent + 1);
1482 for (i = 0; i < indent; i++)
1483 printf (" ");
1484 printf ("right:\n");
1485 print_tree (node->pred_right, indent + 1);
1488 /* Copy STR into BUF and trim blanks from the end of BUF.
1489 Return BUF. */
1491 static char *
1492 blank_rtrim (str, buf)
1493 char *str;
1494 char *buf;
1496 int i;
1498 if (str == NULL)
1499 return (NULL);
1500 strcpy (buf, str);
1501 i = strlen (buf) - 1;
1502 while ((i >= 0) && ((buf[i] == ' ') || buf[i] == '\t'))
1503 i--;
1504 buf[++i] = '\0';
1505 return (buf);
1508 /* Print out the predicate list starting at NODE. */
1510 void
1511 print_list (node)
1512 struct predicate *node;
1514 struct predicate *cur;
1515 char name[256];
1517 cur = node;
1518 while (cur != NULL)
1520 printf ("%s ", blank_rtrim (find_pred_name (cur->pred_func), name));
1521 cur = cur->pred_next;
1523 printf ("\n");
1525 #endif /* DEBUG */