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
PARAMS((char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
, boolean ignore_case
));
91 static boolean launch
PARAMS((struct predicate
*pred_ptr
));
92 static char *format_date
PARAMS((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 (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
200 switch (pred_ptr
->args
.info
.kind
)
203 if (stat_buf
->st_atime
> (time_t) pred_ptr
->args
.info
.l_val
)
207 if (stat_buf
->st_atime
< (time_t) pred_ptr
->args
.info
.l_val
)
211 if ((stat_buf
->st_atime
>= (time_t) pred_ptr
->args
.info
.l_val
)
212 && (stat_buf
->st_atime
< (time_t) pred_ptr
->args
.info
.l_val
+ 60))
220 pred_and (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
222 if (pred_ptr
->pred_left
== NULL
223 || (*pred_ptr
->pred_left
->pred_func
) (pathname
, stat_buf
,
224 pred_ptr
->pred_left
))
226 /* Check whether we need a stat here. */
227 if (pred_ptr
->need_stat
)
229 if (!have_stat
&& (*xstat
) (rel_pathname
, stat_buf
) != 0)
231 error (0, errno
, "%s", pathname
);
237 return ((*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
238 pred_ptr
->pred_right
));
245 pred_anewer (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
247 if (stat_buf
->st_atime
> pred_ptr
->args
.time
)
253 pred_atime (char *pathname
, struct stat
*stat_buf
, 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 (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
282 pred_cmin (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
284 switch (pred_ptr
->args
.info
.kind
)
287 if (stat_buf
->st_ctime
> (time_t) pred_ptr
->args
.info
.l_val
)
291 if (stat_buf
->st_ctime
< (time_t) pred_ptr
->args
.info
.l_val
)
295 if ((stat_buf
->st_ctime
>= (time_t) pred_ptr
->args
.info
.l_val
)
296 && (stat_buf
->st_ctime
< (time_t) pred_ptr
->args
.info
.l_val
+ 60))
304 pred_cnewer (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
306 if (stat_buf
->st_ctime
> pred_ptr
->args
.time
)
312 pred_comma (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
314 if (pred_ptr
->pred_left
!= NULL
)
315 (*pred_ptr
->pred_left
->pred_func
) (pathname
, stat_buf
,
316 pred_ptr
->pred_left
);
317 /* Check whether we need a stat here. */
318 if (pred_ptr
->need_stat
)
320 if (!have_stat
&& (*xstat
) (rel_pathname
, stat_buf
) != 0)
322 error (0, errno
, "%s", pathname
);
328 return ((*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
329 pred_ptr
->pred_right
));
333 pred_ctime (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
335 switch (pred_ptr
->args
.info
.kind
)
338 if (stat_buf
->st_ctime
> (time_t) pred_ptr
->args
.info
.l_val
)
342 if (stat_buf
->st_ctime
< (time_t) pred_ptr
->args
.info
.l_val
)
346 if ((stat_buf
->st_ctime
>= (time_t) pred_ptr
->args
.info
.l_val
)
347 && (stat_buf
->st_ctime
< (time_t) pred_ptr
->args
.info
.l_val
356 pred_empty (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
358 if (S_ISDIR (stat_buf
->st_mode
))
362 boolean empty
= true;
365 d
= opendir (rel_pathname
);
368 error (0, errno
, "%s", pathname
);
372 for (dp
= readdir (d
); dp
; dp
= readdir (d
))
374 if (dp
->d_name
[0] != '.'
375 || (dp
->d_name
[1] != '\0'
376 && (dp
->d_name
[1] != '.' || dp
->d_name
[2] != '\0')))
384 error (0, errno
, "%s", pathname
);
390 else if (S_ISREG (stat_buf
->st_mode
))
391 return (stat_buf
->st_size
== 0);
397 pred_exec (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
401 struct exec_val
*execp
; /* Pointer for efficiency. */
403 execp
= &pred_ptr
->args
.exec_vec
;
405 /* Replace "{}" with the real path in each affected arg. */
406 for (path_pos
= 0; execp
->paths
[path_pos
].offset
>= 0; path_pos
++)
408 register char *from
, *to
;
410 i
= execp
->paths
[path_pos
].offset
;
412 xmalloc (strlen (execp
->paths
[path_pos
].origarg
) + 1
413 + (strlen (pathname
) - 2) * execp
->paths
[path_pos
].count
);
414 for (from
= execp
->paths
[path_pos
].origarg
, to
= execp
->vec
[i
]; *from
; )
415 if (from
[0] == '{' && from
[1] == '}')
417 to
= stpcpy (to
, pathname
);
422 *to
= *from
; /* Copy null. */
425 i
= launch (pred_ptr
);
427 /* Free the temporary args. */
428 for (path_pos
= 0; execp
->paths
[path_pos
].offset
>= 0; path_pos
++)
429 free (execp
->vec
[execp
->paths
[path_pos
].offset
]);
435 pred_false (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
441 pred_fls (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
443 list_file (pathname
, rel_pathname
, stat_buf
, pred_ptr
->args
.stream
);
448 pred_fprint (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
450 fputs (pathname
, pred_ptr
->args
.stream
);
451 putc ('\n', pred_ptr
->args
.stream
);
456 pred_fprint0 (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
458 fputs (pathname
, pred_ptr
->args
.stream
);
459 putc (0, pred_ptr
->args
.stream
);
464 pred_fprintf (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
466 FILE *fp
= pred_ptr
->args
.printf_vec
.stream
;
467 struct segment
*segment
;
470 for (segment
= pred_ptr
->args
.printf_vec
.segment
; segment
;
471 segment
= segment
->next
)
473 if (segment
->kind
& 0xff00) /* Component of date. */
477 switch (segment
->kind
& 0xff)
480 t
= stat_buf
->st_atime
;
483 t
= stat_buf
->st_ctime
;
486 t
= stat_buf
->st_mtime
;
491 fprintf (fp
, segment
->text
,
492 format_date (t
, (segment
->kind
>> 8) & 0xff));
496 switch (segment
->kind
)
498 case KIND_PLAIN
: /* Plain text string (no % conversion). */
499 fwrite (segment
->text
, 1, segment
->text_len
, fp
);
501 case KIND_STOP
: /* Terminate argument and flush output. */
502 fwrite (segment
->text
, 1, segment
->text_len
, fp
);
505 case 'a': /* atime in `ctime' format. */
506 cp
= ctime (&stat_buf
->st_atime
);
508 fprintf (fp
, segment
->text
, cp
);
510 case 'b': /* size in 512-byte blocks */
511 fprintf (fp
, segment
->text
, ST_NBLOCKS (stat_buf
));
513 case 'c': /* ctime in `ctime' format */
514 cp
= ctime (&stat_buf
->st_ctime
);
516 fprintf (fp
, segment
->text
, cp
);
518 case 'd': /* depth in search tree */
519 fprintf (fp
, segment
->text
, curdepth
);
521 case 'f': /* basename of path */
522 cp
= strrchr (pathname
, '/');
527 fprintf (fp
, segment
->text
, cp
);
529 case 'F': /* filesystem type */
530 fprintf (fp
, segment
->text
,
531 filesystem_type (pathname
, rel_pathname
, stat_buf
));
533 case 'g': /* group name */
537 g
= getgrgid (stat_buf
->st_gid
);
540 segment
->text
[segment
->text_len
] = 's';
541 fprintf (fp
, segment
->text
, g
->gr_name
);
546 case 'G': /* GID number */
547 segment
->text
[segment
->text_len
] = 'u';
548 fprintf (fp
, segment
->text
, stat_buf
->st_gid
);
550 case 'h': /* leading directories part of path */
554 cp
= strrchr (pathname
, '/');
555 if (cp
== NULL
) /* No leading directories. */
559 fprintf (fp
, segment
->text
, pathname
);
563 case 'H': /* ARGV element file was found under */
565 char cc
= pathname
[path_length
];
567 pathname
[path_length
] = '\0';
568 fprintf (fp
, segment
->text
, pathname
);
569 pathname
[path_length
] = cc
;
572 case 'i': /* inode number */
573 fprintf (fp
, segment
->text
, stat_buf
->st_ino
);
575 case 'k': /* size in 1K blocks */
576 fprintf (fp
, segment
->text
, (ST_NBLOCKS (stat_buf
) + 1) / 2);
578 case 'l': /* object of symlink */
583 if (S_ISLNK (stat_buf
->st_mode
))
585 linkname
= get_link_name (pathname
, rel_pathname
);
591 fprintf (fp
, segment
->text
, linkname
);
595 fprintf (fp
, segment
->text
, "");
599 case 'm': /* mode as octal number (perms only) */
600 fprintf (fp
, segment
->text
, stat_buf
->st_mode
& 07777);
602 case 'n': /* number of links */
603 fprintf (fp
, segment
->text
, stat_buf
->st_nlink
);
605 case 'p': /* pathname */
606 fprintf (fp
, segment
->text
, pathname
);
608 case 'P': /* pathname with ARGV element stripped */
611 cp
= pathname
+ path_length
;
613 /* Move past the slash between the ARGV element
614 and the rest of the pathname. But if the ARGV element
615 ends in a slash, we didn't add another, so we've
616 already skipped past it. */
621 fprintf (fp
, segment
->text
, cp
);
623 case 's': /* size in bytes */
624 fprintf (fp
, segment
->text
, stat_buf
->st_size
);
626 case 't': /* mtime in `ctime' format */
627 cp
= ctime (&stat_buf
->st_mtime
);
629 fprintf (fp
, segment
->text
, cp
);
631 case 'u': /* user name */
635 p
= getpwuid (stat_buf
->st_uid
);
638 segment
->text
[segment
->text_len
] = 's';
639 fprintf (fp
, segment
->text
, p
->pw_name
);
644 case 'U': /* UID number */
645 segment
->text
[segment
->text_len
] = 'u';
646 fprintf (fp
, segment
->text
, stat_buf
->st_uid
);
654 pred_fstype (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
656 if (strcmp (filesystem_type (pathname
, rel_pathname
, stat_buf
),
657 pred_ptr
->args
.str
) == 0)
663 pred_gid (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
665 switch (pred_ptr
->args
.info
.kind
)
668 if (stat_buf
->st_gid
> pred_ptr
->args
.info
.l_val
)
672 if (stat_buf
->st_gid
< pred_ptr
->args
.info
.l_val
)
676 if (stat_buf
->st_gid
== pred_ptr
->args
.info
.l_val
)
684 pred_group (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
686 if (pred_ptr
->args
.gid
== stat_buf
->st_gid
)
693 pred_ilname (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
695 return insert_lname (pathname
, stat_buf
, pred_ptr
, true);
699 pred_iname (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
703 base
= base_name (pathname
);
704 if (fnmatch (pred_ptr
->args
.str
, base
, FNM_PERIOD
| FNM_CASEFOLD
) == 0)
710 pred_inum (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
712 switch (pred_ptr
->args
.info
.kind
)
715 if (stat_buf
->st_ino
> pred_ptr
->args
.info
.l_val
)
719 if (stat_buf
->st_ino
< pred_ptr
->args
.info
.l_val
)
723 if (stat_buf
->st_ino
== pred_ptr
->args
.info
.l_val
)
731 pred_ipath (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
733 if (fnmatch (pred_ptr
->args
.str
, pathname
, FNM_CASEFOLD
) == 0)
739 pred_links (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
741 switch (pred_ptr
->args
.info
.kind
)
744 if (stat_buf
->st_nlink
> pred_ptr
->args
.info
.l_val
)
748 if (stat_buf
->st_nlink
< pred_ptr
->args
.info
.l_val
)
752 if (stat_buf
->st_nlink
== pred_ptr
->args
.info
.l_val
)
760 pred_lname (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
762 return insert_lname (pathname
, stat_buf
, pred_ptr
, false);
766 insert_lname (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
, boolean ignore_case
)
770 if (S_ISLNK (stat_buf
->st_mode
))
772 char *linkname
= get_link_name (pathname
, rel_pathname
);
775 if (fnmatch (pred_ptr
->args
.str
, linkname
,
776 ignore_case
? FNM_CASEFOLD
: 0) == 0)
786 pred_ls (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
788 list_file (pathname
, rel_pathname
, stat_buf
, stdout
);
793 pred_mmin (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
795 switch (pred_ptr
->args
.info
.kind
)
798 if (stat_buf
->st_mtime
> (time_t) pred_ptr
->args
.info
.l_val
)
802 if (stat_buf
->st_mtime
< (time_t) pred_ptr
->args
.info
.l_val
)
806 if ((stat_buf
->st_mtime
>= (time_t) pred_ptr
->args
.info
.l_val
)
807 && (stat_buf
->st_mtime
< (time_t) pred_ptr
->args
.info
.l_val
+ 60))
815 pred_mtime (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
817 switch (pred_ptr
->args
.info
.kind
)
820 if (stat_buf
->st_mtime
> (time_t) pred_ptr
->args
.info
.l_val
)
824 if (stat_buf
->st_mtime
< (time_t) pred_ptr
->args
.info
.l_val
)
828 if ((stat_buf
->st_mtime
>= (time_t) pred_ptr
->args
.info
.l_val
)
829 && (stat_buf
->st_mtime
< (time_t) pred_ptr
->args
.info
.l_val
838 pred_name (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
842 base
= base_name (pathname
);
843 if (fnmatch (pred_ptr
->args
.str
, base
, FNM_PERIOD
) == 0)
849 pred_negate (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
851 /* Check whether we need a stat here. */
852 if (pred_ptr
->need_stat
)
854 if (!have_stat
&& (*xstat
) (rel_pathname
, stat_buf
) != 0)
856 error (0, errno
, "%s", pathname
);
862 return (!(*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
863 pred_ptr
->pred_right
));
867 pred_newer (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
869 if (stat_buf
->st_mtime
> pred_ptr
->args
.time
)
875 pred_nogroup (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
878 extern char *gid_unused
;
880 return gid_unused
[(unsigned) stat_buf
->st_gid
];
882 return getgrgid (stat_buf
->st_gid
) == NULL
;
887 pred_nouser (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
890 extern char *uid_unused
;
892 return uid_unused
[(unsigned) stat_buf
->st_uid
];
894 return getpwuid (stat_buf
->st_uid
) == NULL
;
899 pred_ok (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
904 /* The draft open standard requires that, in the POSIX locale,
905 the last non-blank character of this prompt be '?'.
906 The exact format is not specified.
907 This standard does not have requirements for locales other than POSIX
909 fprintf (stderr
, _("< %s ... %s > ? "),
910 pred_ptr
->args
.exec_vec
.vec
[0], pathname
);
913 yes
= (i
== 'y' || i
== 'Y');
914 while (i
!= EOF
&& i
!= '\n')
918 return pred_exec (pathname
, stat_buf
, pred_ptr
);
922 pred_open (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
928 pred_or (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
930 if (pred_ptr
->pred_left
== NULL
931 || !(*pred_ptr
->pred_left
->pred_func
) (pathname
, stat_buf
,
932 pred_ptr
->pred_left
))
934 /* Check whether we need a stat here. */
935 if (pred_ptr
->need_stat
)
937 if (!have_stat
&& (*xstat
) (rel_pathname
, stat_buf
) != 0)
939 error (0, errno
, "%s", pathname
);
945 return ((*pred_ptr
->pred_right
->pred_func
) (pathname
, stat_buf
,
946 pred_ptr
->pred_right
));
953 pred_path (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
955 if (fnmatch (pred_ptr
->args
.str
, pathname
, 0) == 0)
961 pred_perm (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
963 if (pred_ptr
->args
.perm
& 010000)
965 /* Magic flag set in parse_perm:
966 true if at least the given bits are set. */
967 if ((stat_buf
->st_mode
& 07777 & pred_ptr
->args
.perm
)
968 == (pred_ptr
->args
.perm
& 07777))
971 else if (pred_ptr
->args
.perm
& 020000)
973 /* Magic flag set in parse_perm:
974 true if any of the given bits are set. */
975 if ((stat_buf
->st_mode
& 07777) & pred_ptr
->args
.perm
)
980 /* True if exactly the given bits are set. */
981 if ((stat_buf
->st_mode
& 07777) == pred_ptr
->args
.perm
)
988 pred_print (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
995 pred_print0 (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
997 fputs (pathname
, stdout
);
1003 pred_prune (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1005 stop_at_current_level
= true;
1006 return (do_dir_first
); /* This is what SunOS find seems to do. */
1010 pred_regex (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1012 int len
= strlen (pathname
);
1013 if (re_match (pred_ptr
->args
.regex
, pathname
, len
, 0,
1014 (struct re_registers
*) NULL
) == len
)
1020 pred_size (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1022 unsigned long f_val
;
1024 f_val
= (stat_buf
->st_size
+ pred_ptr
->args
.size
.blocksize
- 1)
1025 / pred_ptr
->args
.size
.blocksize
;
1026 switch (pred_ptr
->args
.size
.kind
)
1029 if (f_val
> pred_ptr
->args
.size
.size
)
1033 if (f_val
< pred_ptr
->args
.size
.size
)
1037 if (f_val
== pred_ptr
->args
.size
.size
)
1045 pred_true (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1051 pred_type (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1053 unsigned long mode
= stat_buf
->st_mode
;
1054 unsigned long type
= pred_ptr
->args
.type
;
1057 /* POSIX system; check `mode' the slow way. */
1058 if ((S_ISBLK (mode
) && type
== S_IFBLK
)
1059 || (S_ISCHR (mode
) && type
== S_IFCHR
)
1060 || (S_ISDIR (mode
) && type
== S_IFDIR
)
1061 || (S_ISREG (mode
) && type
== S_IFREG
)
1063 || (S_ISLNK (mode
) && type
== S_IFLNK
)
1066 || (S_ISFIFO (mode
) && type
== S_IFIFO
)
1069 || (S_ISSOCK (mode
) && type
== S_IFSOCK
)
1073 /* Unix system; check `mode' the fast way. */
1074 if ((mode
& S_IFMT
) == type
)
1082 pred_uid (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1084 switch (pred_ptr
->args
.info
.kind
)
1087 if (stat_buf
->st_uid
> pred_ptr
->args
.info
.l_val
)
1091 if (stat_buf
->st_uid
< pred_ptr
->args
.info
.l_val
)
1095 if (stat_buf
->st_uid
== pred_ptr
->args
.info
.l_val
)
1103 pred_used (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1107 delta
= stat_buf
->st_atime
- stat_buf
->st_ctime
; /* Use difftime? */
1108 switch (pred_ptr
->args
.info
.kind
)
1111 if (delta
> (time_t) pred_ptr
->args
.info
.l_val
)
1115 if (delta
< (time_t) pred_ptr
->args
.info
.l_val
)
1119 if ((delta
>= (time_t) pred_ptr
->args
.info
.l_val
)
1120 && (delta
< (time_t) pred_ptr
->args
.info
.l_val
+ DAYSECS
))
1128 pred_user (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1130 if (pred_ptr
->args
.uid
== stat_buf
->st_uid
)
1137 pred_xtype (char *pathname
, struct stat
*stat_buf
, struct predicate
*pred_ptr
)
1142 ystat
= xstat
== lstat
? stat
: lstat
;
1143 if ((*ystat
) (rel_pathname
, &sbuf
) != 0)
1145 if (ystat
== stat
&& errno
== ENOENT
)
1146 /* Mimic behavior of ls -lL. */
1147 return (pred_type (pathname
, stat_buf
, pred_ptr
));
1148 error (0, errno
, "%s", pathname
);
1152 return (pred_type (pathname
, &sbuf
, pred_ptr
));
1155 /* 1) fork to get a child; parent remembers the child pid
1156 2) child execs the command requested
1157 3) parent waits for child; checks for proper pid of child
1161 ret errno status(h) status(l)
1163 pid x signal# 0177 stopped
1164 pid x exit arg 0 term by _exit
1165 pid x 0 signal # term by signal
1166 -1 EINTR parent got signal
1167 -1 other some other kind of error
1169 Return true only if the pid matches, status(l) is
1170 zero, and the exit arg (status high) is 0.
1171 Otherwise return false, possibly printing an error message. */
1174 launch (struct predicate
*pred_ptr
)
1177 pid_t wait_ret
, child_pid
;
1178 struct exec_val
*execp
; /* Pointer for efficiency. */
1179 static int first_time
= 1;
1181 execp
= &pred_ptr
->args
.exec_vec
;
1183 /* Make sure output of command doesn't get mixed with find output. */
1187 /* Make sure to listen for the kids. */
1191 signal (SIGCHLD
, SIG_DFL
);
1194 child_pid
= fork ();
1195 if (child_pid
== -1)
1196 error (1, errno
, _("cannot fork"));
1199 /* We be the child. */
1201 if (chdir (starting_dir
) < 0)
1203 error (0, errno
, "%s", starting_dir
);
1207 if (fchdir (starting_desc
) < 0)
1209 error (0, errno
, _("cannot return to starting directory"));
1213 execvp (execp
->vec
[0], execp
->vec
);
1214 error (0, errno
, "%s", execp
->vec
[0]);
1218 wait_ret
= wait (&status
);
1221 error (0, errno
, _("error waiting for %s"), execp
->vec
[0]);
1225 if (wait_ret
!= child_pid
)
1227 error (0, 0, _("wait got pid %d, expected pid %d"), wait_ret
, child_pid
);
1231 if (WIFSTOPPED (status
))
1233 error (0, 0, _("%s stopped by signal %d"),
1234 execp
->vec
[0], WSTOPSIG (status
));
1238 if (WIFSIGNALED (status
))
1240 error (0, 0, _("%s terminated by signal %d"),
1241 execp
->vec
[0], WTERMSIG (status
));
1245 return (!WEXITSTATUS (status
));
1248 /* Return a static string formatting the time WHEN according to the
1249 strftime format character KIND. */
1252 format_date (time_t when
, int kind
)
1255 static char buf
[64]; /* More than enough space. */
1259 sprintf (buf
, "%ld", when
);
1267 if (strftime (buf
, sizeof (buf
), fmt
, localtime (&when
)))
1274 /* Return a pointer to the string representation of
1275 the predicate function PRED_FUNC. */
1278 find_pred_name (pred_func
)
1283 for (i
= 0; pred_table
[i
].pred_func
!= 0; i
++)
1284 if (pred_table
[i
].pred_func
== pred_func
)
1286 return (pred_table
[i
].pred_name
);
1295 for (i
= 0; type_table
[i
].type
!= (short) -1; i
++)
1296 if (type_table
[i
].type
== type
)
1298 return (type_table
[i
].type_name
);
1307 for (i
= 0; prec_table
[i
].prec
!= (short) -1; i
++)
1308 if (prec_table
[i
].prec
== prec
)
1310 return (prec_table
[i
].prec_name
);
1313 /* Walk the expression tree NODE to stdout.
1314 INDENT is the number of levels to indent the left margin. */
1317 print_tree (node
, indent
)
1318 struct predicate
*node
;
1325 for (i
= 0; i
< indent
; i
++)
1327 printf ("pred = %s type = %s prec = %s addr = %x\n",
1328 find_pred_name (node
->pred_func
),
1329 type_name (node
->p_type
), prec_name (node
->p_prec
), node
);
1330 for (i
= 0; i
< indent
; i
++)
1332 printf (_("left:\n"));
1333 print_tree (node
->pred_left
, indent
+ 1);
1334 for (i
= 0; i
< indent
; i
++)
1336 printf (_("right:\n"));
1337 print_tree (node
->pred_right
, indent
+ 1);
1340 /* Copy STR into BUF and trim blanks from the end of BUF.
1344 blank_rtrim (str
, buf
)
1353 i
= strlen (buf
) - 1;
1354 while ((i
>= 0) && ((buf
[i
] == ' ') || buf
[i
] == '\t'))
1360 /* Print out the predicate list starting at NODE. */
1364 struct predicate
*node
;
1366 struct predicate
*cur
;
1372 printf ("%s ", blank_rtrim (find_pred_name (cur
->pred_func
), name
));
1373 cur
= cur
->pred_next
;