* lib/getopt.c: internationalization works with current version of
[findutils.git] / find / pred.c
blob46c3ccfb7b6c81fdfab68978328732f755c2366e
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 #define _GNU_SOURCE
19 #include <config.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <stdio.h>
23 #include <fnmatch.h>
24 #include <signal.h>
25 #include <pwd.h>
26 #include <grp.h>
27 #include "defs.h"
28 #include "modetype.h"
29 #include "wait.h"
31 #if ENABLE_NLS
32 # include <libintl.h>
33 # define _(Text) gettext (Text)
34 #else
35 # define _(Text) Text
36 #endif
37 #ifdef gettext_noop
38 # define N_(String) gettext_noop (String)
39 #else
40 # define N_(String) (String)
41 #endif
43 #if !defined(SIGCHLD) && defined(SIGCLD)
44 #define SIGCHLD SIGCLD
45 #endif
47 #if HAVE_DIRENT_H
48 # include <dirent.h>
49 # define NAMLEN(dirent) strlen((dirent)->d_name)
50 #else
51 # define dirent direct
52 # define NAMLEN(dirent) (dirent)->d_namlen
53 # if HAVE_SYS_NDIR_H
54 # include <sys/ndir.h>
55 # endif
56 # if HAVE_SYS_DIR_H
57 # include <sys/dir.h>
58 # endif
59 # if HAVE_NDIR_H
60 # include <ndir.h>
61 # endif
62 #endif
64 #ifdef CLOSEDIR_VOID
65 /* Fake a return value. */
66 #define CLOSEDIR(d) (closedir (d), 0)
67 #else
68 #define CLOSEDIR(d) closedir (d)
69 #endif
71 /* Extract or fake data from a `struct stat'.
72 ST_NBLOCKS: Number of 512-byte blocks in the file
73 (including indirect blocks).
74 HP-UX, perhaps uniquely, counts st_blocks in 1024-byte units.
75 This workaround loses when mixing HP-UX and 4BSD filesystems, though. */
76 #ifdef _POSIX_SOURCE
77 # define ST_NBLOCKS(statp) (((statp)->st_size + 512 - 1) / 512)
78 #else
79 # ifndef HAVE_ST_BLOCKS
80 # define ST_NBLOCKS(statp) (st_blocks ((statp)->st_size))
81 # else
82 # if defined(hpux) || defined(__hpux__)
83 # define ST_NBLOCKS(statp) ((statp)->st_blocks * 2)
84 # else
85 # define ST_NBLOCKS(statp) ((statp)->st_blocks)
86 # endif
87 # endif
88 #endif
90 static boolean insert_lname P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr, boolean ignore_case));
91 static boolean launch P_((struct predicate *pred_ptr));
92 static char *format_date P_((time_t when, int kind));
94 #ifdef DEBUG
95 struct pred_assoc
97 PFB pred_func;
98 char *pred_name;
101 struct pred_assoc pred_table[] =
103 {pred_amin, "amin "},
104 {pred_and, "and "},
105 {pred_anewer, "anewer "},
106 {pred_atime, "atime "},
107 {pred_close, ") "},
108 {pred_amin, "cmin "},
109 {pred_cnewer, "cnewer "},
110 {pred_comma, ", "},
111 {pred_ctime, "ctime "},
112 {pred_empty, "empty "},
113 {pred_exec, "exec "},
114 {pred_false, "false "},
115 {pred_fprint, "fprint "},
116 {pred_fprint0, "fprint0 "},
117 {pred_fprintf, "fprintf "},
118 {pred_fstype, "fstype "},
119 {pred_gid, "gid "},
120 {pred_group, "group "},
121 {pred_ilname, "ilname "},
122 {pred_iname, "iname "},
123 {pred_inum, "inum "},
124 {pred_ipath, "ipath "},
125 {pred_links, "links "},
126 {pred_lname, "lname "},
127 {pred_ls, "ls "},
128 {pred_amin, "mmin "},
129 {pred_mtime, "mtime "},
130 {pred_name, "name "},
131 {pred_negate, "not "},
132 {pred_newer, "newer "},
133 {pred_nogroup, "nogroup "},
134 {pred_nouser, "nouser "},
135 {pred_ok, "ok "},
136 {pred_open, "( "},
137 {pred_or, "or "},
138 {pred_path, "path "},
139 {pred_perm, "perm "},
140 {pred_print, "print "},
141 {pred_print0, "print0 "},
142 {pred_prune, "prune "},
143 {pred_regex, "regex "},
144 {pred_size, "size "},
145 {pred_true, "true "},
146 {pred_type, "type "},
147 {pred_uid, "uid "},
148 {pred_used, "used "},
149 {pred_user, "user "},
150 {pred_xtype, "xtype "},
151 {0, "none "}
154 struct op_assoc
156 short type;
157 char *type_name;
160 struct op_assoc type_table[] =
162 {NO_TYPE, "no "},
163 {PRIMARY_TYPE, "primary "},
164 {UNI_OP, "uni_op "},
165 {BI_OP, "bi_op "},
166 {OPEN_PAREN, "open_paren "},
167 {CLOSE_PAREN, "close_paren "},
168 {-1, "unknown "}
171 struct prec_assoc
173 short prec;
174 char *prec_name;
177 struct prec_assoc prec_table[] =
179 {NO_PREC, "no "},
180 {COMMA_PREC, "comma "},
181 {OR_PREC, "or "},
182 {AND_PREC, "and "},
183 {NEGATE_PREC, "negate "},
184 {MAX_PREC, "max "},
185 {-1, "unknown "}
187 #endif /* DEBUG */
189 /* Predicate processing routines.
191 PATHNAME is the full pathname of the file being checked.
192 *STAT_BUF contains information about PATHNAME.
193 *PRED_PTR contains information for applying the predicate.
195 Return true if the file passes this predicate, false if not. */
197 boolean
198 pred_amin (pathname, stat_buf, pred_ptr)
199 char *pathname;
200 struct stat *stat_buf;
201 struct predicate *pred_ptr;
203 switch (pred_ptr->args.info.kind)
205 case COMP_GT:
206 if (stat_buf->st_atime > (time_t) pred_ptr->args.info.l_val)
207 return (true);
208 break;
209 case COMP_LT:
210 if (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val)
211 return (true);
212 break;
213 case COMP_EQ:
214 if ((stat_buf->st_atime >= (time_t) pred_ptr->args.info.l_val)
215 && (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val + 60))
216 return (true);
217 break;
219 return (false);
222 boolean
223 pred_and (pathname, stat_buf, pred_ptr)
224 char *pathname;
225 struct stat *stat_buf;
226 struct predicate *pred_ptr;
228 if (pred_ptr->pred_left == NULL
229 || (*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
230 pred_ptr->pred_left))
232 /* Check whether we need a stat here. */
233 if (pred_ptr->need_stat)
235 if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
237 error (0, errno, "%s", pathname);
238 exit_status = 1;
239 return (false);
241 have_stat = true;
243 return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
244 pred_ptr->pred_right));
246 else
247 return (false);
250 boolean
251 pred_anewer (pathname, stat_buf, pred_ptr)
252 char *pathname;
253 struct stat *stat_buf;
254 struct predicate *pred_ptr;
256 if (stat_buf->st_atime > pred_ptr->args.time)
257 return (true);
258 return (false);
261 boolean
262 pred_atime (pathname, stat_buf, pred_ptr)
263 char *pathname;
264 struct stat *stat_buf;
265 struct predicate *pred_ptr;
267 switch (pred_ptr->args.info.kind)
269 case COMP_GT:
270 if (stat_buf->st_atime > (time_t) pred_ptr->args.info.l_val)
271 return (true);
272 break;
273 case COMP_LT:
274 if (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val)
275 return (true);
276 break;
277 case COMP_EQ:
278 if ((stat_buf->st_atime >= (time_t) pred_ptr->args.info.l_val)
279 && (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val
280 + DAYSECS))
281 return (true);
282 break;
284 return (false);
287 boolean
288 pred_close (pathname, stat_buf, pred_ptr)
289 char *pathname;
290 struct stat *stat_buf;
291 struct predicate *pred_ptr;
293 return (true);
296 boolean
297 pred_cmin (pathname, stat_buf, pred_ptr)
298 char *pathname;
299 struct stat *stat_buf;
300 struct predicate *pred_ptr;
302 switch (pred_ptr->args.info.kind)
304 case COMP_GT:
305 if (stat_buf->st_ctime > (time_t) pred_ptr->args.info.l_val)
306 return (true);
307 break;
308 case COMP_LT:
309 if (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val)
310 return (true);
311 break;
312 case COMP_EQ:
313 if ((stat_buf->st_ctime >= (time_t) pred_ptr->args.info.l_val)
314 && (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val + 60))
315 return (true);
316 break;
318 return (false);
321 boolean
322 pred_cnewer (pathname, stat_buf, pred_ptr)
323 char *pathname;
324 struct stat *stat_buf;
325 struct predicate *pred_ptr;
327 if (stat_buf->st_ctime > pred_ptr->args.time)
328 return (true);
329 return (false);
332 boolean
333 pred_comma (pathname, stat_buf, pred_ptr)
334 char *pathname;
335 struct stat *stat_buf;
336 struct predicate *pred_ptr;
338 if (pred_ptr->pred_left != NULL)
339 (*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
340 pred_ptr->pred_left);
341 /* Check whether we need a stat here. */
342 if (pred_ptr->need_stat)
344 if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
346 error (0, errno, "%s", pathname);
347 exit_status = 1;
348 return (false);
350 have_stat = true;
352 return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
353 pred_ptr->pred_right));
356 boolean
357 pred_ctime (pathname, stat_buf, pred_ptr)
358 char *pathname;
359 struct stat *stat_buf;
360 struct predicate *pred_ptr;
362 switch (pred_ptr->args.info.kind)
364 case COMP_GT:
365 if (stat_buf->st_ctime > (time_t) pred_ptr->args.info.l_val)
366 return (true);
367 break;
368 case COMP_LT:
369 if (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val)
370 return (true);
371 break;
372 case COMP_EQ:
373 if ((stat_buf->st_ctime >= (time_t) pred_ptr->args.info.l_val)
374 && (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val
375 + DAYSECS))
376 return (true);
377 break;
379 return (false);
382 boolean
383 pred_empty (pathname, stat_buf, pred_ptr)
384 char *pathname;
385 struct stat *stat_buf;
386 struct predicate *pred_ptr;
388 if (S_ISDIR (stat_buf->st_mode))
390 DIR *d;
391 struct dirent *dp;
392 boolean empty = true;
394 errno = 0;
395 d = opendir (rel_pathname);
396 if (d == NULL)
398 error (0, errno, "%s", pathname);
399 exit_status = 1;
400 return (false);
402 for (dp = readdir (d); dp; dp = readdir (d))
404 if (dp->d_name[0] != '.'
405 || (dp->d_name[1] != '\0'
406 && (dp->d_name[1] != '.' || dp->d_name[2] != '\0')))
408 empty = false;
409 break;
412 if (CLOSEDIR (d))
414 error (0, errno, "%s", pathname);
415 exit_status = 1;
416 return (false);
418 return (empty);
420 else if (S_ISREG (stat_buf->st_mode))
421 return (stat_buf->st_size == 0);
422 else
423 return (false);
426 boolean
427 pred_exec (pathname, stat_buf, pred_ptr)
428 char *pathname;
429 struct stat *stat_buf;
430 struct predicate *pred_ptr;
432 int i;
433 int path_pos;
434 struct exec_val *execp; /* Pointer for efficiency. */
436 execp = &pred_ptr->args.exec_vec;
438 /* Replace "{}" with the real path in each affected arg. */
439 for (path_pos = 0; execp->paths[path_pos].offset >= 0; path_pos++)
441 register char *from, *to;
443 i = execp->paths[path_pos].offset;
444 execp->vec[i] =
445 xmalloc (strlen (execp->paths[path_pos].origarg) + 1
446 + (strlen (pathname) - 2) * execp->paths[path_pos].count);
447 for (from = execp->paths[path_pos].origarg, to = execp->vec[i]; *from; )
448 if (from[0] == '{' && from[1] == '}')
450 to = stpcpy (to, pathname);
451 from += 2;
453 else
454 *to++ = *from++;
455 *to = *from; /* Copy null. */
458 i = launch (pred_ptr);
460 /* Free the temporary args. */
461 for (path_pos = 0; execp->paths[path_pos].offset >= 0; path_pos++)
462 free (execp->vec[execp->paths[path_pos].offset]);
464 return (i);
467 boolean
468 pred_false (pathname, stat_buf, pred_ptr)
469 char *pathname;
470 struct stat *stat_buf;
471 struct predicate *pred_ptr;
473 return (false);
476 boolean
477 pred_fls (pathname, stat_buf, pred_ptr)
478 char *pathname;
479 struct stat *stat_buf;
480 struct predicate *pred_ptr;
482 list_file (pathname, rel_pathname, stat_buf, pred_ptr->args.stream);
483 return (true);
486 boolean
487 pred_fprint (pathname, stat_buf, pred_ptr)
488 char *pathname;
489 struct stat *stat_buf;
490 struct predicate *pred_ptr;
492 fputs (pathname, pred_ptr->args.stream);
493 putc ('\n', pred_ptr->args.stream);
494 return (true);
497 boolean
498 pred_fprint0 (pathname, stat_buf, pred_ptr)
499 char *pathname;
500 struct stat *stat_buf;
501 struct predicate *pred_ptr;
503 fputs (pathname, pred_ptr->args.stream);
504 putc (0, pred_ptr->args.stream);
505 return (true);
508 boolean
509 pred_fprintf (pathname, stat_buf, pred_ptr)
510 char *pathname;
511 struct stat *stat_buf;
512 struct predicate *pred_ptr;
514 FILE *fp = pred_ptr->args.printf_vec.stream;
515 struct segment *segment;
516 char *cp;
518 for (segment = pred_ptr->args.printf_vec.segment; segment;
519 segment = segment->next)
521 if (segment->kind & 0xff00) /* Component of date. */
523 time_t t;
525 switch (segment->kind & 0xff)
527 case 'A':
528 t = stat_buf->st_atime;
529 break;
530 case 'C':
531 t = stat_buf->st_ctime;
532 break;
533 case 'T':
534 t = stat_buf->st_mtime;
535 break;
536 default:
537 abort ();
539 fprintf (fp, segment->text,
540 format_date (t, (segment->kind >> 8) & 0xff));
541 continue;
544 switch (segment->kind)
546 case KIND_PLAIN: /* Plain text string (no % conversion). */
547 fwrite (segment->text, 1, segment->text_len, fp);
548 break;
549 case KIND_STOP: /* Terminate argument and flush output. */
550 fwrite (segment->text, 1, segment->text_len, fp);
551 fflush (fp);
552 return (true);
553 case 'a': /* atime in `ctime' format. */
554 cp = ctime (&stat_buf->st_atime);
555 cp[24] = '\0';
556 fprintf (fp, segment->text, cp);
557 break;
558 case 'b': /* size in 512-byte blocks */
559 fprintf (fp, segment->text, ST_NBLOCKS (stat_buf));
560 break;
561 case 'c': /* ctime in `ctime' format */
562 cp = ctime (&stat_buf->st_ctime);
563 cp[24] = '\0';
564 fprintf (fp, segment->text, cp);
565 break;
566 case 'd': /* depth in search tree */
567 fprintf (fp, segment->text, curdepth);
568 break;
569 case 'f': /* basename of path */
570 cp = strrchr (pathname, '/');
571 if (cp)
572 cp++;
573 else
574 cp = pathname;
575 fprintf (fp, segment->text, cp);
576 break;
577 case 'F': /* filesystem type */
578 fprintf (fp, segment->text,
579 filesystem_type (pathname, rel_pathname, stat_buf));
580 break;
581 case 'g': /* group name */
583 struct group *g;
585 g = getgrgid (stat_buf->st_gid);
586 if (g)
588 segment->text[segment->text_len] = 's';
589 fprintf (fp, segment->text, g->gr_name);
590 break;
592 /* else fallthru */
594 case 'G': /* GID number */
595 segment->text[segment->text_len] = 'u';
596 fprintf (fp, segment->text, stat_buf->st_gid);
597 break;
598 case 'h': /* leading directories part of path */
600 char cc;
602 cp = strrchr (pathname, '/');
603 if (cp == NULL) /* No leading directories. */
604 break;
605 cc = *cp;
606 *cp = '\0';
607 fprintf (fp, segment->text, pathname);
608 *cp = cc;
609 break;
611 case 'H': /* ARGV element file was found under */
613 char cc = pathname[path_length];
615 pathname[path_length] = '\0';
616 fprintf (fp, segment->text, pathname);
617 pathname[path_length] = cc;
618 break;
620 case 'i': /* inode number */
621 fprintf (fp, segment->text, stat_buf->st_ino);
622 break;
623 case 'k': /* size in 1K blocks */
624 fprintf (fp, segment->text, (ST_NBLOCKS (stat_buf) + 1) / 2);
625 break;
626 case 'l': /* object of symlink */
627 #ifdef S_ISLNK
629 char *linkname = 0;
631 if (S_ISLNK (stat_buf->st_mode))
633 linkname = get_link_name (pathname, rel_pathname);
634 if (linkname == 0)
635 exit_status = 1;
637 if (linkname)
639 fprintf (fp, segment->text, linkname);
640 free (linkname);
642 else
643 fprintf (fp, segment->text, "");
645 #endif /* S_ISLNK */
646 break;
647 case 'm': /* mode as octal number (perms only) */
648 fprintf (fp, segment->text, stat_buf->st_mode & 07777);
649 break;
650 case 'n': /* number of links */
651 fprintf (fp, segment->text, stat_buf->st_nlink);
652 break;
653 case 'p': /* pathname */
654 fprintf (fp, segment->text, pathname);
655 break;
656 case 'P': /* pathname with ARGV element stripped */
657 if (curdepth)
659 cp = pathname + path_length;
660 if (*cp == '/')
661 /* Move past the slash between the ARGV element
662 and the rest of the pathname. But if the ARGV element
663 ends in a slash, we didn't add another, so we've
664 already skipped past it. */
665 cp++;
667 else
668 cp = "";
669 fprintf (fp, segment->text, cp);
670 break;
671 case 's': /* size in bytes */
672 fprintf (fp, segment->text, stat_buf->st_size);
673 break;
674 case 't': /* mtime in `ctime' format */
675 cp = ctime (&stat_buf->st_mtime);
676 cp[24] = '\0';
677 fprintf (fp, segment->text, cp);
678 break;
679 case 'u': /* user name */
681 struct passwd *p;
683 p = getpwuid (stat_buf->st_uid);
684 if (p)
686 segment->text[segment->text_len] = 's';
687 fprintf (fp, segment->text, p->pw_name);
688 break;
690 /* else fallthru */
692 case 'U': /* UID number */
693 segment->text[segment->text_len] = 'u';
694 fprintf (fp, segment->text, stat_buf->st_uid);
695 break;
698 return (true);
701 boolean
702 pred_fstype (pathname, stat_buf, pred_ptr)
703 char *pathname;
704 struct stat *stat_buf;
705 struct predicate *pred_ptr;
707 if (strcmp (filesystem_type (pathname, rel_pathname, stat_buf),
708 pred_ptr->args.str) == 0)
709 return (true);
710 return (false);
713 boolean
714 pred_gid (pathname, stat_buf, pred_ptr)
715 char *pathname;
716 struct stat *stat_buf;
717 struct predicate *pred_ptr;
719 switch (pred_ptr->args.info.kind)
721 case COMP_GT:
722 if (stat_buf->st_gid > pred_ptr->args.info.l_val)
723 return (true);
724 break;
725 case COMP_LT:
726 if (stat_buf->st_gid < pred_ptr->args.info.l_val)
727 return (true);
728 break;
729 case COMP_EQ:
730 if (stat_buf->st_gid == pred_ptr->args.info.l_val)
731 return (true);
732 break;
734 return (false);
737 boolean
738 pred_group (pathname, stat_buf, pred_ptr)
739 char *pathname;
740 struct stat *stat_buf;
741 struct predicate *pred_ptr;
743 if (pred_ptr->args.gid == stat_buf->st_gid)
744 return (true);
745 else
746 return (false);
749 boolean
750 pred_ilname (pathname, stat_buf, pred_ptr)
751 char *pathname;
752 struct stat *stat_buf;
753 struct predicate *pred_ptr;
755 return insert_lname (pathname, stat_buf, pred_ptr, true);
758 boolean
759 pred_iname (pathname, stat_buf, pred_ptr)
760 char *pathname;
761 struct stat *stat_buf;
762 struct predicate *pred_ptr;
764 const char *base;
766 base = basename (pathname);
767 if (fnmatch (pred_ptr->args.str, base, FNM_PERIOD | FNM_CASEFOLD) == 0)
768 return (true);
769 return (false);
772 boolean
773 pred_inum (pathname, stat_buf, pred_ptr)
774 char *pathname;
775 struct stat *stat_buf;
776 struct predicate *pred_ptr;
778 switch (pred_ptr->args.info.kind)
780 case COMP_GT:
781 if (stat_buf->st_ino > pred_ptr->args.info.l_val)
782 return (true);
783 break;
784 case COMP_LT:
785 if (stat_buf->st_ino < pred_ptr->args.info.l_val)
786 return (true);
787 break;
788 case COMP_EQ:
789 if (stat_buf->st_ino == pred_ptr->args.info.l_val)
790 return (true);
791 break;
793 return (false);
796 boolean
797 pred_ipath (pathname, stat_buf, pred_ptr)
798 char *pathname;
799 struct stat *stat_buf;
800 struct predicate *pred_ptr;
802 if (fnmatch (pred_ptr->args.str, pathname, FNM_CASEFOLD) == 0)
803 return (true);
804 return (false);
807 boolean
808 pred_links (pathname, stat_buf, pred_ptr)
809 char *pathname;
810 struct stat *stat_buf;
811 struct predicate *pred_ptr;
813 switch (pred_ptr->args.info.kind)
815 case COMP_GT:
816 if (stat_buf->st_nlink > pred_ptr->args.info.l_val)
817 return (true);
818 break;
819 case COMP_LT:
820 if (stat_buf->st_nlink < pred_ptr->args.info.l_val)
821 return (true);
822 break;
823 case COMP_EQ:
824 if (stat_buf->st_nlink == pred_ptr->args.info.l_val)
825 return (true);
826 break;
828 return (false);
831 boolean
832 pred_lname (pathname, stat_buf, pred_ptr)
833 char *pathname;
834 struct stat *stat_buf;
835 struct predicate *pred_ptr;
837 return insert_lname (pathname, stat_buf, pred_ptr, false);
840 static boolean
841 insert_lname (pathname, stat_buf, pred_ptr, ignore_case)
842 char *pathname;
843 struct stat *stat_buf;
844 struct predicate *pred_ptr;
845 boolean ignore_case;
847 boolean ret = false;
848 #ifdef S_ISLNK
849 if (S_ISLNK (stat_buf->st_mode))
851 char *linkname = get_link_name (pathname, rel_pathname);
852 if (linkname)
854 if (fnmatch (pred_ptr->args.str, linkname,
855 ignore_case ? FNM_CASEFOLD : 0) == 0)
856 ret = true;
857 free (linkname);
860 #endif /* S_ISLNK */
861 return (ret);
864 boolean
865 pred_ls (pathname, stat_buf, pred_ptr)
866 char *pathname;
867 struct stat *stat_buf;
868 struct predicate *pred_ptr;
870 list_file (pathname, rel_pathname, stat_buf, stdout);
871 return (true);
874 boolean
875 pred_mmin (pathname, stat_buf, pred_ptr)
876 char *pathname;
877 struct stat *stat_buf;
878 struct predicate *pred_ptr;
880 switch (pred_ptr->args.info.kind)
882 case COMP_GT:
883 if (stat_buf->st_mtime > (time_t) pred_ptr->args.info.l_val)
884 return (true);
885 break;
886 case COMP_LT:
887 if (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val)
888 return (true);
889 break;
890 case COMP_EQ:
891 if ((stat_buf->st_mtime >= (time_t) pred_ptr->args.info.l_val)
892 && (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val + 60))
893 return (true);
894 break;
896 return (false);
899 boolean
900 pred_mtime (pathname, stat_buf, pred_ptr)
901 char *pathname;
902 struct stat *stat_buf;
903 struct predicate *pred_ptr;
905 switch (pred_ptr->args.info.kind)
907 case COMP_GT:
908 if (stat_buf->st_mtime > (time_t) pred_ptr->args.info.l_val)
909 return (true);
910 break;
911 case COMP_LT:
912 if (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val)
913 return (true);
914 break;
915 case COMP_EQ:
916 if ((stat_buf->st_mtime >= (time_t) pred_ptr->args.info.l_val)
917 && (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val
918 + DAYSECS))
919 return (true);
920 break;
922 return (false);
925 boolean
926 pred_name (pathname, stat_buf, pred_ptr)
927 char *pathname;
928 struct stat *stat_buf;
929 struct predicate *pred_ptr;
931 const char *base;
933 base = basename (pathname);
934 if (fnmatch (pred_ptr->args.str, base, FNM_PERIOD) == 0)
935 return (true);
936 return (false);
939 boolean
940 pred_negate (pathname, stat_buf, pred_ptr)
941 char *pathname;
942 struct stat *stat_buf;
943 struct predicate *pred_ptr;
945 /* Check whether we need a stat here. */
946 if (pred_ptr->need_stat)
948 if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
950 error (0, errno, "%s", pathname);
951 exit_status = 1;
952 return (false);
954 have_stat = true;
956 return (!(*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
957 pred_ptr->pred_right));
960 boolean
961 pred_newer (pathname, stat_buf, pred_ptr)
962 char *pathname;
963 struct stat *stat_buf;
964 struct predicate *pred_ptr;
966 if (stat_buf->st_mtime > pred_ptr->args.time)
967 return (true);
968 return (false);
971 boolean
972 pred_nogroup (pathname, stat_buf, pred_ptr)
973 char *pathname;
974 struct stat *stat_buf;
975 struct predicate *pred_ptr;
977 #ifdef CACHE_IDS
978 extern char *gid_unused;
980 return gid_unused[(unsigned) stat_buf->st_gid];
981 #else
982 return getgrgid (stat_buf->st_gid) == NULL;
983 #endif
986 boolean
987 pred_nouser (pathname, stat_buf, pred_ptr)
988 char *pathname;
989 struct stat *stat_buf;
990 struct predicate *pred_ptr;
992 #ifdef CACHE_IDS
993 extern char *uid_unused;
995 return uid_unused[(unsigned) stat_buf->st_uid];
996 #else
997 return getpwuid (stat_buf->st_uid) == NULL;
998 #endif
1001 boolean
1002 pred_ok (pathname, stat_buf, pred_ptr)
1003 char *pathname;
1004 struct stat *stat_buf;
1005 struct predicate *pred_ptr;
1007 int i, yes;
1009 fflush (stdout);
1010 fprintf (stderr, "< %s ... %s > ? ",
1011 pred_ptr->args.exec_vec.vec[0], pathname);
1012 fflush (stderr);
1013 i = getchar ();
1014 yes = (i == 'y' || i == 'Y');
1015 while (i != EOF && i != '\n')
1016 i = getchar ();
1017 if (!yes)
1018 return (false);
1019 return pred_exec (pathname, stat_buf, pred_ptr);
1022 boolean
1023 pred_open (pathname, stat_buf, pred_ptr)
1024 char *pathname;
1025 struct stat *stat_buf;
1026 struct predicate *pred_ptr;
1028 return (true);
1031 boolean
1032 pred_or (pathname, stat_buf, pred_ptr)
1033 char *pathname;
1034 struct stat *stat_buf;
1035 struct predicate *pred_ptr;
1037 if (pred_ptr->pred_left == NULL
1038 || !(*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
1039 pred_ptr->pred_left))
1041 /* Check whether we need a stat here. */
1042 if (pred_ptr->need_stat)
1044 if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
1046 error (0, errno, "%s", pathname);
1047 exit_status = 1;
1048 return (false);
1050 have_stat = true;
1052 return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
1053 pred_ptr->pred_right));
1055 else
1056 return (true);
1059 boolean
1060 pred_path (pathname, stat_buf, pred_ptr)
1061 char *pathname;
1062 struct stat *stat_buf;
1063 struct predicate *pred_ptr;
1065 if (fnmatch (pred_ptr->args.str, pathname, 0) == 0)
1066 return (true);
1067 return (false);
1070 boolean
1071 pred_perm (pathname, stat_buf, pred_ptr)
1072 char *pathname;
1073 struct stat *stat_buf;
1074 struct predicate *pred_ptr;
1076 if (pred_ptr->args.perm & 010000)
1078 /* Magic flag set in parse_perm:
1079 true if at least the given bits are set. */
1080 if ((stat_buf->st_mode & 07777 & pred_ptr->args.perm)
1081 == (pred_ptr->args.perm & 07777))
1082 return (true);
1084 else if (pred_ptr->args.perm & 020000)
1086 /* Magic flag set in parse_perm:
1087 true if any of the given bits are set. */
1088 if ((stat_buf->st_mode & 07777) & pred_ptr->args.perm)
1089 return (true);
1091 else
1093 /* True if exactly the given bits are set. */
1094 if ((stat_buf->st_mode & 07777) == pred_ptr->args.perm)
1095 return (true);
1097 return (false);
1100 boolean
1101 pred_print (pathname, stat_buf, pred_ptr)
1102 char *pathname;
1103 struct stat *stat_buf;
1104 struct predicate *pred_ptr;
1106 puts (pathname);
1107 return (true);
1110 boolean
1111 pred_print0 (pathname, stat_buf, pred_ptr)
1112 char *pathname;
1113 struct stat *stat_buf;
1114 struct predicate *pred_ptr;
1116 fputs (pathname, stdout);
1117 putc (0, stdout);
1118 return (true);
1121 boolean
1122 pred_prune (pathname, stat_buf, pred_ptr)
1123 char *pathname;
1124 struct stat *stat_buf;
1125 struct predicate *pred_ptr;
1127 stop_at_current_level = true;
1128 return (do_dir_first); /* This is what SunOS find seems to do. */
1131 boolean
1132 pred_regex (pathname, stat_buf, pred_ptr)
1133 char *pathname;
1134 struct stat *stat_buf;
1135 struct predicate *pred_ptr;
1137 int len = strlen (pathname);
1138 if (re_match (pred_ptr->args.regex, pathname, len, 0,
1139 (struct re_registers *) NULL) == len)
1140 return (true);
1141 return (false);
1144 boolean
1145 pred_size (pathname, stat_buf, pred_ptr)
1146 char *pathname;
1147 struct stat *stat_buf;
1148 struct predicate *pred_ptr;
1150 unsigned long f_val;
1152 f_val = (stat_buf->st_size + pred_ptr->args.size.blocksize - 1)
1153 / pred_ptr->args.size.blocksize;
1154 switch (pred_ptr->args.size.kind)
1156 case COMP_GT:
1157 if (f_val > pred_ptr->args.size.size)
1158 return (true);
1159 break;
1160 case COMP_LT:
1161 if (f_val < pred_ptr->args.size.size)
1162 return (true);
1163 break;
1164 case COMP_EQ:
1165 if (f_val == pred_ptr->args.size.size)
1166 return (true);
1167 break;
1169 return (false);
1172 boolean
1173 pred_true (pathname, stat_buf, pred_ptr)
1174 char *pathname;
1175 struct stat *stat_buf;
1176 struct predicate *pred_ptr;
1178 return (true);
1181 boolean
1182 pred_type (pathname, stat_buf, pred_ptr)
1183 char *pathname;
1184 struct stat *stat_buf;
1185 struct predicate *pred_ptr;
1187 unsigned long mode = stat_buf->st_mode;
1188 unsigned long type = pred_ptr->args.type;
1190 #ifndef S_IFMT
1191 /* POSIX system; check `mode' the slow way. */
1192 if ((S_ISBLK (mode) && type == S_IFBLK)
1193 || (S_ISCHR (mode) && type == S_IFCHR)
1194 || (S_ISDIR (mode) && type == S_IFDIR)
1195 || (S_ISREG (mode) && type == S_IFREG)
1196 #ifdef S_IFLNK
1197 || (S_ISLNK (mode) && type == S_IFLNK)
1198 #endif
1199 #ifdef S_IFIFO
1200 || (S_ISFIFO (mode) && type == S_IFIFO)
1201 #endif
1202 #ifdef S_IFSOCK
1203 || (S_ISSOCK (mode) && type == S_IFSOCK)
1204 #endif
1206 #else /* S_IFMT */
1207 /* Unix system; check `mode' the fast way. */
1208 if ((mode & S_IFMT) == type)
1209 #endif /* S_IFMT */
1210 return (true);
1211 else
1212 return (false);
1215 boolean
1216 pred_uid (pathname, stat_buf, pred_ptr)
1217 char *pathname;
1218 struct stat *stat_buf;
1219 struct predicate *pred_ptr;
1221 switch (pred_ptr->args.info.kind)
1223 case COMP_GT:
1224 if (stat_buf->st_uid > pred_ptr->args.info.l_val)
1225 return (true);
1226 break;
1227 case COMP_LT:
1228 if (stat_buf->st_uid < pred_ptr->args.info.l_val)
1229 return (true);
1230 break;
1231 case COMP_EQ:
1232 if (stat_buf->st_uid == pred_ptr->args.info.l_val)
1233 return (true);
1234 break;
1236 return (false);
1239 boolean
1240 pred_used (pathname, stat_buf, pred_ptr)
1241 char *pathname;
1242 struct stat *stat_buf;
1243 struct predicate *pred_ptr;
1245 time_t delta;
1247 delta = stat_buf->st_atime - stat_buf->st_ctime; /* Use difftime? */
1248 switch (pred_ptr->args.info.kind)
1250 case COMP_GT:
1251 if (delta > (time_t) pred_ptr->args.info.l_val)
1252 return (true);
1253 break;
1254 case COMP_LT:
1255 if (delta < (time_t) pred_ptr->args.info.l_val)
1256 return (true);
1257 break;
1258 case COMP_EQ:
1259 if ((delta >= (time_t) pred_ptr->args.info.l_val)
1260 && (delta < (time_t) pred_ptr->args.info.l_val + DAYSECS))
1261 return (true);
1262 break;
1264 return (false);
1267 boolean
1268 pred_user (pathname, stat_buf, pred_ptr)
1269 char *pathname;
1270 struct stat *stat_buf;
1271 struct predicate *pred_ptr;
1273 if (pred_ptr->args.uid == stat_buf->st_uid)
1274 return (true);
1275 else
1276 return (false);
1279 boolean
1280 pred_xtype (pathname, stat_buf, pred_ptr)
1281 char *pathname;
1282 struct stat *stat_buf;
1283 struct predicate *pred_ptr;
1285 struct stat sbuf;
1286 int (*ystat) ();
1288 ystat = xstat == lstat ? stat : lstat;
1289 if ((*ystat) (rel_pathname, &sbuf) != 0)
1291 if (ystat == stat && errno == ENOENT)
1292 /* Mimic behavior of ls -lL. */
1293 return (pred_type (pathname, stat_buf, pred_ptr));
1294 error (0, errno, "%s", pathname);
1295 exit_status = 1;
1296 return (false);
1298 return (pred_type (pathname, &sbuf, pred_ptr));
1301 /* 1) fork to get a child; parent remembers the child pid
1302 2) child execs the command requested
1303 3) parent waits for child; checks for proper pid of child
1305 Possible returns:
1307 ret errno status(h) status(l)
1309 pid x signal# 0177 stopped
1310 pid x exit arg 0 term by _exit
1311 pid x 0 signal # term by signal
1312 -1 EINTR parent got signal
1313 -1 other some other kind of error
1315 Return true only if the pid matches, status(l) is
1316 zero, and the exit arg (status high) is 0.
1317 Otherwise return false, possibly printing an error message. */
1319 static boolean
1320 launch (pred_ptr)
1321 struct predicate *pred_ptr;
1323 int status;
1324 pid_t wait_ret, child_pid;
1325 struct exec_val *execp; /* Pointer for efficiency. */
1326 static int first_time = 1;
1328 execp = &pred_ptr->args.exec_vec;
1330 /* Make sure output of command doesn't get mixed with find output. */
1331 fflush (stdout);
1332 fflush (stderr);
1334 /* Make sure to listen for the kids. */
1335 if (first_time)
1337 first_time = 0;
1338 signal (SIGCHLD, SIG_DFL);
1341 child_pid = fork ();
1342 if (child_pid == -1)
1343 error (1, errno, _("cannot fork"));
1344 if (child_pid == 0)
1346 /* We be the child. */
1347 #ifndef HAVE_FCHDIR
1348 if (chdir (starting_dir) < 0)
1350 error (0, errno, "%s", starting_dir);
1351 _exit (1);
1353 #else
1354 if (fchdir (starting_desc) < 0)
1356 error (0, errno, _("cannot return to starting directory"));
1357 _exit (1);
1359 #endif
1360 execvp (execp->vec[0], execp->vec);
1361 error (0, errno, "%s", execp->vec[0]);
1362 _exit (1);
1365 wait_ret = wait (&status);
1366 if (wait_ret == -1)
1368 error (0, errno, _("error waiting for %s"), execp->vec[0]);
1369 exit_status = 1;
1370 return (false);
1372 if (wait_ret != child_pid)
1374 error (0, 0, _("wait got pid %d, expected pid %d"), wait_ret, child_pid);
1375 exit_status = 1;
1376 return (false);
1378 if (WIFSTOPPED (status))
1380 error (0, 0, _("%s stopped by signal %d"),
1381 execp->vec[0], WSTOPSIG (status));
1382 exit_status = 1;
1383 return (false);
1385 if (WIFSIGNALED (status))
1387 error (0, 0, _("%s terminated by signal %d"),
1388 execp->vec[0], WTERMSIG (status));
1389 exit_status = 1;
1390 return (false);
1392 return (!WEXITSTATUS (status));
1395 /* Return a static string formatting the time WHEN according to the
1396 strftime format character KIND. */
1398 static char *
1399 format_date (when, kind)
1400 time_t when;
1401 int kind;
1403 static char fmt[3];
1404 static char buf[64]; /* More than enough space. */
1406 if (kind == '@')
1408 sprintf (buf, "%ld", when);
1409 return (buf);
1411 else
1413 fmt[0] = '%';
1414 fmt[1] = kind;
1415 fmt[2] = '\0';
1416 if (strftime (buf, sizeof (buf), fmt, localtime (&when)))
1417 return (buf);
1419 return "";
1422 #ifdef DEBUG
1423 /* Return a pointer to the string representation of
1424 the predicate function PRED_FUNC. */
1426 char *
1427 find_pred_name (pred_func)
1428 PFB pred_func;
1430 int i;
1432 for (i = 0; pred_table[i].pred_func != 0; i++)
1433 if (pred_table[i].pred_func == pred_func)
1434 break;
1435 return (pred_table[i].pred_name);
1438 static char *
1439 type_name (type)
1440 short type;
1442 int i;
1444 for (i = 0; type_table[i].type != (short) -1; i++)
1445 if (type_table[i].type == type)
1446 break;
1447 return (type_table[i].type_name);
1450 static char *
1451 prec_name (prec)
1452 short prec;
1454 int i;
1456 for (i = 0; prec_table[i].prec != (short) -1; i++)
1457 if (prec_table[i].prec == prec)
1458 break;
1459 return (prec_table[i].prec_name);
1462 /* Walk the expression tree NODE to stdout.
1463 INDENT is the number of levels to indent the left margin. */
1465 void
1466 print_tree (node, indent)
1467 struct predicate *node;
1468 int indent;
1470 int i;
1472 if (node == NULL)
1473 return;
1474 for (i = 0; i < indent; i++)
1475 printf (" ");
1476 printf ("pred = %s type = %s prec = %s addr = %x\n",
1477 find_pred_name (node->pred_func),
1478 type_name (node->p_type), prec_name (node->p_prec), node);
1479 for (i = 0; i < indent; i++)
1480 printf (" ");
1481 printf (_("left:\n"));
1482 print_tree (node->pred_left, indent + 1);
1483 for (i = 0; i < indent; i++)
1484 printf (" ");
1485 printf (_("right:\n"));
1486 print_tree (node->pred_right, indent + 1);
1489 /* Copy STR into BUF and trim blanks from the end of BUF.
1490 Return BUF. */
1492 static char *
1493 blank_rtrim (str, buf)
1494 char *str;
1495 char *buf;
1497 int i;
1499 if (str == NULL)
1500 return (NULL);
1501 strcpy (buf, str);
1502 i = strlen (buf) - 1;
1503 while ((i >= 0) && ((buf[i] == ' ') || buf[i] == '\t'))
1504 i--;
1505 buf[++i] = '\0';
1506 return (buf);
1509 /* Print out the predicate list starting at NODE. */
1511 void
1512 print_list (node)
1513 struct predicate *node;
1515 struct predicate *cur;
1516 char name[256];
1518 cur = node;
1519 while (cur != NULL)
1521 printf ("%s ", blank_rtrim (find_pred_name (cur->pred_func), name));
1522 cur = cur->pred_next;
1524 printf ("\n");
1526 #endif /* DEBUG */