Findutils 4.3.x defaults to using the the FTS implementation of find.
[findutils.git] / find / pred.c
blobec8e94a9bf80d9d642f388561eaaad6fc7df65ab
1 /* pred.c -- execute the expression tree.
2 Copyright (C) 1990, 1991, 1992, 1993, 1994, 2000, 2003,
3 2004, 2005 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
18 USA.
21 #include "defs.h"
23 #include <fnmatch.h>
24 #include <signal.h>
25 #include <pwd.h>
26 #include <grp.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <assert.h>
30 #include <fcntl.h>
31 #include "xalloc.h"
32 #include "dirname.h"
33 #include "human.h"
34 #include "modetype.h"
35 #include "filemode.h"
36 #include "wait.h"
37 #include "printquoted.h"
38 #include "buildcmd.h"
39 #include "yesno.h"
41 #if ENABLE_NLS
42 # include <libintl.h>
43 # define _(Text) gettext (Text)
44 #else
45 # define _(Text) Text
46 #endif
47 #ifdef gettext_noop
48 # define N_(String) gettext_noop (String)
49 #else
50 /* See locate.c for explanation as to why not use (String) */
51 # define N_(String) String
52 #endif
54 #if !defined(SIGCHLD) && defined(SIGCLD)
55 #define SIGCHLD SIGCLD
56 #endif
60 #if HAVE_DIRENT_H
61 # include <dirent.h>
62 # define NAMLEN(dirent) strlen((dirent)->d_name)
63 #else
64 # define dirent direct
65 # define NAMLEN(dirent) (dirent)->d_namlen
66 # if HAVE_SYS_NDIR_H
67 # include <sys/ndir.h>
68 # endif
69 # if HAVE_SYS_DIR_H
70 # include <sys/dir.h>
71 # endif
72 # if HAVE_NDIR_H
73 # include <ndir.h>
74 # endif
75 #endif
77 #ifdef CLOSEDIR_VOID
78 /* Fake a return value. */
79 #define CLOSEDIR(d) (closedir (d), 0)
80 #else
81 #define CLOSEDIR(d) closedir (d)
82 #endif
87 /* Get or fake the disk device blocksize.
88 Usually defined by sys/param.h (if at all). */
89 #ifndef DEV_BSIZE
90 # ifdef BSIZE
91 # define DEV_BSIZE BSIZE
92 # else /* !BSIZE */
93 # define DEV_BSIZE 4096
94 # endif /* !BSIZE */
95 #endif /* !DEV_BSIZE */
97 /* Extract or fake data from a `struct stat'.
98 ST_BLKSIZE: Preferred I/O blocksize for the file, in bytes.
99 ST_NBLOCKS: Number of blocks in the file, including indirect blocks.
100 ST_NBLOCKSIZE: Size of blocks used when calculating ST_NBLOCKS. */
101 #ifndef HAVE_STRUCT_STAT_ST_BLOCKS
102 # define ST_BLKSIZE(statbuf) DEV_BSIZE
103 # if defined(_POSIX_SOURCE) || !defined(BSIZE) /* fileblocks.c uses BSIZE. */
104 # define ST_NBLOCKS(statbuf) \
105 (S_ISREG ((statbuf).st_mode) \
106 || S_ISDIR ((statbuf).st_mode) \
107 ? (statbuf).st_size / ST_NBLOCKSIZE + ((statbuf).st_size % ST_NBLOCKSIZE != 0) : 0)
108 # else /* !_POSIX_SOURCE && BSIZE */
109 # define ST_NBLOCKS(statbuf) \
110 (S_ISREG ((statbuf).st_mode) \
111 || S_ISDIR ((statbuf).st_mode) \
112 ? st_blocks ((statbuf).st_size) : 0)
113 # endif /* !_POSIX_SOURCE && BSIZE */
114 #else /* HAVE_STRUCT_STAT_ST_BLOCKS */
115 /* Some systems, like Sequents, return st_blksize of 0 on pipes. */
116 # define ST_BLKSIZE(statbuf) ((statbuf).st_blksize > 0 \
117 ? (statbuf).st_blksize : DEV_BSIZE)
118 # if defined(hpux) || defined(__hpux__) || defined(__hpux)
119 /* HP-UX counts st_blocks in 1024-byte units.
120 This loses when mixing HP-UX and BSD filesystems with NFS. */
121 # define ST_NBLOCKSIZE 1024
122 # else /* !hpux */
123 # if defined(_AIX) && defined(_I386)
124 /* AIX PS/2 counts st_blocks in 4K units. */
125 # define ST_NBLOCKSIZE (4 * 1024)
126 # else /* not AIX PS/2 */
127 # if defined(_CRAY)
128 # define ST_NBLOCKS(statbuf) \
129 (S_ISREG ((statbuf).st_mode) \
130 || S_ISDIR ((statbuf).st_mode) \
131 ? (statbuf).st_blocks * ST_BLKSIZE(statbuf)/ST_NBLOCKSIZE : 0)
132 # endif /* _CRAY */
133 # endif /* not AIX PS/2 */
134 # endif /* !hpux */
135 #endif /* HAVE_STRUCT_STAT_ST_BLOCKS */
137 #ifndef ST_NBLOCKS
138 # define ST_NBLOCKS(statbuf) \
139 (S_ISREG ((statbuf).st_mode) \
140 || S_ISDIR ((statbuf).st_mode) \
141 ? (statbuf).st_blocks : 0)
142 #endif
144 #ifndef ST_NBLOCKSIZE
145 # define ST_NBLOCKSIZE 512
146 #endif
149 #undef MAX
150 #define MAX(a, b) ((a) > (b) ? (a) : (b))
152 static boolean insert_lname PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr, boolean ignore_case));
154 static char *format_date PARAMS((time_t when, int kind));
155 static char *ctime_format PARAMS((time_t when));
157 #ifdef DEBUG
158 struct pred_assoc
160 PRED_FUNC pred_func;
161 char *pred_name;
164 struct pred_assoc pred_table[] =
166 {pred_amin, "amin "},
167 {pred_and, "and "},
168 {pred_anewer, "anewer "},
169 {pred_atime, "atime "},
170 {pred_close, ") "},
171 {pred_amin, "cmin "},
172 {pred_cnewer, "cnewer "},
173 {pred_comma, ", "},
174 {pred_ctime, "ctime "},
175 {pred_delete, "delete "},
176 {pred_empty, "empty "},
177 {pred_exec, "exec "},
178 {pred_execdir, "execdir "},
179 {pred_false, "false "},
180 {pred_fprint, "fprint "},
181 {pred_fprint0, "fprint0 "},
182 {pred_fprintf, "fprintf "},
183 {pred_fstype, "fstype "},
184 {pred_gid, "gid "},
185 {pred_group, "group "},
186 {pred_ilname, "ilname "},
187 {pred_iname, "iname "},
188 {pred_inum, "inum "},
189 {pred_ipath, "ipath "},
190 {pred_links, "links "},
191 {pred_lname, "lname "},
192 {pred_ls, "ls "},
193 {pred_amin, "mmin "},
194 {pred_mtime, "mtime "},
195 {pred_name, "name "},
196 {pred_negate, "not "},
197 {pred_newer, "newer "},
198 {pred_nogroup, "nogroup "},
199 {pred_nouser, "nouser "},
200 {pred_ok, "ok "},
201 {pred_okdir, "okdir "},
202 {pred_open, "( "},
203 {pred_or, "or "},
204 {pred_path, "path "},
205 {pred_perm, "perm "},
206 {pred_print, "print "},
207 {pred_print0, "print0 "},
208 {pred_prune, "prune "},
209 {pred_regex, "regex "},
210 {pred_samefile,"samefile "},
211 {pred_size, "size "},
212 {pred_true, "true "},
213 {pred_type, "type "},
214 {pred_uid, "uid "},
215 {pred_used, "used "},
216 {pred_user, "user "},
217 {pred_xtype, "xtype "},
218 {0, "none "}
221 struct op_assoc
223 short type;
224 char *type_name;
227 struct op_assoc type_table[] =
229 {NO_TYPE, "no "},
230 {PRIMARY_TYPE, "primary "},
231 {UNI_OP, "uni_op "},
232 {BI_OP, "bi_op "},
233 {OPEN_PAREN, "open_paren "},
234 {CLOSE_PAREN, "close_paren "},
235 {-1, "unknown "}
238 struct prec_assoc
240 short prec;
241 char *prec_name;
244 struct prec_assoc prec_table[] =
246 {NO_PREC, "no "},
247 {COMMA_PREC, "comma "},
248 {OR_PREC, "or "},
249 {AND_PREC, "and "},
250 {NEGATE_PREC, "negate "},
251 {MAX_PREC, "max "},
252 {-1, "unknown "}
254 #endif /* DEBUG */
256 /* Predicate processing routines.
258 PATHNAME is the full pathname of the file being checked.
259 *STAT_BUF contains information about PATHNAME.
260 *PRED_PTR contains information for applying the predicate.
262 Return true if the file passes this predicate, false if not. */
265 /* pred_timewindow
267 * Returns true if THE_TIME is
268 * COMP_GT: after the specified time
269 * COMP_LT: before the specified time
270 * COMP_EQ: less than WINDOW seconds after the specified time.
272 static boolean
273 pred_timewindow(time_t the_time, struct predicate const *pred_ptr, int window)
275 switch (pred_ptr->args.info.kind)
277 case COMP_GT:
278 if (the_time > (time_t) pred_ptr->args.info.l_val)
279 return true;
280 break;
281 case COMP_LT:
282 if (the_time < (time_t) pred_ptr->args.info.l_val)
283 return true;
284 break;
285 case COMP_EQ:
286 if ((the_time >= (time_t) pred_ptr->args.info.l_val)
287 && (the_time < (time_t) pred_ptr->args.info.l_val + window))
288 return true;
289 break;
291 return false;
295 boolean
296 pred_amin (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
298 (void) &pathname;
299 return pred_timewindow(stat_buf->st_atime, pred_ptr, 60);
302 boolean
303 pred_and (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
305 if (pred_ptr->pred_left == NULL
306 || (*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
307 pred_ptr->pred_left))
309 /* Check whether we need a stat here. */
310 if (get_info(pathname, state.rel_pathname, stat_buf, pred_ptr) != 0)
311 return false;
312 return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
313 pred_ptr->pred_right));
315 else
316 return (false);
319 boolean
320 pred_anewer (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
322 (void) &pathname;
324 if (stat_buf->st_atime > pred_ptr->args.time)
325 return (true);
326 return (false);
329 boolean
330 pred_atime (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
332 (void) &pathname;
333 return pred_timewindow(stat_buf->st_atime, pred_ptr, DAYSECS);
336 boolean
337 pred_close (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
339 (void) &pathname;
340 (void) &stat_buf;
341 (void) &pred_ptr;
343 return true;
346 boolean
347 pred_cmin (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
349 (void) pathname;
350 return pred_timewindow(stat_buf->st_ctime, pred_ptr, 60);
353 boolean
354 pred_cnewer (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
356 (void) pathname;
358 if (stat_buf->st_ctime > pred_ptr->args.time)
359 return true;
360 else
361 return false;
364 boolean
365 pred_comma (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
367 if (pred_ptr->pred_left != NULL)
368 (*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
369 pred_ptr->pred_left);
370 /* Check whether we need a stat here. */
371 /* TODO: what about need_type? */
372 if (get_info(pathname, state.rel_pathname, stat_buf, pred_ptr) != 0)
373 return false;
374 return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
375 pred_ptr->pred_right));
378 boolean
379 pred_ctime (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
381 (void) &pathname;
382 return pred_timewindow(stat_buf->st_ctime, pred_ptr, DAYSECS);
385 boolean
386 pred_delete (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
388 (void) pred_ptr;
389 (void) stat_buf;
390 if (strcmp (state.rel_pathname, "."))
392 if (0 != remove (state.rel_pathname))
394 error (0, errno, "cannot delete %s", pathname);
395 return false;
397 else
399 return true;
403 /* nothing to do. */
404 return true;
407 boolean
408 pred_empty (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
410 (void) pathname;
411 (void) pred_ptr;
413 if (S_ISDIR (stat_buf->st_mode))
415 DIR *d;
416 struct dirent *dp;
417 boolean empty = true;
419 errno = 0;
420 d = opendir (state.rel_pathname);
421 if (d == NULL)
423 error (0, errno, "%s", pathname);
424 state.exit_status = 1;
425 return false;
427 for (dp = readdir (d); dp; dp = readdir (d))
429 if (dp->d_name[0] != '.'
430 || (dp->d_name[1] != '\0'
431 && (dp->d_name[1] != '.' || dp->d_name[2] != '\0')))
433 empty = false;
434 break;
437 if (CLOSEDIR (d))
439 error (0, errno, "%s", pathname);
440 state.exit_status = 1;
441 return false;
443 return (empty);
445 else if (S_ISREG (stat_buf->st_mode))
446 return (stat_buf->st_size == 0);
447 else
448 return (false);
451 static boolean
452 new_impl_pred_exec (const char *pathname, struct stat *stat_buf,
453 struct predicate *pred_ptr,
454 const char *prefix, size_t pfxlen)
456 struct exec_val *execp = &pred_ptr->args.exec_vec;
457 size_t len = strlen(pathname);
459 (void) stat_buf;
461 if (execp->multiple)
463 /* Push the argument onto the current list.
464 * The command may or may not be run at this point,
465 * depending on the command line length limits.
467 bc_push_arg(&execp->ctl,
468 &execp->state,
469 pathname, len+1,
470 prefix, pfxlen,
473 /* POSIX: If the primary expression is punctuated by a plus
474 * sign, the primary shall always evaluate as true
476 return true;
478 else
480 int i;
482 for (i=0; i<execp->num_args; ++i)
484 bc_do_insert(&execp->ctl,
485 &execp->state,
486 execp->replace_vec[i],
487 strlen(execp->replace_vec[i]),
488 prefix, pfxlen,
489 pathname, len,
493 /* Actually invoke the command. */
494 return execp->ctl.exec_callback(&execp->ctl,
495 &execp->state);
500 boolean
501 pred_exec (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
503 return new_impl_pred_exec(pathname, stat_buf, pred_ptr, NULL, 0);
506 boolean
507 pred_execdir (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
509 const char *prefix = (state.rel_pathname[0] == '/') ? NULL : "./";
510 (void) &pathname;
511 return new_impl_pred_exec (state.rel_pathname, stat_buf, pred_ptr,
512 prefix, (prefix ? 2 : 0));
515 boolean
516 pred_false (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
518 (void) &pathname;
519 (void) &stat_buf;
520 (void) &pred_ptr;
523 return (false);
526 boolean
527 pred_fls (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
529 list_file (pathname, state.rel_pathname, stat_buf, options.start_time,
530 options.output_block_size, pred_ptr->args.stream);
531 return (true);
534 boolean
535 pred_fprint (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
537 (void) &pathname;
538 (void) &stat_buf;
540 print_quoted(pred_ptr->args.printf_vec.stream,
541 pred_ptr->args.printf_vec.quote_opts,
542 pred_ptr->args.printf_vec.dest_is_tty,
543 "%s\n",
544 pathname);
545 return true;
548 boolean
549 pred_fprint0 (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
551 (void) &pathname;
552 (void) &stat_buf;
554 fputs (pathname, pred_ptr->args.stream);
555 putc (0, pred_ptr->args.stream);
556 return (true);
561 static char*
562 mode_to_filetype(mode_t m)
564 return
565 m == S_IFSOCK ? "s" :
566 m == S_IFLNK ? "l" :
567 m == S_IFREG ? "f" :
568 m == S_IFBLK ? "b" :
569 m == S_IFDIR ? "d" :
570 m == S_IFCHR ? "c" :
571 #ifdef S_IFDOOR
572 m == S_IFDOOR ? "D" :
573 #endif
574 m == S_IFIFO ? "p" : "U";
578 boolean
579 pred_fprintf (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
581 FILE *fp = pred_ptr->args.printf_vec.stream;
582 const struct quoting_options *qopts = pred_ptr->args.printf_vec.quote_opts;
583 boolean ttyflag = pred_ptr->args.printf_vec.dest_is_tty;
584 struct segment *segment;
585 char *cp;
586 char hbuf[LONGEST_HUMAN_READABLE + 1];
588 for (segment = pred_ptr->args.printf_vec.segment; segment;
589 segment = segment->next)
591 if (segment->kind & 0xff00) /* Component of date. */
593 time_t t;
595 switch (segment->kind & 0xff)
597 case 'A':
598 t = stat_buf->st_atime;
599 break;
600 case 'C':
601 t = stat_buf->st_ctime;
602 break;
603 case 'T':
604 t = stat_buf->st_mtime;
605 break;
606 default:
607 abort ();
609 /* We trust the output of format_date not to contain
610 * nasty characters, though the value of the date
611 * is itself untrusted data.
613 /* trusted */
614 fprintf (fp, segment->text,
615 format_date (t, (segment->kind >> 8) & 0xff));
616 continue;
619 switch (segment->kind)
621 case KIND_PLAIN: /* Plain text string (no % conversion). */
622 /* trusted */
623 fwrite (segment->text, 1, segment->text_len, fp);
624 break;
625 case KIND_STOP: /* Terminate argument and flush output. */
626 /* trusted */
627 fwrite (segment->text, 1, segment->text_len, fp);
628 fflush (fp);
629 return (true);
630 case 'a': /* atime in `ctime' format. */
631 /* UNTRUSTED, probably unexploitable */
632 fprintf (fp, segment->text, ctime_format (stat_buf->st_atime));
633 break;
634 case 'b': /* size in 512-byte blocks */
635 /* UNTRUSTED, probably unexploitable */
636 fprintf (fp, segment->text,
637 human_readable ((uintmax_t) ST_NBLOCKS (*stat_buf),
638 hbuf, human_ceiling,
639 ST_NBLOCKSIZE, 512));
640 break;
641 case 'c': /* ctime in `ctime' format */
642 /* UNTRUSTED, probably unexploitable */
643 fprintf (fp, segment->text, ctime_format (stat_buf->st_ctime));
644 break;
645 case 'd': /* depth in search tree */
646 /* UNTRUSTED, probably unexploitable */
647 fprintf (fp, segment->text, state.curdepth);
648 break;
649 case 'D': /* Device on which file exists (stat.st_dev) */
650 /* trusted */
651 fprintf (fp, segment->text,
652 human_readable ((uintmax_t) stat_buf->st_dev, hbuf,
653 human_ceiling, 1, 1));
654 break;
655 case 'f': /* base name of path */
656 /* sanitised */
657 print_quoted (fp, qopts, ttyflag, segment->text, base_name (pathname));
658 break;
659 case 'F': /* filesystem type */
660 /* trusted */
661 print_quoted (fp, qopts, ttyflag, segment->text, filesystem_type (stat_buf, pathname));
662 break;
663 case 'g': /* group name */
664 /* trusted */
665 /* (well, the actual group is selected by the user but
666 * its name was selected by the system administrator)
669 struct group *g;
671 g = getgrgid (stat_buf->st_gid);
672 if (g)
674 segment->text[segment->text_len] = 's';
675 fprintf (fp, segment->text, g->gr_name);
676 break;
678 /* else fallthru */
680 case 'G': /* GID number */
681 /* UNTRUSTED, probably unexploitable */
682 fprintf (fp, segment->text,
683 human_readable ((uintmax_t) stat_buf->st_gid, hbuf,
684 human_ceiling, 1, 1));
685 break;
686 case 'h': /* leading directories part of path */
687 /* sanitised */
689 char cc;
691 cp = strrchr (pathname, '/');
692 if (cp == NULL) /* No leading directories. */
694 /* If there is no slash in the pathname, we still
695 * print the string because it contains characters
696 * other than just '%s'. The %h expands to ".".
698 print_quoted (fp, qopts, ttyflag, segment->text, ".");
700 else
702 cc = *cp;
703 *cp = '\0';
704 print_quoted (fp, qopts, ttyflag, segment->text, pathname);
705 *cp = cc;
707 break;
709 case 'H': /* ARGV element file was found under */
710 /* trusted */
712 char cc = pathname[state.starting_path_length];
714 pathname[state.starting_path_length] = '\0';
715 fprintf (fp, segment->text, pathname);
716 pathname[state.starting_path_length] = cc;
717 break;
719 case 'i': /* inode number */
720 /* UNTRUSTED, but not exploitable I think */
721 fprintf (fp, segment->text,
722 human_readable ((uintmax_t) stat_buf->st_ino, hbuf,
723 human_ceiling,
724 1, 1));
725 break;
726 case 'k': /* size in 1K blocks */
727 /* UNTRUSTED, but not exploitable I think */
728 fprintf (fp, segment->text,
729 human_readable ((uintmax_t) ST_NBLOCKS (*stat_buf),
730 hbuf, human_ceiling,
731 ST_NBLOCKSIZE, 1024));
732 break;
733 case 'l': /* object of symlink */
734 /* sanitised */
735 #ifdef S_ISLNK
737 char *linkname = 0;
739 if (S_ISLNK (stat_buf->st_mode))
741 linkname = get_link_name (pathname, state.rel_pathname);
742 if (linkname == 0)
743 state.exit_status = 1;
745 if (linkname)
747 print_quoted (fp, qopts, ttyflag, segment->text, linkname);
748 free (linkname);
750 else
751 print_quoted (fp, qopts, ttyflag, segment->text, "");
753 #endif /* S_ISLNK */
754 break;
756 case 'M': /* mode as 10 chars (eg., "-rwxr-x--x" */
757 /* UNTRUSTED, probably unexploitable */
759 char modestring[16] ;
760 mode_string (stat_buf->st_mode, modestring);
761 modestring[10] = '\0';
762 fprintf (fp, segment->text, modestring);
764 break;
766 case 'm': /* mode as octal number (perms only) */
767 /* UNTRUSTED, probably unexploitable */
769 /* Output the mode portably using the traditional numbers,
770 even if the host unwisely uses some other numbering
771 scheme. But help the compiler in the common case where
772 the host uses the traditional numbering scheme. */
773 mode_t m = stat_buf->st_mode;
774 boolean traditional_numbering_scheme =
775 (S_ISUID == 04000 && S_ISGID == 02000 && S_ISVTX == 01000
776 && S_IRUSR == 00400 && S_IWUSR == 00200 && S_IXUSR == 00100
777 && S_IRGRP == 00040 && S_IWGRP == 00020 && S_IXGRP == 00010
778 && S_IROTH == 00004 && S_IWOTH == 00002 && S_IXOTH == 00001);
779 fprintf (fp, segment->text,
780 (traditional_numbering_scheme
781 ? m & MODE_ALL
782 : ((m & S_ISUID ? 04000 : 0)
783 | (m & S_ISGID ? 02000 : 0)
784 | (m & S_ISVTX ? 01000 : 0)
785 | (m & S_IRUSR ? 00400 : 0)
786 | (m & S_IWUSR ? 00200 : 0)
787 | (m & S_IXUSR ? 00100 : 0)
788 | (m & S_IRGRP ? 00040 : 0)
789 | (m & S_IWGRP ? 00020 : 0)
790 | (m & S_IXGRP ? 00010 : 0)
791 | (m & S_IROTH ? 00004 : 0)
792 | (m & S_IWOTH ? 00002 : 0)
793 | (m & S_IXOTH ? 00001 : 0))));
795 break;
797 case 'n': /* number of links */
798 /* UNTRUSTED, probably unexploitable */
799 fprintf (fp, segment->text,
800 human_readable ((uintmax_t) stat_buf->st_nlink,
801 hbuf,
802 human_ceiling,
803 1, 1));
804 break;
805 case 'p': /* pathname */
806 /* sanitised */
807 print_quoted (fp, qopts, ttyflag, segment->text, pathname);
808 break;
809 case 'P': /* pathname with ARGV element stripped */
810 /* sanitised */
811 if (state.curdepth > 0)
813 cp = pathname + state.starting_path_length;
814 if (*cp == '/')
815 /* Move past the slash between the ARGV element
816 and the rest of the pathname. But if the ARGV element
817 ends in a slash, we didn't add another, so we've
818 already skipped past it. */
819 cp++;
821 else
822 cp = "";
823 print_quoted (fp, qopts, ttyflag, segment->text, cp);
824 break;
825 case 's': /* size in bytes */
826 /* UNTRUSTED, probably unexploitable */
827 fprintf (fp, segment->text,
828 human_readable ((uintmax_t) stat_buf->st_size,
829 hbuf, human_ceiling, 1, 1));
830 break;
831 case 't': /* mtime in `ctime' format */
832 /* UNTRUSTED, probably unexploitable */
833 fprintf (fp, segment->text, ctime_format (stat_buf->st_mtime));
834 break;
835 case 'u': /* user name */
836 /* trusted */
837 /* (well, the actual user is selected by the user on systems
838 * where chown is not restricted, but the user name was
839 * selected by the system administrator)
842 struct passwd *p;
844 p = getpwuid (stat_buf->st_uid);
845 if (p)
847 segment->text[segment->text_len] = 's';
848 fprintf (fp, segment->text, p->pw_name);
849 break;
851 /* else fallthru */
854 case 'U': /* UID number */
855 /* UNTRUSTED, probably unexploitable */
856 fprintf (fp, segment->text,
857 human_readable ((uintmax_t) stat_buf->st_uid, hbuf,
858 human_ceiling, 1, 1));
859 break;
861 /* type of filesystem entry like `ls -l`: (d,-,l,s,p,b,c,n) n=nonexistent(symlink) */
862 case 'Y': /* in case of symlink */
863 /* trusted */
865 #ifdef S_ISLNK
866 if (S_ISLNK (stat_buf->st_mode))
868 struct stat sbuf;
869 /* If we would normally follow links, do not do so.
870 * If we would normally not follow links, do so.
872 if ((following_links() ? lstat : stat)
873 (state.rel_pathname, &sbuf) != 0)
875 if ( errno == ENOENT ) {
876 fprintf (fp, segment->text, "N");
877 break;
879 if ( errno == ELOOP ) {
880 fprintf (fp, segment->text, "L");
881 break;
883 error (0, errno, "%s", pathname);
884 /* exit_status = 1;
885 return (false); */
887 fprintf (fp, segment->text,
888 mode_to_filetype(sbuf.st_mode & S_IFMT));
890 #endif /* S_ISLNK */
891 else
893 fprintf (fp, segment->text,
894 mode_to_filetype(stat_buf->st_mode & S_IFMT));
897 break;
899 case 'y':
900 /* trusted */
902 fprintf (fp, segment->text,
903 mode_to_filetype(stat_buf->st_mode & S_IFMT));
905 break;
908 return true;
911 boolean
912 pred_fstype (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
914 (void) pathname;
916 if (strcmp (filesystem_type (stat_buf, pathname), pred_ptr->args.str) == 0)
917 return true;
918 else
919 return false;
922 boolean
923 pred_gid (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
925 (void) pathname;
927 switch (pred_ptr->args.info.kind)
929 case COMP_GT:
930 if (stat_buf->st_gid > pred_ptr->args.info.l_val)
931 return (true);
932 break;
933 case COMP_LT:
934 if (stat_buf->st_gid < pred_ptr->args.info.l_val)
935 return (true);
936 break;
937 case COMP_EQ:
938 if (stat_buf->st_gid == pred_ptr->args.info.l_val)
939 return (true);
940 break;
942 return (false);
945 boolean
946 pred_group (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
948 (void) pathname;
950 if (pred_ptr->args.gid == stat_buf->st_gid)
951 return (true);
952 else
953 return (false);
956 boolean
957 pred_ilname (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
959 return insert_lname (pathname, stat_buf, pred_ptr, true);
962 boolean
963 pred_iname (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
965 const char *base;
967 (void) stat_buf;
969 /* FNM_PERIOD is not used here because POSIX requires that it not be.
970 * See http://standards.ieee.org/reading/ieee/interp/1003-2-92_int/pasc-1003.2-126.html
972 base = base_name (pathname);
973 if (fnmatch (pred_ptr->args.str, base, FNM_CASEFOLD) == 0)
974 return (true);
975 return (false);
978 boolean
979 pred_inum (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
981 (void) pathname;
983 switch (pred_ptr->args.info.kind)
985 case COMP_GT:
986 if (stat_buf->st_ino > pred_ptr->args.info.l_val)
987 return (true);
988 break;
989 case COMP_LT:
990 if (stat_buf->st_ino < pred_ptr->args.info.l_val)
991 return (true);
992 break;
993 case COMP_EQ:
994 if (stat_buf->st_ino == pred_ptr->args.info.l_val)
995 return (true);
996 break;
998 return (false);
1001 boolean
1002 pred_ipath (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1004 (void) stat_buf;
1006 if (fnmatch (pred_ptr->args.str, pathname, FNM_CASEFOLD) == 0)
1007 return (true);
1008 return (false);
1011 boolean
1012 pred_links (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1014 (void) pathname;
1016 switch (pred_ptr->args.info.kind)
1018 case COMP_GT:
1019 if (stat_buf->st_nlink > pred_ptr->args.info.l_val)
1020 return (true);
1021 break;
1022 case COMP_LT:
1023 if (stat_buf->st_nlink < pred_ptr->args.info.l_val)
1024 return (true);
1025 break;
1026 case COMP_EQ:
1027 if (stat_buf->st_nlink == pred_ptr->args.info.l_val)
1028 return (true);
1029 break;
1031 return (false);
1034 boolean
1035 pred_lname (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1037 return insert_lname (pathname, stat_buf, pred_ptr, false);
1040 static boolean
1041 insert_lname (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr, boolean ignore_case)
1043 boolean ret = false;
1044 #ifdef S_ISLNK
1045 if (S_ISLNK (stat_buf->st_mode))
1047 char *linkname = get_link_name (pathname, state.rel_pathname);
1048 if (linkname)
1050 if (fnmatch (pred_ptr->args.str, linkname,
1051 ignore_case ? FNM_CASEFOLD : 0) == 0)
1052 ret = true;
1053 free (linkname);
1056 #endif /* S_ISLNK */
1057 return (ret);
1060 boolean
1061 pred_ls (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1063 (void) pred_ptr;
1065 list_file (pathname, state.rel_pathname, stat_buf, options.start_time,
1066 options.output_block_size, stdout);
1067 return (true);
1070 boolean
1071 pred_mmin (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1073 (void) &pathname;
1074 return pred_timewindow(stat_buf->st_mtime, pred_ptr, 60);
1077 boolean
1078 pred_mtime (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1080 (void) pathname;
1081 return pred_timewindow(stat_buf->st_mtime, pred_ptr, DAYSECS);
1084 boolean
1085 pred_name (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1087 const char *base;
1089 (void) stat_buf;
1090 base = base_name (pathname);
1092 /* FNM_PERIOD is not used here because POSIX requires that it not be.
1093 * See http://standards.ieee.org/reading/ieee/interp/1003-2-92_int/pasc-1003.2-126.html
1095 if (fnmatch (pred_ptr->args.str, base, 0) == 0)
1096 return (true);
1097 return (false);
1100 boolean
1101 pred_negate (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1103 /* Check whether we need a stat here. */
1104 /* TODO: what about need_type? */
1105 if (get_info(pathname, state.rel_pathname, stat_buf, pred_ptr) != 0)
1106 return false;
1107 return (!(*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
1108 pred_ptr->pred_right));
1111 boolean
1112 pred_newer (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1114 (void) pathname;
1116 if (stat_buf->st_mtime > pred_ptr->args.time)
1117 return (true);
1118 return (false);
1121 boolean
1122 pred_nogroup (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1124 (void) pathname;
1125 (void) pred_ptr;
1127 #ifdef CACHE_IDS
1128 extern char *gid_unused;
1130 return gid_unused[(unsigned) stat_buf->st_gid];
1131 #else
1132 return getgrgid (stat_buf->st_gid) == NULL;
1133 #endif
1136 boolean
1137 pred_nouser (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1139 #ifdef CACHE_IDS
1140 extern char *uid_unused;
1141 #endif
1143 (void) pathname;
1144 (void) pred_ptr;
1146 #ifdef CACHE_IDS
1147 return uid_unused[(unsigned) stat_buf->st_uid];
1148 #else
1149 return getpwuid (stat_buf->st_uid) == NULL;
1150 #endif
1154 static boolean
1155 is_ok(const char *program, const char *arg)
1157 fflush (stdout);
1158 /* The draft open standard requires that, in the POSIX locale,
1159 the last non-blank character of this prompt be '?'.
1160 The exact format is not specified.
1161 This standard does not have requirements for locales other than POSIX
1163 /* XXX: printing UNTRUSTED data here. */
1164 fprintf (stderr, _("< %s ... %s > ? "), program, arg);
1165 fflush (stderr);
1166 return yesno();
1169 boolean
1170 pred_ok (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1172 if (is_ok(pred_ptr->args.exec_vec.replace_vec[0], pathname))
1173 return new_impl_pred_exec (pathname, stat_buf, pred_ptr, NULL, 0);
1174 else
1175 return false;
1178 boolean
1179 pred_okdir (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1181 const char *prefix = (state.rel_pathname[0] == '/') ? NULL : "./";
1182 if (is_ok(pred_ptr->args.exec_vec.replace_vec[0], pathname))
1183 return new_impl_pred_exec (state.rel_pathname, stat_buf, pred_ptr,
1184 prefix, (prefix ? 2 : 0));
1185 else
1186 return false;
1189 boolean
1190 pred_open (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1192 (void) pathname;
1193 (void) stat_buf;
1194 (void) pred_ptr;
1195 return true;
1198 boolean
1199 pred_or (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1201 if (pred_ptr->pred_left == NULL
1202 || !(*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
1203 pred_ptr->pred_left))
1205 if (get_info(pathname, state.rel_pathname, stat_buf, pred_ptr) != 0)
1206 return false;
1207 return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
1208 pred_ptr->pred_right));
1210 else
1211 return true;
1214 boolean
1215 pred_path (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1217 (void) stat_buf;
1218 if (fnmatch (pred_ptr->args.str, pathname, 0) == 0)
1219 return (true);
1220 return (false);
1223 boolean
1224 pred_perm (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1226 (void) pathname;
1227 switch (pred_ptr->args.perm.kind)
1229 case PERM_AT_LEAST:
1230 return (stat_buf->st_mode & pred_ptr->args.perm.val) == pred_ptr->args.perm.val;
1231 break;
1233 case PERM_ANY:
1234 return (stat_buf->st_mode & pred_ptr->args.perm.val) != 0;
1235 break;
1237 case PERM_EXACT:
1238 return (stat_buf->st_mode & MODE_ALL) == pred_ptr->args.perm.val;
1239 break;
1241 default:
1242 abort ();
1243 break;
1247 boolean
1248 pred_print (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1250 (void) stat_buf;
1251 (void) pred_ptr;
1252 /* puts (pathname); */
1253 print_quoted(pred_ptr->args.printf_vec.stream,
1254 pred_ptr->args.printf_vec.quote_opts,
1255 pred_ptr->args.printf_vec.dest_is_tty,
1256 "%s\n", pathname);
1257 return true;
1260 boolean
1261 pred_print0 (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1263 (void) stat_buf;
1264 (void) pred_ptr;
1265 fputs (pathname, stdout);
1266 putc (0, stdout);
1267 return (true);
1270 boolean
1271 pred_prune (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1273 (void) pathname;
1274 (void) stat_buf;
1275 (void) pred_ptr;
1276 state.stop_at_current_level = true;
1277 return (options.do_dir_first); /* This is what SunOS find seems to do. */
1280 boolean
1281 pred_quit (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1283 (void) pathname;
1284 (void) stat_buf;
1285 (void) pred_ptr;
1287 /* Run any cleanups. This includes executing any command lines
1288 * we have partly built but not executed.
1290 cleanup();
1292 /* Since -exec and friends don't leave child processes running in the
1293 * background, there is no need to wait for them here.
1295 exit(state.exit_status); /* 0 for success, etc. */
1298 boolean
1299 pred_regex (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1301 int len = strlen (pathname);
1302 (void) stat_buf;
1303 if (re_match (pred_ptr->args.regex, pathname, len, 0,
1304 (struct re_registers *) NULL) == len)
1305 return (true);
1306 return (false);
1309 boolean
1310 pred_size (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1312 uintmax_t f_val;
1314 (void) pathname;
1315 f_val = ((stat_buf->st_size / pred_ptr->args.size.blocksize)
1316 + (stat_buf->st_size % pred_ptr->args.size.blocksize != 0));
1317 switch (pred_ptr->args.size.kind)
1319 case COMP_GT:
1320 if (f_val > pred_ptr->args.size.size)
1321 return (true);
1322 break;
1323 case COMP_LT:
1324 if (f_val < pred_ptr->args.size.size)
1325 return (true);
1326 break;
1327 case COMP_EQ:
1328 if (f_val == pred_ptr->args.size.size)
1329 return (true);
1330 break;
1332 return (false);
1335 boolean
1336 pred_samefile (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1338 /* Potential optimisation: because of the loop protection, we always
1339 * know the device of the current directory, hence the device number
1340 * of the file we're currently considering. If -L is not in effect,
1341 * and the device number of the file we're looking for is not the
1342 * same as the device number of the current directory, this
1343 * predicate cannot return true. Hence there would be no need to
1344 * stat the file we're lookingn at.
1346 (void) pathname;
1348 return stat_buf->st_ino == pred_ptr->args.fileid.ino
1349 && stat_buf->st_dev == pred_ptr->args.fileid.dev;
1352 boolean
1353 pred_true (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1355 (void) pathname;
1356 (void) stat_buf;
1357 (void) pred_ptr;
1358 return true;
1361 boolean
1362 pred_type (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1364 mode_t mode;
1365 mode_t type = pred_ptr->args.type;
1367 assert(state.have_type);
1368 assert(state.type != 0);
1370 (void) pathname;
1372 if (state.have_stat)
1373 mode = stat_buf->st_mode;
1374 else
1375 mode = state.type;
1377 #ifndef S_IFMT
1378 /* POSIX system; check `mode' the slow way. */
1379 if ((S_ISBLK (mode) && type == S_IFBLK)
1380 || (S_ISCHR (mode) && type == S_IFCHR)
1381 || (S_ISDIR (mode) && type == S_IFDIR)
1382 || (S_ISREG (mode) && type == S_IFREG)
1383 #ifdef S_IFLNK
1384 || (S_ISLNK (mode) && type == S_IFLNK)
1385 #endif
1386 #ifdef S_IFIFO
1387 || (S_ISFIFO (mode) && type == S_IFIFO)
1388 #endif
1389 #ifdef S_IFSOCK
1390 || (S_ISSOCK (mode) && type == S_IFSOCK)
1391 #endif
1392 #ifdef S_IFDOOR
1393 || (S_ISDOOR (mode) && type == S_IFDOOR)
1394 #endif
1396 #else /* S_IFMT */
1397 /* Unix system; check `mode' the fast way. */
1398 if ((mode & S_IFMT) == type)
1399 #endif /* S_IFMT */
1400 return (true);
1401 else
1402 return (false);
1405 boolean
1406 pred_uid (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1408 (void) pathname;
1409 switch (pred_ptr->args.info.kind)
1411 case COMP_GT:
1412 if (stat_buf->st_uid > pred_ptr->args.info.l_val)
1413 return (true);
1414 break;
1415 case COMP_LT:
1416 if (stat_buf->st_uid < pred_ptr->args.info.l_val)
1417 return (true);
1418 break;
1419 case COMP_EQ:
1420 if (stat_buf->st_uid == pred_ptr->args.info.l_val)
1421 return (true);
1422 break;
1424 return (false);
1427 boolean
1428 pred_used (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1430 time_t delta;
1432 (void) pathname;
1433 delta = stat_buf->st_atime - stat_buf->st_ctime; /* Use difftime? */
1434 return pred_timewindow(delta, pred_ptr, DAYSECS);
1437 boolean
1438 pred_user (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1440 (void) pathname;
1441 if (pred_ptr->args.uid == stat_buf->st_uid)
1442 return (true);
1443 else
1444 return (false);
1447 boolean
1448 pred_xtype (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1450 struct stat sbuf; /* local copy, not stat_buf because we're using a different stat method */
1451 int (*ystat) (const char*, struct stat *p);
1453 /* If we would normally stat the link itself, stat the target instead.
1454 * If we would normally follow the link, stat the link itself instead.
1456 if (following_links())
1457 ystat = optionp_stat;
1458 else
1459 ystat = optionl_stat;
1461 if ((*ystat) (state.rel_pathname, &sbuf) != 0)
1463 if (following_links() && errno == ENOENT)
1465 /* If we failed to follow the symlink,
1466 * fall back on looking at the symlink itself.
1468 /* Mimic behavior of ls -lL. */
1469 return (pred_type (pathname, stat_buf, pred_ptr));
1471 else
1473 error (0, errno, "%s", pathname);
1474 state.exit_status = 1;
1476 return false;
1478 /* Now that we have our stat() information, query it in the same
1479 * way that -type does.
1481 return (pred_type (pathname, &sbuf, pred_ptr));
1484 /* 1) fork to get a child; parent remembers the child pid
1485 2) child execs the command requested
1486 3) parent waits for child; checks for proper pid of child
1488 Possible returns:
1490 ret errno status(h) status(l)
1492 pid x signal# 0177 stopped
1493 pid x exit arg 0 term by _exit
1494 pid x 0 signal # term by signal
1495 -1 EINTR parent got signal
1496 -1 other some other kind of error
1498 Return true only if the pid matches, status(l) is
1499 zero, and the exit arg (status high) is 0.
1500 Otherwise return false, possibly printing an error message. */
1503 static void
1504 prep_child_for_exec (boolean close_stdin)
1506 if (close_stdin)
1508 const char inputfile[] = "/dev/null";
1509 /* fprintf(stderr, "attaching stdin to /dev/null\n"); */
1511 close(0);
1512 if (open(inputfile, O_RDONLY) < 0)
1514 /* This is not entirely fatal, since
1515 * executing the child with a closed
1516 * stdin is almost as good as executing it
1517 * with its stdin attached to /dev/null.
1519 error (0, errno, "%s", inputfile);
1527 launch (const struct buildcmd_control *ctl,
1528 struct buildcmd_state *buildstate)
1530 int wait_status;
1531 pid_t child_pid;
1532 static int first_time = 1;
1533 const struct exec_val *execp = buildstate->usercontext;
1535 /* Null terminate the arg list. */
1536 bc_push_arg (ctl, buildstate, (char *) NULL, 0, NULL, 0, false);
1538 /* Make sure output of command doesn't get mixed with find output. */
1539 fflush (stdout);
1540 fflush (stderr);
1542 /* Make sure to listen for the kids. */
1543 if (first_time)
1545 first_time = 0;
1546 signal (SIGCHLD, SIG_DFL);
1549 child_pid = fork ();
1550 if (child_pid == -1)
1551 error (1, errno, _("cannot fork"));
1552 if (child_pid == 0)
1554 /* We be the child. */
1555 prep_child_for_exec(execp->close_stdin);
1557 /* For -exec and -ok, change directory back to the starting directory.
1558 * for -execdir and -okdir, stay in the directory we are searching
1559 * (the latter is more secure).
1561 if (!execp->use_current_dir)
1563 /* Even if DEBUG_STAT is set, don't announce our change of
1564 * directory, since we're not going to emit a subsequent
1565 * announcement of a call to stat() anyway, as we're about
1566 * to exec something.
1568 if (starting_desc < 0
1569 ? chdir (starting_dir) != 0
1570 : fchdir (starting_desc) != 0)
1572 error (0, errno, "%s", starting_dir);
1573 _exit (1);
1577 execvp (buildstate->cmd_argv[0], buildstate->cmd_argv);
1578 error (0, errno, "%s", buildstate->cmd_argv[0]);
1579 _exit (1);
1583 /* In parent; set up for next time. */
1584 bc_clear_args(ctl, buildstate);
1587 while (waitpid (child_pid, &wait_status, 0) == (pid_t) -1)
1589 if (errno != EINTR)
1591 error (0, errno, _("error waiting for %s"), buildstate->cmd_argv[0]);
1592 state.exit_status = 1;
1593 return 0; /* FAIL */
1597 if (WIFSIGNALED (wait_status))
1599 error (0, 0, _("%s terminated by signal %d"),
1600 buildstate->cmd_argv[0], WTERMSIG (wait_status));
1602 if (execp->multiple)
1604 /* -exec \; just returns false if the invoked command fails.
1605 * -exec {} + returns true if the invoked command fails, but
1606 * sets the program exit status.
1608 state.exit_status = 1;
1611 return 1; /* OK */
1614 if (0 == WEXITSTATUS (wait_status))
1616 return 1; /* OK */
1618 else
1620 if (execp->multiple)
1622 /* -exec \; just returns false if the invoked command fails.
1623 * -exec {} + returns true if the invoked command fails, but
1624 * sets the program exit status.
1626 state.exit_status = 1;
1628 return 0; /* FAIL */
1634 /* Return a static string formatting the time WHEN according to the
1635 strftime format character KIND. */
1637 static char *
1638 format_date (time_t when, int kind)
1640 static char buf[MAX (LONGEST_HUMAN_READABLE + 2, 64)];
1641 struct tm *tm;
1642 char fmt[6];
1644 fmt[0] = '%';
1645 fmt[1] = kind;
1646 fmt[2] = '\0';
1647 if (kind == '+')
1648 strcpy (fmt, "%F+%T");
1650 if (kind != '@'
1651 && (tm = localtime (&when))
1652 && strftime (buf, sizeof buf, fmt, tm))
1653 return buf;
1654 else
1656 uintmax_t w = when;
1657 char *p = human_readable (when < 0 ? -w : w, buf + 1,
1658 human_ceiling, 1, 1);
1659 if (when < 0)
1660 *--p = '-';
1661 return p;
1665 static char *
1666 ctime_format (time_t when)
1668 char *r = ctime (&when);
1669 if (!r)
1671 /* The time cannot be represented as a struct tm.
1672 Output it as an integer. */
1673 return format_date (when, '@');
1675 else
1677 /* Remove the trailing newline from the ctime output,
1678 being careful not to assume that the output is fixed-width. */
1679 *strchr (r, '\n') = '\0';
1680 return r;
1684 #ifdef DEBUG
1685 /* Return a pointer to the string representation of
1686 the predicate function PRED_FUNC. */
1688 char *
1689 find_pred_name (PRED_FUNC func)
1691 int i;
1693 for (i = 0; pred_table[i].pred_func != 0; i++)
1694 if (pred_table[i].pred_func == func)
1695 break;
1696 return pred_table[i].pred_name;
1699 static char *
1700 type_name (type)
1701 short type;
1703 int i;
1705 for (i = 0; type_table[i].type != (short) -1; i++)
1706 if (type_table[i].type == type)
1707 break;
1708 return (type_table[i].type_name);
1711 static char *
1712 prec_name (prec)
1713 short prec;
1715 int i;
1717 for (i = 0; prec_table[i].prec != (short) -1; i++)
1718 if (prec_table[i].prec == prec)
1719 break;
1720 return (prec_table[i].prec_name);
1723 /* Walk the expression tree NODE to stdout.
1724 INDENT is the number of levels to indent the left margin. */
1726 void
1727 print_tree (FILE *fp, struct predicate *node, int indent)
1729 int i;
1731 if (node == NULL)
1732 return;
1733 for (i = 0; i < indent; i++)
1734 fprintf (fp, " ");
1735 fprintf (fp, "pred = %s type = %s prec = %s addr = %p\n",
1736 find_pred_name (node->pred_func),
1737 type_name (node->p_type), prec_name (node->p_prec), node);
1738 if (node->need_stat || node->need_type)
1740 int comma = 0;
1742 for (i = 0; i < indent; i++)
1743 fprintf (fp, " ");
1745 fprintf (fp, "Needs ");
1746 if (node->need_stat)
1748 fprintf (fp, "stat");
1749 comma = 1;
1751 if (node->need_type)
1753 fprintf (fp, "%stype", comma ? "," : "");
1755 fprintf (fp, "\n");
1758 for (i = 0; i < indent; i++)
1759 fprintf (fp, " ");
1760 fprintf (fp, "left:\n");
1761 print_tree (fp, node->pred_left, indent + 1);
1762 for (i = 0; i < indent; i++)
1763 fprintf (fp, " ");
1764 fprintf (fp, "right:\n");
1765 print_tree (fp, node->pred_right, indent + 1);
1768 /* Copy STR into BUF and trim blanks from the end of BUF.
1769 Return BUF. */
1771 static char *
1772 blank_rtrim (str, buf)
1773 char *str;
1774 char *buf;
1776 int i;
1778 if (str == NULL)
1779 return (NULL);
1780 strcpy (buf, str);
1781 i = strlen (buf) - 1;
1782 while ((i >= 0) && ((buf[i] == ' ') || buf[i] == '\t'))
1783 i--;
1784 buf[++i] = '\0';
1785 return (buf);
1788 /* Print out the predicate list starting at NODE. */
1790 void
1791 print_list (FILE *fp, struct predicate *node)
1793 struct predicate *cur;
1794 char name[256];
1796 cur = node;
1797 while (cur != NULL)
1799 fprintf (fp, "%s ", blank_rtrim (find_pred_name (cur->pred_func), name));
1800 cur = cur->pred_next;
1802 fprintf (fp, "\n");
1806 /* Print out the predicate list starting at NODE. */
1809 static void
1810 print_parenthesised(FILE *fp, struct predicate *node)
1812 int parens = 0;
1814 if (node)
1816 if ( ( (node->pred_func == pred_or)
1817 || (node->pred_func == pred_and) )
1818 && node->pred_left == NULL)
1820 /* We print "<nothing> or X" as just "X"
1821 * We print "<nothing> and X" as just "X"
1823 print_parenthesised(fp, node->pred_right);
1825 else
1827 if (node->pred_left || node->pred_right)
1828 parens = 1;
1830 if (parens)
1831 fprintf(fp, "%s", " ( ");
1832 print_optlist(fp, node);
1833 if (parens)
1834 fprintf(fp, "%s", " ) ");
1839 void
1840 print_optlist (FILE *fp, struct predicate *p)
1842 char name[256];
1844 if (p)
1846 print_parenthesised(fp, p->pred_left);
1847 fprintf (fp,
1848 "%s%s%s ",
1849 p->need_stat ? "[stat called here] " : "",
1850 p->need_type ? "[type needed here] " : "",
1851 blank_rtrim (find_pred_name (p->pred_func), name));
1852 print_parenthesised(fp, p->pred_right);
1856 #endif /* DEBUG */
1859 void
1860 pred_sanity_check(const struct predicate *predicates)
1862 const struct predicate *p;
1864 for (p=predicates; p != NULL; p=p->pred_next)
1866 /* All predicates must do something. */
1867 assert(p->pred_func != NULL);
1869 /* All predicates must have a parser table entry. */
1870 assert(p->parser_entry != NULL);
1872 /* If the parser table tells us that just one predicate function is
1873 * possible, verify that that is still the one that is in effect.
1874 * If the parser has NULL for the predicate function, that means that
1875 * the parse_xxx function fills it in, so we can't check it.
1877 if (p->parser_entry->pred_func)
1879 assert(p->parser_entry->pred_func == p->pred_func);
1882 switch (p->parser_entry->type)
1884 /* Options all take effect during parsing, so there should
1885 * be no predicate entries corresponding to them. Hence we
1886 * should not see any ARG_OPTION or ARG_POSITIONAL_OPTION
1887 * items.
1889 * This is a silly way of coding this test, but it prevents
1890 * a compiler warning (i.e. otherwise it would think that
1891 * there would be case statements missing).
1893 case ARG_OPTION:
1894 case ARG_POSITIONAL_OPTION:
1895 assert(p->parser_entry->type != ARG_OPTION);
1896 assert(p->parser_entry->type != ARG_POSITIONAL_OPTION);
1897 break;
1899 case ARG_ACTION:
1900 assert(p->side_effects); /* actions have side effects. */
1901 if (p->pred_func != pred_prune && p->pred_func != pred_quit)
1903 /* actions other than -prune and -quit should
1904 * inhibit the default -print
1906 assert(p->no_default_print);
1908 break;
1910 case ARG_PUNCTUATION:
1911 case ARG_TEST:
1912 /* Punctuation and tests should have no side
1913 * effects and not inhibit default print.
1915 assert(!p->no_default_print);
1916 assert(!p->side_effects);
1917 break;