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>
31 #if !defined(SIGCHLD) && defined(SIGCLD)
32 #define SIGCHLD SIGCLD
37 # define NAMLEN(dirent) strlen((dirent)->d_name)
39 # define dirent direct
40 # define NAMLEN(dirent) (dirent)->d_namlen
42 # include <sys/ndir.h>
53 /* Fake a return value. */
54 #define CLOSEDIR(d) (closedir (d), 0)
56 #define CLOSEDIR(d) closedir (d)
59 /* Extract or fake data from a `struct stat'.
60 ST_NBLOCKS: Number of 512-byte blocks in the file
61 (including indirect blocks).
62 HP-UX, perhaps uniquely, counts st_blocks in 1024-byte units.
63 This workaround loses when mixing HP-UX and 4BSD filesystems, though. */
65 # define ST_NBLOCKS(statp) (((statp)->st_size + 512 - 1) / 512)
67 # ifndef HAVE_ST_BLOCKS
68 # define ST_NBLOCKS(statp) (st_blocks ((statp)->st_size))
70 # if defined(hpux) || defined(__hpux__)
71 # define ST_NBLOCKS(statp) ((statp)->st_blocks * 2)
73 # define ST_NBLOCKS(statp) ((statp)->st_blocks)
78 static boolean insert_lname
P_((char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
, boolean ignore_case
));
79 static boolean launch
P_((struct predicate
*pred_ptr
));
80 static char *format_date
P_((time_t when
, int kind
));
89 struct pred_assoc pred_table
[] =
93 {pred_anewer
, "anewer "},
94 {pred_atime
, "atime "},
97 {pred_cnewer
, "cnewer "},
99 {pred_ctime
, "ctime "},
100 {pred_empty
, "empty "},
101 {pred_exec
, "exec "},
102 {pred_false
, "false "},
103 {pred_fprint
, "fprint "},
104 {pred_fprint0
, "fprint0 "},
105 {pred_fprintf
, "fprintf "},
106 {pred_fstype
, "fstype "},
108 {pred_group
, "group "},
109 {pred_ilname
, "ilname "},
110 {pred_iname
, "iname "},
111 {pred_inum
, "inum "},
112 {pred_ipath
, "ipath "},
113 {pred_links
, "links "},
114 {pred_lname
, "lname "},
116 {pred_amin
, "mmin "},
117 {pred_mtime
, "mtime "},
118 {pred_name
, "name "},
119 {pred_negate
, "not "},
120 {pred_newer
, "newer "},
121 {pred_nogroup
, "nogroup "},
122 {pred_nouser
, "nouser "},
126 {pred_path
, "path "},
127 {pred_perm
, "perm "},
128 {pred_print
, "print "},
129 {pred_print0
, "print0 "},
130 {pred_prune
, "prune "},
131 {pred_regex
, "regex "},
132 {pred_size
, "size "},
133 {pred_true
, "true "},
134 {pred_type
, "type "},
136 {pred_used
, "used "},
137 {pred_user
, "user "},
138 {pred_xtype
, "xtype "},
148 struct op_assoc type_table
[] =
151 {PRIMARY_TYPE
, "primary "},
154 {OPEN_PAREN
, "open_paren "},
155 {CLOSE_PAREN
, "close_paren "},
165 struct prec_assoc prec_table
[] =
168 {COMMA_PREC
, "comma "},
171 {NEGATE_PREC
, "negate "},
177 /* Predicate processing routines.
179 PATHNAME is the full pathname of the file being checked.
180 *STAT_BUF contains information about PATHNAME.
181 *PRED_PTR contains information for applying the predicate.
183 Return true if the file passes this predicate, false if not. */
186 pred_amin (pathname
, stat_buf
, pred_ptr
)
188 struct stat
*stat_buf
;
189 struct predicate
*pred_ptr
;
191 switch (pred_ptr
->args
.info
.kind
)
194 if (stat_buf
->st_atime
> (time_t) pred_ptr
->args
.info
.l_val
)
198 if (stat_buf
->st_atime
< (time_t) pred_ptr
->args
.info
.l_val
)
202 if ((stat_buf
->st_atime
>= (time_t) pred_ptr
->args
.info
.l_val
)
203 && (stat_buf
->st_atime
< (time_t) pred_ptr
->args
.info
.l_val
+ 60))
211 pred_and (pathname
, stat_buf
, pred_ptr
)
213 struct stat
*stat_buf
;
214 struct predicate
*pred_ptr
;
216 if (pred_ptr
->pred_left
== NULL
217 || (*pred_ptr
->pred_left
->pred_func
) (pathname
, stat_buf
,
218 pred_ptr
->pred_left
))
220 /* Check whether we need a stat here. */
221 if (pred_ptr
->need_stat
)
223 if (!have_stat
&& (*xstat
) (rel_pathname
, stat_buf
) != 0)
225 error (0, errno
, "%s", pathname
);
231 return ((*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
232 pred_ptr
->pred_right
));
239 pred_anewer (pathname
, stat_buf
, pred_ptr
)
241 struct stat
*stat_buf
;
242 struct predicate
*pred_ptr
;
244 if (stat_buf
->st_atime
> pred_ptr
->args
.time
)
250 pred_atime (pathname
, stat_buf
, pred_ptr
)
252 struct stat
*stat_buf
;
253 struct predicate
*pred_ptr
;
255 switch (pred_ptr
->args
.info
.kind
)
258 if (stat_buf
->st_atime
> (time_t) pred_ptr
->args
.info
.l_val
)
262 if (stat_buf
->st_atime
< (time_t) pred_ptr
->args
.info
.l_val
)
266 if ((stat_buf
->st_atime
>= (time_t) pred_ptr
->args
.info
.l_val
)
267 && (stat_buf
->st_atime
< (time_t) pred_ptr
->args
.info
.l_val
276 pred_close (pathname
, stat_buf
, pred_ptr
)
278 struct stat
*stat_buf
;
279 struct predicate
*pred_ptr
;
285 pred_cmin (pathname
, stat_buf
, pred_ptr
)
287 struct stat
*stat_buf
;
288 struct predicate
*pred_ptr
;
290 switch (pred_ptr
->args
.info
.kind
)
293 if (stat_buf
->st_ctime
> (time_t) pred_ptr
->args
.info
.l_val
)
297 if (stat_buf
->st_ctime
< (time_t) pred_ptr
->args
.info
.l_val
)
301 if ((stat_buf
->st_ctime
>= (time_t) pred_ptr
->args
.info
.l_val
)
302 && (stat_buf
->st_ctime
< (time_t) pred_ptr
->args
.info
.l_val
+ 60))
310 pred_cnewer (pathname
, stat_buf
, pred_ptr
)
312 struct stat
*stat_buf
;
313 struct predicate
*pred_ptr
;
315 if (stat_buf
->st_ctime
> pred_ptr
->args
.time
)
321 pred_comma (pathname
, stat_buf
, pred_ptr
)
323 struct stat
*stat_buf
;
324 struct predicate
*pred_ptr
;
326 if (pred_ptr
->pred_left
!= NULL
)
327 (*pred_ptr
->pred_left
->pred_func
) (pathname
, stat_buf
,
328 pred_ptr
->pred_left
);
329 /* Check whether we need a stat here. */
330 if (pred_ptr
->need_stat
)
332 if (!have_stat
&& (*xstat
) (rel_pathname
, stat_buf
) != 0)
334 error (0, errno
, "%s", pathname
);
340 return ((*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
341 pred_ptr
->pred_right
));
345 pred_ctime (pathname
, stat_buf
, pred_ptr
)
347 struct stat
*stat_buf
;
348 struct predicate
*pred_ptr
;
350 switch (pred_ptr
->args
.info
.kind
)
353 if (stat_buf
->st_ctime
> (time_t) pred_ptr
->args
.info
.l_val
)
357 if (stat_buf
->st_ctime
< (time_t) pred_ptr
->args
.info
.l_val
)
361 if ((stat_buf
->st_ctime
>= (time_t) pred_ptr
->args
.info
.l_val
)
362 && (stat_buf
->st_ctime
< (time_t) pred_ptr
->args
.info
.l_val
371 pred_empty (pathname
, stat_buf
, pred_ptr
)
373 struct stat
*stat_buf
;
374 struct predicate
*pred_ptr
;
376 if (S_ISDIR (stat_buf
->st_mode
))
380 boolean empty
= true;
383 d
= opendir (rel_pathname
);
386 error (0, errno
, "%s", pathname
);
390 for (dp
= readdir (d
); dp
; dp
= readdir (d
))
392 if (dp
->d_name
[0] != '.'
393 || (dp
->d_name
[1] != '\0'
394 && (dp
->d_name
[1] != '.' || dp
->d_name
[2] != '\0')))
402 error (0, errno
, "%s", pathname
);
408 else if (S_ISREG (stat_buf
->st_mode
))
409 return (stat_buf
->st_size
== 0);
415 pred_exec (pathname
, stat_buf
, pred_ptr
)
417 struct stat
*stat_buf
;
418 struct predicate
*pred_ptr
;
422 struct exec_val
*execp
; /* Pointer for efficiency. */
424 execp
= &pred_ptr
->args
.exec_vec
;
426 /* Replace "{}" with the real path in each affected arg. */
427 for (path_pos
= 0; execp
->paths
[path_pos
].offset
>= 0; path_pos
++)
429 register char *from
, *to
;
431 i
= execp
->paths
[path_pos
].offset
;
433 xmalloc (strlen (execp
->paths
[path_pos
].origarg
) + 1
434 + (strlen (pathname
) - 2) * execp
->paths
[path_pos
].count
);
435 for (from
= execp
->paths
[path_pos
].origarg
, to
= execp
->vec
[i
]; *from
; )
436 if (from
[0] == '{' && from
[1] == '}')
438 to
= stpcpy (to
, pathname
);
443 *to
= *from
; /* Copy null. */
446 i
= launch (pred_ptr
);
448 /* Free the temporary args. */
449 for (path_pos
= 0; execp
->paths
[path_pos
].offset
>= 0; path_pos
++)
450 free (execp
->vec
[execp
->paths
[path_pos
].offset
]);
456 pred_false (pathname
, stat_buf
, pred_ptr
)
458 struct stat
*stat_buf
;
459 struct predicate
*pred_ptr
;
465 pred_fls (pathname
, stat_buf
, pred_ptr
)
467 struct stat
*stat_buf
;
468 struct predicate
*pred_ptr
;
470 list_file (pathname
, rel_pathname
, stat_buf
, pred_ptr
->args
.stream
);
475 pred_fprint (pathname
, stat_buf
, pred_ptr
)
477 struct stat
*stat_buf
;
478 struct predicate
*pred_ptr
;
480 fputs (pathname
, pred_ptr
->args
.stream
);
481 putc ('\n', pred_ptr
->args
.stream
);
486 pred_fprint0 (pathname
, stat_buf
, pred_ptr
)
488 struct stat
*stat_buf
;
489 struct predicate
*pred_ptr
;
491 fputs (pathname
, pred_ptr
->args
.stream
);
492 putc (0, pred_ptr
->args
.stream
);
497 pred_fprintf (pathname
, stat_buf
, pred_ptr
)
499 struct stat
*stat_buf
;
500 struct predicate
*pred_ptr
;
502 FILE *fp
= pred_ptr
->args
.printf_vec
.stream
;
503 struct segment
*segment
;
506 for (segment
= pred_ptr
->args
.printf_vec
.segment
; segment
;
507 segment
= segment
->next
)
509 if (segment
->kind
& 0xff00) /* Component of date. */
513 switch (segment
->kind
& 0xff)
516 t
= stat_buf
->st_atime
;
519 t
= stat_buf
->st_ctime
;
522 t
= stat_buf
->st_mtime
;
527 fprintf (fp
, segment
->text
,
528 format_date (t
, (segment
->kind
>> 8) & 0xff));
532 switch (segment
->kind
)
534 case KIND_PLAIN
: /* Plain text string (no % conversion). */
535 fwrite (segment
->text
, 1, segment
->text_len
, fp
);
537 case KIND_STOP
: /* Terminate argument and flush output. */
538 fwrite (segment
->text
, 1, segment
->text_len
, fp
);
541 case 'a': /* atime in `ctime' format. */
542 cp
= ctime (&stat_buf
->st_atime
);
544 fprintf (fp
, segment
->text
, cp
);
546 case 'b': /* size in 512-byte blocks */
547 fprintf (fp
, segment
->text
, ST_NBLOCKS (stat_buf
));
549 case 'c': /* ctime in `ctime' format */
550 cp
= ctime (&stat_buf
->st_ctime
);
552 fprintf (fp
, segment
->text
, cp
);
554 case 'd': /* depth in search tree */
555 fprintf (fp
, segment
->text
, curdepth
);
557 case 'f': /* basename of path */
558 cp
= strrchr (pathname
, '/');
563 fprintf (fp
, segment
->text
, cp
);
565 case 'F': /* filesystem type */
566 fprintf (fp
, segment
->text
,
567 filesystem_type (pathname
, rel_pathname
, stat_buf
));
569 case 'g': /* group name */
573 g
= getgrgid (stat_buf
->st_gid
);
576 segment
->text
[segment
->text_len
] = 's';
577 fprintf (fp
, segment
->text
, g
->gr_name
);
582 case 'G': /* GID number */
583 segment
->text
[segment
->text_len
] = 'u';
584 fprintf (fp
, segment
->text
, stat_buf
->st_gid
);
586 case 'h': /* leading directories part of path */
590 cp
= strrchr (pathname
, '/');
591 if (cp
== NULL
) /* No leading directories. */
595 fprintf (fp
, segment
->text
, pathname
);
599 case 'H': /* ARGV element file was found under */
601 char cc
= pathname
[path_length
];
603 pathname
[path_length
] = '\0';
604 fprintf (fp
, segment
->text
, pathname
);
605 pathname
[path_length
] = cc
;
608 case 'i': /* inode number */
609 fprintf (fp
, segment
->text
, stat_buf
->st_ino
);
611 case 'k': /* size in 1K blocks */
612 fprintf (fp
, segment
->text
, (ST_NBLOCKS (stat_buf
) + 1) / 2);
614 case 'l': /* object of symlink */
619 if (S_ISLNK (stat_buf
->st_mode
))
621 linkname
= get_link_name (pathname
, rel_pathname
);
627 fprintf (fp
, segment
->text
, linkname
);
631 fprintf (fp
, segment
->text
, "");
635 case 'm': /* mode as octal number (perms only) */
636 fprintf (fp
, segment
->text
, stat_buf
->st_mode
& 07777);
638 case 'n': /* number of links */
639 fprintf (fp
, segment
->text
, stat_buf
->st_nlink
);
641 case 'p': /* pathname */
642 fprintf (fp
, segment
->text
, pathname
);
644 case 'P': /* pathname with ARGV element stripped */
647 cp
= pathname
+ path_length
;
649 /* Move past the slash between the ARGV element
650 and the rest of the pathname. But if the ARGV element
651 ends in a slash, we didn't add another, so we've
652 already skipped past it. */
657 fprintf (fp
, segment
->text
, cp
);
659 case 's': /* size in bytes */
660 fprintf (fp
, segment
->text
, stat_buf
->st_size
);
662 case 't': /* mtime in `ctime' format */
663 cp
= ctime (&stat_buf
->st_mtime
);
665 fprintf (fp
, segment
->text
, cp
);
667 case 'u': /* user name */
671 p
= getpwuid (stat_buf
->st_uid
);
674 segment
->text
[segment
->text_len
] = 's';
675 fprintf (fp
, segment
->text
, p
->pw_name
);
680 case 'U': /* UID number */
681 segment
->text
[segment
->text_len
] = 'u';
682 fprintf (fp
, segment
->text
, stat_buf
->st_uid
);
690 pred_fstype (pathname
, stat_buf
, pred_ptr
)
692 struct stat
*stat_buf
;
693 struct predicate
*pred_ptr
;
695 if (strcmp (filesystem_type (pathname
, rel_pathname
, stat_buf
),
696 pred_ptr
->args
.str
) == 0)
702 pred_gid (pathname
, stat_buf
, pred_ptr
)
704 struct stat
*stat_buf
;
705 struct predicate
*pred_ptr
;
707 switch (pred_ptr
->args
.info
.kind
)
710 if (stat_buf
->st_gid
> pred_ptr
->args
.info
.l_val
)
714 if (stat_buf
->st_gid
< pred_ptr
->args
.info
.l_val
)
718 if (stat_buf
->st_gid
== pred_ptr
->args
.info
.l_val
)
726 pred_group (pathname
, stat_buf
, pred_ptr
)
728 struct stat
*stat_buf
;
729 struct predicate
*pred_ptr
;
731 if (pred_ptr
->args
.gid
== stat_buf
->st_gid
)
738 pred_ilname (pathname
, stat_buf
, pred_ptr
)
740 struct stat
*stat_buf
;
741 struct predicate
*pred_ptr
;
743 return insert_lname (pathname
, stat_buf
, pred_ptr
, true);
747 pred_iname (pathname
, stat_buf
, pred_ptr
)
749 struct stat
*stat_buf
;
750 struct predicate
*pred_ptr
;
754 base
= basename (pathname
);
755 if (fnmatch (pred_ptr
->args
.str
, base
, FNM_PERIOD
| FNM_CASEFOLD
) == 0)
761 pred_inum (pathname
, stat_buf
, pred_ptr
)
763 struct stat
*stat_buf
;
764 struct predicate
*pred_ptr
;
766 switch (pred_ptr
->args
.info
.kind
)
769 if (stat_buf
->st_ino
> pred_ptr
->args
.info
.l_val
)
773 if (stat_buf
->st_ino
< pred_ptr
->args
.info
.l_val
)
777 if (stat_buf
->st_ino
== pred_ptr
->args
.info
.l_val
)
785 pred_ipath (pathname
, stat_buf
, pred_ptr
)
787 struct stat
*stat_buf
;
788 struct predicate
*pred_ptr
;
790 if (fnmatch (pred_ptr
->args
.str
, pathname
, FNM_CASEFOLD
) == 0)
796 pred_links (pathname
, stat_buf
, pred_ptr
)
798 struct stat
*stat_buf
;
799 struct predicate
*pred_ptr
;
801 switch (pred_ptr
->args
.info
.kind
)
804 if (stat_buf
->st_nlink
> pred_ptr
->args
.info
.l_val
)
808 if (stat_buf
->st_nlink
< pred_ptr
->args
.info
.l_val
)
812 if (stat_buf
->st_nlink
== pred_ptr
->args
.info
.l_val
)
820 pred_lname (pathname
, stat_buf
, pred_ptr
)
822 struct stat
*stat_buf
;
823 struct predicate
*pred_ptr
;
825 return insert_lname (pathname
, stat_buf
, pred_ptr
, false);
829 insert_lname (pathname
, stat_buf
, pred_ptr
, ignore_case
)
831 struct stat
*stat_buf
;
832 struct predicate
*pred_ptr
;
837 if (S_ISLNK (stat_buf
->st_mode
))
839 char *linkname
= get_link_name (pathname
, rel_pathname
);
842 if (fnmatch (pred_ptr
->args
.str
, linkname
,
843 ignore_case
? FNM_CASEFOLD
: 0) == 0)
853 pred_ls (pathname
, stat_buf
, pred_ptr
)
855 struct stat
*stat_buf
;
856 struct predicate
*pred_ptr
;
858 list_file (pathname
, rel_pathname
, stat_buf
, stdout
);
863 pred_mmin (pathname
, stat_buf
, pred_ptr
)
865 struct stat
*stat_buf
;
866 struct predicate
*pred_ptr
;
868 switch (pred_ptr
->args
.info
.kind
)
871 if (stat_buf
->st_mtime
> (time_t) pred_ptr
->args
.info
.l_val
)
875 if (stat_buf
->st_mtime
< (time_t) pred_ptr
->args
.info
.l_val
)
879 if ((stat_buf
->st_mtime
>= (time_t) pred_ptr
->args
.info
.l_val
)
880 && (stat_buf
->st_mtime
< (time_t) pred_ptr
->args
.info
.l_val
+ 60))
888 pred_mtime (pathname
, stat_buf
, pred_ptr
)
890 struct stat
*stat_buf
;
891 struct predicate
*pred_ptr
;
893 switch (pred_ptr
->args
.info
.kind
)
896 if (stat_buf
->st_mtime
> (time_t) pred_ptr
->args
.info
.l_val
)
900 if (stat_buf
->st_mtime
< (time_t) pred_ptr
->args
.info
.l_val
)
904 if ((stat_buf
->st_mtime
>= (time_t) pred_ptr
->args
.info
.l_val
)
905 && (stat_buf
->st_mtime
< (time_t) pred_ptr
->args
.info
.l_val
914 pred_name (pathname
, stat_buf
, pred_ptr
)
916 struct stat
*stat_buf
;
917 struct predicate
*pred_ptr
;
921 base
= basename (pathname
);
922 if (fnmatch (pred_ptr
->args
.str
, base
, FNM_PERIOD
) == 0)
928 pred_negate (pathname
, stat_buf
, pred_ptr
)
930 struct stat
*stat_buf
;
931 struct predicate
*pred_ptr
;
933 /* Check whether we need a stat here. */
934 if (pred_ptr
->need_stat
)
936 if (!have_stat
&& (*xstat
) (rel_pathname
, stat_buf
) != 0)
938 error (0, errno
, "%s", pathname
);
944 return (!(*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
945 pred_ptr
->pred_right
));
949 pred_newer (pathname
, stat_buf
, pred_ptr
)
951 struct stat
*stat_buf
;
952 struct predicate
*pred_ptr
;
954 if (stat_buf
->st_mtime
> pred_ptr
->args
.time
)
960 pred_nogroup (pathname
, stat_buf
, pred_ptr
)
962 struct stat
*stat_buf
;
963 struct predicate
*pred_ptr
;
966 extern char *gid_unused
;
968 return gid_unused
[(unsigned) stat_buf
->st_gid
];
970 return getgrgid (stat_buf
->st_gid
) == NULL
;
975 pred_nouser (pathname
, stat_buf
, pred_ptr
)
977 struct stat
*stat_buf
;
978 struct predicate
*pred_ptr
;
981 extern char *uid_unused
;
983 return uid_unused
[(unsigned) stat_buf
->st_uid
];
985 return getpwuid (stat_buf
->st_uid
) == NULL
;
990 pred_ok (pathname
, stat_buf
, pred_ptr
)
992 struct stat
*stat_buf
;
993 struct predicate
*pred_ptr
;
998 fprintf (stderr
, "< %s ... %s > ? ",
999 pred_ptr
->args
.exec_vec
.vec
[0], pathname
);
1002 yes
= (i
== 'y' || i
== 'Y');
1003 while (i
!= EOF
&& i
!= '\n')
1007 return pred_exec (pathname
, stat_buf
, pred_ptr
);
1011 pred_open (pathname
, stat_buf
, pred_ptr
)
1013 struct stat
*stat_buf
;
1014 struct predicate
*pred_ptr
;
1020 pred_or (pathname
, stat_buf
, pred_ptr
)
1022 struct stat
*stat_buf
;
1023 struct predicate
*pred_ptr
;
1025 if (pred_ptr
->pred_left
== NULL
1026 || !(*pred_ptr
->pred_left
->pred_func
) (pathname
, stat_buf
,
1027 pred_ptr
->pred_left
))
1029 /* Check whether we need a stat here. */
1030 if (pred_ptr
->need_stat
)
1032 if (!have_stat
&& (*xstat
) (rel_pathname
, stat_buf
) != 0)
1034 error (0, errno
, "%s", pathname
);
1040 return ((*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
1041 pred_ptr
->pred_right
));
1048 pred_path (pathname
, stat_buf
, pred_ptr
)
1050 struct stat
*stat_buf
;
1051 struct predicate
*pred_ptr
;
1053 if (fnmatch (pred_ptr
->args
.str
, pathname
, 0) == 0)
1059 pred_perm (pathname
, stat_buf
, pred_ptr
)
1061 struct stat
*stat_buf
;
1062 struct predicate
*pred_ptr
;
1064 if (pred_ptr
->args
.perm
& 010000)
1066 /* Magic flag set in parse_perm:
1067 true if at least the given bits are set. */
1068 if ((stat_buf
->st_mode
& 07777 & pred_ptr
->args
.perm
)
1069 == (pred_ptr
->args
.perm
& 07777))
1072 else if (pred_ptr
->args
.perm
& 020000)
1074 /* Magic flag set in parse_perm:
1075 true if any of the given bits are set. */
1076 if ((stat_buf
->st_mode
& 07777) & pred_ptr
->args
.perm
)
1081 /* True if exactly the given bits are set. */
1082 if ((stat_buf
->st_mode
& 07777) == pred_ptr
->args
.perm
)
1089 pred_print (pathname
, stat_buf
, pred_ptr
)
1091 struct stat
*stat_buf
;
1092 struct predicate
*pred_ptr
;
1099 pred_print0 (pathname
, stat_buf
, pred_ptr
)
1101 struct stat
*stat_buf
;
1102 struct predicate
*pred_ptr
;
1104 fputs (pathname
, stdout
);
1110 pred_prune (pathname
, stat_buf
, pred_ptr
)
1112 struct stat
*stat_buf
;
1113 struct predicate
*pred_ptr
;
1115 stop_at_current_level
= true;
1116 return (do_dir_first
); /* This is what SunOS find seems to do. */
1120 pred_regex (pathname
, stat_buf
, pred_ptr
)
1122 struct stat
*stat_buf
;
1123 struct predicate
*pred_ptr
;
1125 int len
= strlen (pathname
);
1126 if (re_match (pred_ptr
->args
.regex
, pathname
, len
, 0,
1127 (struct re_registers
*) NULL
) == len
)
1133 pred_size (pathname
, stat_buf
, pred_ptr
)
1135 struct stat
*stat_buf
;
1136 struct predicate
*pred_ptr
;
1138 unsigned long f_val
;
1140 f_val
= (stat_buf
->st_size
+ pred_ptr
->args
.size
.blocksize
- 1)
1141 / pred_ptr
->args
.size
.blocksize
;
1142 switch (pred_ptr
->args
.size
.kind
)
1145 if (f_val
> pred_ptr
->args
.size
.size
)
1149 if (f_val
< pred_ptr
->args
.size
.size
)
1153 if (f_val
== pred_ptr
->args
.size
.size
)
1161 pred_true (pathname
, stat_buf
, pred_ptr
)
1163 struct stat
*stat_buf
;
1164 struct predicate
*pred_ptr
;
1170 pred_type (pathname
, stat_buf
, pred_ptr
)
1172 struct stat
*stat_buf
;
1173 struct predicate
*pred_ptr
;
1175 unsigned long mode
= stat_buf
->st_mode
;
1176 unsigned long type
= pred_ptr
->args
.type
;
1179 /* POSIX system; check `mode' the slow way. */
1180 if ((S_ISBLK (mode
) && type
== S_IFBLK
)
1181 || (S_ISCHR (mode
) && type
== S_IFCHR
)
1182 || (S_ISDIR (mode
) && type
== S_IFDIR
)
1183 || (S_ISREG (mode
) && type
== S_IFREG
)
1185 || (S_ISLNK (mode
) && type
== S_IFLNK
)
1188 || (S_ISFIFO (mode
) && type
== S_IFIFO
)
1191 || (S_ISSOCK (mode
) && type
== S_IFSOCK
)
1195 /* Unix system; check `mode' the fast way. */
1196 if ((mode
& S_IFMT
) == type
)
1204 pred_uid (pathname
, stat_buf
, pred_ptr
)
1206 struct stat
*stat_buf
;
1207 struct predicate
*pred_ptr
;
1209 switch (pred_ptr
->args
.info
.kind
)
1212 if (stat_buf
->st_uid
> pred_ptr
->args
.info
.l_val
)
1216 if (stat_buf
->st_uid
< pred_ptr
->args
.info
.l_val
)
1220 if (stat_buf
->st_uid
== pred_ptr
->args
.info
.l_val
)
1228 pred_used (pathname
, stat_buf
, pred_ptr
)
1230 struct stat
*stat_buf
;
1231 struct predicate
*pred_ptr
;
1235 delta
= stat_buf
->st_atime
- stat_buf
->st_ctime
; /* Use difftime? */
1236 switch (pred_ptr
->args
.info
.kind
)
1239 if (delta
> (time_t) pred_ptr
->args
.info
.l_val
)
1243 if (delta
< (time_t) pred_ptr
->args
.info
.l_val
)
1247 if ((delta
>= (time_t) pred_ptr
->args
.info
.l_val
)
1248 && (delta
< (time_t) pred_ptr
->args
.info
.l_val
+ DAYSECS
))
1256 pred_user (pathname
, stat_buf
, pred_ptr
)
1258 struct stat
*stat_buf
;
1259 struct predicate
*pred_ptr
;
1261 if (pred_ptr
->args
.uid
== stat_buf
->st_uid
)
1268 pred_xtype (pathname
, stat_buf
, pred_ptr
)
1270 struct stat
*stat_buf
;
1271 struct predicate
*pred_ptr
;
1276 ystat
= xstat
== lstat
? stat
: lstat
;
1277 if ((*ystat
) (rel_pathname
, &sbuf
) != 0)
1279 if (ystat
== stat
&& errno
== ENOENT
)
1280 /* Mimic behavior of ls -lL. */
1281 return (pred_type (pathname
, stat_buf
, pred_ptr
));
1282 error (0, errno
, "%s", pathname
);
1286 return (pred_type (pathname
, &sbuf
, pred_ptr
));
1289 /* 1) fork to get a child; parent remembers the child pid
1290 2) child execs the command requested
1291 3) parent waits for child; checks for proper pid of child
1295 ret errno status(h) status(l)
1297 pid x signal# 0177 stopped
1298 pid x exit arg 0 term by _exit
1299 pid x 0 signal # term by signal
1300 -1 EINTR parent got signal
1301 -1 other some other kind of error
1303 Return true only if the pid matches, status(l) is
1304 zero, and the exit arg (status high) is 0.
1305 Otherwise return false, possibly printing an error message. */
1309 struct predicate
*pred_ptr
;
1312 pid_t wait_ret
, child_pid
;
1313 struct exec_val
*execp
; /* Pointer for efficiency. */
1314 static int first_time
= 1;
1316 execp
= &pred_ptr
->args
.exec_vec
;
1318 /* Make sure output of command doesn't get mixed with find output. */
1322 /* Make sure to listen for the kids. */
1326 signal (SIGCHLD
, SIG_DFL
);
1329 child_pid
= fork ();
1330 if (child_pid
== -1)
1331 error (1, errno
, "cannot fork");
1334 /* We be the child. */
1336 if (chdir (starting_dir
) < 0)
1338 error (0, errno
, "%s", starting_dir
);
1342 if (fchdir (starting_desc
) < 0)
1344 error (0, errno
, "cannot return to starting directory");
1348 execvp (execp
->vec
[0], execp
->vec
);
1349 error (0, errno
, "%s", execp
->vec
[0]);
1353 wait_ret
= wait (&status
);
1356 error (0, errno
, "error waiting for %s", execp
->vec
[0]);
1360 if (wait_ret
!= child_pid
)
1362 error (0, 0, "wait got pid %d, expected pid %d", wait_ret
, child_pid
);
1366 if (WIFSTOPPED (status
))
1368 error (0, 0, "%s stopped by signal %d",
1369 execp
->vec
[0], WSTOPSIG (status
));
1373 if (WIFSIGNALED (status
))
1375 error (0, 0, "%s terminated by signal %d",
1376 execp
->vec
[0], WTERMSIG (status
));
1380 return (!WEXITSTATUS (status
));
1383 /* Return a static string formatting the time WHEN according to the
1384 strftime format character KIND. */
1387 format_date (when
, kind
)
1392 static char buf
[64]; /* More than enough space. */
1396 sprintf (buf
, "%ld", when
);
1404 if (strftime (buf
, sizeof (buf
), fmt
, localtime (&when
)))
1411 /* Return a pointer to the string representation of
1412 the predicate function PRED_FUNC. */
1415 find_pred_name (pred_func
)
1420 for (i
= 0; pred_table
[i
].pred_func
!= 0; i
++)
1421 if (pred_table
[i
].pred_func
== pred_func
)
1423 return (pred_table
[i
].pred_name
);
1432 for (i
= 0; type_table
[i
].type
!= (short) -1; i
++)
1433 if (type_table
[i
].type
== type
)
1435 return (type_table
[i
].type_name
);
1444 for (i
= 0; prec_table
[i
].prec
!= (short) -1; i
++)
1445 if (prec_table
[i
].prec
== prec
)
1447 return (prec_table
[i
].prec_name
);
1450 /* Walk the expression tree NODE to stdout.
1451 INDENT is the number of levels to indent the left margin. */
1454 print_tree (node
, indent
)
1455 struct predicate
*node
;
1462 for (i
= 0; i
< indent
; i
++)
1464 printf ("pred = %s type = %s prec = %s addr = %x\n",
1465 find_pred_name (node
->pred_func
),
1466 type_name (node
->p_type
), prec_name (node
->p_prec
), node
);
1467 for (i
= 0; i
< indent
; i
++)
1470 print_tree (node
->pred_left
, indent
+ 1);
1471 for (i
= 0; i
< indent
; i
++)
1473 printf ("right:\n");
1474 print_tree (node
->pred_right
, indent
+ 1);
1477 /* Copy STR into BUF and trim blanks from the end of BUF.
1481 blank_rtrim (str
, buf
)
1490 i
= strlen (buf
) - 1;
1491 while ((i
>= 0) && ((buf
[i
] == ' ') || buf
[i
] == '\t'))
1497 /* Print out the predicate list starting at NODE. */
1501 struct predicate
*node
;
1503 struct predicate
*cur
;
1509 printf ("%s ", blank_rtrim (find_pred_name (cur
->pred_func
), name
));
1510 cur
= cur
->pred_next
;