home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / f / find37.zip / find-3.7 / find / pred.c < prev    next >
C/C++ Source or Header  |  1992-07-13  |  35KB  |  1,531 lines

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