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)
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. */
20 #include <sys/types.h>
33 # define _(Text) gettext (Text)
38 # define N_(String) gettext_noop (String)
40 # define N_(String) (String)
43 #if !defined(SIGCHLD) && defined(SIGCLD)
44 #define SIGCHLD SIGCLD
49 # define NAMLEN(dirent) strlen((dirent)->d_name)
51 # define dirent direct
52 # define NAMLEN(dirent) (dirent)->d_namlen
54 # include <sys/ndir.h>
65 /* Fake a return value. */
66 #define CLOSEDIR(d) (closedir (d), 0)
68 #define CLOSEDIR(d) closedir (d)
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. */
77 # define ST_NBLOCKS(statp) (((statp)->st_size + 512 - 1) / 512)
79 # ifndef HAVE_ST_BLOCKS
80 # define ST_NBLOCKS(statp) (st_blocks ((statp)->st_size))
82 # if defined(hpux) || defined(__hpux__)
83 # define ST_NBLOCKS(statp) ((statp)->st_blocks * 2)
85 # define ST_NBLOCKS(statp) ((statp)->st_blocks)
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
));
101 struct pred_assoc pred_table
[] =
103 {pred_amin
, "amin "},
105 {pred_anewer
, "anewer "},
106 {pred_atime
, "atime "},
108 {pred_amin
, "cmin "},
109 {pred_cnewer
, "cnewer "},
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 "},
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 "},
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 "},
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 "},
148 {pred_used
, "used "},
149 {pred_user
, "user "},
150 {pred_xtype
, "xtype "},
160 struct op_assoc type_table
[] =
163 {PRIMARY_TYPE
, "primary "},
166 {OPEN_PAREN
, "open_paren "},
167 {CLOSE_PAREN
, "close_paren "},
177 struct prec_assoc prec_table
[] =
180 {COMMA_PREC
, "comma "},
183 {NEGATE_PREC
, "negate "},
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. */
198 pred_amin (pathname
, stat_buf
, pred_ptr
)
200 struct stat
*stat_buf
;
201 struct predicate
*pred_ptr
;
203 switch (pred_ptr
->args
.info
.kind
)
206 if (stat_buf
->st_atime
> (time_t) pred_ptr
->args
.info
.l_val
)
210 if (stat_buf
->st_atime
< (time_t) pred_ptr
->args
.info
.l_val
)
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))
223 pred_and (pathname
, stat_buf
, pred_ptr
)
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
);
243 return ((*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
244 pred_ptr
->pred_right
));
251 pred_anewer (pathname
, stat_buf
, pred_ptr
)
253 struct stat
*stat_buf
;
254 struct predicate
*pred_ptr
;
256 if (stat_buf
->st_atime
> pred_ptr
->args
.time
)
262 pred_atime (pathname
, stat_buf
, pred_ptr
)
264 struct stat
*stat_buf
;
265 struct predicate
*pred_ptr
;
267 switch (pred_ptr
->args
.info
.kind
)
270 if (stat_buf
->st_atime
> (time_t) pred_ptr
->args
.info
.l_val
)
274 if (stat_buf
->st_atime
< (time_t) pred_ptr
->args
.info
.l_val
)
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
288 pred_close (pathname
, stat_buf
, pred_ptr
)
290 struct stat
*stat_buf
;
291 struct predicate
*pred_ptr
;
297 pred_cmin (pathname
, stat_buf
, pred_ptr
)
299 struct stat
*stat_buf
;
300 struct predicate
*pred_ptr
;
302 switch (pred_ptr
->args
.info
.kind
)
305 if (stat_buf
->st_ctime
> (time_t) pred_ptr
->args
.info
.l_val
)
309 if (stat_buf
->st_ctime
< (time_t) pred_ptr
->args
.info
.l_val
)
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))
322 pred_cnewer (pathname
, stat_buf
, pred_ptr
)
324 struct stat
*stat_buf
;
325 struct predicate
*pred_ptr
;
327 if (stat_buf
->st_ctime
> pred_ptr
->args
.time
)
333 pred_comma (pathname
, stat_buf
, pred_ptr
)
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
);
352 return ((*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
353 pred_ptr
->pred_right
));
357 pred_ctime (pathname
, stat_buf
, pred_ptr
)
359 struct stat
*stat_buf
;
360 struct predicate
*pred_ptr
;
362 switch (pred_ptr
->args
.info
.kind
)
365 if (stat_buf
->st_ctime
> (time_t) pred_ptr
->args
.info
.l_val
)
369 if (stat_buf
->st_ctime
< (time_t) pred_ptr
->args
.info
.l_val
)
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
383 pred_empty (pathname
, stat_buf
, pred_ptr
)
385 struct stat
*stat_buf
;
386 struct predicate
*pred_ptr
;
388 if (S_ISDIR (stat_buf
->st_mode
))
392 boolean empty
= true;
395 d
= opendir (rel_pathname
);
398 error (0, errno
, "%s", pathname
);
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')))
414 error (0, errno
, "%s", pathname
);
420 else if (S_ISREG (stat_buf
->st_mode
))
421 return (stat_buf
->st_size
== 0);
427 pred_exec (pathname
, stat_buf
, pred_ptr
)
429 struct stat
*stat_buf
;
430 struct predicate
*pred_ptr
;
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
;
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
);
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
]);
468 pred_false (pathname
, stat_buf
, pred_ptr
)
470 struct stat
*stat_buf
;
471 struct predicate
*pred_ptr
;
477 pred_fls (pathname
, stat_buf
, pred_ptr
)
479 struct stat
*stat_buf
;
480 struct predicate
*pred_ptr
;
482 list_file (pathname
, rel_pathname
, stat_buf
, pred_ptr
->args
.stream
);
487 pred_fprint (pathname
, stat_buf
, pred_ptr
)
489 struct stat
*stat_buf
;
490 struct predicate
*pred_ptr
;
492 fputs (pathname
, pred_ptr
->args
.stream
);
493 putc ('\n', pred_ptr
->args
.stream
);
498 pred_fprint0 (pathname
, stat_buf
, pred_ptr
)
500 struct stat
*stat_buf
;
501 struct predicate
*pred_ptr
;
503 fputs (pathname
, pred_ptr
->args
.stream
);
504 putc (0, pred_ptr
->args
.stream
);
509 pred_fprintf (pathname
, stat_buf
, pred_ptr
)
511 struct stat
*stat_buf
;
512 struct predicate
*pred_ptr
;
514 FILE *fp
= pred_ptr
->args
.printf_vec
.stream
;
515 struct segment
*segment
;
518 for (segment
= pred_ptr
->args
.printf_vec
.segment
; segment
;
519 segment
= segment
->next
)
521 if (segment
->kind
& 0xff00) /* Component of date. */
525 switch (segment
->kind
& 0xff)
528 t
= stat_buf
->st_atime
;
531 t
= stat_buf
->st_ctime
;
534 t
= stat_buf
->st_mtime
;
539 fprintf (fp
, segment
->text
,
540 format_date (t
, (segment
->kind
>> 8) & 0xff));
544 switch (segment
->kind
)
546 case KIND_PLAIN
: /* Plain text string (no % conversion). */
547 fwrite (segment
->text
, 1, segment
->text_len
, fp
);
549 case KIND_STOP
: /* Terminate argument and flush output. */
550 fwrite (segment
->text
, 1, segment
->text_len
, fp
);
553 case 'a': /* atime in `ctime' format. */
554 cp
= ctime (&stat_buf
->st_atime
);
556 fprintf (fp
, segment
->text
, cp
);
558 case 'b': /* size in 512-byte blocks */
559 fprintf (fp
, segment
->text
, ST_NBLOCKS (stat_buf
));
561 case 'c': /* ctime in `ctime' format */
562 cp
= ctime (&stat_buf
->st_ctime
);
564 fprintf (fp
, segment
->text
, cp
);
566 case 'd': /* depth in search tree */
567 fprintf (fp
, segment
->text
, curdepth
);
569 case 'f': /* basename of path */
570 cp
= strrchr (pathname
, '/');
575 fprintf (fp
, segment
->text
, cp
);
577 case 'F': /* filesystem type */
578 fprintf (fp
, segment
->text
,
579 filesystem_type (pathname
, rel_pathname
, stat_buf
));
581 case 'g': /* group name */
585 g
= getgrgid (stat_buf
->st_gid
);
588 segment
->text
[segment
->text_len
] = 's';
589 fprintf (fp
, segment
->text
, g
->gr_name
);
594 case 'G': /* GID number */
595 segment
->text
[segment
->text_len
] = 'u';
596 fprintf (fp
, segment
->text
, stat_buf
->st_gid
);
598 case 'h': /* leading directories part of path */
602 cp
= strrchr (pathname
, '/');
603 if (cp
== NULL
) /* No leading directories. */
607 fprintf (fp
, segment
->text
, pathname
);
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
;
620 case 'i': /* inode number */
621 fprintf (fp
, segment
->text
, stat_buf
->st_ino
);
623 case 'k': /* size in 1K blocks */
624 fprintf (fp
, segment
->text
, (ST_NBLOCKS (stat_buf
) + 1) / 2);
626 case 'l': /* object of symlink */
631 if (S_ISLNK (stat_buf
->st_mode
))
633 linkname
= get_link_name (pathname
, rel_pathname
);
639 fprintf (fp
, segment
->text
, linkname
);
643 fprintf (fp
, segment
->text
, "");
647 case 'm': /* mode as octal number (perms only) */
648 fprintf (fp
, segment
->text
, stat_buf
->st_mode
& 07777);
650 case 'n': /* number of links */
651 fprintf (fp
, segment
->text
, stat_buf
->st_nlink
);
653 case 'p': /* pathname */
654 fprintf (fp
, segment
->text
, pathname
);
656 case 'P': /* pathname with ARGV element stripped */
659 cp
= pathname
+ path_length
;
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. */
669 fprintf (fp
, segment
->text
, cp
);
671 case 's': /* size in bytes */
672 fprintf (fp
, segment
->text
, stat_buf
->st_size
);
674 case 't': /* mtime in `ctime' format */
675 cp
= ctime (&stat_buf
->st_mtime
);
677 fprintf (fp
, segment
->text
, cp
);
679 case 'u': /* user name */
683 p
= getpwuid (stat_buf
->st_uid
);
686 segment
->text
[segment
->text_len
] = 's';
687 fprintf (fp
, segment
->text
, p
->pw_name
);
692 case 'U': /* UID number */
693 segment
->text
[segment
->text_len
] = 'u';
694 fprintf (fp
, segment
->text
, stat_buf
->st_uid
);
702 pred_fstype (pathname
, stat_buf
, pred_ptr
)
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)
714 pred_gid (pathname
, stat_buf
, pred_ptr
)
716 struct stat
*stat_buf
;
717 struct predicate
*pred_ptr
;
719 switch (pred_ptr
->args
.info
.kind
)
722 if (stat_buf
->st_gid
> pred_ptr
->args
.info
.l_val
)
726 if (stat_buf
->st_gid
< pred_ptr
->args
.info
.l_val
)
730 if (stat_buf
->st_gid
== pred_ptr
->args
.info
.l_val
)
738 pred_group (pathname
, stat_buf
, pred_ptr
)
740 struct stat
*stat_buf
;
741 struct predicate
*pred_ptr
;
743 if (pred_ptr
->args
.gid
== stat_buf
->st_gid
)
750 pred_ilname (pathname
, stat_buf
, pred_ptr
)
752 struct stat
*stat_buf
;
753 struct predicate
*pred_ptr
;
755 return insert_lname (pathname
, stat_buf
, pred_ptr
, true);
759 pred_iname (pathname
, stat_buf
, pred_ptr
)
761 struct stat
*stat_buf
;
762 struct predicate
*pred_ptr
;
766 base
= basename (pathname
);
767 if (fnmatch (pred_ptr
->args
.str
, base
, FNM_PERIOD
| FNM_CASEFOLD
) == 0)
773 pred_inum (pathname
, stat_buf
, pred_ptr
)
775 struct stat
*stat_buf
;
776 struct predicate
*pred_ptr
;
778 switch (pred_ptr
->args
.info
.kind
)
781 if (stat_buf
->st_ino
> pred_ptr
->args
.info
.l_val
)
785 if (stat_buf
->st_ino
< pred_ptr
->args
.info
.l_val
)
789 if (stat_buf
->st_ino
== pred_ptr
->args
.info
.l_val
)
797 pred_ipath (pathname
, stat_buf
, pred_ptr
)
799 struct stat
*stat_buf
;
800 struct predicate
*pred_ptr
;
802 if (fnmatch (pred_ptr
->args
.str
, pathname
, FNM_CASEFOLD
) == 0)
808 pred_links (pathname
, stat_buf
, pred_ptr
)
810 struct stat
*stat_buf
;
811 struct predicate
*pred_ptr
;
813 switch (pred_ptr
->args
.info
.kind
)
816 if (stat_buf
->st_nlink
> pred_ptr
->args
.info
.l_val
)
820 if (stat_buf
->st_nlink
< pred_ptr
->args
.info
.l_val
)
824 if (stat_buf
->st_nlink
== pred_ptr
->args
.info
.l_val
)
832 pred_lname (pathname
, stat_buf
, pred_ptr
)
834 struct stat
*stat_buf
;
835 struct predicate
*pred_ptr
;
837 return insert_lname (pathname
, stat_buf
, pred_ptr
, false);
841 insert_lname (pathname
, stat_buf
, pred_ptr
, ignore_case
)
843 struct stat
*stat_buf
;
844 struct predicate
*pred_ptr
;
849 if (S_ISLNK (stat_buf
->st_mode
))
851 char *linkname
= get_link_name (pathname
, rel_pathname
);
854 if (fnmatch (pred_ptr
->args
.str
, linkname
,
855 ignore_case
? FNM_CASEFOLD
: 0) == 0)
865 pred_ls (pathname
, stat_buf
, pred_ptr
)
867 struct stat
*stat_buf
;
868 struct predicate
*pred_ptr
;
870 list_file (pathname
, rel_pathname
, stat_buf
, stdout
);
875 pred_mmin (pathname
, stat_buf
, pred_ptr
)
877 struct stat
*stat_buf
;
878 struct predicate
*pred_ptr
;
880 switch (pred_ptr
->args
.info
.kind
)
883 if (stat_buf
->st_mtime
> (time_t) pred_ptr
->args
.info
.l_val
)
887 if (stat_buf
->st_mtime
< (time_t) pred_ptr
->args
.info
.l_val
)
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))
900 pred_mtime (pathname
, stat_buf
, pred_ptr
)
902 struct stat
*stat_buf
;
903 struct predicate
*pred_ptr
;
905 switch (pred_ptr
->args
.info
.kind
)
908 if (stat_buf
->st_mtime
> (time_t) pred_ptr
->args
.info
.l_val
)
912 if (stat_buf
->st_mtime
< (time_t) pred_ptr
->args
.info
.l_val
)
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
926 pred_name (pathname
, stat_buf
, pred_ptr
)
928 struct stat
*stat_buf
;
929 struct predicate
*pred_ptr
;
933 base
= basename (pathname
);
934 if (fnmatch (pred_ptr
->args
.str
, base
, FNM_PERIOD
) == 0)
940 pred_negate (pathname
, stat_buf
, pred_ptr
)
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
);
956 return (!(*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
957 pred_ptr
->pred_right
));
961 pred_newer (pathname
, stat_buf
, pred_ptr
)
963 struct stat
*stat_buf
;
964 struct predicate
*pred_ptr
;
966 if (stat_buf
->st_mtime
> pred_ptr
->args
.time
)
972 pred_nogroup (pathname
, stat_buf
, pred_ptr
)
974 struct stat
*stat_buf
;
975 struct predicate
*pred_ptr
;
978 extern char *gid_unused
;
980 return gid_unused
[(unsigned) stat_buf
->st_gid
];
982 return getgrgid (stat_buf
->st_gid
) == NULL
;
987 pred_nouser (pathname
, stat_buf
, pred_ptr
)
989 struct stat
*stat_buf
;
990 struct predicate
*pred_ptr
;
993 extern char *uid_unused
;
995 return uid_unused
[(unsigned) stat_buf
->st_uid
];
997 return getpwuid (stat_buf
->st_uid
) == NULL
;
1002 pred_ok (pathname
, stat_buf
, pred_ptr
)
1004 struct stat
*stat_buf
;
1005 struct predicate
*pred_ptr
;
1010 fprintf (stderr
, "< %s ... %s > ? ",
1011 pred_ptr
->args
.exec_vec
.vec
[0], pathname
);
1014 yes
= (i
== 'y' || i
== 'Y');
1015 while (i
!= EOF
&& i
!= '\n')
1019 return pred_exec (pathname
, stat_buf
, pred_ptr
);
1023 pred_open (pathname
, stat_buf
, pred_ptr
)
1025 struct stat
*stat_buf
;
1026 struct predicate
*pred_ptr
;
1032 pred_or (pathname
, stat_buf
, pred_ptr
)
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
);
1052 return ((*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
1053 pred_ptr
->pred_right
));
1060 pred_path (pathname
, stat_buf
, pred_ptr
)
1062 struct stat
*stat_buf
;
1063 struct predicate
*pred_ptr
;
1065 if (fnmatch (pred_ptr
->args
.str
, pathname
, 0) == 0)
1071 pred_perm (pathname
, stat_buf
, pred_ptr
)
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))
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
)
1093 /* True if exactly the given bits are set. */
1094 if ((stat_buf
->st_mode
& 07777) == pred_ptr
->args
.perm
)
1101 pred_print (pathname
, stat_buf
, pred_ptr
)
1103 struct stat
*stat_buf
;
1104 struct predicate
*pred_ptr
;
1111 pred_print0 (pathname
, stat_buf
, pred_ptr
)
1113 struct stat
*stat_buf
;
1114 struct predicate
*pred_ptr
;
1116 fputs (pathname
, stdout
);
1122 pred_prune (pathname
, stat_buf
, pred_ptr
)
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. */
1132 pred_regex (pathname
, stat_buf
, pred_ptr
)
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
)
1145 pred_size (pathname
, stat_buf
, pred_ptr
)
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
)
1157 if (f_val
> pred_ptr
->args
.size
.size
)
1161 if (f_val
< pred_ptr
->args
.size
.size
)
1165 if (f_val
== pred_ptr
->args
.size
.size
)
1173 pred_true (pathname
, stat_buf
, pred_ptr
)
1175 struct stat
*stat_buf
;
1176 struct predicate
*pred_ptr
;
1182 pred_type (pathname
, stat_buf
, pred_ptr
)
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
;
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
)
1197 || (S_ISLNK (mode
) && type
== S_IFLNK
)
1200 || (S_ISFIFO (mode
) && type
== S_IFIFO
)
1203 || (S_ISSOCK (mode
) && type
== S_IFSOCK
)
1207 /* Unix system; check `mode' the fast way. */
1208 if ((mode
& S_IFMT
) == type
)
1216 pred_uid (pathname
, stat_buf
, pred_ptr
)
1218 struct stat
*stat_buf
;
1219 struct predicate
*pred_ptr
;
1221 switch (pred_ptr
->args
.info
.kind
)
1224 if (stat_buf
->st_uid
> pred_ptr
->args
.info
.l_val
)
1228 if (stat_buf
->st_uid
< pred_ptr
->args
.info
.l_val
)
1232 if (stat_buf
->st_uid
== pred_ptr
->args
.info
.l_val
)
1240 pred_used (pathname
, stat_buf
, pred_ptr
)
1242 struct stat
*stat_buf
;
1243 struct predicate
*pred_ptr
;
1247 delta
= stat_buf
->st_atime
- stat_buf
->st_ctime
; /* Use difftime? */
1248 switch (pred_ptr
->args
.info
.kind
)
1251 if (delta
> (time_t) pred_ptr
->args
.info
.l_val
)
1255 if (delta
< (time_t) pred_ptr
->args
.info
.l_val
)
1259 if ((delta
>= (time_t) pred_ptr
->args
.info
.l_val
)
1260 && (delta
< (time_t) pred_ptr
->args
.info
.l_val
+ DAYSECS
))
1268 pred_user (pathname
, stat_buf
, pred_ptr
)
1270 struct stat
*stat_buf
;
1271 struct predicate
*pred_ptr
;
1273 if (pred_ptr
->args
.uid
== stat_buf
->st_uid
)
1280 pred_xtype (pathname
, stat_buf
, pred_ptr
)
1282 struct stat
*stat_buf
;
1283 struct predicate
*pred_ptr
;
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
);
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
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. */
1321 struct predicate
*pred_ptr
;
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. */
1334 /* Make sure to listen for the kids. */
1338 signal (SIGCHLD
, SIG_DFL
);
1341 child_pid
= fork ();
1342 if (child_pid
== -1)
1343 error (1, errno
, _("cannot fork"));
1346 /* We be the child. */
1348 if (chdir (starting_dir
) < 0)
1350 error (0, errno
, "%s", starting_dir
);
1354 if (fchdir (starting_desc
) < 0)
1356 error (0, errno
, _("cannot return to starting directory"));
1360 execvp (execp
->vec
[0], execp
->vec
);
1361 error (0, errno
, "%s", execp
->vec
[0]);
1365 wait_ret
= wait (&status
);
1368 error (0, errno
, _("error waiting for %s"), execp
->vec
[0]);
1372 if (wait_ret
!= child_pid
)
1374 error (0, 0, _("wait got pid %d, expected pid %d"), wait_ret
, child_pid
);
1378 if (WIFSTOPPED (status
))
1380 error (0, 0, _("%s stopped by signal %d"),
1381 execp
->vec
[0], WSTOPSIG (status
));
1385 if (WIFSIGNALED (status
))
1387 error (0, 0, _("%s terminated by signal %d"),
1388 execp
->vec
[0], WTERMSIG (status
));
1392 return (!WEXITSTATUS (status
));
1395 /* Return a static string formatting the time WHEN according to the
1396 strftime format character KIND. */
1399 format_date (when
, kind
)
1404 static char buf
[64]; /* More than enough space. */
1408 sprintf (buf
, "%ld", when
);
1416 if (strftime (buf
, sizeof (buf
), fmt
, localtime (&when
)))
1423 /* Return a pointer to the string representation of
1424 the predicate function PRED_FUNC. */
1427 find_pred_name (pred_func
)
1432 for (i
= 0; pred_table
[i
].pred_func
!= 0; i
++)
1433 if (pred_table
[i
].pred_func
== pred_func
)
1435 return (pred_table
[i
].pred_name
);
1444 for (i
= 0; type_table
[i
].type
!= (short) -1; i
++)
1445 if (type_table
[i
].type
== type
)
1447 return (type_table
[i
].type_name
);
1456 for (i
= 0; prec_table
[i
].prec
!= (short) -1; i
++)
1457 if (prec_table
[i
].prec
== prec
)
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. */
1466 print_tree (node
, indent
)
1467 struct predicate
*node
;
1474 for (i
= 0; i
< indent
; i
++)
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
++)
1481 printf (_("left:\n"));
1482 print_tree (node
->pred_left
, indent
+ 1);
1483 for (i
= 0; i
< indent
; i
++)
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.
1493 blank_rtrim (str
, buf
)
1502 i
= strlen (buf
) - 1;
1503 while ((i
>= 0) && ((buf
[i
] == ' ') || buf
[i
] == '\t'))
1509 /* Print out the predicate list starting at NODE. */
1513 struct predicate
*node
;
1515 struct predicate
*cur
;
1521 printf ("%s ", blank_rtrim (find_pred_name (cur
->pred_func
), name
));
1522 cur
= cur
->pred_next
;