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. */
19 #include <sys/types.h>
30 #if !defined(SIGCHLD) && defined(SIGCLD)
31 #define SIGCHLD SIGCLD
34 #ifndef _POSIX_VERSION
35 struct passwd
*getpwuid ();
36 struct group
*getgrgid ();
41 # define NAMLEN(dirent) strlen((dirent)->d_name)
43 # define dirent direct
44 # define NAMLEN(dirent) (dirent)->d_namlen
46 # include <sys/ndir.h>
57 /* Fake a return value. */
58 #define CLOSEDIR(d) (closedir (d), 0)
60 #define CLOSEDIR(d) closedir (d)
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. */
73 # define ST_NBLOCKS(statp) (((statp)->st_size + 512 - 1) / 512)
75 # ifndef HAVE_ST_BLOCKS
76 # define ST_NBLOCKS(statp) (st_blocks ((statp)->st_size))
78 # if defined(hpux) || defined(__hpux__)
79 # define ST_NBLOCKS(statp) ((statp)->st_blocks * 2)
81 # define ST_NBLOCKS(statp) ((statp)->st_blocks)
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
));
100 struct pred_assoc pred_table
[] =
102 {pred_amin
, "amin "},
104 {pred_anewer
, "anewer "},
105 {pred_atime
, "atime "},
107 {pred_amin
, "cmin "},
108 {pred_cnewer
, "cnewer "},
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 "},
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 "},
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 "},
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 "},
147 {pred_used
, "used "},
148 {pred_user
, "user "},
149 {pred_xtype
, "xtype "},
159 struct op_assoc type_table
[] =
162 {PRIMARY_TYPE
, "primary "},
165 {OPEN_PAREN
, "open_paren "},
166 {CLOSE_PAREN
, "close_paren "},
176 struct prec_assoc prec_table
[] =
179 {COMMA_PREC
, "comma "},
182 {NEGATE_PREC
, "negate "},
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. */
197 pred_amin (pathname
, stat_buf
, pred_ptr
)
199 struct stat
*stat_buf
;
200 struct predicate
*pred_ptr
;
202 switch (pred_ptr
->args
.info
.kind
)
205 if (stat_buf
->st_atime
> (time_t) pred_ptr
->args
.info
.l_val
)
209 if (stat_buf
->st_atime
< (time_t) pred_ptr
->args
.info
.l_val
)
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))
222 pred_and (pathname
, stat_buf
, pred_ptr
)
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
);
242 return ((*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
243 pred_ptr
->pred_right
));
250 pred_anewer (pathname
, stat_buf
, pred_ptr
)
252 struct stat
*stat_buf
;
253 struct predicate
*pred_ptr
;
255 if (stat_buf
->st_atime
> pred_ptr
->args
.time
)
261 pred_atime (pathname
, stat_buf
, pred_ptr
)
263 struct stat
*stat_buf
;
264 struct predicate
*pred_ptr
;
266 switch (pred_ptr
->args
.info
.kind
)
269 if (stat_buf
->st_atime
> (time_t) pred_ptr
->args
.info
.l_val
)
273 if (stat_buf
->st_atime
< (time_t) pred_ptr
->args
.info
.l_val
)
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
287 pred_close (pathname
, stat_buf
, pred_ptr
)
289 struct stat
*stat_buf
;
290 struct predicate
*pred_ptr
;
296 pred_cmin (pathname
, stat_buf
, pred_ptr
)
298 struct stat
*stat_buf
;
299 struct predicate
*pred_ptr
;
301 switch (pred_ptr
->args
.info
.kind
)
304 if (stat_buf
->st_ctime
> (time_t) pred_ptr
->args
.info
.l_val
)
308 if (stat_buf
->st_ctime
< (time_t) pred_ptr
->args
.info
.l_val
)
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))
321 pred_cnewer (pathname
, stat_buf
, pred_ptr
)
323 struct stat
*stat_buf
;
324 struct predicate
*pred_ptr
;
326 if (stat_buf
->st_ctime
> pred_ptr
->args
.time
)
332 pred_comma (pathname
, stat_buf
, pred_ptr
)
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
);
351 return ((*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
352 pred_ptr
->pred_right
));
356 pred_ctime (pathname
, stat_buf
, pred_ptr
)
358 struct stat
*stat_buf
;
359 struct predicate
*pred_ptr
;
361 switch (pred_ptr
->args
.info
.kind
)
364 if (stat_buf
->st_ctime
> (time_t) pred_ptr
->args
.info
.l_val
)
368 if (stat_buf
->st_ctime
< (time_t) pred_ptr
->args
.info
.l_val
)
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
382 pred_empty (pathname
, stat_buf
, pred_ptr
)
384 struct stat
*stat_buf
;
385 struct predicate
*pred_ptr
;
387 if (S_ISDIR (stat_buf
->st_mode
))
391 boolean empty
= true;
394 d
= opendir (rel_pathname
);
397 error (0, errno
, "%s", pathname
);
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')))
413 error (0, errno
, "%s", pathname
);
419 else if (S_ISREG (stat_buf
->st_mode
))
420 return (stat_buf
->st_size
== 0);
426 pred_exec (pathname
, stat_buf
, pred_ptr
)
428 struct stat
*stat_buf
;
429 struct predicate
*pred_ptr
;
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
;
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
);
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
]);
467 pred_false (pathname
, stat_buf
, pred_ptr
)
469 struct stat
*stat_buf
;
470 struct predicate
*pred_ptr
;
476 pred_fls (pathname
, stat_buf
, pred_ptr
)
478 struct stat
*stat_buf
;
479 struct predicate
*pred_ptr
;
481 list_file (pathname
, rel_pathname
, stat_buf
, pred_ptr
->args
.stream
);
486 pred_fprint (pathname
, stat_buf
, pred_ptr
)
488 struct stat
*stat_buf
;
489 struct predicate
*pred_ptr
;
491 fputs (pathname
, pred_ptr
->args
.stream
);
492 putc ('\n', pred_ptr
->args
.stream
);
497 pred_fprint0 (pathname
, stat_buf
, pred_ptr
)
499 struct stat
*stat_buf
;
500 struct predicate
*pred_ptr
;
502 fputs (pathname
, pred_ptr
->args
.stream
);
503 putc (0, pred_ptr
->args
.stream
);
508 pred_fprintf (pathname
, stat_buf
, pred_ptr
)
510 struct stat
*stat_buf
;
511 struct predicate
*pred_ptr
;
513 FILE *fp
= pred_ptr
->args
.printf_vec
.stream
;
514 struct segment
*segment
;
517 for (segment
= pred_ptr
->args
.printf_vec
.segment
; segment
;
518 segment
= segment
->next
)
520 if (segment
->kind
& 0xff00) /* Component of date. */
524 switch (segment
->kind
& 0xff)
527 t
= stat_buf
->st_atime
;
530 t
= stat_buf
->st_ctime
;
533 t
= stat_buf
->st_mtime
;
538 fprintf (fp
, segment
->text
,
539 format_date (t
, (segment
->kind
>> 8) & 0xff));
543 switch (segment
->kind
)
545 case KIND_PLAIN
: /* Plain text string (no % conversion). */
546 fwrite (segment
->text
, 1, segment
->text_len
, fp
);
548 case KIND_STOP
: /* Terminate argument and flush output. */
549 fwrite (segment
->text
, 1, segment
->text_len
, fp
);
552 case 'a': /* atime in `ctime' format. */
553 cp
= ctime (&stat_buf
->st_atime
);
555 fprintf (fp
, segment
->text
, cp
);
557 case 'b': /* size in 512-byte blocks */
558 fprintf (fp
, segment
->text
, ST_NBLOCKS (stat_buf
));
560 case 'c': /* ctime in `ctime' format */
561 cp
= ctime (&stat_buf
->st_ctime
);
563 fprintf (fp
, segment
->text
, cp
);
565 case 'd': /* depth in search tree */
566 fprintf (fp
, segment
->text
, curdepth
);
568 case 'f': /* basename of path */
569 cp
= strrchr (pathname
, '/');
574 fprintf (fp
, segment
->text
, cp
);
576 case 'F': /* filesystem type */
577 fprintf (fp
, segment
->text
,
578 filesystem_type (pathname
, rel_pathname
, stat_buf
));
580 case 'g': /* group name */
584 g
= getgrgid (stat_buf
->st_gid
);
587 segment
->text
[segment
->text_len
] = 's';
588 fprintf (fp
, segment
->text
, g
->gr_name
);
593 case 'G': /* GID number */
594 segment
->text
[segment
->text_len
] = 'u';
595 fprintf (fp
, segment
->text
, stat_buf
->st_gid
);
597 case 'h': /* leading directories part of path */
601 cp
= strrchr (pathname
, '/');
602 if (cp
== NULL
) /* No leading directories. */
606 fprintf (fp
, segment
->text
, pathname
);
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
;
619 case 'i': /* inode number */
620 fprintf (fp
, segment
->text
, stat_buf
->st_ino
);
622 case 'k': /* size in 1K blocks */
623 fprintf (fp
, segment
->text
, (ST_NBLOCKS (stat_buf
) + 1) / 2);
625 case 'l': /* object of symlink */
630 if (S_ISLNK (stat_buf
->st_mode
))
632 linkname
= get_link_name (pathname
, rel_pathname
);
638 fprintf (fp
, segment
->text
, linkname
);
642 fprintf (fp
, segment
->text
, "");
646 case 'm': /* mode as octal number (perms only) */
647 fprintf (fp
, segment
->text
, stat_buf
->st_mode
& 07777);
649 case 'n': /* number of links */
650 fprintf (fp
, segment
->text
, stat_buf
->st_nlink
);
652 case 'p': /* pathname */
653 fprintf (fp
, segment
->text
, pathname
);
655 case 'P': /* pathname with ARGV element stripped */
658 cp
= pathname
+ path_length
;
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. */
668 fprintf (fp
, segment
->text
, cp
);
670 case 's': /* size in bytes */
671 fprintf (fp
, segment
->text
, stat_buf
->st_size
);
673 case 't': /* mtime in `ctime' format */
674 cp
= ctime (&stat_buf
->st_mtime
);
676 fprintf (fp
, segment
->text
, cp
);
678 case 'u': /* user name */
682 p
= getpwuid (stat_buf
->st_uid
);
685 segment
->text
[segment
->text_len
] = 's';
686 fprintf (fp
, segment
->text
, p
->pw_name
);
691 case 'U': /* UID number */
692 segment
->text
[segment
->text_len
] = 'u';
693 fprintf (fp
, segment
->text
, stat_buf
->st_uid
);
701 pred_fstype (pathname
, stat_buf
, pred_ptr
)
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)
713 pred_gid (pathname
, stat_buf
, pred_ptr
)
715 struct stat
*stat_buf
;
716 struct predicate
*pred_ptr
;
718 switch (pred_ptr
->args
.info
.kind
)
721 if (stat_buf
->st_gid
> pred_ptr
->args
.info
.l_val
)
725 if (stat_buf
->st_gid
< pred_ptr
->args
.info
.l_val
)
729 if (stat_buf
->st_gid
== pred_ptr
->args
.info
.l_val
)
737 pred_group (pathname
, stat_buf
, pred_ptr
)
739 struct stat
*stat_buf
;
740 struct predicate
*pred_ptr
;
742 if (pred_ptr
->args
.gid
== stat_buf
->st_gid
)
749 pred_ilname (pathname
, stat_buf
, pred_ptr
)
751 struct stat
*stat_buf
;
752 struct predicate
*pred_ptr
;
754 return insert_lname (pathname
, stat_buf
, pred_ptr
, true);
758 pred_iname (pathname
, stat_buf
, pred_ptr
)
760 struct stat
*stat_buf
;
761 struct predicate
*pred_ptr
;
765 base
= basename (pathname
);
766 if (fnmatch (pred_ptr
->args
.str
, base
, FNM_PERIOD
| FNM_CASEFOLD
) == 0)
772 pred_inum (pathname
, stat_buf
, pred_ptr
)
774 struct stat
*stat_buf
;
775 struct predicate
*pred_ptr
;
777 switch (pred_ptr
->args
.info
.kind
)
780 if (stat_buf
->st_ino
> pred_ptr
->args
.info
.l_val
)
784 if (stat_buf
->st_ino
< pred_ptr
->args
.info
.l_val
)
788 if (stat_buf
->st_ino
== pred_ptr
->args
.info
.l_val
)
796 pred_ipath (pathname
, stat_buf
, pred_ptr
)
798 struct stat
*stat_buf
;
799 struct predicate
*pred_ptr
;
801 if (fnmatch (pred_ptr
->args
.str
, pathname
, FNM_CASEFOLD
) == 0)
807 pred_links (pathname
, stat_buf
, pred_ptr
)
809 struct stat
*stat_buf
;
810 struct predicate
*pred_ptr
;
812 switch (pred_ptr
->args
.info
.kind
)
815 if (stat_buf
->st_nlink
> pred_ptr
->args
.info
.l_val
)
819 if (stat_buf
->st_nlink
< pred_ptr
->args
.info
.l_val
)
823 if (stat_buf
->st_nlink
== pred_ptr
->args
.info
.l_val
)
831 pred_lname (pathname
, stat_buf
, pred_ptr
)
833 struct stat
*stat_buf
;
834 struct predicate
*pred_ptr
;
836 return insert_lname (pathname
, stat_buf
, pred_ptr
, false);
840 insert_lname (pathname
, stat_buf
, pred_ptr
, ignore_case
)
842 struct stat
*stat_buf
;
843 struct predicate
*pred_ptr
;
848 if (S_ISLNK (stat_buf
->st_mode
))
850 char *linkname
= get_link_name (pathname
, rel_pathname
);
853 if (fnmatch (pred_ptr
->args
.str
, linkname
,
854 ignore_case
? FNM_CASEFOLD
: 0) == 0)
864 pred_ls (pathname
, stat_buf
, pred_ptr
)
866 struct stat
*stat_buf
;
867 struct predicate
*pred_ptr
;
869 list_file (pathname
, rel_pathname
, stat_buf
, stdout
);
874 pred_mmin (pathname
, stat_buf
, pred_ptr
)
876 struct stat
*stat_buf
;
877 struct predicate
*pred_ptr
;
879 switch (pred_ptr
->args
.info
.kind
)
882 if (stat_buf
->st_mtime
> (time_t) pred_ptr
->args
.info
.l_val
)
886 if (stat_buf
->st_mtime
< (time_t) pred_ptr
->args
.info
.l_val
)
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))
899 pred_mtime (pathname
, stat_buf
, pred_ptr
)
901 struct stat
*stat_buf
;
902 struct predicate
*pred_ptr
;
904 switch (pred_ptr
->args
.info
.kind
)
907 if (stat_buf
->st_mtime
> (time_t) pred_ptr
->args
.info
.l_val
)
911 if (stat_buf
->st_mtime
< (time_t) pred_ptr
->args
.info
.l_val
)
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
925 pred_name (pathname
, stat_buf
, pred_ptr
)
927 struct stat
*stat_buf
;
928 struct predicate
*pred_ptr
;
932 base
= basename (pathname
);
933 if (fnmatch (pred_ptr
->args
.str
, base
, FNM_PERIOD
) == 0)
939 pred_negate (pathname
, stat_buf
, pred_ptr
)
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
);
955 return (!(*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
956 pred_ptr
->pred_right
));
960 pred_newer (pathname
, stat_buf
, pred_ptr
)
962 struct stat
*stat_buf
;
963 struct predicate
*pred_ptr
;
965 if (stat_buf
->st_mtime
> pred_ptr
->args
.time
)
971 pred_nogroup (pathname
, stat_buf
, pred_ptr
)
973 struct stat
*stat_buf
;
974 struct predicate
*pred_ptr
;
977 extern char *gid_unused
;
979 return gid_unused
[(unsigned) stat_buf
->st_gid
];
981 return getgrgid (stat_buf
->st_gid
) == NULL
;
986 pred_nouser (pathname
, stat_buf
, pred_ptr
)
988 struct stat
*stat_buf
;
989 struct predicate
*pred_ptr
;
992 extern char *uid_unused
;
994 return uid_unused
[(unsigned) stat_buf
->st_uid
];
996 return getpwuid (stat_buf
->st_uid
) == NULL
;
1001 pred_ok (pathname
, stat_buf
, pred_ptr
)
1003 struct stat
*stat_buf
;
1004 struct predicate
*pred_ptr
;
1009 fprintf (stderr
, "< %s ... %s > ? ",
1010 pred_ptr
->args
.exec_vec
.vec
[0], pathname
);
1013 yes
= (i
== 'y' || i
== 'Y');
1014 while (i
!= EOF
&& i
!= '\n')
1018 return pred_exec (pathname
, stat_buf
, pred_ptr
);
1022 pred_open (pathname
, stat_buf
, pred_ptr
)
1024 struct stat
*stat_buf
;
1025 struct predicate
*pred_ptr
;
1031 pred_or (pathname
, stat_buf
, pred_ptr
)
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
);
1051 return ((*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
1052 pred_ptr
->pred_right
));
1059 pred_path (pathname
, stat_buf
, pred_ptr
)
1061 struct stat
*stat_buf
;
1062 struct predicate
*pred_ptr
;
1064 if (fnmatch (pred_ptr
->args
.str
, pathname
, 0) == 0)
1070 pred_perm (pathname
, stat_buf
, pred_ptr
)
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))
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
)
1092 /* True if exactly the given bits are set. */
1093 if ((stat_buf
->st_mode
& 07777) == pred_ptr
->args
.perm
)
1100 pred_print (pathname
, stat_buf
, pred_ptr
)
1102 struct stat
*stat_buf
;
1103 struct predicate
*pred_ptr
;
1110 pred_print0 (pathname
, stat_buf
, pred_ptr
)
1112 struct stat
*stat_buf
;
1113 struct predicate
*pred_ptr
;
1115 fputs (pathname
, stdout
);
1121 pred_prune (pathname
, stat_buf
, pred_ptr
)
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. */
1131 pred_regex (pathname
, stat_buf
, pred_ptr
)
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
)
1144 pred_size (pathname
, stat_buf
, pred_ptr
)
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
)
1156 if (f_val
> pred_ptr
->args
.size
.size
)
1160 if (f_val
< pred_ptr
->args
.size
.size
)
1164 if (f_val
== pred_ptr
->args
.size
.size
)
1172 pred_true (pathname
, stat_buf
, pred_ptr
)
1174 struct stat
*stat_buf
;
1175 struct predicate
*pred_ptr
;
1181 pred_type (pathname
, stat_buf
, pred_ptr
)
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
;
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
)
1196 || (S_ISLNK (mode
) && type
== S_IFLNK
)
1199 || (S_ISFIFO (mode
) && type
== S_IFIFO
)
1202 || (S_ISSOCK (mode
) && type
== S_IFSOCK
)
1206 /* Unix system; check `mode' the fast way. */
1207 if ((mode
& S_IFMT
) == type
)
1215 pred_uid (pathname
, stat_buf
, pred_ptr
)
1217 struct stat
*stat_buf
;
1218 struct predicate
*pred_ptr
;
1220 switch (pred_ptr
->args
.info
.kind
)
1223 if (stat_buf
->st_uid
> pred_ptr
->args
.info
.l_val
)
1227 if (stat_buf
->st_uid
< pred_ptr
->args
.info
.l_val
)
1231 if (stat_buf
->st_uid
== pred_ptr
->args
.info
.l_val
)
1239 pred_used (pathname
, stat_buf
, pred_ptr
)
1241 struct stat
*stat_buf
;
1242 struct predicate
*pred_ptr
;
1246 delta
= stat_buf
->st_atime
- stat_buf
->st_ctime
; /* Use difftime? */
1247 switch (pred_ptr
->args
.info
.kind
)
1250 if (delta
> (time_t) pred_ptr
->args
.info
.l_val
)
1254 if (delta
< (time_t) pred_ptr
->args
.info
.l_val
)
1258 if ((delta
>= (time_t) pred_ptr
->args
.info
.l_val
)
1259 && (delta
< (time_t) pred_ptr
->args
.info
.l_val
+ DAYSECS
))
1267 pred_user (pathname
, stat_buf
, pred_ptr
)
1269 struct stat
*stat_buf
;
1270 struct predicate
*pred_ptr
;
1272 if (pred_ptr
->args
.uid
== stat_buf
->st_uid
)
1279 pred_xtype (pathname
, stat_buf
, pred_ptr
)
1281 struct stat
*stat_buf
;
1282 struct predicate
*pred_ptr
;
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
);
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
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. */
1320 struct predicate
*pred_ptr
;
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. */
1333 /* Make sure to listen for the kids. */
1337 signal (SIGCHLD
, SIG_DFL
);
1340 child_pid
= fork ();
1341 if (child_pid
== -1)
1342 error (1, errno
, "cannot fork");
1345 /* We be the child. */
1347 if (chdir (starting_dir
) < 0)
1349 error (0, errno
, "%s", starting_dir
);
1353 if (fchdir (starting_desc
) < 0)
1355 error (0, errno
, "cannot return to starting directory");
1359 execvp (execp
->vec
[0], execp
->vec
);
1360 error (0, errno
, "%s", execp
->vec
[0]);
1364 wait_ret
= wait (&status
);
1367 error (0, errno
, "error waiting for %s", execp
->vec
[0]);
1371 if (wait_ret
!= child_pid
)
1373 error (0, 0, "wait got pid %d, expected pid %d", wait_ret
, child_pid
);
1377 if (WIFSTOPPED (status
))
1379 error (0, 0, "%s stopped by signal %d",
1380 execp
->vec
[0], WSTOPSIG (status
));
1384 if (WIFSIGNALED (status
))
1386 error (0, 0, "%s terminated by signal %d",
1387 execp
->vec
[0], WTERMSIG (status
));
1391 return (!WEXITSTATUS (status
));
1394 /* Return a static string formatting the time WHEN according to the
1395 strftime format character KIND. */
1398 format_date (when
, kind
)
1403 static char buf
[64]; /* More than enough space. */
1407 sprintf (buf
, "%ld", when
);
1415 if (strftime (buf
, sizeof (buf
), fmt
, localtime (&when
)))
1422 /* Return a pointer to the string representation of
1423 the predicate function PRED_FUNC. */
1426 find_pred_name (pred_func
)
1431 for (i
= 0; pred_table
[i
].pred_func
!= 0; i
++)
1432 if (pred_table
[i
].pred_func
== pred_func
)
1434 return (pred_table
[i
].pred_name
);
1443 for (i
= 0; type_table
[i
].type
!= (short) -1; i
++)
1444 if (type_table
[i
].type
== type
)
1446 return (type_table
[i
].type_name
);
1455 for (i
= 0; prec_table
[i
].prec
!= (short) -1; i
++)
1456 if (prec_table
[i
].prec
== prec
)
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. */
1465 print_tree (node
, indent
)
1466 struct predicate
*node
;
1473 for (i
= 0; i
< indent
; i
++)
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
++)
1481 print_tree (node
->pred_left
, indent
+ 1);
1482 for (i
= 0; i
< indent
; i
++)
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.
1492 blank_rtrim (str
, buf
)
1501 i
= strlen (buf
) - 1;
1502 while ((i
>= 0) && ((buf
[i
] == ' ') || buf
[i
] == '\t'))
1508 /* Print out the predicate list starting at NODE. */
1512 struct predicate
*node
;
1514 struct predicate
*cur
;
1520 printf ("%s ", blank_rtrim (find_pred_name (cur
->pred_func
), name
));
1521 cur
= cur
->pred_next
;