source: trunk/essentials/sys-apps/findutils/find/pred.c

Last change on this file was 3170, checked in by bird, 18 years ago

findutils 4.3.2

File size: 45.3 KB
Line 
1/* pred.c -- execute the expression tree.
2 Copyright (C) 1990, 1991, 1992, 1993, 1994, 2000, 2003,
3 2004, 2005 Free Software Foundation, Inc.
4
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.
9
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.
14
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.
19*/
20
21#include "defs.h"
22
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"
40#include "listfile.h"
41
42#if ENABLE_NLS
43# include <libintl.h>
44# define _(Text) gettext (Text)
45#else
46# define _(Text) Text
47#endif
48#ifdef gettext_noop
49# define N_(String) gettext_noop (String)
50#else
51/* See locate.c for explanation as to why not use (String) */
52# define N_(String) String
53#endif
54
55#if !defined(SIGCHLD) && defined(SIGCLD)
56#define SIGCHLD SIGCLD
57#endif
58
59
60
61#if HAVE_DIRENT_H
62# include <dirent.h>
63# define NAMLEN(dirent) strlen((dirent)->d_name)
64#else
65# define dirent direct
66# define NAMLEN(dirent) (dirent)->d_namlen
67# if HAVE_SYS_NDIR_H
68# include <sys/ndir.h>
69# endif
70# if HAVE_SYS_DIR_H
71# include <sys/dir.h>
72# endif
73# if HAVE_NDIR_H
74# include <ndir.h>
75# endif
76#endif
77
78#ifdef CLOSEDIR_VOID
79/* Fake a return value. */
80#define CLOSEDIR(d) (closedir (d), 0)
81#else
82#define CLOSEDIR(d) closedir (d)
83#endif
84
85
86
87
88/* Get or fake the disk device blocksize.
89 Usually defined by sys/param.h (if at all). */
90#ifndef DEV_BSIZE
91# ifdef BSIZE
92# define DEV_BSIZE BSIZE
93# else /* !BSIZE */
94# define DEV_BSIZE 4096
95# endif /* !BSIZE */
96#endif /* !DEV_BSIZE */
97
98/* Extract or fake data from a `struct stat'.
99 ST_BLKSIZE: Preferred I/O blocksize for the file, in bytes.
100 ST_NBLOCKS: Number of blocks in the file, including indirect blocks.
101 ST_NBLOCKSIZE: Size of blocks used when calculating ST_NBLOCKS. */
102#ifndef HAVE_STRUCT_STAT_ST_BLOCKS
103# define ST_BLKSIZE(statbuf) DEV_BSIZE
104# if defined(_POSIX_SOURCE) || !defined(BSIZE) /* fileblocks.c uses BSIZE. */
105# define ST_NBLOCKS(statbuf) \
106 (S_ISREG ((statbuf).st_mode) \
107 || S_ISDIR ((statbuf).st_mode) \
108 ? (statbuf).st_size / ST_NBLOCKSIZE + ((statbuf).st_size % ST_NBLOCKSIZE != 0) : 0)
109# else /* !_POSIX_SOURCE && BSIZE */
110# define ST_NBLOCKS(statbuf) \
111 (S_ISREG ((statbuf).st_mode) \
112 || S_ISDIR ((statbuf).st_mode) \
113 ? st_blocks ((statbuf).st_size) : 0)
114# endif /* !_POSIX_SOURCE && BSIZE */
115#else /* HAVE_STRUCT_STAT_ST_BLOCKS */
116/* Some systems, like Sequents, return st_blksize of 0 on pipes. */
117# define ST_BLKSIZE(statbuf) ((statbuf).st_blksize > 0 \
118 ? (statbuf).st_blksize : DEV_BSIZE)
119# if defined(hpux) || defined(__hpux__) || defined(__hpux)
120/* HP-UX counts st_blocks in 1024-byte units.
121 This loses when mixing HP-UX and BSD filesystems with NFS. */
122# define ST_NBLOCKSIZE 1024
123# else /* !hpux */
124# if defined(_AIX) && defined(_I386)
125/* AIX PS/2 counts st_blocks in 4K units. */
126# define ST_NBLOCKSIZE (4 * 1024)
127# else /* not AIX PS/2 */
128# if defined(_CRAY)
129# define ST_NBLOCKS(statbuf) \
130 (S_ISREG ((statbuf).st_mode) \
131 || S_ISDIR ((statbuf).st_mode) \
132 ? (statbuf).st_blocks * ST_BLKSIZE(statbuf)/ST_NBLOCKSIZE : 0)
133# endif /* _CRAY */
134# endif /* not AIX PS/2 */
135# endif /* !hpux */
136#endif /* HAVE_STRUCT_STAT_ST_BLOCKS */
137
138#ifndef ST_NBLOCKS
139# define ST_NBLOCKS(statbuf) \
140 (S_ISREG ((statbuf).st_mode) \
141 || S_ISDIR ((statbuf).st_mode) \
142 ? (statbuf).st_blocks : 0)
143#endif
144
145#ifndef ST_NBLOCKSIZE
146# define ST_NBLOCKSIZE 512
147#endif
148
149
150#undef MAX
151#define MAX(a, b) ((a) > (b) ? (a) : (b))
152
153static boolean match_lname PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr, boolean ignore_case));
154
155static char *format_date PARAMS((time_t when, int kind));
156static char *ctime_format PARAMS((time_t when));
157
158#ifdef DEBUG
159struct pred_assoc
160{
161 PRED_FUNC pred_func;
162 char *pred_name;
163};
164
165struct pred_assoc pred_table[] =
166{
167 {pred_amin, "amin "},
168 {pred_and, "and "},
169 {pred_anewer, "anewer "},
170 {pred_atime, "atime "},
171 {pred_close, ") "},
172 {pred_cmin, "cmin "},
173 {pred_cnewer, "cnewer "},
174 {pred_comma, ", "},
175 {pred_ctime, "ctime "},
176 {pred_delete, "delete "},
177 {pred_empty, "empty "},
178 {pred_exec, "exec "},
179 {pred_execdir, "execdir "},
180 {pred_executable, "executable "},
181 {pred_false, "false "},
182 {pred_fprint, "fprint "},
183 {pred_fprint0, "fprint0 "},
184 {pred_fprintf, "fprintf "},
185 {pred_fstype, "fstype "},
186 {pred_gid, "gid "},
187 {pred_group, "group "},
188 {pred_ilname, "ilname "},
189 {pred_iname, "iname "},
190 {pred_inum, "inum "},
191 {pred_ipath, "ipath "},
192 {pred_links, "links "},
193 {pred_lname, "lname "},
194 {pred_ls, "ls "},
195 {pred_mmin, "mmin "},
196 {pred_mtime, "mtime "},
197 {pred_name, "name "},
198 {pred_negate, "not "},
199 {pred_newer, "newer "},
200 {pred_nogroup, "nogroup "},
201 {pred_nouser, "nouser "},
202 {pred_ok, "ok "},
203 {pred_okdir, "okdir "},
204 {pred_open, "( "},
205 {pred_or, "or "},
206 {pred_path, "path "},
207 {pred_perm, "perm "},
208 {pred_print, "print "},
209 {pred_print0, "print0 "},
210 {pred_prune, "prune "},
211 {pred_quit, "quit "},
212 {pred_readable, "readable "},
213 {pred_regex, "regex "},
214 {pred_samefile,"samefile "},
215 {pred_size, "size "},
216 {pred_true, "true "},
217 {pred_type, "type "},
218 {pred_uid, "uid "},
219 {pred_used, "used "},
220 {pred_user, "user "},
221 {pred_writable, "writable "},
222 {pred_xtype, "xtype "},
223 {0, "none "}
224};
225#endif
226
227
228/* Predicate processing routines.
229
230 PATHNAME is the full pathname of the file being checked.
231 *STAT_BUF contains information about PATHNAME.
232 *PRED_PTR contains information for applying the predicate.
233
234 Return true if the file passes this predicate, false if not. */
235
236
237/* pred_timewindow
238 *
239 * Returns true if THE_TIME is
240 * COMP_GT: after the specified time
241 * COMP_LT: before the specified time
242 * COMP_EQ: less than WINDOW seconds after the specified time.
243 */
244static boolean
245pred_timewindow(time_t the_time, struct predicate const *pred_ptr, int window)
246{
247 switch (pred_ptr->args.info.kind)
248 {
249 case COMP_GT:
250 if (the_time > (time_t) pred_ptr->args.info.l_val)
251 return true;
252 break;
253 case COMP_LT:
254 if (the_time < (time_t) pred_ptr->args.info.l_val)
255 return true;
256 break;
257 case COMP_EQ:
258 if ((the_time >= (time_t) pred_ptr->args.info.l_val)
259 && (the_time < (time_t) pred_ptr->args.info.l_val + window))
260 return true;
261 break;
262 }
263 return false;
264}
265
266
267boolean
268pred_amin (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
269{
270 (void) &pathname;
271 return pred_timewindow(stat_buf->st_atime, pred_ptr, 60);
272}
273
274boolean
275pred_and (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
276{
277 if (pred_ptr->pred_left == NULL
278 || (*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
279 pred_ptr->pred_left))
280 {
281 /* Check whether we need a stat here. */
282 if (get_info(pathname, state.rel_pathname, stat_buf, pred_ptr) != 0)
283 return false;
284 return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
285 pred_ptr->pred_right));
286 }
287 else
288 return (false);
289}
290
291boolean
292pred_anewer (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
293{
294 (void) &pathname;
295
296 if (stat_buf->st_atime > pred_ptr->args.time)
297 return (true);
298 return (false);
299}
300
301boolean
302pred_atime (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
303{
304 (void) &pathname;
305 return pred_timewindow(stat_buf->st_atime, pred_ptr, DAYSECS);
306}
307
308boolean
309pred_close (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
310{
311 (void) &pathname;
312 (void) &stat_buf;
313 (void) &pred_ptr;
314
315 return true;
316}
317
318boolean
319pred_cmin (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
320{
321 (void) pathname;
322 return pred_timewindow(stat_buf->st_ctime, pred_ptr, 60);
323}
324
325boolean
326pred_cnewer (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
327{
328 (void) pathname;
329
330 if (stat_buf->st_ctime > pred_ptr->args.time)
331 return true;
332 else
333 return false;
334}
335
336boolean
337pred_comma (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
338{
339 if (pred_ptr->pred_left != NULL)
340 (*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
341 pred_ptr->pred_left);
342 /* Check whether we need a stat here. */
343 /* TODO: what about need_type? */
344 if (get_info(pathname, state.rel_pathname, stat_buf, pred_ptr) != 0)
345 return false;
346 return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
347 pred_ptr->pred_right));
348}
349
350boolean
351pred_ctime (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
352{
353 (void) &pathname;
354 return pred_timewindow(stat_buf->st_ctime, pred_ptr, DAYSECS);
355}
356
357boolean
358pred_delete (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
359{
360 (void) pred_ptr;
361 (void) stat_buf;
362 if (strcmp (state.rel_pathname, "."))
363 {
364 if (0 != remove (state.rel_pathname))
365 {
366 error (0, errno, "cannot delete %s", pathname);
367 return false;
368 }
369 else
370 {
371 return true;
372 }
373 }
374
375 /* nothing to do. */
376 return true;
377}
378
379boolean
380pred_empty (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
381{
382 (void) pathname;
383 (void) pred_ptr;
384
385 if (S_ISDIR (stat_buf->st_mode))
386 {
387 DIR *d;
388 struct dirent *dp;
389 boolean empty = true;
390
391 errno = 0;
392 d = opendir (state.rel_pathname);
393 if (d == NULL)
394 {
395 error (0, errno, "%s", pathname);
396 state.exit_status = 1;
397 return false;
398 }
399 for (dp = readdir (d); dp; dp = readdir (d))
400 {
401 if (dp->d_name[0] != '.'
402 || (dp->d_name[1] != '\0'
403 && (dp->d_name[1] != '.' || dp->d_name[2] != '\0')))
404 {
405 empty = false;
406 break;
407 }
408 }
409 if (CLOSEDIR (d))
410 {
411 error (0, errno, "%s", pathname);
412 state.exit_status = 1;
413 return false;
414 }
415 return (empty);
416 }
417 else if (S_ISREG (stat_buf->st_mode))
418 return (stat_buf->st_size == 0);
419 else
420 return (false);
421}
422
423static boolean
424new_impl_pred_exec (const char *pathname, struct stat *stat_buf,
425 struct predicate *pred_ptr,
426 const char *prefix, size_t pfxlen)
427{
428 struct exec_val *execp = &pred_ptr->args.exec_vec;
429 size_t len = strlen(pathname);
430
431 (void) stat_buf;
432
433 if (execp->multiple)
434 {
435 /* Push the argument onto the current list.
436 * The command may or may not be run at this point,
437 * depending on the command line length limits.
438 */
439 bc_push_arg(&execp->ctl,
440 &execp->state,
441 pathname, len+1,
442 prefix, pfxlen,
443 0);
444
445 /* POSIX: If the primary expression is punctuated by a plus
446 * sign, the primary shall always evaluate as true
447 */
448 return true;
449 }
450 else
451 {
452 int i;
453
454 for (i=0; i<execp->num_args; ++i)
455 {
456 bc_do_insert(&execp->ctl,
457 &execp->state,
458 execp->replace_vec[i],
459 strlen(execp->replace_vec[i]),
460 prefix, pfxlen,
461 pathname, len,
462 0);
463 }
464
465 /* Actually invoke the command. */
466 return execp->ctl.exec_callback(&execp->ctl,
467 &execp->state);
468 }
469}
470
471
472boolean
473pred_exec (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
474{
475 return new_impl_pred_exec(pathname, stat_buf, pred_ptr, NULL, 0);
476}
477
478boolean
479pred_execdir (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
480{
481 const char *prefix = (state.rel_pathname[0] == '/') ? NULL : "./";
482 (void) &pathname;
483 return new_impl_pred_exec (state.rel_pathname, stat_buf, pred_ptr,
484 prefix, (prefix ? 2 : 0));
485}
486
487boolean
488pred_false (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
489{
490 (void) &pathname;
491 (void) &stat_buf;
492 (void) &pred_ptr;
493
494
495 return (false);
496}
497
498boolean
499pred_fls (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
500{
501 list_file (pathname, state.rel_pathname, stat_buf, options.start_time,
502 options.output_block_size,
503 pred_ptr->literal_control_chars, pred_ptr->args.stream);
504 return true;
505}
506
507boolean
508pred_fprint (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
509{
510 (void) &pathname;
511 (void) &stat_buf;
512
513 print_quoted(pred_ptr->args.printf_vec.stream,
514 pred_ptr->args.printf_vec.quote_opts,
515 pred_ptr->args.printf_vec.dest_is_tty,
516 "%s\n",
517 pathname);
518 return true;
519}
520
521boolean
522pred_fprint0 (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
523{
524 (void) &pathname;
525 (void) &stat_buf;
526
527 fputs (pathname, pred_ptr->args.stream);
528 putc (0, pred_ptr->args.stream);
529 return (true);
530}
531
532
533
534static char*
535mode_to_filetype(mode_t m)
536{
537 return
538 m == S_IFSOCK ? "s" :
539 m == S_IFLNK ? "l" :
540 m == S_IFREG ? "f" :
541 m == S_IFBLK ? "b" :
542 m == S_IFDIR ? "d" :
543 m == S_IFCHR ? "c" :
544#ifdef S_IFDOOR
545 m == S_IFDOOR ? "D" :
546#endif
547 m == S_IFIFO ? "p" : "U";
548}
549
550
551boolean
552pred_fprintf (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
553{
554 FILE *fp = pred_ptr->args.printf_vec.stream;
555 const struct quoting_options *qopts = pred_ptr->args.printf_vec.quote_opts;
556 boolean ttyflag = pred_ptr->args.printf_vec.dest_is_tty;
557 struct segment *segment;
558 char *cp;
559 char hbuf[LONGEST_HUMAN_READABLE + 1];
560
561 for (segment = pred_ptr->args.printf_vec.segment; segment;
562 segment = segment->next)
563 {
564 if (segment->kind & 0xff00) /* Component of date. */
565 {
566 time_t t;
567
568 switch (segment->kind & 0xff)
569 {
570 case 'A':
571 t = stat_buf->st_atime;
572 break;
573 case 'C':
574 t = stat_buf->st_ctime;
575 break;
576 case 'T':
577 t = stat_buf->st_mtime;
578 break;
579 default:
580 abort ();
581 }
582 /* We trust the output of format_date not to contain
583 * nasty characters, though the value of the date
584 * is itself untrusted data.
585 */
586 /* trusted */
587 fprintf (fp, segment->text,
588 format_date (t, (segment->kind >> 8) & 0xff));
589 continue;
590 }
591
592 switch (segment->kind)
593 {
594 case KIND_PLAIN: /* Plain text string (no % conversion). */
595 /* trusted */
596 fwrite (segment->text, 1, segment->text_len, fp);
597 break;
598 case KIND_STOP: /* Terminate argument and flush output. */
599 /* trusted */
600 fwrite (segment->text, 1, segment->text_len, fp);
601 fflush (fp);
602 return (true);
603 case 'a': /* atime in `ctime' format. */
604 /* UNTRUSTED, probably unexploitable */
605 fprintf (fp, segment->text, ctime_format (stat_buf->st_atime));
606 break;
607 case 'b': /* size in 512-byte blocks */
608 /* UNTRUSTED, probably unexploitable */
609 fprintf (fp, segment->text,
610 human_readable ((uintmax_t) ST_NBLOCKS (*stat_buf),
611 hbuf, human_ceiling,
612 ST_NBLOCKSIZE, 512));
613 break;
614 case 'c': /* ctime in `ctime' format */
615 /* UNTRUSTED, probably unexploitable */
616 fprintf (fp, segment->text, ctime_format (stat_buf->st_ctime));
617 break;
618 case 'd': /* depth in search tree */
619 /* UNTRUSTED, probably unexploitable */
620 fprintf (fp, segment->text, state.curdepth);
621 break;
622 case 'D': /* Device on which file exists (stat.st_dev) */
623 /* trusted */
624 fprintf (fp, segment->text,
625 human_readable ((uintmax_t) stat_buf->st_dev, hbuf,
626 human_ceiling, 1, 1));
627 break;
628 case 'f': /* base name of path */
629 /* sanitised */
630 print_quoted (fp, qopts, ttyflag, segment->text, base_name (pathname));
631 break;
632 case 'F': /* filesystem type */
633 /* trusted */
634 print_quoted (fp, qopts, ttyflag, segment->text, filesystem_type (stat_buf, pathname));
635 break;
636 case 'g': /* group name */
637 /* trusted */
638 /* (well, the actual group is selected by the user but
639 * its name was selected by the system administrator)
640 */
641 {
642 struct group *g;
643
644 g = getgrgid (stat_buf->st_gid);
645 if (g)
646 {
647 segment->text[segment->text_len] = 's';
648 fprintf (fp, segment->text, g->gr_name);
649 break;
650 }
651 /* else fallthru */
652 }
653 case 'G': /* GID number */
654 /* UNTRUSTED, probably unexploitable */
655 fprintf (fp, segment->text,
656 human_readable ((uintmax_t) stat_buf->st_gid, hbuf,
657 human_ceiling, 1, 1));
658 break;
659 case 'h': /* leading directories part of path */
660 /* sanitised */
661 {
662 char cc;
663
664 cp = strrchr (pathname, '/');
665 if (cp == NULL) /* No leading directories. */
666 {
667 /* If there is no slash in the pathname, we still
668 * print the string because it contains characters
669 * other than just '%s'. The %h expands to ".".
670 */
671 print_quoted (fp, qopts, ttyflag, segment->text, ".");
672 }
673 else
674 {
675 cc = *cp;
676 *cp = '\0';
677 print_quoted (fp, qopts, ttyflag, segment->text, pathname);
678 *cp = cc;
679 }
680 break;
681 }
682 case 'H': /* ARGV element file was found under */
683 /* trusted */
684 {
685 char cc = pathname[state.starting_path_length];
686
687 pathname[state.starting_path_length] = '\0';
688 fprintf (fp, segment->text, pathname);
689 pathname[state.starting_path_length] = cc;
690 break;
691 }
692 case 'i': /* inode number */
693 /* UNTRUSTED, but not exploitable I think */
694 fprintf (fp, segment->text,
695 human_readable ((uintmax_t) stat_buf->st_ino, hbuf,
696 human_ceiling,
697 1, 1));
698 break;
699 case 'k': /* size in 1K blocks */
700 /* UNTRUSTED, but not exploitable I think */
701 fprintf (fp, segment->text,
702 human_readable ((uintmax_t) ST_NBLOCKS (*stat_buf),
703 hbuf, human_ceiling,
704 ST_NBLOCKSIZE, 1024));
705 break;
706 case 'l': /* object of symlink */
707 /* sanitised */
708#ifdef S_ISLNK
709 {
710 char *linkname = 0;
711
712 if (S_ISLNK (stat_buf->st_mode))
713 {
714 linkname = get_link_name (pathname, state.rel_pathname);
715 if (linkname == 0)
716 state.exit_status = 1;
717 }
718 if (linkname)
719 {
720 print_quoted (fp, qopts, ttyflag, segment->text, linkname);
721 free (linkname);
722 }
723 else
724 print_quoted (fp, qopts, ttyflag, segment->text, "");
725 }
726#endif /* S_ISLNK */
727 break;
728
729 case 'M': /* mode as 10 chars (eg., "-rwxr-x--x" */
730 /* UNTRUSTED, probably unexploitable */
731 {
732 char modestring[16] ;
733 filemodestring (stat_buf, modestring);
734 modestring[10] = '\0';
735 fprintf (fp, segment->text, modestring);
736 }
737 break;
738
739 case 'm': /* mode as octal number (perms only) */
740 /* UNTRUSTED, probably unexploitable */
741 {
742 /* Output the mode portably using the traditional numbers,
743 even if the host unwisely uses some other numbering
744 scheme. But help the compiler in the common case where
745 the host uses the traditional numbering scheme. */
746 mode_t m = stat_buf->st_mode;
747 boolean traditional_numbering_scheme =
748 (S_ISUID == 04000 && S_ISGID == 02000 && S_ISVTX == 01000
749 && S_IRUSR == 00400 && S_IWUSR == 00200 && S_IXUSR == 00100
750 && S_IRGRP == 00040 && S_IWGRP == 00020 && S_IXGRP == 00010
751 && S_IROTH == 00004 && S_IWOTH == 00002 && S_IXOTH == 00001);
752 fprintf (fp, segment->text,
753 (traditional_numbering_scheme
754 ? m & MODE_ALL
755 : ((m & S_ISUID ? 04000 : 0)
756 | (m & S_ISGID ? 02000 : 0)
757 | (m & S_ISVTX ? 01000 : 0)
758 | (m & S_IRUSR ? 00400 : 0)
759 | (m & S_IWUSR ? 00200 : 0)
760 | (m & S_IXUSR ? 00100 : 0)
761 | (m & S_IRGRP ? 00040 : 0)
762 | (m & S_IWGRP ? 00020 : 0)
763 | (m & S_IXGRP ? 00010 : 0)
764 | (m & S_IROTH ? 00004 : 0)
765 | (m & S_IWOTH ? 00002 : 0)
766 | (m & S_IXOTH ? 00001 : 0))));
767 }
768 break;
769
770 case 'n': /* number of links */
771 /* UNTRUSTED, probably unexploitable */
772 fprintf (fp, segment->text,
773 human_readable ((uintmax_t) stat_buf->st_nlink,
774 hbuf,
775 human_ceiling,
776 1, 1));
777 break;
778 case 'p': /* pathname */
779 /* sanitised */
780 print_quoted (fp, qopts, ttyflag, segment->text, pathname);
781 break;
782 case 'P': /* pathname with ARGV element stripped */
783 /* sanitised */
784 if (state.curdepth > 0)
785 {
786 cp = pathname + state.starting_path_length;
787 if (*cp == '/')
788 /* Move past the slash between the ARGV element
789 and the rest of the pathname. But if the ARGV element
790 ends in a slash, we didn't add another, so we've
791 already skipped past it. */
792 cp++;
793 }
794 else
795 cp = "";
796 print_quoted (fp, qopts, ttyflag, segment->text, cp);
797 break;
798 case 's': /* size in bytes */
799 /* UNTRUSTED, probably unexploitable */
800 fprintf (fp, segment->text,
801 human_readable ((uintmax_t) stat_buf->st_size,
802 hbuf, human_ceiling, 1, 1));
803 break;
804 case 't': /* mtime in `ctime' format */
805 /* UNTRUSTED, probably unexploitable */
806 fprintf (fp, segment->text, ctime_format (stat_buf->st_mtime));
807 break;
808 case 'u': /* user name */
809 /* trusted */
810 /* (well, the actual user is selected by the user on systems
811 * where chown is not restricted, but the user name was
812 * selected by the system administrator)
813 */
814 {
815 struct passwd *p;
816
817 p = getpwuid (stat_buf->st_uid);
818 if (p)
819 {
820 segment->text[segment->text_len] = 's';
821 fprintf (fp, segment->text, p->pw_name);
822 break;
823 }
824 /* else fallthru */
825 }
826
827 case 'U': /* UID number */
828 /* UNTRUSTED, probably unexploitable */
829 fprintf (fp, segment->text,
830 human_readable ((uintmax_t) stat_buf->st_uid, hbuf,
831 human_ceiling, 1, 1));
832 break;
833
834 /* type of filesystem entry like `ls -l`: (d,-,l,s,p,b,c,n) n=nonexistent(symlink) */
835 case 'Y': /* in case of symlink */
836 /* trusted */
837 {
838#ifdef S_ISLNK
839 if (S_ISLNK (stat_buf->st_mode))
840 {
841 struct stat sbuf;
842 /* If we would normally follow links, do not do so.
843 * If we would normally not follow links, do so.
844 */
845 if ((following_links() ? lstat : stat)
846 (state.rel_pathname, &sbuf) != 0)
847 {
848 if ( errno == ENOENT ) {
849 fprintf (fp, segment->text, "N");
850 break;
851 };
852 if ( errno == ELOOP ) {
853 fprintf (fp, segment->text, "L");
854 break;
855 };
856 error (0, errno, "%s", pathname);
857 /* exit_status = 1;
858 return (false); */
859 }
860 fprintf (fp, segment->text,
861 mode_to_filetype(sbuf.st_mode & S_IFMT));
862 }
863#endif /* S_ISLNK */
864 else
865 {
866 fprintf (fp, segment->text,
867 mode_to_filetype(stat_buf->st_mode & S_IFMT));
868 }
869 }
870 break;
871
872 case 'y':
873 /* trusted */
874 {
875 fprintf (fp, segment->text,
876 mode_to_filetype(stat_buf->st_mode & S_IFMT));
877 }
878 break;
879 }
880 }
881 return true;
882}
883
884boolean
885pred_fstype (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
886{
887 (void) pathname;
888
889 if (strcmp (filesystem_type (stat_buf, pathname), pred_ptr->args.str) == 0)
890 return true;
891 else
892 return false;
893}
894
895boolean
896pred_gid (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
897{
898 (void) pathname;
899
900 switch (pred_ptr->args.info.kind)
901 {
902 case COMP_GT:
903 if (stat_buf->st_gid > pred_ptr->args.info.l_val)
904 return (true);
905 break;
906 case COMP_LT:
907 if (stat_buf->st_gid < pred_ptr->args.info.l_val)
908 return (true);
909 break;
910 case COMP_EQ:
911 if (stat_buf->st_gid == pred_ptr->args.info.l_val)
912 return (true);
913 break;
914 }
915 return (false);
916}
917
918boolean
919pred_group (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
920{
921 (void) pathname;
922
923 if (pred_ptr->args.gid == stat_buf->st_gid)
924 return (true);
925 else
926 return (false);
927}
928
929boolean
930pred_ilname (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
931{
932 return match_lname (pathname, stat_buf, pred_ptr, true);
933}
934
935boolean
936pred_iname (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
937{
938 const char *base;
939
940 (void) stat_buf;
941
942 /* FNM_PERIOD is not used here because POSIX requires that it not be.
943 * See http://standards.ieee.org/reading/ieee/interp/1003-2-92_int/pasc-1003.2-126.html
944 */
945 base = base_name (pathname);
946 if (fnmatch (pred_ptr->args.str, base, FNM_CASEFOLD) == 0)
947 return (true);
948 return (false);
949}
950
951boolean
952pred_inum (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
953{
954 (void) pathname;
955
956 switch (pred_ptr->args.info.kind)
957 {
958 case COMP_GT:
959 if (stat_buf->st_ino > pred_ptr->args.info.l_val)
960 return (true);
961 break;
962 case COMP_LT:
963 if (stat_buf->st_ino < pred_ptr->args.info.l_val)
964 return (true);
965 break;
966 case COMP_EQ:
967 if (stat_buf->st_ino == pred_ptr->args.info.l_val)
968 return (true);
969 break;
970 }
971 return (false);
972}
973
974boolean
975pred_ipath (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
976{
977 (void) stat_buf;
978
979 if (fnmatch (pred_ptr->args.str, pathname, FNM_CASEFOLD) == 0)
980 return (true);
981 return (false);
982}
983
984boolean
985pred_links (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
986{
987 (void) pathname;
988
989 switch (pred_ptr->args.info.kind)
990 {
991 case COMP_GT:
992 if (stat_buf->st_nlink > pred_ptr->args.info.l_val)
993 return (true);
994 break;
995 case COMP_LT:
996 if (stat_buf->st_nlink < pred_ptr->args.info.l_val)
997 return (true);
998 break;
999 case COMP_EQ:
1000 if (stat_buf->st_nlink == pred_ptr->args.info.l_val)
1001 return (true);
1002 break;
1003 }
1004 return (false);
1005}
1006
1007boolean
1008pred_lname (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1009{
1010 return match_lname (pathname, stat_buf, pred_ptr, false);
1011}
1012
1013static boolean
1014match_lname (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr, boolean ignore_case)
1015{
1016 boolean ret = false;
1017#ifdef S_ISLNK
1018 if (S_ISLNK (stat_buf->st_mode))
1019 {
1020 char *linkname = get_link_name (pathname, state.rel_pathname);
1021 if (linkname)
1022 {
1023 if (fnmatch (pred_ptr->args.str, linkname,
1024 ignore_case ? FNM_CASEFOLD : 0) == 0)
1025 ret = true;
1026 free (linkname);
1027 }
1028 }
1029#endif /* S_ISLNK */
1030 return ret;
1031}
1032
1033boolean
1034pred_ls (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1035{
1036 list_file (pathname, state.rel_pathname, stat_buf, options.start_time,
1037 options.output_block_size,
1038 pred_ptr->literal_control_chars,
1039 stdout);
1040 return true;
1041}
1042
1043boolean
1044pred_mmin (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1045{
1046 (void) &pathname;
1047 return pred_timewindow(stat_buf->st_mtime, pred_ptr, 60);
1048}
1049
1050boolean
1051pred_mtime (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1052{
1053 (void) pathname;
1054 return pred_timewindow(stat_buf->st_mtime, pred_ptr, DAYSECS);
1055}
1056
1057boolean
1058pred_name (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1059{
1060 const char *base;
1061
1062 (void) stat_buf;
1063 base = base_name (pathname);
1064
1065 /* FNM_PERIOD is not used here because POSIX requires that it not be.
1066 * See http://standards.ieee.org/reading/ieee/interp/1003-2-92_int/pasc-1003.2-126.html
1067 */
1068 if (fnmatch (pred_ptr->args.str, base, 0) == 0)
1069 return (true);
1070 return (false);
1071}
1072
1073boolean
1074pred_negate (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1075{
1076 /* Check whether we need a stat here. */
1077 /* TODO: what about need_type? */
1078 if (get_info(pathname, state.rel_pathname, stat_buf, pred_ptr) != 0)
1079 return false;
1080 return (!(*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
1081 pred_ptr->pred_right));
1082}
1083
1084boolean
1085pred_newer (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1086{
1087 (void) pathname;
1088
1089 if (stat_buf->st_mtime > pred_ptr->args.time)
1090 return (true);
1091 return (false);
1092}
1093
1094boolean
1095pred_nogroup (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1096{
1097 (void) pathname;
1098 (void) pred_ptr;
1099
1100#ifdef CACHE_IDS
1101 extern char *gid_unused;
1102
1103 return gid_unused[(unsigned) stat_buf->st_gid];
1104#else
1105 return getgrgid (stat_buf->st_gid) == NULL;
1106#endif
1107}
1108
1109boolean
1110pred_nouser (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1111{
1112#ifdef CACHE_IDS
1113 extern char *uid_unused;
1114#endif
1115
1116 (void) pathname;
1117 (void) pred_ptr;
1118
1119#ifdef CACHE_IDS
1120 return uid_unused[(unsigned) stat_buf->st_uid];
1121#else
1122 return getpwuid (stat_buf->st_uid) == NULL;
1123#endif
1124}
1125
1126
1127static boolean
1128is_ok(const char *program, const char *arg)
1129{
1130 fflush (stdout);
1131 /* The draft open standard requires that, in the POSIX locale,
1132 the last non-blank character of this prompt be '?'.
1133 The exact format is not specified.
1134 This standard does not have requirements for locales other than POSIX
1135 */
1136 /* XXX: printing UNTRUSTED data here. */
1137 fprintf (stderr, _("< %s ... %s > ? "), program, arg);
1138 fflush (stderr);
1139 return yesno();
1140}
1141
1142boolean
1143pred_ok (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1144{
1145 if (is_ok(pred_ptr->args.exec_vec.replace_vec[0], pathname))
1146 return new_impl_pred_exec (pathname, stat_buf, pred_ptr, NULL, 0);
1147 else
1148 return false;
1149}
1150
1151boolean
1152pred_okdir (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1153{
1154 const char *prefix = (state.rel_pathname[0] == '/') ? NULL : "./";
1155 if (is_ok(pred_ptr->args.exec_vec.replace_vec[0], pathname))
1156 return new_impl_pred_exec (state.rel_pathname, stat_buf, pred_ptr,
1157 prefix, (prefix ? 2 : 0));
1158 else
1159 return false;
1160}
1161
1162boolean
1163pred_open (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1164{
1165 (void) pathname;
1166 (void) stat_buf;
1167 (void) pred_ptr;
1168 return true;
1169}
1170
1171boolean
1172pred_or (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1173{
1174 if (pred_ptr->pred_left == NULL
1175 || !(*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
1176 pred_ptr->pred_left))
1177 {
1178 if (get_info(pathname, state.rel_pathname, stat_buf, pred_ptr) != 0)
1179 return false;
1180 return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
1181 pred_ptr->pred_right));
1182 }
1183 else
1184 return true;
1185}
1186
1187boolean
1188pred_path (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1189{
1190 (void) stat_buf;
1191 if (fnmatch (pred_ptr->args.str, pathname, 0) == 0)
1192 return (true);
1193 return (false);
1194}
1195
1196boolean
1197pred_perm (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1198{
1199 mode_t mode = stat_buf->st_mode;
1200 mode_t perm_val = pred_ptr->args.perm.val[S_ISDIR (mode) != 0];
1201 (void) pathname;
1202 switch (pred_ptr->args.perm.kind)
1203 {
1204 case PERM_AT_LEAST:
1205 return (mode & perm_val) == perm_val;
1206 break;
1207
1208 case PERM_ANY:
1209 /* True if any of the bits set in the mask are also set in the file's mode.
1210 *
1211 *
1212 * Otherwise, if onum is prefixed by a hyphen, the primary shall
1213 * evaluate as true if at least all of the bits specified in
1214 * onum that are also set in the octal mask 07777 are set.
1215 *
1216 * Eric Blake's interpretation is that the mode argument is zero,
1217
1218 */
1219 if (0 == perm_val)
1220 return true; /* Savannah bug 14748; we used to return false */
1221 else
1222 return (mode & perm_val) != 0;
1223 break;
1224
1225 case PERM_EXACT:
1226 return (mode & MODE_ALL) == perm_val;
1227 break;
1228
1229 default:
1230 abort ();
1231 break;
1232 }
1233}
1234
1235
1236boolean
1237pred_executable (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1238{
1239 (void) pathname;
1240 (void) stat_buf;
1241 (void) pred_ptr;
1242
1243 return 0 == access(state.rel_pathname, X_OK);
1244}
1245
1246boolean
1247pred_readable (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1248{
1249 (void) pathname;
1250 (void) stat_buf;
1251 (void) pred_ptr;
1252
1253 return 0 == access(state.rel_pathname, R_OK);
1254}
1255
1256boolean
1257pred_writable (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1258{
1259 (void) pathname;
1260 (void) stat_buf;
1261 (void) pred_ptr;
1262
1263 return 0 == access(state.rel_pathname, W_OK);
1264}
1265
1266boolean
1267pred_print (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1268{
1269 (void) stat_buf;
1270 (void) pred_ptr;
1271 /* puts (pathname); */
1272 print_quoted(pred_ptr->args.printf_vec.stream,
1273 pred_ptr->args.printf_vec.quote_opts,
1274 pred_ptr->args.printf_vec.dest_is_tty,
1275 "%s\n", pathname);
1276 return true;
1277}
1278
1279boolean
1280pred_print0 (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1281{
1282 (void) stat_buf;
1283 (void) pred_ptr;
1284 fputs (pathname, stdout);
1285 putc (0, stdout);
1286 return (true);
1287}
1288
1289boolean
1290pred_prune (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1291{
1292 (void) pathname;
1293 (void) pred_ptr;
1294
1295 if (options.do_dir_first == true &&
1296 stat_buf != NULL &&
1297 S_ISDIR(stat_buf->st_mode))
1298 state.stop_at_current_level = true;
1299
1300 return (options.do_dir_first); /* This is what SunOS find seems to do. */
1301}
1302
1303boolean
1304pred_quit (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1305{
1306 (void) pathname;
1307 (void) stat_buf;
1308 (void) pred_ptr;
1309
1310 /* Run any cleanups. This includes executing any command lines
1311 * we have partly built but not executed.
1312 */
1313 cleanup();
1314
1315 /* Since -exec and friends don't leave child processes running in the
1316 * background, there is no need to wait for them here.
1317 */
1318 exit(state.exit_status); /* 0 for success, etc. */
1319}
1320
1321boolean
1322pred_regex (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1323{
1324 int len = strlen (pathname);
1325(void) stat_buf;
1326 if (re_match (pred_ptr->args.regex, pathname, len, 0,
1327 (struct re_registers *) NULL) == len)
1328 return (true);
1329 return (false);
1330}
1331
1332boolean
1333pred_size (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1334{
1335 uintmax_t f_val;
1336
1337 (void) pathname;
1338 f_val = ((stat_buf->st_size / pred_ptr->args.size.blocksize)
1339 + (stat_buf->st_size % pred_ptr->args.size.blocksize != 0));
1340 switch (pred_ptr->args.size.kind)
1341 {
1342 case COMP_GT:
1343 if (f_val > pred_ptr->args.size.size)
1344 return (true);
1345 break;
1346 case COMP_LT:
1347 if (f_val < pred_ptr->args.size.size)
1348 return (true);
1349 break;
1350 case COMP_EQ:
1351 if (f_val == pred_ptr->args.size.size)
1352 return (true);
1353 break;
1354 }
1355 return (false);
1356}
1357
1358boolean
1359pred_samefile (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1360{
1361 /* Potential optimisation: because of the loop protection, we always
1362 * know the device of the current directory, hence the device number
1363 * of the file we're currently considering. If -L is not in effect,
1364 * and the device number of the file we're looking for is not the
1365 * same as the device number of the current directory, this
1366 * predicate cannot return true. Hence there would be no need to
1367 * stat the file we're lookingn at.
1368 */
1369 (void) pathname;
1370
1371 return stat_buf->st_ino == pred_ptr->args.fileid.ino
1372 && stat_buf->st_dev == pred_ptr->args.fileid.dev;
1373}
1374
1375boolean
1376pred_true (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1377{
1378 (void) pathname;
1379 (void) stat_buf;
1380 (void) pred_ptr;
1381 return true;
1382}
1383
1384boolean
1385pred_type (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1386{
1387 mode_t mode;
1388 mode_t type = pred_ptr->args.type;
1389
1390 assert(state.have_type);
1391 assert(state.type != 0);
1392
1393 (void) pathname;
1394
1395 if (state.have_stat)
1396 mode = stat_buf->st_mode;
1397 else
1398 mode = state.type;
1399
1400#ifndef S_IFMT
1401 /* POSIX system; check `mode' the slow way. */
1402 if ((S_ISBLK (mode) && type == S_IFBLK)
1403 || (S_ISCHR (mode) && type == S_IFCHR)
1404 || (S_ISDIR (mode) && type == S_IFDIR)
1405 || (S_ISREG (mode) && type == S_IFREG)
1406#ifdef S_IFLNK
1407 || (S_ISLNK (mode) && type == S_IFLNK)
1408#endif
1409#ifdef S_IFIFO
1410 || (S_ISFIFO (mode) && type == S_IFIFO)
1411#endif
1412#ifdef S_IFSOCK
1413 || (S_ISSOCK (mode) && type == S_IFSOCK)
1414#endif
1415#ifdef S_IFDOOR
1416 || (S_ISDOOR (mode) && type == S_IFDOOR)
1417#endif
1418 )
1419#else /* S_IFMT */
1420 /* Unix system; check `mode' the fast way. */
1421 if ((mode & S_IFMT) == type)
1422#endif /* S_IFMT */
1423 return (true);
1424 else
1425 return (false);
1426}
1427
1428boolean
1429pred_uid (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1430{
1431 (void) pathname;
1432 switch (pred_ptr->args.info.kind)
1433 {
1434 case COMP_GT:
1435 if (stat_buf->st_uid > pred_ptr->args.info.l_val)
1436 return (true);
1437 break;
1438 case COMP_LT:
1439 if (stat_buf->st_uid < pred_ptr->args.info.l_val)
1440 return (true);
1441 break;
1442 case COMP_EQ:
1443 if (stat_buf->st_uid == pred_ptr->args.info.l_val)
1444 return (true);
1445 break;
1446 }
1447 return (false);
1448}
1449
1450boolean
1451pred_used (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1452{
1453 time_t delta;
1454
1455 (void) pathname;
1456 delta = stat_buf->st_atime - stat_buf->st_ctime; /* Use difftime? */
1457 return pred_timewindow(delta, pred_ptr, DAYSECS);
1458}
1459
1460boolean
1461pred_user (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1462{
1463 (void) pathname;
1464 if (pred_ptr->args.uid == stat_buf->st_uid)
1465 return (true);
1466 else
1467 return (false);
1468}
1469
1470boolean
1471pred_xtype (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1472{
1473 struct stat sbuf; /* local copy, not stat_buf because we're using a different stat method */
1474 int (*ystat) (const char*, struct stat *p);
1475
1476 /* If we would normally stat the link itself, stat the target instead.
1477 * If we would normally follow the link, stat the link itself instead.
1478 */
1479 if (following_links())
1480 ystat = optionp_stat;
1481 else
1482 ystat = optionl_stat;
1483
1484 if ((*ystat) (state.rel_pathname, &sbuf) != 0)
1485 {
1486 if (following_links() && errno == ENOENT)
1487 {
1488 /* If we failed to follow the symlink,
1489 * fall back on looking at the symlink itself.
1490 */
1491 /* Mimic behavior of ls -lL. */
1492 return (pred_type (pathname, stat_buf, pred_ptr));
1493 }
1494 else
1495 {
1496 error (0, errno, "%s", pathname);
1497 state.exit_status = 1;
1498 }
1499 return false;
1500 }
1501 /* Now that we have our stat() information, query it in the same
1502 * way that -type does.
1503 */
1504 return (pred_type (pathname, &sbuf, pred_ptr));
1505}
1506
1507
1508/* 1) fork to get a child; parent remembers the child pid
1509 2) child execs the command requested
1510 3) parent waits for child; checks for proper pid of child
1511
1512 Possible returns:
1513
1514 ret errno status(h) status(l)
1515
1516 pid x signal# 0177 stopped
1517 pid x exit arg 0 term by _exit
1518 pid x 0 signal # term by signal
1519 -1 EINTR parent got signal
1520 -1 other some other kind of error
1521
1522 Return true only if the pid matches, status(l) is
1523 zero, and the exit arg (status high) is 0.
1524 Otherwise return false, possibly printing an error message. */
1525
1526
1527static void
1528prep_child_for_exec (boolean close_stdin)
1529{
1530 if (close_stdin)
1531 {
1532 const char inputfile[] = "/dev/null";
1533 /* fprintf(stderr, "attaching stdin to /dev/null\n"); */
1534
1535 close(0);
1536 if (open(inputfile, O_RDONLY) < 0)
1537 {
1538 /* This is not entirely fatal, since
1539 * executing the child with a closed
1540 * stdin is almost as good as executing it
1541 * with its stdin attached to /dev/null.
1542 */
1543 error (0, errno, "%s", inputfile);
1544 }
1545 }
1546}
1547
1548
1549
1550int
1551launch (const struct buildcmd_control *ctl,
1552 struct buildcmd_state *buildstate)
1553{
1554 int wait_status;
1555 pid_t child_pid;
1556 static int first_time = 1;
1557 const struct exec_val *execp = buildstate->usercontext;
1558
1559 /* Null terminate the arg list. */
1560 bc_push_arg (ctl, buildstate, (char *) NULL, 0, NULL, 0, false);
1561
1562 /* Make sure output of command doesn't get mixed with find output. */
1563 fflush (stdout);
1564 fflush (stderr);
1565
1566 /* Make sure to listen for the kids. */
1567 if (first_time)
1568 {
1569 first_time = 0;
1570 signal (SIGCHLD, SIG_DFL);
1571 }
1572
1573 child_pid = fork ();
1574 if (child_pid == -1)
1575 error (1, errno, _("cannot fork"));
1576 if (child_pid == 0)
1577 {
1578 /* We be the child. */
1579 prep_child_for_exec(execp->close_stdin);
1580
1581 /* For -exec and -ok, change directory back to the starting directory.
1582 * for -execdir and -okdir, stay in the directory we are searching
1583 * (the latter is more secure).
1584 */
1585 if (!execp->use_current_dir)
1586 {
1587 /* Even if DebugSearch is set, don't announce our change of
1588 * directory, since we're not going to emit a subsequent
1589 * announcement of a call to stat() anyway, as we're about
1590 * to exec something.
1591 */
1592 if (starting_desc < 0
1593 ? chdir (starting_dir) != 0
1594 : fchdir (starting_desc) != 0)
1595 {
1596 error (0, errno, "%s", starting_dir);
1597 _exit (1);
1598 }
1599 }
1600
1601 execvp (buildstate->cmd_argv[0], buildstate->cmd_argv);
1602 error (0, errno, "%s", buildstate->cmd_argv[0]);
1603 _exit (1);
1604 }
1605
1606
1607 /* In parent; set up for next time. */
1608 bc_clear_args(ctl, buildstate);
1609
1610
1611 while (waitpid (child_pid, &wait_status, 0) == (pid_t) -1)
1612 {
1613 if (errno != EINTR)
1614 {
1615 error (0, errno, _("error waiting for %s"), buildstate->cmd_argv[0]);
1616 state.exit_status = 1;
1617 return 0; /* FAIL */
1618 }
1619 }
1620
1621 if (WIFSIGNALED (wait_status))
1622 {
1623 error (0, 0, _("%s terminated by signal %d"),
1624 buildstate->cmd_argv[0], WTERMSIG (wait_status));
1625
1626 if (execp->multiple)
1627 {
1628 /* -exec \; just returns false if the invoked command fails.
1629 * -exec {} + returns true if the invoked command fails, but
1630 * sets the program exit status.
1631 */
1632 state.exit_status = 1;
1633 }
1634
1635 return 1; /* OK */
1636 }
1637
1638 if (0 == WEXITSTATUS (wait_status))
1639 {
1640 return 1; /* OK */
1641 }
1642 else
1643 {
1644 if (execp->multiple)
1645 {
1646 /* -exec \; just returns false if the invoked command fails.
1647 * -exec {} + returns true if the invoked command fails, but
1648 * sets the program exit status.
1649 */
1650 state.exit_status = 1;
1651 }
1652 return 0; /* FAIL */
1653 }
1654
1655}
1656
1657
1658/* Return a static string formatting the time WHEN according to the
1659 strftime format character KIND. */
1660
1661static char *
1662format_date (time_t when, int kind)
1663{
1664 static char buf[MAX (LONGEST_HUMAN_READABLE + 2, 64)];
1665 struct tm *tm;
1666 char fmt[6];
1667
1668 fmt[0] = '%';
1669 fmt[1] = kind;
1670 fmt[2] = '\0';
1671 if (kind == '+')
1672 strcpy (fmt, "%F+%T");
1673
1674 if (kind != '@'
1675 && (tm = localtime (&when))
1676 && strftime (buf, sizeof buf, fmt, tm))
1677 return buf;
1678 else
1679 {
1680 uintmax_t w = when;
1681 char *p = human_readable (when < 0 ? -w : w, buf + 1,
1682 human_ceiling, 1, 1);
1683 if (when < 0)
1684 *--p = '-';
1685 return p;
1686 }
1687}
1688
1689static char *
1690ctime_format (time_t when)
1691{
1692 char *r = ctime (&when);
1693 if (!r)
1694 {
1695 /* The time cannot be represented as a struct tm.
1696 Output it as an integer. */
1697 return format_date (when, '@');
1698 }
1699 else
1700 {
1701 /* Remove the trailing newline from the ctime output,
1702 being careful not to assume that the output is fixed-width. */
1703 *strchr (r, '\n') = '\0';
1704 return r;
1705 }
1706}
1707
1708
1709/* Copy STR into BUF and trim blanks from the end of BUF.
1710 Return BUF. */
1711
1712static char *
1713blank_rtrim (str, buf)
1714 char *str;
1715 char *buf;
1716{
1717 int i;
1718
1719 if (str == NULL)
1720 return (NULL);
1721 strcpy (buf, str);
1722 i = strlen (buf) - 1;
1723 while ((i >= 0) && ((buf[i] == ' ') || buf[i] == '\t'))
1724 i--;
1725 buf[++i] = '\0';
1726 return (buf);
1727}
1728
1729
1730/* Print out the predicate list starting at NODE. */
1731void
1732print_list (FILE *fp, struct predicate *node)
1733{
1734 struct predicate *cur;
1735 char name[256];
1736
1737 cur = node;
1738 while (cur != NULL)
1739 {
1740 fprintf (fp, "%s ", blank_rtrim (cur->p_name, name));
1741 cur = cur->pred_next;
1742 }
1743 fprintf (fp, "\n");
1744}
1745
1746
1747/* Print out the predicate list starting at NODE. */
1748static void
1749print_parenthesised(FILE *fp, struct predicate *node)
1750{
1751 int parens = 0;
1752
1753 if (node)
1754 {
1755 if ( ( (node->pred_func == pred_or)
1756 || (node->pred_func == pred_and) )
1757 && node->pred_left == NULL)
1758 {
1759 /* We print "<nothing> or X" as just "X"
1760 * We print "<nothing> and X" as just "X"
1761 */
1762 print_parenthesised(fp, node->pred_right);
1763 }
1764 else
1765 {
1766 if (node->pred_left || node->pred_right)
1767 parens = 1;
1768
1769 if (parens)
1770 fprintf(fp, "%s", " ( ");
1771 print_optlist(fp, node);
1772 if (parens)
1773 fprintf(fp, "%s", " ) ");
1774 }
1775 }
1776}
1777
1778
1779void
1780print_optlist (FILE *fp, const struct predicate *p)
1781{
1782 if (p)
1783 {
1784 print_parenthesised(fp, p->pred_left);
1785 fprintf (fp,
1786 "%s%s",
1787 p->need_stat ? "[call stat] " : "",
1788 p->need_type ? "[need type] " : "");
1789 print_predicate(fp, p);
1790 fprintf(fp, " [%g] ", p->est_success_rate);
1791 print_parenthesised(fp, p->pred_right);
1792 }
1793}
1794
1795
1796void
1797pred_sanity_check(const struct predicate *predicates)
1798{
1799 const struct predicate *p;
1800
1801 for (p=predicates; p != NULL; p=p->pred_next)
1802 {
1803 /* All predicates must do something. */
1804 assert(p->pred_func != NULL);
1805
1806 /* All predicates must have a parser table entry. */
1807 assert(p->parser_entry != NULL);
1808
1809 /* If the parser table tells us that just one predicate function is
1810 * possible, verify that that is still the one that is in effect.
1811 * If the parser has NULL for the predicate function, that means that
1812 * the parse_xxx function fills it in, so we can't check it.
1813 */
1814 if (p->parser_entry->pred_func)
1815 {
1816 assert(p->parser_entry->pred_func == p->pred_func);
1817 }
1818
1819 switch (p->parser_entry->type)
1820 {
1821 /* Options all take effect during parsing, so there should
1822 * be no predicate entries corresponding to them. Hence we
1823 * should not see any ARG_OPTION or ARG_POSITIONAL_OPTION
1824 * items.
1825 *
1826 * This is a silly way of coding this test, but it prevents
1827 * a compiler warning (i.e. otherwise it would think that
1828 * there would be case statements missing).
1829 */
1830 case ARG_OPTION:
1831 case ARG_POSITIONAL_OPTION:
1832 assert(p->parser_entry->type != ARG_OPTION);
1833 assert(p->parser_entry->type != ARG_POSITIONAL_OPTION);
1834 break;
1835
1836 case ARG_ACTION:
1837 assert(p->side_effects); /* actions have side effects. */
1838 if (p->pred_func != pred_prune && p->pred_func != pred_quit)
1839 {
1840 /* actions other than -prune and -quit should
1841 * inhibit the default -print
1842 */
1843 assert(p->no_default_print);
1844 }
1845 break;
1846
1847 case ARG_PUNCTUATION:
1848 case ARG_TEST:
1849 case ARG_NOOP:
1850 /* Punctuation and tests should have no side
1851 * effects and not inhibit default print.
1852 */
1853 assert(!p->no_default_print);
1854 assert(!p->side_effects);
1855 break;
1856
1857 }
1858 }
1859}
Note: See TracBrowser for help on using the repository browser.