home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 9 / FreshFishVol9-CD2.bin / bbs / gnu / findutils-4.1-src.lha / findutils-4.1 / find / pred.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-12  |  34.2 KB  |  1,529 lines

  1. /* pred.c -- execute the expression tree.
  2.    Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
  3.  
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2, or (at your option)
  7.    any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. #include <config.h>
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #include <stdio.h>
  22. #include <signal.h>
  23. #include <pwd.h>
  24. #include <grp.h>
  25. #include "defs.h"
  26. /* Put fnmatch.h after defs.h, since defs.h includes unistd.h, which on
  27.    some systems defines FNM_PATHNAME, which fnmatch.h then wants to undef
  28.    and do it's own way. */
  29. #include <fnmatch.h>
  30. #include "modetype.h"
  31. #include "wait.h"
  32.  
  33. #if !defined(SIGCHLD) && defined(SIGCLD)
  34. #define SIGCHLD SIGCLD
  35. #endif
  36.  
  37. #ifndef _POSIX_VERSION
  38. struct passwd *getpwuid ();
  39. struct group *getgrgid ();
  40. #endif
  41.  
  42. #if HAVE_DIRENT_H
  43. # include <dirent.h>
  44. # define NAMLEN(dirent) strlen((dirent)->d_name)
  45. #else
  46. # define dirent direct
  47. # define NAMLEN(dirent) (dirent)->d_namlen
  48. # if HAVE_SYS_NDIR_H
  49. #  include <sys/ndir.h>
  50. # endif
  51. # if HAVE_SYS_DIR_H
  52. #  include <sys/dir.h>
  53. # endif
  54. # if HAVE_NDIR_H
  55. #  include <ndir.h>
  56. # endif
  57. #endif
  58.  
  59. #ifdef CLOSEDIR_VOID
  60. /* Fake a return value. */
  61. #define CLOSEDIR(d) (closedir (d), 0)
  62. #else
  63. #define CLOSEDIR(d) closedir (d)
  64. #endif
  65.  
  66. #ifndef S_IFLNK
  67. #define lstat stat
  68. #endif
  69.  
  70. /* Extract or fake data from a `struct stat'.
  71.    ST_NBLOCKS: Number of 512-byte blocks in the file
  72.    (including indirect blocks).
  73.    HP-UX, perhaps uniquely, counts st_blocks in 1024-byte units.
  74.    This workaround loses when mixing HP-UX and 4BSD filesystems, though.  */
  75. #ifdef _POSIX_SOURCE
  76. # define ST_NBLOCKS(statp) (((statp)->st_size + 512 - 1) / 512)
  77. #else
  78. # ifndef HAVE_ST_BLOCKS
  79. #  define ST_NBLOCKS(statp) (st_blocks ((statp)->st_size))
  80. # else
  81. #  if defined(hpux) || defined(__hpux__)
  82. #   define ST_NBLOCKS(statp) ((statp)->st_blocks * 2)
  83. #  else
  84. #   define ST_NBLOCKS(statp) ((statp)->st_blocks)
  85. #  endif
  86. # endif
  87. #endif
  88.  
  89. int lstat ();
  90. int stat ();
  91.  
  92. static boolean insert_lname P_((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr, boolean ignore_case));
  93. static boolean launch P_((struct predicate *pred_ptr));
  94. static char *format_date P_((time_t when, int kind));
  95.  
  96. #ifdef    DEBUG
  97. struct pred_assoc
  98. {
  99.   PFB pred_func;
  100.   char *pred_name;
  101. };
  102.  
  103. struct pred_assoc pred_table[] =
  104. {
  105.   {pred_amin, "amin    "},
  106.   {pred_and, "and     "},
  107.   {pred_anewer, "anewer  "},
  108.   {pred_atime, "atime   "},
  109.   {pred_close, ")       "},
  110.   {pred_amin, "cmin    "},
  111.   {pred_cnewer, "cnewer  "},
  112.   {pred_comma, ",       "},
  113.   {pred_ctime, "ctime   "},
  114.   {pred_empty, "empty   "},
  115.   {pred_exec, "exec    "},
  116.   {pred_false, "false   "},
  117.   {pred_fprint, "fprint  "},
  118.   {pred_fprint0, "fprint0 "},
  119.   {pred_fprintf, "fprintf "},
  120.   {pred_fstype, "fstype  "},
  121.   {pred_gid, "gid     "},
  122.   {pred_group, "group   "},
  123.   {pred_ilname, "ilname  "},
  124.   {pred_iname, "iname   "},
  125.   {pred_inum, "inum    "},
  126.   {pred_ipath, "ipath   "},
  127.   {pred_links, "links   "},
  128.   {pred_lname, "lname   "},
  129.   {pred_ls, "ls      "},
  130.   {pred_amin, "mmin    "},
  131.   {pred_mtime, "mtime   "},
  132.   {pred_name, "name    "},
  133.   {pred_negate, "not     "},
  134.   {pred_newer, "newer   "},
  135.   {pred_nogroup, "nogroup "},
  136.   {pred_nouser, "nouser  "},
  137.   {pred_ok, "ok      "},
  138.   {pred_open, "(       "},
  139.   {pred_or, "or      "},
  140.   {pred_path, "path    "},
  141.   {pred_perm, "perm    "},
  142.   {pred_print, "print   "},
  143.   {pred_print0, "print0  "},
  144.   {pred_prune, "prune   "},
  145.   {pred_regex, "regex   "},
  146.   {pred_size, "size    "},
  147.   {pred_true, "true    "},
  148.   {pred_type, "type    "},
  149.   {pred_uid, "uid     "},
  150.   {pred_used, "used    "},
  151.   {pred_user, "user    "},
  152.   {pred_xtype, "xtype   "},
  153.   {0, "none    "}
  154. };
  155.  
  156. struct op_assoc
  157. {
  158.   short type;
  159.   char *type_name;
  160. };
  161.  
  162. struct op_assoc type_table[] =
  163. {
  164.   {NO_TYPE, "no          "},
  165.   {PRIMARY_TYPE, "primary      "},
  166.   {UNI_OP, "uni_op      "},
  167.   {BI_OP, "bi_op       "},
  168.   {OPEN_PAREN, "open_paren  "},
  169.   {CLOSE_PAREN, "close_paren "},
  170.   {-1, "unknown     "}
  171. };
  172.  
  173. struct prec_assoc
  174. {
  175.   short prec;
  176.   char *prec_name;
  177. };
  178.  
  179. struct prec_assoc prec_table[] =
  180. {
  181.   {NO_PREC, "no      "},
  182.   {COMMA_PREC, "comma   "},
  183.   {OR_PREC, "or      "},
  184.   {AND_PREC, "and     "},
  185.   {NEGATE_PREC, "negate  "},
  186.   {MAX_PREC, "max     "},
  187.   {-1, "unknown "}
  188. };
  189. #endif    /* DEBUG */
  190.  
  191. /* Predicate processing routines.
  192.  
  193.    PATHNAME is the full pathname of the file being checked.
  194.    *STAT_BUF contains information about PATHNAME.
  195.    *PRED_PTR contains information for applying the predicate.
  196.  
  197.    Return true if the file passes this predicate, false if not. */
  198.  
  199. boolean
  200. pred_amin (pathname, stat_buf, pred_ptr)
  201.      char *pathname;
  202.      struct stat *stat_buf;
  203.      struct predicate *pred_ptr;
  204. {
  205.   switch (pred_ptr->args.info.kind)
  206.     {
  207.     case COMP_GT:
  208.       if (stat_buf->st_atime > (time_t) pred_ptr->args.info.l_val)
  209.     return (true);
  210.       break;
  211.     case COMP_LT:
  212.       if (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val)
  213.     return (true);
  214.       break;
  215.     case COMP_EQ:
  216.       if ((stat_buf->st_atime >= (time_t) pred_ptr->args.info.l_val)
  217.       && (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val + 60))
  218.     return (true);
  219.       break;
  220.     }
  221.   return (false);
  222. }
  223.  
  224. boolean
  225. pred_and (pathname, stat_buf, pred_ptr)
  226.      char *pathname;
  227.      struct stat *stat_buf;
  228.      struct predicate *pred_ptr;
  229. {
  230.   if (pred_ptr->pred_left == NULL
  231.       || (*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
  232.                         pred_ptr->pred_left))
  233.     {
  234.       /* Check whether we need a stat here. */
  235.       if (pred_ptr->need_stat)
  236.     {
  237.       if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
  238.         {
  239.           error (0, errno, "%s", pathname);
  240.           exit_status = 1;
  241.           return (false);
  242.         }
  243.       have_stat = true;
  244.     }
  245.       return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
  246.                           pred_ptr->pred_right));
  247.     }
  248.   else
  249.     return (false);
  250. }
  251.  
  252. boolean
  253. pred_anewer (pathname, stat_buf, pred_ptr)
  254.      char *pathname;
  255.      struct stat *stat_buf;
  256.      struct predicate *pred_ptr;
  257. {
  258.   if (stat_buf->st_atime > pred_ptr->args.time)
  259.     return (true);
  260.   return (false);
  261. }
  262.  
  263. boolean
  264. pred_atime (pathname, stat_buf, pred_ptr)
  265.      char *pathname;
  266.      struct stat *stat_buf;
  267.      struct predicate *pred_ptr;
  268. {
  269.   switch (pred_ptr->args.info.kind)
  270.     {
  271.     case COMP_GT:
  272.       if (stat_buf->st_atime > (time_t) pred_ptr->args.info.l_val)
  273.     return (true);
  274.       break;
  275.     case COMP_LT:
  276.       if (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val)
  277.     return (true);
  278.       break;
  279.     case COMP_EQ:
  280.       if ((stat_buf->st_atime >= (time_t) pred_ptr->args.info.l_val)
  281.       && (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val
  282.           + DAYSECS))
  283.     return (true);
  284.       break;
  285.     }
  286.   return (false);
  287. }
  288.  
  289. boolean
  290. pred_close (pathname, stat_buf, pred_ptr)
  291.      char *pathname;
  292.      struct stat *stat_buf;
  293.      struct predicate *pred_ptr;
  294. {
  295.   return (true);
  296. }
  297.  
  298. boolean
  299. pred_cmin (pathname, stat_buf, pred_ptr)
  300.      char *pathname;
  301.      struct stat *stat_buf;
  302.      struct predicate *pred_ptr;
  303. {
  304.   switch (pred_ptr->args.info.kind)
  305.     {
  306.     case COMP_GT:
  307.       if (stat_buf->st_ctime > (time_t) pred_ptr->args.info.l_val)
  308.     return (true);
  309.       break;
  310.     case COMP_LT:
  311.       if (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val)
  312.     return (true);
  313.       break;
  314.     case COMP_EQ:
  315.       if ((stat_buf->st_ctime >= (time_t) pred_ptr->args.info.l_val)
  316.       && (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val + 60))
  317.     return (true);
  318.       break;
  319.     }
  320.   return (false);
  321. }
  322.  
  323. boolean
  324. pred_cnewer (pathname, stat_buf, pred_ptr)
  325.      char *pathname;
  326.      struct stat *stat_buf;
  327.      struct predicate *pred_ptr;
  328. {
  329.   if (stat_buf->st_ctime > pred_ptr->args.time)
  330.     return (true);
  331.   return (false);
  332. }
  333.  
  334. boolean
  335. pred_comma (pathname, stat_buf, pred_ptr)
  336.      char *pathname;
  337.      struct stat *stat_buf;
  338.      struct predicate *pred_ptr;
  339. {
  340.   if (pred_ptr->pred_left != NULL)
  341.     (*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
  342.                        pred_ptr->pred_left);
  343.   /* Check whether we need a stat here. */
  344.   if (pred_ptr->need_stat)
  345.     {
  346.       if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
  347.     {
  348.       error (0, errno, "%s", pathname);
  349.       exit_status = 1;
  350.       return (false);
  351.     }
  352.       have_stat = true;
  353.     }
  354.   return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
  355.                           pred_ptr->pred_right));
  356. }
  357.  
  358. boolean
  359. pred_ctime (pathname, stat_buf, pred_ptr)
  360.      char *pathname;
  361.      struct stat *stat_buf;
  362.      struct predicate *pred_ptr;
  363. {
  364.   switch (pred_ptr->args.info.kind)
  365.     {
  366.     case COMP_GT:
  367.       if (stat_buf->st_ctime > (time_t) pred_ptr->args.info.l_val)
  368.     return (true);
  369.       break;
  370.     case COMP_LT:
  371.       if (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val)
  372.     return (true);
  373.       break;
  374.     case COMP_EQ:
  375.       if ((stat_buf->st_ctime >= (time_t) pred_ptr->args.info.l_val)
  376.       && (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val
  377.           + DAYSECS))
  378.     return (true);
  379.       break;
  380.     }
  381.   return (false);
  382. }
  383.  
  384. boolean
  385. pred_empty (pathname, stat_buf, pred_ptr)
  386.      char *pathname;
  387.      struct stat *stat_buf;
  388.      struct predicate *pred_ptr;
  389. {
  390.   if (S_ISDIR (stat_buf->st_mode))
  391.     {
  392.       DIR *d;
  393.       struct dirent *dp;
  394.       boolean empty = true;
  395.  
  396.       errno = 0;
  397.       d = opendir (rel_pathname);
  398.       if (d == NULL)
  399.     {
  400.       error (0, errno, "%s", pathname);
  401.       exit_status = 1;
  402.       return (false);
  403.     }
  404.       for (dp = readdir (d); dp; dp = readdir (d))
  405.     {
  406.       if (dp->d_name[0] != '.'
  407.           || (dp->d_name[1] != '\0'
  408.           && (dp->d_name[1] != '.' || dp->d_name[2] != '\0')))
  409.         {
  410.           empty = false;
  411.           break;
  412.         }
  413.     }
  414.       if (CLOSEDIR (d))
  415.     {
  416.       error (0, errno, "%s", pathname);
  417.       exit_status = 1;
  418.       return (false);
  419.     }
  420.       return (empty);
  421.     }
  422.   else if (S_ISREG (stat_buf->st_mode))
  423.     return (stat_buf->st_size == 0);
  424.   else
  425.     return (false);
  426. }
  427.  
  428. boolean
  429. pred_exec (pathname, stat_buf, pred_ptr)
  430.      char *pathname;
  431.      struct stat *stat_buf;
  432.      struct predicate *pred_ptr;
  433. {
  434.   int i;
  435.   int path_pos;
  436.   struct exec_val *execp;    /* Pointer for efficiency. */
  437.  
  438.   execp = &pred_ptr->args.exec_vec;
  439.  
  440.   /* Replace "{}" with the real path in each affected arg. */
  441.   for (path_pos = 0; execp->paths[path_pos].offset >= 0; path_pos++)
  442.     {
  443.       register char *from, *to;
  444.  
  445.       i = execp->paths[path_pos].offset;
  446.       execp->vec[i] =
  447.     xmalloc (strlen (execp->paths[path_pos].origarg) + 1
  448.          + (strlen (pathname) - 2) * execp->paths[path_pos].count);
  449.       for (from = execp->paths[path_pos].origarg, to = execp->vec[i]; *from; )
  450.     if (from[0] == '{' && from[1] == '}')
  451.       {
  452.         to = stpcpy (to, pathname);
  453.         from += 2;
  454.       }
  455.     else
  456.       *to++ = *from++;
  457.       *to = *from;        /* Copy null. */
  458.     }
  459.  
  460.   i = launch (pred_ptr);
  461.  
  462.   /* Free the temporary args. */
  463.   for (path_pos = 0; execp->paths[path_pos].offset >= 0; path_pos++)
  464.     free (execp->vec[execp->paths[path_pos].offset]);
  465.  
  466.   return (i);
  467. }
  468.  
  469. boolean
  470. pred_false (pathname, stat_buf, pred_ptr)
  471.      char *pathname;
  472.      struct stat *stat_buf;
  473.      struct predicate *pred_ptr;
  474. {
  475.   return (false);
  476. }
  477.  
  478. boolean
  479. pred_fls (pathname, stat_buf, pred_ptr)
  480.      char *pathname;
  481.      struct stat *stat_buf;
  482.      struct predicate *pred_ptr;
  483. {
  484.   list_file (pathname, rel_pathname, stat_buf, pred_ptr->args.stream);
  485.   return (true);
  486. }
  487.  
  488. boolean
  489. pred_fprint (pathname, stat_buf, pred_ptr)
  490.      char *pathname;
  491.      struct stat *stat_buf;
  492.      struct predicate *pred_ptr;
  493. {
  494.   fputs (pathname, pred_ptr->args.stream);
  495.   putc ('\n', pred_ptr->args.stream);
  496.   return (true);
  497. }
  498.  
  499. boolean
  500. pred_fprint0 (pathname, stat_buf, pred_ptr)
  501.      char *pathname;
  502.      struct stat *stat_buf;
  503.      struct predicate *pred_ptr;
  504. {
  505.   fputs (pathname, pred_ptr->args.stream);
  506.   putc (0, pred_ptr->args.stream);
  507.   return (true);
  508. }
  509.  
  510. boolean
  511. pred_fprintf (pathname, stat_buf, pred_ptr)
  512.      char *pathname;
  513.      struct stat *stat_buf;
  514.      struct predicate *pred_ptr;
  515. {
  516.   FILE *fp = pred_ptr->args.printf_vec.stream;
  517.   struct segment *segment;
  518.   char *cp;
  519.  
  520.   for (segment = pred_ptr->args.printf_vec.segment; segment;
  521.        segment = segment->next)
  522.     {
  523.       if (segment->kind & 0xff00) /* Component of date. */
  524.     {
  525.       time_t t;
  526.  
  527.       switch (segment->kind & 0xff)
  528.         {
  529.         case 'A':
  530.           t = stat_buf->st_atime;
  531.           break;
  532.         case 'C':
  533.           t = stat_buf->st_ctime;
  534.           break;
  535.         case 'T':
  536.           t = stat_buf->st_mtime;
  537.           break;
  538.         default:
  539.           abort ();
  540.         }
  541.       fprintf (fp, segment->text,
  542.            format_date (t, (segment->kind >> 8) & 0xff));
  543.       continue;
  544.     }
  545.  
  546.       switch (segment->kind)
  547.     {
  548.     case KIND_PLAIN:    /* Plain text string (no % conversion). */
  549.       fwrite (segment->text, 1, segment->text_len, fp);
  550.       break;
  551.     case KIND_STOP:        /* Terminate argument and flush output. */
  552.       fwrite (segment->text, 1, segment->text_len, fp);
  553.       fflush (fp);
  554.       return (true);
  555.     case 'a':        /* atime in `ctime' format. */
  556.       cp = ctime (&stat_buf->st_atime);
  557.       cp[24] = '\0';
  558.       fprintf (fp, segment->text, cp);
  559.       break;
  560.     case 'b':        /* size in 512-byte blocks */
  561.       fprintf (fp, segment->text, ST_NBLOCKS (stat_buf));
  562.       break;
  563.     case 'c':        /* ctime in `ctime' format */
  564.       cp = ctime (&stat_buf->st_ctime);
  565.       cp[24] = '\0';
  566.       fprintf (fp, segment->text, cp);
  567.       break;
  568.     case 'd':        /* depth in search tree */
  569.       fprintf (fp, segment->text, curdepth);
  570.       break;
  571.     case 'f':        /* basename of path */
  572.       cp = strrchr (pathname, '/');
  573.       if (cp)
  574.         cp++;
  575.       else
  576.         cp = pathname;
  577.       fprintf (fp, segment->text, cp);
  578.       break;
  579.     case 'F':        /* filesystem type */
  580.       fprintf (fp, segment->text,
  581.            filesystem_type (pathname, rel_pathname, stat_buf));
  582.       break;
  583.     case 'g':        /* group name */
  584.       {
  585.         struct group *g;
  586.  
  587.         g = getgrgid (stat_buf->st_gid);
  588.         if (g)
  589.           {
  590.         segment->text[segment->text_len] = 's';
  591.         fprintf (fp, segment->text, g->gr_name);
  592.         break;
  593.           }
  594.         /* else fallthru */
  595.       }
  596.     case 'G':        /* GID number */
  597.       segment->text[segment->text_len] = 'u';
  598.       fprintf (fp, segment->text, stat_buf->st_gid);
  599.       break;
  600.     case 'h':        /* leading directories part of path */
  601.       {
  602.         char cc;
  603.  
  604.         cp = strrchr (pathname, '/');
  605.         if (cp == NULL)    /* No leading directories. */
  606.           break;
  607.         cc = *cp;
  608.         *cp = '\0';
  609.         fprintf (fp, segment->text, pathname);
  610.         *cp = cc;
  611.         break;
  612.       }
  613.     case 'H':        /* ARGV element file was found under */
  614.       {
  615.         char cc = pathname[path_length];
  616.  
  617.         pathname[path_length] = '\0';
  618.         fprintf (fp, segment->text, pathname);
  619.         pathname[path_length] = cc;
  620.         break;
  621.       }
  622.     case 'i':        /* inode number */
  623.       fprintf (fp, segment->text, stat_buf->st_ino);
  624.       break;
  625.     case 'k':        /* size in 1K blocks */
  626.       fprintf (fp, segment->text, (ST_NBLOCKS (stat_buf) + 1) / 2);
  627.       break;
  628.     case 'l':        /* object of symlink */
  629. #ifdef S_ISLNK
  630.       {
  631.         char *linkname = 0;
  632.  
  633.         if (S_ISLNK (stat_buf->st_mode))
  634.           {
  635.         linkname = get_link_name (pathname, rel_pathname);
  636.         if (linkname == 0)
  637.           exit_status = 1;
  638.           }
  639.         if (linkname)
  640.           {
  641.         fprintf (fp, segment->text, linkname);
  642.         free (linkname);
  643.           }
  644.         else
  645.           fprintf (fp, segment->text, "");
  646.       }
  647. #endif                /* S_ISLNK */
  648.       break;
  649.     case 'm':        /* mode as octal number (perms only) */
  650.       fprintf (fp, segment->text, stat_buf->st_mode & 07777);
  651.       break;
  652.     case 'n':        /* number of links */
  653.       fprintf (fp, segment->text, stat_buf->st_nlink);
  654.       break;
  655.     case 'p':        /* pathname */
  656.       fprintf (fp, segment->text, pathname);
  657.       break;
  658.     case 'P':        /* pathname with ARGV element stripped */
  659.       if (curdepth)
  660.         {
  661.           cp = pathname + path_length;
  662.           if (*cp == '/')
  663.         /* Move past the slash between the ARGV element
  664.            and the rest of the pathname.  But if the ARGV element
  665.            ends in a slash, we didn't add another, so we've
  666.            already skipped past it.  */
  667.         cp++;
  668.         }
  669.       else
  670.         cp = "";
  671.       fprintf (fp, segment->text, cp);
  672.       break;
  673.     case 's':        /* size in bytes */
  674.       fprintf (fp, segment->text, stat_buf->st_size);
  675.       break;
  676.     case 't':        /* mtime in `ctime' format */
  677.       cp = ctime (&stat_buf->st_mtime);
  678.       cp[24] = '\0';
  679.       fprintf (fp, segment->text, cp);
  680.       break;
  681.     case 'u':        /* user name */
  682.       {
  683.         struct passwd *p;
  684.  
  685.         p = getpwuid (stat_buf->st_uid);
  686.         if (p)
  687.           {
  688.         segment->text[segment->text_len] = 's';
  689.         fprintf (fp, segment->text, p->pw_name);
  690.         break;
  691.           }
  692.         /* else fallthru */
  693.       }
  694.     case 'U':        /* UID number */
  695.       segment->text[segment->text_len] = 'u';
  696.       fprintf (fp, segment->text, stat_buf->st_uid);
  697.       break;
  698.     }
  699.     }
  700.   return (true);
  701. }
  702.  
  703. boolean
  704. pred_fstype (pathname, stat_buf, pred_ptr)
  705.      char *pathname;
  706.      struct stat *stat_buf;
  707.      struct predicate *pred_ptr;
  708. {
  709.   if (strcmp (filesystem_type (pathname, rel_pathname, stat_buf),
  710.           pred_ptr->args.str) == 0)
  711.     return (true);
  712.   return (false);
  713. }
  714.  
  715. boolean
  716. pred_gid (pathname, stat_buf, pred_ptr)
  717.      char *pathname;
  718.      struct stat *stat_buf;
  719.      struct predicate *pred_ptr;
  720. {
  721.   switch (pred_ptr->args.info.kind)
  722.     {
  723.     case COMP_GT:
  724.       if (stat_buf->st_gid > pred_ptr->args.info.l_val)
  725.     return (true);
  726.       break;
  727.     case COMP_LT:
  728.       if (stat_buf->st_gid < pred_ptr->args.info.l_val)
  729.     return (true);
  730.       break;
  731.     case COMP_EQ:
  732.       if (stat_buf->st_gid == pred_ptr->args.info.l_val)
  733.     return (true);
  734.       break;
  735.     }
  736.   return (false);
  737. }
  738.  
  739. boolean
  740. pred_group (pathname, stat_buf, pred_ptr)
  741.      char *pathname;
  742.      struct stat *stat_buf;
  743.      struct predicate *pred_ptr;
  744. {
  745.   if (pred_ptr->args.gid == stat_buf->st_gid)
  746.     return (true);
  747.   else
  748.     return (false);
  749. }
  750.  
  751. boolean
  752. pred_ilname (pathname, stat_buf, pred_ptr)
  753.      char *pathname;
  754.      struct stat *stat_buf;
  755.      struct predicate *pred_ptr;
  756. {
  757.   return insert_lname (pathname, stat_buf, pred_ptr, true);
  758. }
  759.  
  760. boolean
  761. pred_iname (pathname, stat_buf, pred_ptr)
  762.      char *pathname;
  763.      struct stat *stat_buf;
  764.      struct predicate *pred_ptr;
  765. {
  766.   char *base;
  767.  
  768.   base = basename (pathname);
  769.   if (fnmatch (pred_ptr->args.str, base, FNM_PERIOD | FNM_CASEFOLD) == 0)
  770.     return (true);
  771.   return (false);
  772. }
  773.  
  774. boolean
  775. pred_inum (pathname, stat_buf, pred_ptr)
  776.      char *pathname;
  777.      struct stat *stat_buf;
  778.      struct predicate *pred_ptr;
  779. {
  780.   switch (pred_ptr->args.info.kind)
  781.     {
  782.     case COMP_GT:
  783.       if (stat_buf->st_ino > pred_ptr->args.info.l_val)
  784.     return (true);
  785.       break;
  786.     case COMP_LT:
  787.       if (stat_buf->st_ino < pred_ptr->args.info.l_val)
  788.     return (true);
  789.       break;
  790.     case COMP_EQ:
  791.       if (stat_buf->st_ino == pred_ptr->args.info.l_val)
  792.     return (true);
  793.       break;
  794.     }
  795.   return (false);
  796. }
  797.  
  798. boolean
  799. pred_ipath (pathname, stat_buf, pred_ptr)
  800.      char *pathname;
  801.      struct stat *stat_buf;
  802.      struct predicate *pred_ptr;
  803. {
  804.   if (fnmatch (pred_ptr->args.str, pathname, FNM_CASEFOLD) == 0)
  805.     return (true);
  806.   return (false);
  807. }
  808.  
  809. boolean
  810. pred_links (pathname, stat_buf, pred_ptr)
  811.      char *pathname;
  812.      struct stat *stat_buf;
  813.      struct predicate *pred_ptr;
  814. {
  815.   switch (pred_ptr->args.info.kind)
  816.     {
  817.     case COMP_GT:
  818.       if (stat_buf->st_nlink > pred_ptr->args.info.l_val)
  819.     return (true);
  820.       break;
  821.     case COMP_LT:
  822.       if (stat_buf->st_nlink < pred_ptr->args.info.l_val)
  823.     return (true);
  824.       break;
  825.     case COMP_EQ:
  826.       if (stat_buf->st_nlink == pred_ptr->args.info.l_val)
  827.     return (true);
  828.       break;
  829.     }
  830.   return (false);
  831. }
  832.  
  833. boolean
  834. pred_lname (pathname, stat_buf, pred_ptr)
  835.      char *pathname;
  836.      struct stat *stat_buf;
  837.      struct predicate *pred_ptr;
  838. {
  839.   return insert_lname (pathname, stat_buf, pred_ptr, false);
  840. }
  841.  
  842. static boolean
  843. insert_lname (pathname, stat_buf, pred_ptr, ignore_case)
  844.      char *pathname;
  845.      struct stat *stat_buf;
  846.      struct predicate *pred_ptr;
  847.      boolean ignore_case;
  848. {
  849.   boolean ret = false;
  850. #ifdef S_ISLNK
  851.   if (S_ISLNK (stat_buf->st_mode))
  852.     {
  853.       char *linkname = get_link_name (pathname, rel_pathname);
  854.       if (linkname)
  855.     {
  856.       if (fnmatch (pred_ptr->args.str, linkname,
  857.                ignore_case ? FNM_CASEFOLD : 0) == 0)
  858.         ret = true;
  859.       free (linkname);
  860.     }
  861.     }
  862. #endif /* S_ISLNK */
  863.   return (ret);
  864. }
  865.  
  866. boolean
  867. pred_ls (pathname, stat_buf, pred_ptr)
  868.      char *pathname;
  869.      struct stat *stat_buf;
  870.      struct predicate *pred_ptr;
  871. {
  872.   list_file (pathname, rel_pathname, stat_buf, stdout);
  873.   return (true);
  874. }
  875.  
  876. boolean
  877. pred_mmin (pathname, stat_buf, pred_ptr)
  878.      char *pathname;
  879.      struct stat *stat_buf;
  880.      struct predicate *pred_ptr;
  881. {
  882.   switch (pred_ptr->args.info.kind)
  883.     {
  884.     case COMP_GT:
  885.       if (stat_buf->st_mtime > (time_t) pred_ptr->args.info.l_val)
  886.     return (true);
  887.       break;
  888.     case COMP_LT:
  889.       if (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val)
  890.     return (true);
  891.       break;
  892.     case COMP_EQ:
  893.       if ((stat_buf->st_mtime >= (time_t) pred_ptr->args.info.l_val)
  894.       && (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val + 60))
  895.     return (true);
  896.       break;
  897.     }
  898.   return (false);
  899. }
  900.  
  901. boolean
  902. pred_mtime (pathname, stat_buf, pred_ptr)
  903.      char *pathname;
  904.      struct stat *stat_buf;
  905.      struct predicate *pred_ptr;
  906. {
  907.   switch (pred_ptr->args.info.kind)
  908.     {
  909.     case COMP_GT:
  910.       if (stat_buf->st_mtime > (time_t) pred_ptr->args.info.l_val)
  911.     return (true);
  912.       break;
  913.     case COMP_LT:
  914.       if (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val)
  915.     return (true);
  916.       break;
  917.     case COMP_EQ:
  918.       if ((stat_buf->st_mtime >= (time_t) pred_ptr->args.info.l_val)
  919.       && (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val
  920.           + DAYSECS))
  921.     return (true);
  922.       break;
  923.     }
  924.   return (false);
  925. }
  926.  
  927. boolean
  928. pred_name (pathname, stat_buf, pred_ptr)
  929.      char *pathname;
  930.      struct stat *stat_buf;
  931.      struct predicate *pred_ptr;
  932. {
  933.   char *base;
  934.  
  935.   base = basename (pathname);
  936.   if (fnmatch (pred_ptr->args.str, base, FNM_PERIOD) == 0)
  937.     return (true);
  938.   return (false);
  939. }
  940.  
  941. boolean
  942. pred_negate (pathname, stat_buf, pred_ptr)
  943.      char *pathname;
  944.      struct stat *stat_buf;
  945.      struct predicate *pred_ptr;
  946. {
  947.   /* Check whether we need a stat here. */
  948.   if (pred_ptr->need_stat)
  949.     {
  950.       if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
  951.     {
  952.       error (0, errno, "%s", pathname);
  953.       exit_status = 1;
  954.       return (false);
  955.     }
  956.       have_stat = true;
  957.     }
  958.   return (!(*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
  959.                           pred_ptr->pred_right));
  960. }
  961.  
  962. boolean
  963. pred_newer (pathname, stat_buf, pred_ptr)
  964.      char *pathname;
  965.      struct stat *stat_buf;
  966.      struct predicate *pred_ptr;
  967. {
  968.   if (stat_buf->st_mtime > pred_ptr->args.time)
  969.     return (true);
  970.   return (false);
  971. }
  972.  
  973. boolean
  974. pred_nogroup (pathname, stat_buf, pred_ptr)
  975.      char *pathname;
  976.      struct stat *stat_buf;
  977.      struct predicate *pred_ptr;
  978. {
  979. #ifdef CACHE_IDS
  980.   extern char *gid_unused;
  981.  
  982.   return gid_unused[(unsigned) stat_buf->st_gid];
  983. #else
  984.   return getgrgid (stat_buf->st_gid) == NULL;
  985. #endif
  986. }
  987.  
  988. boolean
  989. pred_nouser (pathname, stat_buf, pred_ptr)
  990.      char *pathname;
  991.      struct stat *stat_buf;
  992.      struct predicate *pred_ptr;
  993. {
  994. #ifdef CACHE_IDS
  995.   extern char *uid_unused;
  996.  
  997.   return uid_unused[(unsigned) stat_buf->st_uid];
  998. #else
  999.   return getpwuid (stat_buf->st_uid) == NULL;
  1000. #endif
  1001. }
  1002.  
  1003. boolean
  1004. pred_ok (pathname, stat_buf, pred_ptr)
  1005.      char *pathname;
  1006.      struct stat *stat_buf;
  1007.      struct predicate *pred_ptr;
  1008. {
  1009.   int i, yes;
  1010.   
  1011.   fflush (stdout);
  1012.   fprintf (stderr, "< %s ... %s > ? ",
  1013.        pred_ptr->args.exec_vec.vec[0], pathname);
  1014.   fflush (stderr);
  1015.   i = getchar ();
  1016.   yes = (i == 'y' || i == 'Y');
  1017.   while (i != EOF && i != '\n')
  1018.     i = getchar ();
  1019.   if (!yes)
  1020.     return (false);
  1021.   return pred_exec (pathname, stat_buf, pred_ptr);
  1022. }
  1023.  
  1024. boolean
  1025. pred_open (pathname, stat_buf, pred_ptr)
  1026.      char *pathname;
  1027.      struct stat *stat_buf;
  1028.      struct predicate *pred_ptr;
  1029. {
  1030.   return (true);
  1031. }
  1032.  
  1033. boolean
  1034. pred_or (pathname, stat_buf, pred_ptr)
  1035.      char *pathname;
  1036.      struct stat *stat_buf;
  1037.      struct predicate *pred_ptr;
  1038. {
  1039.   if (pred_ptr->pred_left == NULL
  1040.       || !(*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
  1041.                          pred_ptr->pred_left))
  1042.     {
  1043.       /* Check whether we need a stat here. */
  1044.       if (pred_ptr->need_stat)
  1045.     {
  1046.       if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
  1047.         {
  1048.           error (0, errno, "%s", pathname);
  1049.           exit_status = 1;
  1050.           return (false);
  1051.         }
  1052.       have_stat = true;
  1053.     }
  1054.       return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
  1055.                           pred_ptr->pred_right));
  1056.     }
  1057.   else
  1058.     return (true);
  1059. }
  1060.  
  1061. boolean
  1062. pred_path (pathname, stat_buf, pred_ptr)
  1063.      char *pathname;
  1064.      struct stat *stat_buf;
  1065.      struct predicate *pred_ptr;
  1066. {
  1067.   if (fnmatch (pred_ptr->args.str, pathname, 0) == 0)
  1068.     return (true);
  1069.   return (false);
  1070. }
  1071.  
  1072. boolean
  1073. pred_perm (pathname, stat_buf, pred_ptr)
  1074.      char *pathname;
  1075.      struct stat *stat_buf;
  1076.      struct predicate *pred_ptr;
  1077. {
  1078.   if (pred_ptr->args.perm & 010000)
  1079.     {
  1080.       /* Magic flag set in parse_perm:
  1081.      true if at least the given bits are set. */
  1082.       if ((stat_buf->st_mode & 07777 & pred_ptr->args.perm)
  1083.       == (pred_ptr->args.perm & 07777))
  1084.     return (true);
  1085.     }
  1086.   else if (pred_ptr->args.perm & 020000)
  1087.     {
  1088.       /* Magic flag set in parse_perm:
  1089.      true if any of the given bits are set. */
  1090.       if ((stat_buf->st_mode & 07777) & pred_ptr->args.perm)
  1091.     return (true);
  1092.     }
  1093.   else
  1094.     {
  1095.       /* True if exactly the given bits are set. */
  1096.       if ((stat_buf->st_mode & 07777) == pred_ptr->args.perm)
  1097.     return (true);
  1098.     }
  1099.   return (false);
  1100. }
  1101.  
  1102. boolean
  1103. pred_print (pathname, stat_buf, pred_ptr)
  1104.      char *pathname;
  1105.      struct stat *stat_buf;
  1106.      struct predicate *pred_ptr;
  1107. {
  1108.   puts (pathname);
  1109.   return (true);
  1110. }
  1111.  
  1112. boolean
  1113. pred_print0 (pathname, stat_buf, pred_ptr)
  1114.      char *pathname;
  1115.      struct stat *stat_buf;
  1116.      struct predicate *pred_ptr;
  1117. {
  1118.   fputs (pathname, stdout);
  1119.   putc (0, stdout);
  1120.   return (true);
  1121. }
  1122.  
  1123. boolean
  1124. pred_prune (pathname, stat_buf, pred_ptr)
  1125.      char *pathname;
  1126.      struct stat *stat_buf;
  1127.      struct predicate *pred_ptr;
  1128. {
  1129.   stop_at_current_level = true;
  1130.   return (do_dir_first);    /* This is what SunOS find seems to do. */
  1131. }
  1132.  
  1133. boolean
  1134. pred_regex (pathname, stat_buf, pred_ptr)
  1135.      char *pathname;
  1136.      struct stat *stat_buf;
  1137.      struct predicate *pred_ptr;
  1138. {
  1139.   int len = strlen (pathname);
  1140.   if (re_match (pred_ptr->args.regex, pathname, len, 0,
  1141.         (struct re_registers *) NULL) == len)
  1142.     return (true);
  1143.   return (false);
  1144. }
  1145.  
  1146. boolean
  1147. pred_size (pathname, stat_buf, pred_ptr)
  1148.      char *pathname;
  1149.      struct stat *stat_buf;
  1150.      struct predicate *pred_ptr;
  1151. {
  1152.   unsigned long f_val;
  1153.  
  1154.   f_val = (stat_buf->st_size + pred_ptr->args.size.blocksize - 1)
  1155.     / pred_ptr->args.size.blocksize;
  1156.   switch (pred_ptr->args.size.kind)
  1157.     {
  1158.     case COMP_GT:
  1159.       if (f_val > pred_ptr->args.size.size)
  1160.     return (true);
  1161.       break;
  1162.     case COMP_LT:
  1163.       if (f_val < pred_ptr->args.size.size)
  1164.     return (true);
  1165.       break;
  1166.     case COMP_EQ:
  1167.       if (f_val == pred_ptr->args.size.size)
  1168.     return (true);
  1169.       break;
  1170.     }
  1171.   return (false);
  1172. }
  1173.  
  1174. boolean
  1175. pred_true (pathname, stat_buf, pred_ptr)
  1176.      char *pathname;
  1177.      struct stat *stat_buf;
  1178.      struct predicate *pred_ptr;
  1179. {
  1180.   return (true);
  1181. }
  1182.  
  1183. boolean
  1184. pred_type (pathname, stat_buf, pred_ptr)
  1185.      char *pathname;
  1186.      struct stat *stat_buf;
  1187.      struct predicate *pred_ptr;
  1188. {
  1189.   unsigned long mode = stat_buf->st_mode;
  1190.   unsigned long type = pred_ptr->args.type;
  1191.  
  1192. #ifndef S_IFMT
  1193.   /* POSIX system; check `mode' the slow way. */
  1194.   if ((S_ISBLK (mode) && type == S_IFBLK)
  1195.       || (S_ISCHR (mode) && type == S_IFCHR)
  1196.       || (S_ISDIR (mode) && type == S_IFDIR)
  1197.       || (S_ISREG (mode) && type == S_IFREG)
  1198. #ifdef S_IFLNK
  1199.       || (S_ISLNK (mode) && type == S_IFLNK)
  1200. #endif
  1201. #ifdef S_IFIFO
  1202.       || (S_ISFIFO (mode) && type == S_IFIFO)
  1203. #endif
  1204. #ifdef S_IFSOCK
  1205.       || (S_ISSOCK (mode) && type == S_IFSOCK)
  1206. #endif
  1207.       )
  1208. #else /* S_IFMT */
  1209.   /* Unix system; check `mode' the fast way. */
  1210.   if ((mode & S_IFMT) == type)
  1211. #endif /* S_IFMT */
  1212.     return (true);
  1213.   else
  1214.     return (false);
  1215. }
  1216.  
  1217. boolean
  1218. pred_uid (pathname, stat_buf, pred_ptr)
  1219.      char *pathname;
  1220.      struct stat *stat_buf;
  1221.      struct predicate *pred_ptr;
  1222. {
  1223.   switch (pred_ptr->args.info.kind)
  1224.     {
  1225.     case COMP_GT:
  1226.       if (stat_buf->st_uid > pred_ptr->args.info.l_val)
  1227.     return (true);
  1228.       break;
  1229.     case COMP_LT:
  1230.       if (stat_buf->st_uid < pred_ptr->args.info.l_val)
  1231.     return (true);
  1232.       break;
  1233.     case COMP_EQ:
  1234.       if (stat_buf->st_uid == pred_ptr->args.info.l_val)
  1235.     return (true);
  1236.       break;
  1237.     }
  1238.   return (false);
  1239. }
  1240.  
  1241. boolean
  1242. pred_used (pathname, stat_buf, pred_ptr)
  1243.      char *pathname;
  1244.      struct stat *stat_buf;
  1245.      struct predicate *pred_ptr;
  1246. {
  1247.   time_t delta;
  1248.  
  1249.   delta = stat_buf->st_atime - stat_buf->st_ctime; /* Use difftime? */
  1250.   switch (pred_ptr->args.info.kind)
  1251.     {
  1252.     case COMP_GT:
  1253.       if (delta > (time_t) pred_ptr->args.info.l_val)
  1254.     return (true);
  1255.       break;
  1256.     case COMP_LT:
  1257.       if (delta < (time_t) pred_ptr->args.info.l_val)
  1258.     return (true);
  1259.       break;
  1260.     case COMP_EQ:
  1261.       if ((delta >= (time_t) pred_ptr->args.info.l_val)
  1262.       && (delta < (time_t) pred_ptr->args.info.l_val + DAYSECS))
  1263.     return (true);
  1264.       break;
  1265.     }
  1266.   return (false);
  1267. }
  1268.  
  1269. boolean
  1270. pred_user (pathname, stat_buf, pred_ptr)
  1271.      char *pathname;
  1272.      struct stat *stat_buf;
  1273.      struct predicate *pred_ptr;
  1274. {
  1275.   if (pred_ptr->args.uid == stat_buf->st_uid)
  1276.     return (true);
  1277.   else
  1278.     return (false);
  1279. }
  1280.  
  1281. boolean
  1282. pred_xtype (pathname, stat_buf, pred_ptr)
  1283.      char *pathname;
  1284.      struct stat *stat_buf;
  1285.      struct predicate *pred_ptr;
  1286. {
  1287.   struct stat sbuf;
  1288.   int (*ystat) ();
  1289.  
  1290.   ystat = xstat == lstat ? stat : lstat;
  1291.   if ((*ystat) (rel_pathname, &sbuf) != 0)
  1292.     {
  1293.       if (ystat == stat && errno == ENOENT)
  1294.     /* Mimic behavior of ls -lL. */
  1295.     return (pred_type (pathname, stat_buf, pred_ptr));
  1296.       error (0, errno, "%s", pathname);
  1297.       exit_status = 1;
  1298.       return (false);
  1299.     }
  1300.   return (pred_type (pathname, &sbuf, pred_ptr));
  1301. }
  1302.  
  1303. /*  1) fork to get a child; parent remembers the child pid
  1304.     2) child execs the command requested
  1305.     3) parent waits for child; checks for proper pid of child
  1306.  
  1307.     Possible returns:
  1308.  
  1309.     ret        errno    status(h)   status(l)
  1310.  
  1311.     pid        x    signal#        0177    stopped
  1312.     pid        x    exit arg    0        term by _exit
  1313.     pid        x    0        signal #    term by signal
  1314.     -1        EINTR                parent got signal
  1315.     -1        other                some other kind of error
  1316.  
  1317.     Return true only if the pid matches, status(l) is
  1318.     zero, and the exit arg (status high) is 0.
  1319.     Otherwise return false, possibly printing an error message. */
  1320.  
  1321. static boolean
  1322. launch (pred_ptr)
  1323.      struct predicate *pred_ptr;
  1324. {
  1325.   int status;
  1326.   pid_t wait_ret, child_pid;
  1327.   struct exec_val *execp;    /* Pointer for efficiency. */
  1328.   static int first_time = 1;
  1329.  
  1330.   execp = &pred_ptr->args.exec_vec;
  1331.  
  1332.   /* Make sure output of command doesn't get mixed with find output. */
  1333.   fflush (stdout);
  1334.   fflush (stderr);
  1335.  
  1336.   /* Make sure to listen for the kids.  */
  1337.   if (first_time)
  1338.     {
  1339.       first_time = 0;
  1340.       signal (SIGCHLD, SIG_DFL);
  1341.     }
  1342.  
  1343.   child_pid = vfork ();
  1344.   if (child_pid == -1)
  1345.     error (1, errno, "cannot fork");
  1346.   if (child_pid == 0)
  1347.     {
  1348.       /* We be the child. */
  1349. #ifndef HAVE_FCHDIR
  1350.       if (chdir (starting_dir) < 0)
  1351.     {
  1352.       error (0, errno, "%s", starting_dir);
  1353.       _exit (1);
  1354.     }
  1355. #else
  1356.       if (fchdir (starting_desc) < 0)
  1357.     {
  1358.       error (0, errno, "cannot return to starting directory");
  1359.       _exit (1);
  1360.     }
  1361. #endif
  1362.       execvp (execp->vec[0], execp->vec);
  1363.       error (0, errno, "%s", execp->vec[0]);
  1364.       _exit (1);
  1365.     }
  1366.  
  1367.   wait_ret = wait (&status);
  1368.   if (wait_ret == -1)
  1369.     {
  1370.       error (0, errno, "error waiting for %s", execp->vec[0]);
  1371.       exit_status = 1;
  1372.       return (false);
  1373.     }
  1374.   if (wait_ret != child_pid)
  1375.     {
  1376.       error (0, 0, "wait got pid %d, expected pid %d", wait_ret, child_pid);
  1377.       exit_status = 1;
  1378.       return (false);
  1379.     }
  1380.   if (WIFSTOPPED (status))
  1381.     {
  1382.       error (0, 0, "%s stopped by signal %d", 
  1383.          execp->vec[0], WSTOPSIG (status));
  1384.       exit_status = 1;
  1385.       return (false);
  1386.     }
  1387.   if (WIFSIGNALED (status))
  1388.     {
  1389.       error (0, 0, "%s terminated by signal %d",
  1390.          execp->vec[0], WTERMSIG (status));
  1391.       exit_status = 1;
  1392.       return (false);
  1393.     }
  1394.   return (!WEXITSTATUS (status));
  1395. }
  1396.  
  1397. /* Return a static string formatting the time WHEN according to the
  1398.    strftime format character KIND.  */
  1399.  
  1400. static char *
  1401. format_date (when, kind)
  1402.      time_t when;
  1403.      int kind;
  1404. {
  1405.   static char fmt[3];
  1406.   static char buf[64];        /* More than enough space. */
  1407.  
  1408.   if (kind == '@')
  1409.     {
  1410.       sprintf (buf, "%ld", when);
  1411.       return (buf);
  1412.     }
  1413.   else
  1414.     {
  1415.       fmt[0] = '%';
  1416.       fmt[1] = kind;
  1417.       fmt[2] = '\0';
  1418.       if (strftime (buf, sizeof (buf), fmt, localtime (&when)))
  1419.     return (buf);
  1420.     }
  1421.   return "";
  1422. }
  1423.  
  1424. #ifdef    DEBUG
  1425. /* Return a pointer to the string representation of 
  1426.    the predicate function PRED_FUNC. */
  1427.  
  1428. char *
  1429. find_pred_name (pred_func)
  1430.      PFB pred_func;
  1431. {
  1432.   int i;
  1433.  
  1434.   for (i = 0; pred_table[i].pred_func != 0; i++)
  1435.     if (pred_table[i].pred_func == pred_func)
  1436.       break;
  1437.   return (pred_table[i].pred_name);
  1438. }
  1439.  
  1440. static char *
  1441. type_name (type)
  1442.      short type;
  1443. {
  1444.   int i;
  1445.  
  1446.   for (i = 0; type_table[i].type != (short) -1; i++)
  1447.     if (type_table[i].type == type)
  1448.       break;
  1449.   return (type_table[i].type_name);
  1450. }
  1451.  
  1452. static char *
  1453. prec_name (prec)
  1454.      short prec;
  1455. {
  1456.   int i;
  1457.  
  1458.   for (i = 0; prec_table[i].prec != (short) -1; i++)
  1459.     if (prec_table[i].prec == prec)
  1460.       break;
  1461.   return (prec_table[i].prec_name);
  1462. }
  1463.  
  1464. /* Walk the expression tree NODE to stdout.
  1465.    INDENT is the number of levels to indent the left margin. */
  1466.  
  1467. void
  1468. print_tree (node, indent)
  1469.      struct predicate *node;
  1470.      int indent;
  1471. {
  1472.   int i;
  1473.  
  1474.   if (node == NULL)
  1475.     return;
  1476.   for (i = 0; i < indent; i++)
  1477.     printf ("    ");
  1478.   printf ("pred = %s type = %s prec = %s addr = %x\n",
  1479.       find_pred_name (node->pred_func),
  1480.       type_name (node->p_type), prec_name (node->p_prec), node);
  1481.   for (i = 0; i < indent; i++)
  1482.     printf ("    ");
  1483.   printf ("left:\n");
  1484.   print_tree (node->pred_left, indent + 1);
  1485.   for (i = 0; i < indent; i++)
  1486.     printf ("    ");
  1487.   printf ("right:\n");
  1488.   print_tree (node->pred_right, indent + 1);
  1489. }
  1490.  
  1491. /* Copy STR into BUF and trim blanks from the end of BUF.
  1492.    Return BUF. */
  1493.  
  1494. static char *
  1495. blank_rtrim (str, buf)
  1496.      char *str;
  1497.      char *buf;
  1498. {
  1499.   int i;
  1500.  
  1501.   if (str == NULL)
  1502.     return (NULL);
  1503.   strcpy (buf, str);
  1504.   i = strlen (buf) - 1;
  1505.   while ((i >= 0) && ((buf[i] == ' ') || buf[i] == '\t'))
  1506.     i--;
  1507.   buf[++i] = '\0';
  1508.   return (buf);
  1509. }
  1510.  
  1511. /* Print out the predicate list starting at NODE. */
  1512.  
  1513. void
  1514. print_list (node)
  1515.      struct predicate *node;
  1516. {
  1517.   struct predicate *cur;
  1518.   char name[256];
  1519.  
  1520.   cur = node;
  1521.   while (cur != NULL)
  1522.     {
  1523.       printf ("%s ", blank_rtrim (find_pred_name (cur->pred_func), name));
  1524.       cur = cur->pred_next;
  1525.     }
  1526.   printf ("\n");
  1527. }
  1528. #endif    /* DEBUG */
  1529.