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 / parser.c < prev    next >
C/C++ Source or Header  |  1992-07-13  |  41KB  |  1,773 lines

  1. /* parser.c -- convert the command line args into an 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 <ctype.h>
  19. #include <stdio.h>
  20. #include <sys/types.h>
  21. #include <sys/stat.h>
  22. #include <pwd.h>
  23. #include <grp.h>
  24.  
  25. #ifdef HAVE_UNISTD_H
  26. #include <unistd.h>
  27. #endif
  28.  
  29. #if defined(USG) || defined(STDC_HEADERS)
  30. #include <string.h>
  31. #define index strchr
  32. #define rindex strrchr
  33. #else /* not (USG or STDC_HEADERS) */
  34. #include <strings.h>
  35. #endif /* USG or STDC_HEADERS */
  36.  
  37. #ifndef _POSIX_VERSION
  38. struct group *getgrnam ();
  39. struct group *getgrent ();
  40. struct passwd *getpwnam ();
  41. struct passwd *getpwent ();
  42. #endif
  43.  
  44. #include "modechange.h"
  45. #include "defs.h"
  46. #include "modetype.h"
  47.  
  48. #ifndef S_IFLNK
  49. #define lstat stat
  50. #endif
  51.  
  52. char *strstr ();
  53. int lstat ();
  54. int stat ();
  55. long atol ();
  56. struct tm *localtime ();
  57. #ifdef _POSIX_SOURCE
  58. #define endgrent()
  59. #define endpwent()
  60. #else
  61. void endgrent ();
  62. void endpwent ();
  63. #endif
  64.  
  65. #if !__STDC__
  66. #define const
  67. #endif
  68.  
  69. boolean parse_amin ();
  70. boolean parse_and ();
  71. boolean parse_anewer ();
  72. boolean parse_atime ();
  73. boolean parse_close ();
  74. boolean parse_cmin ();
  75. boolean parse_cnewer ();
  76. boolean parse_comma ();
  77. boolean parse_ctime ();
  78. boolean parse_daystart ();
  79. boolean parse_depth ();
  80. boolean parse_empty ();
  81. boolean parse_exec ();
  82. boolean parse_false ();
  83. boolean parse_follow ();
  84. boolean parse_fprint ();
  85. boolean parse_fprint0 ();
  86. boolean parse_fprintf ();
  87. boolean parse_fstype ();
  88. boolean parse_gid ();
  89. boolean parse_group ();
  90. boolean parse_inum ();
  91. boolean parse_links ();
  92. boolean parse_lname ();
  93. boolean parse_ls ();
  94. boolean parse_maxdepth ();
  95. boolean parse_mindepth ();
  96. boolean parse_mmin ();
  97. boolean parse_mtime ();
  98. boolean parse_name ();
  99. boolean parse_negate ();
  100. boolean parse_newer ();
  101. boolean parse_noleaf ();
  102. boolean parse_nogroup ();
  103. boolean parse_nouser ();
  104. boolean parse_ok ();
  105. boolean parse_open ();
  106. boolean parse_or ();
  107. boolean parse_path ();
  108. boolean parse_perm ();
  109. boolean parse_print ();
  110. boolean parse_print0 ();
  111. boolean parse_printf ();
  112. boolean parse_prune ();
  113. boolean parse_regex ();
  114. boolean parse_size ();
  115. boolean parse_true ();
  116. boolean parse_type ();
  117. boolean parse_uid ();
  118. boolean parse_used ();
  119. boolean parse_user ();
  120. boolean parse_version ();
  121. boolean parse_xdev ();
  122. boolean parse_xtype ();
  123.  
  124. boolean pred_amin ();
  125. boolean pred_and ();
  126. boolean pred_anewer ();
  127. boolean pred_atime ();
  128. boolean pred_close ();
  129. boolean pred_cmin ();
  130. boolean pred_cnewer ();
  131. boolean pred_comma ();
  132. boolean pred_ctime ();
  133. /* no pred_daystart */
  134. /* no pred_depth */
  135. boolean pred_empty ();
  136. boolean pred_exec ();
  137. boolean pred_false ();
  138. /* no pred_follow */
  139. boolean pred_fprint ();
  140. boolean pred_fprint0 ();
  141. boolean pred_fprintf ();
  142. boolean pred_fstype ();
  143. boolean pred_gid ();
  144. boolean pred_group ();
  145. boolean pred_inum ();
  146. boolean pred_links ();
  147. boolean pred_lname ();
  148. boolean pred_ls ();
  149. /* no pred_maxdepth */
  150. /* no pred_mindepth */
  151. boolean pred_mmin ();
  152. boolean pred_mtime ();
  153. boolean pred_name ();
  154. boolean pred_negate ();
  155. boolean pred_newer ();
  156. /* no pred_noleaf */
  157. boolean pred_nogroup ();
  158. boolean pred_nouser ();
  159. boolean pred_ok ();
  160. boolean pred_open ();
  161. boolean pred_or ();
  162. boolean pred_path ();
  163. boolean pred_perm ();
  164. boolean pred_print ();
  165. boolean pred_print0 ();
  166. /* no pred_printf */
  167. boolean pred_prune ();
  168. boolean pred_regex ();
  169. boolean pred_size ();
  170. boolean pred_true ();
  171. boolean pred_type ();
  172. boolean pred_uid ();
  173. boolean pred_used ();
  174. boolean pred_user ();
  175. /* no pred_version */
  176. /* no pred_xdev */
  177. boolean pred_xtype ();
  178.  
  179. boolean get_num ();
  180. boolean get_num_days ();
  181. boolean insert_exec_ok ();
  182. boolean insert_fprintf ();
  183. boolean insert_num ();
  184. boolean insert_time ();
  185. boolean insert_type ();
  186. FILE *open_output_file ();
  187. struct segment **make_segment ();
  188.  
  189. #ifdef    DEBUG
  190. char *find_pred_name ();
  191. #endif    /* DEBUG */
  192.  
  193. struct parser_table_t
  194. {
  195.   char *parser_name;
  196.   PFB parser_func;
  197. };
  198.  
  199. /* GNU find predicates that are not mentioned in POSIX.2 are marked `GNU'.
  200.    If they are in some Unix versions of find, they are marked `Unix'. */
  201.  
  202. struct parser_table_t parse_table[] =
  203. {
  204.   {"!", parse_negate},
  205.   {"not", parse_negate},    /* GNU */
  206.   {"(", parse_open},
  207.   {")", parse_close},
  208.   {",", parse_comma},        /* GNU */
  209.   {"a", parse_and},
  210.   {"amin", parse_amin},        /* GNU */
  211.   {"and", parse_and},        /* GNU */
  212.   {"anewer", parse_anewer},    /* GNU */
  213.   {"atime", parse_atime},
  214.   {"cmin", parse_cmin},        /* GNU */
  215.   {"cnewer", parse_cnewer},    /* GNU */
  216. #ifdef UNIMPLEMENTED_UNIX
  217.   /* It's pretty ugly for find to know about archive formats.
  218.      Plus what it could do with cpio archives is very limited.
  219.      Better to leave it out.  */
  220.   {"cpio", parse_cpio},        /* Unix */
  221. #endif
  222.   {"ctime", parse_ctime},
  223.   {"daystart", parse_daystart},    /* GNU */
  224.   {"depth", parse_depth},
  225.   {"empty", parse_empty},    /* GNU */
  226.   {"exec", parse_exec},
  227.   {"false", parse_false},    /* GNU */
  228.   {"follow", parse_follow},    /* GNU, Unix */
  229.   {"fprint", parse_fprint},    /* GNU */
  230.   {"fprint0", parse_fprint0},    /* GNU */
  231.   {"fprintf", parse_fprintf},    /* GNU */
  232.   {"fstype", parse_fstype},    /* GNU, Unix */
  233.   {"gid", parse_gid},        /* GNU */
  234.   {"group", parse_group},
  235.   {"inum", parse_inum},        /* GNU, Unix */
  236.   {"links", parse_links},
  237.   {"lname", parse_lname},    /* GNU */
  238.   {"ls", parse_ls},        /* GNU, Unix */
  239.   {"maxdepth", parse_maxdepth},    /* GNU */
  240.   {"mindepth", parse_mindepth},    /* GNU */
  241.   {"mmin", parse_mmin},        /* GNU */
  242.   {"mtime", parse_mtime},
  243.   {"name", parse_name},
  244. #ifdef UNIMPLEMENTED_UNIX
  245.   {"ncpio", parse_ncpio},    /* Unix */
  246. #endif
  247.   {"newer", parse_newer},
  248.   {"noleaf", parse_noleaf},    /* GNU */
  249.   {"nogroup", parse_nogroup},
  250.   {"nouser", parse_nouser},
  251.   {"o", parse_or},
  252.   {"or", parse_or},        /* GNU */
  253.   {"ok", parse_ok},
  254.   {"path", parse_path},        /* GNU, HP-UX */
  255.   {"perm", parse_perm},
  256.   {"print", parse_print},
  257.   {"print0", parse_print0},    /* GNU */
  258.   {"printf", parse_printf},    /* GNU */
  259.   {"prune", parse_prune},
  260.   {"regex", parse_regex},    /* GNU */
  261.   {"size", parse_size},
  262.   {"true", parse_true},        /* GNU */
  263.   {"type", parse_type},
  264.   {"uid", parse_uid},        /* GNU */
  265.   {"used", parse_used},        /* GNU */
  266.   {"user", parse_user},
  267.   {"version", parse_version},    /* GNU */
  268.   {"xdev", parse_xdev},
  269.   {"xtype", parse_xtype},    /* GNU */
  270.   {0, 0}
  271. };
  272.  
  273. /* Return a pointer to the parser function to invoke for predicate
  274.    SEARCH_NAME.
  275.    Return NULL if SEARCH_NAME is not a valid predicate name. */
  276.  
  277. PFB
  278. find_parser (search_name)
  279.      char *search_name;
  280. {
  281.   int i;
  282.  
  283.   if (*search_name == '-')
  284.     search_name++;
  285.   for (i = 0; parse_table[i].parser_name != 0; i++)
  286.     if (strcmp (parse_table[i].parser_name, search_name) == 0)
  287.       return (parse_table[i].parser_func);
  288.   return (NULL);
  289. }
  290.  
  291. /* The parsers are responsible to continue scanning ARGV for
  292.    their arguments.  Each parser knows what is and isn't
  293.    allowed for itself.
  294.    
  295.    ARGV is the argument array.
  296.    *ARG_PTR is the index to start at in ARGV,
  297.    updated to point beyond the last element consumed.
  298.  
  299.    The predicate structure is updated with the new information. */
  300.  
  301. boolean
  302. parse_amin (argv, arg_ptr)
  303.      char *argv[];
  304.      int *arg_ptr;
  305. {
  306.   struct predicate *our_pred;
  307.   unsigned long num;
  308.   enum comparison_type c_type;
  309.  
  310.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  311.     return (false);
  312.   if (!get_num_days (argv[*arg_ptr], &num, &c_type))
  313.     return (false);
  314.   our_pred = insert_victim (pred_amin);
  315.   our_pred->args.info.kind = c_type;
  316.   our_pred->args.info.l_val = cur_day_start + DAYSECS - num * 60;
  317.   (*arg_ptr)++;
  318.   return (true);
  319. }
  320.  
  321. boolean
  322. parse_and (argv, arg_ptr)
  323.      char *argv[];
  324.      int *arg_ptr;
  325. {
  326.   struct predicate *our_pred;
  327.  
  328.   our_pred = get_new_pred ();
  329.   our_pred->pred_func = pred_and;
  330. #ifdef    DEBUG
  331.   our_pred->p_name = find_pred_name (pred_and);
  332. #endif    /* DEBUG */
  333.   our_pred->p_type = BI_OP;
  334.   our_pred->p_prec = AND_PREC;
  335.   our_pred->need_stat = false;
  336.   return (true);
  337. }
  338.  
  339. boolean
  340. parse_anewer (argv, arg_ptr)
  341.      char *argv[];
  342.      int *arg_ptr;
  343. {
  344.   struct predicate *our_pred;
  345.   struct stat stat_newer;
  346.  
  347.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  348.     return (false);
  349.   if ((*xstat) (argv[*arg_ptr], &stat_newer))
  350.     error (1, errno, "%s", argv[*arg_ptr]);
  351.   our_pred = insert_victim (pred_anewer);
  352.   our_pred->args.time = stat_newer.st_mtime;
  353.   (*arg_ptr)++;
  354.   return (true);
  355. }
  356.  
  357. boolean
  358. parse_atime (argv, arg_ptr)
  359.      char *argv[];
  360.      int *arg_ptr;
  361. {
  362.   return (insert_time (argv, arg_ptr, pred_atime));
  363. }
  364.  
  365. boolean
  366. parse_close (argv, arg_ptr)
  367.      char *argv[];
  368.      int *arg_ptr;
  369. {
  370.   struct predicate *our_pred;
  371.  
  372.   our_pred = get_new_pred ();
  373.   our_pred->pred_func = pred_close;
  374. #ifdef    DEBUG
  375.   our_pred->p_name = find_pred_name (pred_close);
  376. #endif    /* DEBUG */
  377.   our_pred->p_type = CLOSE_PAREN;
  378.   our_pred->p_prec = NO_PREC;
  379.   our_pred->need_stat = false;
  380.   return (true);
  381. }
  382.  
  383. boolean
  384. parse_cmin (argv, arg_ptr)
  385.      char *argv[];
  386.      int *arg_ptr;
  387. {
  388.   struct predicate *our_pred;
  389.   unsigned long num;
  390.   enum comparison_type c_type;
  391.  
  392.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  393.     return (false);
  394.   if (!get_num_days (argv[*arg_ptr], &num, &c_type))
  395.     return (false);
  396.   our_pred = insert_victim (pred_cmin);
  397.   our_pred->args.info.kind = c_type;
  398.   our_pred->args.info.l_val = cur_day_start + DAYSECS - num * 60;
  399.   (*arg_ptr)++;
  400.   return (true);
  401. }
  402.  
  403. boolean
  404. parse_cnewer (argv, arg_ptr)
  405.      char *argv[];
  406.      int *arg_ptr;
  407. {
  408.   struct predicate *our_pred;
  409.   struct stat stat_newer;
  410.  
  411.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  412.     return (false);
  413.   if ((*xstat) (argv[*arg_ptr], &stat_newer))
  414.     error (1, errno, "%s", argv[*arg_ptr]);
  415.   our_pred = insert_victim (pred_cnewer);
  416.   our_pred->args.time = stat_newer.st_mtime;
  417.   (*arg_ptr)++;
  418.   return (true);
  419. }
  420.  
  421. boolean
  422. parse_comma (argv, arg_ptr)
  423.      char *argv[];
  424.      int *arg_ptr;
  425. {
  426.   struct predicate *our_pred;
  427.  
  428.   our_pred = get_new_pred ();
  429.   our_pred->pred_func = pred_comma;
  430. #ifdef    DEBUG
  431.   our_pred->p_name = find_pred_name (pred_comma);
  432. #endif /* DEBUG */
  433.   our_pred->p_type = BI_OP;
  434.   our_pred->p_prec = COMMA_PREC;
  435.   our_pred->need_stat = false;
  436.   return (true);
  437. }
  438.  
  439. boolean
  440. parse_ctime (argv, arg_ptr)
  441.      char *argv[];
  442.      int *arg_ptr;
  443. {
  444.   return (insert_time (argv, arg_ptr, pred_ctime));
  445. }
  446.  
  447. boolean
  448. parse_daystart (argv, arg_ptr)
  449.      char *argv[];
  450.      int *arg_ptr;
  451. {
  452.   struct tm *local;
  453.  
  454.   if (full_days == false)
  455.     {
  456.       cur_day_start += DAYSECS;
  457.       local = localtime (&cur_day_start);
  458.       cur_day_start -= local->tm_sec + local->tm_min * 60
  459.     + local->tm_hour * 3600;
  460.       full_days = true;
  461.     }
  462.   return (true);
  463. }
  464.  
  465. boolean
  466. parse_depth (argv, arg_ptr)
  467.      char *argv[];
  468.      int *arg_ptr;
  469. {
  470.   do_dir_first = false;
  471.   return (true);
  472. }
  473.  
  474. boolean
  475. parse_empty (argv, arg_ptr)
  476.      char *argv[];
  477.      int *arg_ptr;
  478. {
  479.   insert_victim (pred_empty);
  480.   return (true);
  481. }
  482.  
  483. boolean
  484. parse_exec (argv, arg_ptr)
  485.      char *argv[];
  486.      int *arg_ptr;
  487. {
  488.   return (insert_exec_ok (pred_exec, argv, arg_ptr));
  489. }
  490.  
  491. boolean
  492. parse_false (argv, arg_ptr)
  493.      char *argv[];
  494.      int *arg_ptr;
  495. {
  496.   struct predicate *our_pred;
  497.  
  498.   our_pred = insert_victim (pred_false);
  499.   our_pred->need_stat = false;
  500.   return (true);
  501. }
  502.  
  503. boolean 
  504. parse_fprintf (argv, arg_ptr)
  505.      char *argv[];
  506.      int *arg_ptr;
  507. {
  508.   FILE *fp;
  509.  
  510.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  511.     return (false);
  512.   fp = open_output_file (argv[*arg_ptr]);
  513.   (*arg_ptr)++;
  514.   return (insert_fprintf (fp, pred_fprintf, argv, arg_ptr));
  515. }
  516.  
  517. boolean
  518. parse_follow (argv, arg_ptr)
  519.      char *argv[];
  520.      int *arg_ptr;
  521. {
  522.   xstat = stat;
  523.   no_leaf_check = true;
  524.   return (true);
  525. }
  526.  
  527. boolean
  528. parse_fprint (argv, arg_ptr)
  529.      char *argv[];
  530.      int *arg_ptr;
  531. {
  532.   struct predicate *our_pred;
  533.  
  534.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  535.     return (false);
  536.   our_pred = insert_victim (pred_fprint);
  537.   our_pred->args.stream = open_output_file (argv[*arg_ptr]);
  538.   our_pred->side_effects = true;
  539.   our_pred->need_stat = false;
  540.   (*arg_ptr)++;
  541.   return (true);
  542. }
  543.  
  544. boolean
  545. parse_fprint0 (argv, arg_ptr)
  546.      char *argv[];
  547.      int *arg_ptr;
  548. {
  549.   struct predicate *our_pred;
  550.  
  551.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  552.     return (false);
  553.   our_pred = insert_victim (pred_fprint0);
  554.   our_pred->args.stream = open_output_file (argv[*arg_ptr]);
  555.   our_pred->side_effects = true;
  556.   our_pred->need_stat = false;
  557.   (*arg_ptr)++;
  558.   return (true);
  559. }
  560.  
  561. boolean
  562. parse_fstype (argv, arg_ptr)
  563.      char *argv[];
  564.      int *arg_ptr;
  565. {
  566.   struct predicate *our_pred;
  567.  
  568.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  569.     return (false);
  570.   our_pred = insert_victim (pred_fstype);
  571.   our_pred->args.str = argv[*arg_ptr];
  572.   (*arg_ptr)++;
  573.   return (true);
  574. }
  575.  
  576. boolean
  577. parse_gid (argv, arg_ptr)
  578.      char *argv[];
  579.      int *arg_ptr;
  580. {
  581.   return (insert_num (argv, arg_ptr, pred_gid));
  582. }
  583.  
  584. boolean
  585. parse_group (argv, arg_ptr)
  586.      char *argv[];
  587.      int *arg_ptr;
  588. {
  589.   struct group *cur_gr;
  590.   struct predicate *our_pred;
  591.   int gid, gid_len;
  592.  
  593.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  594.     return (false);
  595.   cur_gr = getgrnam (argv[*arg_ptr]);
  596.   endgrent ();
  597.   if (cur_gr != NULL)
  598.     gid = cur_gr->gr_gid;
  599.   else
  600.     {
  601.       gid_len = strspn (argv[*arg_ptr], "0123456789");
  602.       if ((gid_len == 0) || (argv[*arg_ptr][gid_len] != '\0'))
  603.     return (false);
  604.       gid = atoi (argv[*arg_ptr]);
  605.     }
  606.   our_pred = insert_victim (pred_group);
  607.   our_pred->args.gid = (short) gid;
  608.   (*arg_ptr)++;
  609.   return (true);
  610. }
  611.  
  612. boolean
  613. parse_inum (argv, arg_ptr)
  614.      char *argv[];
  615.      int *arg_ptr;
  616. {
  617.   return (insert_num (argv, arg_ptr, pred_inum));
  618. }
  619.  
  620. boolean
  621. parse_links (argv, arg_ptr)
  622.      char *argv[];
  623.      int *arg_ptr;
  624. {
  625.   return (insert_num (argv, arg_ptr, pred_links));
  626. }
  627.  
  628. boolean
  629. parse_lname (argv, arg_ptr)
  630.      char *argv[];
  631.      int *arg_ptr;
  632. {
  633.   struct predicate *our_pred;
  634.  
  635.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  636.     return (false);
  637.   our_pred = insert_victim (pred_lname);
  638.   our_pred->args.str = argv[*arg_ptr];
  639.   (*arg_ptr)++;
  640.   return (true);
  641. }
  642.  
  643. boolean
  644. parse_ls (argv, arg_ptr)
  645.      char *argv[];
  646.      int *arg_ptr;
  647. {
  648.   struct predicate *our_pred;
  649.  
  650.   our_pred = insert_victim (pred_ls);
  651.   our_pred->side_effects = true;
  652.   return (true);
  653. }
  654.  
  655. boolean
  656. parse_maxdepth (argv, arg_ptr)
  657.      char *argv[];
  658.      int *arg_ptr;
  659. {
  660.   int depth_len;
  661.  
  662.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  663.     return (false);
  664.   depth_len = strspn (argv[*arg_ptr], "0123456789");
  665.   if ((depth_len == 0) || (argv[*arg_ptr][depth_len] != '\0'))
  666.     return (false);
  667.   maxdepth = atoi (argv[*arg_ptr]);
  668.   if (maxdepth < 0)
  669.     return (false);
  670.   (*arg_ptr)++;
  671.   return (true);
  672. }
  673.  
  674. boolean
  675. parse_mindepth (argv, arg_ptr)
  676.      char *argv[];
  677.      int *arg_ptr;
  678. {
  679.   int depth_len;
  680.  
  681.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  682.     return (false);
  683.   depth_len = strspn (argv[*arg_ptr], "0123456789");
  684.   if ((depth_len == 0) || (argv[*arg_ptr][depth_len] != '\0'))
  685.     return (false);
  686.   mindepth = atoi (argv[*arg_ptr]);
  687.   if (mindepth < 0)
  688.     return (false);
  689.   (*arg_ptr)++;
  690.   return (true);
  691. }
  692.  
  693. boolean
  694. parse_mmin (argv, arg_ptr)
  695.      char *argv[];
  696.      int *arg_ptr;
  697. {
  698.   struct predicate *our_pred;
  699.   unsigned long num;
  700.   enum comparison_type c_type;
  701.  
  702.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  703.     return (false);
  704.   if (!get_num_days (argv[*arg_ptr], &num, &c_type))
  705.     return (false);
  706.   our_pred = insert_victim (pred_mmin);
  707.   our_pred->args.info.kind = c_type;
  708.   our_pred->args.info.l_val = cur_day_start + DAYSECS - num * 60;
  709.   (*arg_ptr)++;
  710.   return (true);
  711. }
  712.  
  713. boolean
  714. parse_mtime (argv, arg_ptr)
  715.      char *argv[];
  716.      int *arg_ptr;
  717. {
  718.   return (insert_time (argv, arg_ptr, pred_mtime));
  719. }
  720.  
  721. boolean
  722. parse_name (argv, arg_ptr)
  723.      char *argv[];
  724.      int *arg_ptr;
  725. {
  726.   struct predicate *our_pred;
  727.  
  728.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  729.     return (false);
  730.   our_pred = insert_victim (pred_name);
  731.   our_pred->need_stat = false;
  732.   our_pred->args.str = argv[*arg_ptr];
  733.   (*arg_ptr)++;
  734.   return (true);
  735. }
  736.  
  737. boolean
  738. parse_negate (argv, arg_ptr)
  739.      char *argv[];
  740.      int *arg_ptr;
  741. {
  742.   struct predicate *our_pred;
  743.  
  744.   our_pred = get_new_pred_chk_op ();
  745.   our_pred->pred_func = pred_negate;
  746. #ifdef    DEBUG
  747.   our_pred->p_name = find_pred_name (pred_negate);
  748. #endif    /* DEBUG */
  749.   our_pred->p_type = UNI_OP;
  750.   our_pred->p_prec = NEGATE_PREC;
  751.   our_pred->need_stat = false;
  752.   return (true);
  753. }
  754.  
  755. boolean
  756. parse_newer (argv, arg_ptr)
  757.      char *argv[];
  758.      int *arg_ptr;
  759. {
  760.   struct predicate *our_pred;
  761.   struct stat stat_newer;
  762.  
  763.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  764.     return (false);
  765.   if ((*xstat) (argv[*arg_ptr], &stat_newer))
  766.     error (1, errno, "%s", argv[*arg_ptr]);
  767.   our_pred = insert_victim (pred_newer);
  768.   our_pred->args.time = stat_newer.st_mtime;
  769.   (*arg_ptr)++;
  770.   return (true);
  771. }
  772.  
  773. boolean
  774. parse_noleaf (argv, arg_ptr)
  775.      char *argv[];
  776.      int *arg_ptr;
  777. {
  778.   no_leaf_check = true;
  779.   return true;
  780. }
  781.  
  782. #ifdef CACHE_IDS
  783. /* Arbitrary amount by which to increase size
  784.    of `uid_unused' and `gid_unused'. */
  785. #define ALLOC_STEP 2048
  786.  
  787. /* Boolean: if uid_unused[n] is nonzero, then UID n has no passwd entry. */
  788. char *uid_unused = NULL;
  789.  
  790. /* Number of elements in `uid_unused'. */
  791. unsigned uid_allocated;
  792.  
  793. /* Similar for GIDs and group entries. */
  794. char *gid_unused = NULL;
  795. unsigned gid_allocated;
  796. #endif
  797.  
  798. boolean
  799. parse_nogroup (argv, arg_ptr)
  800.      char *argv[];
  801.      int *arg_ptr;
  802. {
  803.   struct predicate *our_pred;
  804.  
  805.   our_pred = insert_victim (pred_nogroup);
  806. #ifdef CACHE_IDS
  807.   if (gid_unused == NULL)
  808.     {
  809.       struct group *gr;
  810.  
  811.       gid_allocated = ALLOC_STEP;
  812.       gid_unused = xmalloc (gid_allocated);
  813.       memset (gid_unused, 1, gid_allocated);
  814.       setgrent ();
  815.       while ((gr = getgrent ()) != NULL)
  816.     {
  817.       if ((unsigned) gr->gr_gid >= gid_allocated)
  818.         {
  819.           unsigned new_allocated = gr->gr_gid + ALLOC_STEP;
  820.           gid_unused = xrealloc (gid_unused, new_allocated);
  821.           memset (gid_unused + gid_allocated, 1,
  822.               new_allocated - gid_allocated);
  823.           gid_allocated = new_allocated;
  824.         }
  825.       gid_unused[(unsigned) gr->gr_gid] = 0;
  826.     }
  827.       endgrent ();
  828.     }
  829. #endif
  830.   return (true);
  831. }
  832.  
  833. boolean
  834. parse_nouser (argv, arg_ptr)
  835.      char *argv[];
  836.      int *arg_ptr;
  837. {
  838.   struct predicate *our_pred;
  839.  
  840.   our_pred = insert_victim (pred_nouser);
  841. #ifdef CACHE_IDS
  842.   if (uid_unused == NULL)
  843.     {
  844.       struct passwd *pw;
  845.  
  846.       uid_allocated = ALLOC_STEP;
  847.       uid_unused = xmalloc (uid_allocated);
  848.       memset (uid_unused, 1, uid_allocated);
  849.       setpwent ();
  850.       while ((pw = getpwent ()) != NULL)
  851.     {
  852.       if ((unsigned) pw->pw_uid >= uid_allocated)
  853.         {
  854.           unsigned new_allocated = pw->pw_uid + ALLOC_STEP;
  855.           uid_unused = xrealloc (uid_unused, new_allocated);
  856.           memset (uid_unused + uid_allocated, 1,
  857.               new_allocated - uid_allocated);
  858.           uid_allocated = new_allocated;
  859.         }
  860.       uid_unused[(unsigned) pw->pw_uid] = 0;
  861.     }
  862.       endpwent ();
  863.     }
  864. #endif
  865.   return (true);
  866. }
  867.  
  868. boolean
  869. parse_ok (argv, arg_ptr)
  870.      char *argv[];
  871.      int *arg_ptr;
  872. {
  873.   return (insert_exec_ok (pred_ok, argv, arg_ptr));
  874. }
  875.  
  876. boolean
  877. parse_open (argv, arg_ptr)
  878.      char *argv[];
  879.      int *arg_ptr;
  880. {
  881.   struct predicate *our_pred;
  882.  
  883.   our_pred = get_new_pred_chk_op ();
  884.   our_pred->pred_func = pred_open;
  885. #ifdef    DEBUG
  886.   our_pred->p_name = find_pred_name (pred_open);
  887. #endif    /* DEBUG */
  888.   our_pred->p_type = OPEN_PAREN;
  889.   our_pred->p_prec = NO_PREC;
  890.   our_pred->need_stat = false;
  891.   return (true);
  892. }
  893.  
  894. boolean
  895. parse_or (argv, arg_ptr)
  896.      char *argv[];
  897.      int *arg_ptr;
  898. {
  899.   struct predicate *our_pred;
  900.  
  901.   our_pred = get_new_pred ();
  902.   our_pred->pred_func = pred_or;
  903. #ifdef    DEBUG
  904.   our_pred->p_name = find_pred_name (pred_or);
  905. #endif    /* DEBUG */
  906.   our_pred->p_type = BI_OP;
  907.   our_pred->p_prec = OR_PREC;
  908.   our_pred->need_stat = false;
  909.   return (true);
  910. }
  911.  
  912. boolean
  913. parse_path (argv, arg_ptr)
  914.      char *argv[];
  915.      int *arg_ptr;
  916. {
  917.   struct predicate *our_pred;
  918.  
  919.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  920.     return (false);
  921.   our_pred = insert_victim (pred_path);
  922.   our_pred->need_stat = false;
  923.   our_pred->args.str = argv[*arg_ptr];
  924.   (*arg_ptr)++;
  925.   return (true);
  926. }
  927.  
  928. boolean
  929. parse_perm (argv, arg_ptr)
  930.      char *argv[];
  931.      int *arg_ptr;
  932. {
  933.   unsigned long perm_val;
  934.   int mode_start = 0;
  935.   struct mode_change *change;
  936.   struct predicate *our_pred;
  937.  
  938.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  939.     return (false);
  940.  
  941.   switch (argv[*arg_ptr][0])
  942.     {
  943.     case '-':
  944.     case '+':
  945.       mode_start = 1;
  946.       break;
  947.     default:
  948.       /* empty */
  949.       break;
  950.     }
  951.  
  952.   change = mode_compile (argv[*arg_ptr] + mode_start, MODE_MASK_PLUS);
  953.   if (change == MODE_INVALID)
  954.     error (1, 0, "invalid mode `%s'", argv[*arg_ptr]);
  955.   else if (change == MODE_MEMORY_EXHAUSTED)
  956.     error (1, 0, "virtual memory exhausted");
  957.   perm_val = mode_adjust (0, change);
  958.   mode_free (change);
  959.  
  960.   our_pred = insert_victim (pred_perm);
  961.  
  962.   switch (argv[*arg_ptr][0])
  963.     {
  964.     case '-':
  965.       /* Set magic flag to indicate true if at least the given bits are set. */
  966.       our_pred->args.perm = (perm_val & 07777) | 010000;
  967.       break;
  968.     case '+':
  969.       /* Set magic flag to indicate true if any of the given bits are set. */
  970.       our_pred->args.perm = (perm_val & 07777) | 020000;
  971.       break;
  972.     default:
  973.       /* True if exactly the given bits are set. */
  974.       our_pred->args.perm = (perm_val & 07777);
  975.       break;
  976.     }
  977.   (*arg_ptr)++;
  978.   return (true);
  979. }
  980.  
  981. boolean
  982. parse_print (argv, arg_ptr)
  983.      char *argv[];
  984.      int *arg_ptr;
  985. {
  986.   struct predicate *our_pred;
  987.  
  988.   our_pred = insert_victim (pred_print);
  989.   /* -print has the side effect of printing.  This prevents us
  990.      from doing undesired multiple printing when the user has
  991.      already specified -print. */
  992.   our_pred->side_effects = true;
  993.   our_pred->need_stat = false;
  994.   return (true);
  995. }
  996.  
  997. boolean
  998. parse_print0 (argv, arg_ptr)
  999.      char *argv[];
  1000.      int *arg_ptr;
  1001. {
  1002.   struct predicate *our_pred;
  1003.  
  1004.   our_pred = insert_victim (pred_print0);
  1005.   /* -print0 has the side effect of printing.  This prevents us
  1006.      from doing undesired multiple printing when the user has
  1007.      already specified -print0. */
  1008.   our_pred->side_effects = true;
  1009.   our_pred->need_stat = false;
  1010.   return (true);
  1011. }
  1012.  
  1013. boolean
  1014. parse_printf (argv, arg_ptr)
  1015.      char *argv[];
  1016.      int *arg_ptr;
  1017. {
  1018.   return (insert_fprintf (stdout, pred_fprintf, argv, arg_ptr));
  1019. }
  1020.  
  1021. boolean
  1022. parse_prune (argv, arg_ptr)
  1023.      char *argv[];
  1024.      int *arg_ptr;
  1025. {
  1026.   struct predicate *our_pred;
  1027.  
  1028.   our_pred = insert_victim (pred_prune);
  1029.   our_pred->need_stat = false;
  1030.   return (true);
  1031. }
  1032.  
  1033. boolean
  1034. parse_regex (argv, arg_ptr)
  1035.      char *argv[];
  1036.      int *arg_ptr;
  1037. {
  1038.   struct predicate *our_pred;
  1039.   struct re_pattern_buffer *re;
  1040.   const char *error_message;
  1041.  
  1042.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  1043.     return (false);
  1044.   our_pred = insert_victim (pred_regex);
  1045.   our_pred->need_stat = false;
  1046.   re = (struct re_pattern_buffer *)
  1047.     xmalloc (sizeof (struct re_pattern_buffer));
  1048.   our_pred->args.regex = re;
  1049.   re->allocated = 100;
  1050.   re->buffer = (unsigned char *) xmalloc (re->allocated);
  1051.   re->fastmap = NULL;
  1052.   re->translate = NULL;
  1053.   error_message = re_compile_pattern (argv[*arg_ptr], strlen (argv[*arg_ptr]),
  1054.                       re);
  1055.   if (error_message)
  1056.     error (1, 0, "%s", error_message);
  1057.   (*arg_ptr)++;
  1058.   return (true);
  1059. }
  1060.  
  1061. boolean
  1062. parse_size (argv, arg_ptr)
  1063.      char *argv[];
  1064.      int *arg_ptr;
  1065. {
  1066.   struct predicate *our_pred;
  1067.   unsigned long num;
  1068.   enum comparison_type c_type;
  1069.   int blksize = 512;
  1070.   int len;
  1071.  
  1072.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  1073.     return (false);
  1074.   len = strlen (argv[*arg_ptr]);
  1075.   if (len == 0)
  1076.     error (1, 0, "invalid null argument to -size");
  1077.   switch (argv[*arg_ptr][len - 1])
  1078.     {
  1079.     case 'c':
  1080.       blksize = 1;
  1081.       argv[*arg_ptr][len - 1] = '\0';
  1082.       break;
  1083.  
  1084.     case 'k':
  1085.       blksize = 1024;
  1086.       argv[*arg_ptr][len - 1] = '\0';
  1087.       break;
  1088.  
  1089.     case '0':
  1090.     case '1':
  1091.     case '2':
  1092.     case '3':
  1093.     case '4':
  1094.     case '5':
  1095.     case '6':
  1096.     case '7':
  1097.     case '8':
  1098.     case '9':
  1099.       break;
  1100.  
  1101.     default:
  1102.       error (1, 0, "invalid -size type `%c'", argv[*arg_ptr][len - 1]);
  1103.     }
  1104.   if (!get_num (argv[*arg_ptr], &num, &c_type))
  1105.     return (false);
  1106.   our_pred = insert_victim (pred_size);
  1107.   our_pred->args.size.kind = c_type;
  1108.   our_pred->args.size.blocksize = blksize;
  1109.   our_pred->args.size.size = num;
  1110.   (*arg_ptr)++;
  1111.   return (true);
  1112. }
  1113.  
  1114. boolean
  1115. parse_true (argv, arg_ptr)
  1116.      char *argv[];
  1117.      int *arg_ptr;
  1118. {
  1119.   struct predicate *our_pred;
  1120.  
  1121.   our_pred = insert_victim (pred_true);
  1122.   our_pred->need_stat = false;
  1123.   return (true);
  1124. }
  1125.  
  1126. boolean
  1127. parse_type (argv, arg_ptr)
  1128.      char *argv[];
  1129.      int *arg_ptr;
  1130. {
  1131.   return insert_type (argv, arg_ptr, pred_type);
  1132. }
  1133.  
  1134. boolean
  1135. parse_uid (argv, arg_ptr)
  1136.      char *argv[];
  1137.      int *arg_ptr;
  1138. {
  1139.   return (insert_num (argv, arg_ptr, pred_uid));
  1140. }
  1141.  
  1142. boolean
  1143. parse_used (argv, arg_ptr)
  1144.      char *argv[];
  1145.      int *arg_ptr;
  1146.  
  1147. {
  1148.   struct predicate *our_pred;
  1149.   unsigned long num_days;
  1150.   enum comparison_type c_type;
  1151.  
  1152.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  1153.     return (false);
  1154.   if (!get_num (argv[*arg_ptr], &num_days, &c_type))
  1155.     return (false);
  1156.   our_pred = insert_victim (pred_used);
  1157.   our_pred->args.info.kind = c_type;
  1158.   our_pred->args.info.l_val = num_days * DAYSECS;
  1159.   (*arg_ptr)++;
  1160.   return (true);
  1161. }
  1162.  
  1163. boolean
  1164. parse_user (argv, arg_ptr)
  1165.      char *argv[];
  1166.      int *arg_ptr;
  1167. {
  1168.   struct passwd *cur_pwd;
  1169.   struct predicate *our_pred;
  1170.   int uid, uid_len;
  1171.  
  1172.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  1173.     return (false);
  1174.   cur_pwd = getpwnam (argv[*arg_ptr]);
  1175.   endpwent ();
  1176.   if (cur_pwd != NULL)
  1177.     uid = cur_pwd->pw_uid;
  1178.   else
  1179.     {
  1180.       uid_len = strspn (argv[*arg_ptr], "0123456789");
  1181.       if ((uid_len == 0) || (argv[*arg_ptr][uid_len] != '\0'))
  1182.     return (false);
  1183.       uid = atoi (argv[*arg_ptr]);
  1184.     }
  1185.   our_pred = insert_victim (pred_user);
  1186.   our_pred->args.uid = (short) uid;
  1187.   (*arg_ptr)++;
  1188.   return (true);
  1189. }
  1190.  
  1191. boolean
  1192. parse_version (argv, arg_ptr)
  1193.      char *argv[];
  1194.      int *arg_ptr;
  1195. {
  1196.   extern char *version_string;
  1197.  
  1198.   fflush (stdout);
  1199.   fprintf (stderr, "%s", version_string);
  1200.   fflush (stderr);
  1201.   return true;
  1202. }
  1203.  
  1204. boolean
  1205. parse_xdev (argv, arg_ptr)
  1206.      char *argv[];
  1207.      int *arg_ptr;
  1208. {
  1209.   stay_on_filesystem = true;
  1210.   return true;
  1211. }
  1212.  
  1213. boolean
  1214. parse_xtype (argv, arg_ptr)
  1215.      char *argv[];
  1216.      int *arg_ptr;
  1217. {
  1218.   return insert_type (argv, arg_ptr, pred_xtype);
  1219. }
  1220.  
  1221. boolean
  1222. insert_type (argv, arg_ptr, which_pred)
  1223.      char *argv[];
  1224.      int *arg_ptr;
  1225.      boolean (*which_pred) ();
  1226. {
  1227.   unsigned long type_cell;
  1228.   struct predicate *our_pred;
  1229.  
  1230.   if ((argv == NULL) || (argv[*arg_ptr] == NULL)
  1231.       || (strlen (argv[*arg_ptr]) != 1))
  1232.     return (false);
  1233.   switch (argv[*arg_ptr][0])
  1234.     {
  1235.     case 'b':            /* block special */
  1236.       type_cell = S_IFBLK;
  1237.       break;
  1238.     case 'c':            /* character special */
  1239.       type_cell = S_IFCHR;
  1240.       break;
  1241.     case 'd':            /* directory */
  1242.       type_cell = S_IFDIR;
  1243.       break;
  1244.     case 'f':            /* regular file */
  1245.       type_cell = S_IFREG;
  1246.       break;
  1247. #ifdef S_IFLNK
  1248.     case 'l':            /* symbolic link */
  1249.       type_cell = S_IFLNK;
  1250.       break;
  1251. #endif
  1252. #ifdef S_IFIFO
  1253.     case 'p':            /* pipe */
  1254.       type_cell = S_IFIFO;
  1255.       break;
  1256. #endif
  1257. #ifdef S_IFSOCK
  1258.     case 's':            /* socket */
  1259.       type_cell = S_IFSOCK;
  1260.       break;
  1261. #endif
  1262.     default:            /* None of the above ... nuke 'em. */
  1263.       return (false);
  1264.     }
  1265.   our_pred = insert_victim (which_pred);
  1266.   our_pred->args.type = type_cell;
  1267.   (*arg_ptr)++;            /* Move on to next argument. */
  1268.   return (true);
  1269. }
  1270.  
  1271. /* If true, we've determined that the current fprintf predicate
  1272.    uses stat information. */
  1273. static boolean fprintf_stat_needed;
  1274.  
  1275. boolean
  1276. insert_fprintf (fp, func, argv, arg_ptr)
  1277.      FILE *fp;
  1278.      boolean (*func) ();
  1279.      char *argv[];
  1280.      int *arg_ptr;
  1281. {
  1282.   char *format;            /* Beginning of unprocessed format string. */
  1283.   register char *scan;        /* Current address in scanning `format'. */
  1284.   register char *scan2;        /* Address inside of element being scanned. */
  1285.   struct segment **segmentp;    /* Address of current segment. */
  1286.   struct predicate *our_pred;
  1287.  
  1288.   format = argv[(*arg_ptr)++];
  1289.  
  1290.   fprintf_stat_needed = false;    /* Might be overridden later. */
  1291.   our_pred = insert_victim (func);
  1292.   our_pred->side_effects = true;
  1293.   our_pred->args.printf_vec.stream = fp;
  1294.   segmentp = &our_pred->args.printf_vec.segment;
  1295.   *segmentp = NULL;
  1296.  
  1297.   for (scan = format; *scan; scan++)
  1298.     {
  1299.       if (*scan == '\\')
  1300.     {
  1301.       scan2 = scan + 1;
  1302.       if (*scan2 >= '0' && *scan2 <= '7')
  1303.         {
  1304.           register int n, i;
  1305.  
  1306.           for (i = n = 0; i < 3 && (*scan2 >= '0' && *scan2 <= '7');
  1307.            i++, scan2++)
  1308.         n = 8 * n + *scan2 - '0';
  1309.           scan2--;
  1310.           *scan = n;
  1311.         }
  1312.       else
  1313.         {
  1314.           switch (*scan2)
  1315.         {
  1316.         case 'a':
  1317.           *scan = 7;
  1318.           break;
  1319.         case 'b':
  1320.           *scan = '\b';
  1321.           break;
  1322.         case 'c':
  1323.           make_segment (segmentp, format, scan - format, KIND_STOP);
  1324.           return (true);
  1325.         case 'f':
  1326.           *scan = '\f';
  1327.           break;
  1328.         case 'n':
  1329.           *scan = '\n';
  1330.           break;
  1331.         case 'r':
  1332.           *scan = '\r';
  1333.           break;
  1334.         case 't':
  1335.           *scan = '\t';
  1336.           break;
  1337.         case 'v':
  1338.           *scan = '\v';
  1339.           break;
  1340.         case '\\':
  1341.           /* *scan = '\\'; * it already is */
  1342.           break;
  1343.         default:
  1344.           scan++;
  1345.           continue;
  1346.         }
  1347.         }
  1348.       segmentp = make_segment (segmentp, format, scan - format + 1,
  1349.                    KIND_PLAIN);
  1350.       format = scan2 + 1;    /* Move past the escape. */
  1351.       scan = scan2;        /* Incremented immediately by `for'. */
  1352.     }
  1353.       else if (*scan == '%')
  1354.     {
  1355.       if (scan[1] == '%')
  1356.         {
  1357.           segmentp = make_segment (segmentp, format, scan - format + 1,
  1358.                        KIND_PLAIN);
  1359.           scan++;
  1360.           format = scan + 1;
  1361.           continue;
  1362.         }
  1363.       /* Scan past flags, width and precision, to verify kind. */
  1364.       for (scan2 = scan; *++scan2 && index ("-+ #", *scan2);)
  1365.         /* Do nothing. */ ;
  1366.       while (isdigit (*scan2))
  1367.         scan2++;
  1368.       if (*scan2 == '.')
  1369.         for (scan2++; isdigit (*scan2); scan2++)
  1370.           /* Do nothing. */ ;
  1371.       if (index ("abcdfgGhHiklmnpPstuU", *scan2))
  1372.         {
  1373.           segmentp = make_segment (segmentp, format, scan2 - format,
  1374.                        (int) *scan2);
  1375.           scan = scan2;
  1376.           format = scan + 1;
  1377.         }
  1378.       else if (index ("ACT", *scan2) && scan2[1])
  1379.         {
  1380.           segmentp = make_segment (segmentp, format, scan2 - format,
  1381.                        *scan2 | (scan2[1] << 8));
  1382.           scan = scan2 + 1;
  1383.           format = scan + 1;
  1384.           continue;
  1385.         }
  1386.       else
  1387.         {
  1388.           /* An unrecognized % escape.  Print the char after the %. */
  1389.           segmentp = make_segment (segmentp, format, scan - format,
  1390.                        KIND_PLAIN);
  1391.           format = scan + 1;
  1392.           continue;
  1393.         }
  1394.     }
  1395.     }
  1396.  
  1397.   if (scan > format)
  1398.     make_segment (segmentp, format, scan - format, KIND_PLAIN);
  1399.   our_pred->need_stat = fprintf_stat_needed;
  1400.   return (true);
  1401. }
  1402.  
  1403. /* Create a new fprintf segment in *SEGMENT, with type KIND,
  1404.    from the text in FORMAT, which has length LEN.
  1405.    Return the address of the `next' pointer of the new segment. */
  1406.  
  1407. struct segment **
  1408. make_segment (segment, format, len, kind)
  1409.      struct segment **segment;
  1410.      char *format;
  1411.      int len, kind;
  1412. {
  1413.   char *fmt;
  1414.  
  1415.   *segment = (struct segment *) xmalloc (sizeof (struct segment));
  1416.  
  1417.   (*segment)->kind = kind;
  1418.   (*segment)->next = NULL;
  1419.   (*segment)->text_len = len;
  1420.  
  1421.   fmt = (*segment)->text = xmalloc (len + 3);    /* room for "ld\0" */
  1422.   strncpy (fmt, format, len);
  1423.   fmt += len;
  1424.  
  1425.   switch (kind & 0xff)
  1426.     {
  1427.     case KIND_PLAIN:        /* Plain text string, no % conversion. */
  1428.     case KIND_STOP:        /* Terminate argument, no newline. */
  1429.       break;
  1430.  
  1431.     case 'a':            /* atime in `ctime' format */
  1432.     case 'c':            /* ctime in `ctime' format */
  1433.     case 'g':            /* group name */
  1434.     case 'l':            /* object of symlink */
  1435.     case 't':            /* mtime in `ctime' format */
  1436.     case 'u':            /* user name */
  1437.     case 'A':            /* atime in user-specified strftime format */
  1438.     case 'C':            /* ctime in user-specified strftime format */
  1439.     case 'T':            /* mtime in user-specified strftime format */
  1440.       fprintf_stat_needed = true;
  1441.       /* FALLTHROUGH */
  1442.     case 'f':            /* basename of path */
  1443.     case 'h':            /* leading directories part of path */
  1444.     case 'H':            /* ARGV element file was found under */
  1445.     case 'p':            /* pathname */
  1446.     case 'P':            /* pathname with ARGV element stripped */
  1447.       *fmt++ = 's';
  1448.       break;
  1449.  
  1450.     case 'b':            /* size in 512-byte blocks */
  1451.     case 'k':            /* size in 1K blocks */
  1452.     case 's':            /* size in bytes */
  1453.       *fmt++ = 'l';
  1454.       /*FALLTHROUGH*/
  1455.     case 'n':            /* number of links */
  1456.       fprintf_stat_needed = true;
  1457.       /* FALLTHROUGH */
  1458.     case 'd':            /* depth in search tree (0 = ARGV element) */
  1459.       *fmt++ = 'd';
  1460.       break;
  1461.  
  1462.     case 'i':            /* inode number */
  1463.       *fmt++ = 'l';
  1464.       /*FALLTHROUGH*/
  1465.     case 'G':            /* GID number */
  1466.     case 'U':            /* UID number */
  1467.       *fmt++ = 'u';
  1468.       fprintf_stat_needed = true;
  1469.       break;
  1470.  
  1471.     case 'm':            /* mode as octal number (perms only) */
  1472.       *fmt++ = 'o';
  1473.       fprintf_stat_needed = true;
  1474.       break;
  1475.     }
  1476.   *fmt = '\0';
  1477.  
  1478.   return (&(*segment)->next);
  1479. }
  1480.  
  1481. boolean
  1482. insert_exec_ok (func, argv, arg_ptr)
  1483.      boolean (*func) ();
  1484.      char *argv[];
  1485.      int *arg_ptr;
  1486. {
  1487.   int start, end;        /* Indexes in ARGV of start & end of cmd. */
  1488.   int num_paths;        /* Number of args with path replacements. */
  1489.   int path_pos;            /* Index in array of path replacements. */
  1490.   int vec_pos;            /* Index in array of args. */
  1491.   struct predicate *our_pred;
  1492.   struct exec_val *execp;    /* Pointer for efficiency. */
  1493.  
  1494.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  1495.     return (false);
  1496.  
  1497.   /* Count the number of args with path replacements, up until the ';'. */
  1498.   start = *arg_ptr;
  1499.   for (end = start, num_paths = 0;
  1500.        (argv[end] != NULL)
  1501.        && ((argv[end][0] != ';') || (argv[end][1] != '\0'));
  1502.        end++)
  1503.     if (strstr (argv[end], "{}"))
  1504.       num_paths++;
  1505.   /* Fail if no command given or no semicolon found. */
  1506.   if ((end == start) || (argv[end] == NULL))
  1507.     {
  1508.       *arg_ptr = end;
  1509.       return (false);
  1510.     }
  1511.  
  1512.   our_pred = insert_victim (func);
  1513.   our_pred->side_effects = true;
  1514.   execp = &our_pred->args.exec_vec;
  1515.   execp->paths =
  1516.     (struct path_arg *) xmalloc (sizeof (struct path_arg) * (num_paths + 1));
  1517.   execp->vec = (char **) xmalloc (sizeof (char *) * (end - start + 1));
  1518.   /* Record the positions of all args, and the args with path replacements. */
  1519.   for (end = start, path_pos = vec_pos = 0;
  1520.        (argv[end] != NULL)
  1521.        && ((argv[end][0] != ';') || (argv[end][1] != '\0'));
  1522.        end++)
  1523.     {
  1524.       register char *p;
  1525.       
  1526.       execp->paths[path_pos].count = 0;
  1527.       for (p = argv[end]; *p; ++p)
  1528.     if (p[0] == '{' && p[1] == '}')
  1529.       {
  1530.         execp->paths[path_pos].count++;
  1531.         ++p;
  1532.       }
  1533.       if (execp->paths[path_pos].count)
  1534.     {
  1535.       execp->paths[path_pos].offset = vec_pos;
  1536.       execp->paths[path_pos].origarg = argv[end];
  1537.       path_pos++;
  1538.     }
  1539.       execp->vec[vec_pos++] = argv[end];
  1540.     }
  1541.   execp->paths[path_pos].offset = -1;
  1542.   execp->vec[vec_pos] = NULL;
  1543.  
  1544.   if (argv[end] == NULL)
  1545.     *arg_ptr = end;
  1546.   else
  1547.     *arg_ptr = end + 1;
  1548.   return (true);
  1549. }
  1550.  
  1551. /* Get a number of days and comparison type.
  1552.    STR is the ASCII representation.
  1553.    Set *NUM_DAYS to the number of days, taken as being from
  1554.    the current moment (or possibly midnight).  Thus the sense of the
  1555.    comparison type appears to be reversed.
  1556.    Set *COMP_TYPE to the kind of comparison that is requested.
  1557.  
  1558.    Return true if all okay, false if input error.
  1559.  
  1560.    Used by -atime, -ctime and -mtime (parsers) to
  1561.    get the appropriate information for a time predicate processor. */
  1562.  
  1563. boolean
  1564. get_num_days (str, num_days, comp_type)
  1565.      char *str;
  1566.      unsigned long *num_days;
  1567.      enum comparison_type *comp_type;
  1568. {
  1569.   int len_days;            /* length of field */
  1570.  
  1571.   if (str == NULL)
  1572.     return (false);
  1573.   switch (str[0])
  1574.     {
  1575.     case '+':
  1576.       *comp_type = COMP_LT;
  1577.       str++;
  1578.       break;
  1579.     case '-':
  1580.       *comp_type = COMP_GT;
  1581.       str++;
  1582.       break;
  1583.     case '0':
  1584.     case '1':
  1585.     case '2':
  1586.     case '3':
  1587.     case '4':
  1588.     case '5':
  1589.     case '6':
  1590.     case '7':
  1591.     case '8':
  1592.     case '9':
  1593.       *comp_type = COMP_EQ;
  1594.       break;
  1595.     default:
  1596.       return (false);
  1597.     }
  1598.  
  1599.   /* We know the first char has been reasonable.  Find the
  1600.      number of days to play with. */
  1601.   len_days = strspn (str, "0123456789");
  1602.   if ((len_days == 0) || (str[len_days] != '\0'))
  1603.     return (false);
  1604.   *num_days = (unsigned long) atol (str);
  1605.   return (true);
  1606. }
  1607.  
  1608. /* Insert a time predicate PRED.
  1609.    ARGV is a pointer to the argument array.
  1610.    ARG_PTR is a pointer to an index into the array, incremented if
  1611.    all went well.
  1612.  
  1613.    Return true if input is valid, false if not.
  1614.  
  1615.    A new predicate node is assigned, along with an argument node
  1616.    obtained with malloc.
  1617.  
  1618.    Used by -atime, -ctime, and -mtime parsers. */
  1619.  
  1620. boolean
  1621. insert_time (argv, arg_ptr, pred)
  1622.      char *argv[];
  1623.      int *arg_ptr;
  1624.      PFB pred;
  1625. {
  1626.   struct predicate *our_pred;
  1627.   unsigned long num_days;
  1628.   enum comparison_type c_type;
  1629.  
  1630.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  1631.     return (false);
  1632.   if (!get_num_days (argv[*arg_ptr], &num_days, &c_type))
  1633.     return (false);
  1634.   our_pred = insert_victim (pred);
  1635.   our_pred->args.info.kind = c_type;
  1636.   our_pred->args.info.l_val = cur_day_start - num_days * DAYSECS
  1637.     + ((c_type == COMP_GT) ? DAYSECS - 1 : 0);
  1638.   (*arg_ptr)++;
  1639. #ifdef    DEBUG
  1640.   printf ("inserting %s\n", our_pred->p_name);
  1641.   printf ("    type: %s    %s  ",
  1642.       (c_type == COMP_GT) ? "gt" :
  1643.       ((c_type == COMP_LT) ? "lt" : ((c_type == COMP_EQ) ? "eq" : "?")),
  1644.       (c_type == COMP_GT) ? " >" :
  1645.       ((c_type == COMP_LT) ? " <" : ((c_type == COMP_EQ) ? ">=" : " ?")));
  1646.   printf ("%ld %s", our_pred->args.info.l_val,
  1647.       ctime (&our_pred->args.info.l_val));
  1648.   if (c_type == COMP_EQ)
  1649.     {
  1650.       our_pred->args.info.l_val += DAYSECS;
  1651.       printf ("                 <  %ld %s", our_pred->args.info.l_val,
  1652.           ctime (&our_pred->args.info.l_val));
  1653.       our_pred->args.info.l_val -= DAYSECS;
  1654.     }
  1655. #endif    /* DEBUG */
  1656.   return (true);
  1657. }
  1658.  
  1659. /* Get a number with comparision information.
  1660.    The sense of the comparision information is 'normal'; that is,
  1661.    '+' looks for inums or links > than the number and '-' less than.
  1662.    
  1663.    STR is the ASCII representation of the number.
  1664.    Set *NUM to the number.
  1665.    Set *COMP_TYPE to the kind of comparison that is requested.
  1666.  
  1667.    Return true if all okay, false if input error.
  1668.  
  1669.    Used by the -inum and -links predicate parsers. */
  1670.  
  1671. boolean
  1672. get_num (str, num, comp_type)
  1673.      char *str;
  1674.      unsigned long *num;
  1675.      enum comparison_type *comp_type;
  1676. {
  1677.   int len_num;            /* Length of field. */
  1678.  
  1679.   if (str == NULL)
  1680.     return (false);
  1681.   switch (str[0])
  1682.     {
  1683.     case '+':
  1684.       *comp_type = COMP_GT;
  1685.       str++;
  1686.       break;
  1687.     case '-':
  1688.       *comp_type = COMP_LT;
  1689.       str++;
  1690.       break;
  1691.     case '0':
  1692.     case '1':
  1693.     case '2':
  1694.     case '3':
  1695.     case '4':
  1696.     case '5':
  1697.     case '6':
  1698.     case '7':
  1699.     case '8':
  1700.     case '9':
  1701.       *comp_type = COMP_EQ;
  1702.       break;
  1703.     default:
  1704.       return (false);
  1705.     }
  1706.  
  1707.   /* We know the first char has been reasonable.  Find the number of
  1708.      days to play with. */
  1709.   len_num = strspn (str, "0123456789");
  1710.   if ((len_num == 0) || (str[len_num] != '\0'))
  1711.     return (false);
  1712.   *num = (unsigned long) atol (str);
  1713.   return (true);
  1714. }
  1715.  
  1716. /* Insert a number predicate.
  1717.    ARGV is a pointer to the argument array.
  1718.    *ARG_PTR is an index into ARGV, incremented if all went well.
  1719.    *PRED is the predicate processor to insert.
  1720.  
  1721.    Return true if input is valid, false if error.
  1722.    
  1723.    A new predicate node is assigned, along with an argument node
  1724.    obtained with malloc.
  1725.  
  1726.    Used by -inum and -links parsers. */
  1727.  
  1728. boolean
  1729. insert_num (argv, arg_ptr, pred)
  1730.      char *argv[];
  1731.      int *arg_ptr;
  1732.      PFB pred;
  1733. {
  1734.   struct predicate *our_pred;
  1735.   unsigned long num;
  1736.   enum comparison_type c_type;
  1737.  
  1738.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  1739.     return (false);
  1740.   if (!get_num (argv[*arg_ptr], &num, &c_type))
  1741.     return (false);
  1742.   our_pred = insert_victim (pred);
  1743.   our_pred->args.info.kind = c_type;
  1744.   our_pred->args.info.l_val = num;
  1745.   (*arg_ptr)++;
  1746. #ifdef    DEBUG
  1747.   printf ("inserting %s\n", our_pred->p_name);
  1748.   printf ("    type: %s    %s  ",
  1749.       (c_type == COMP_GT) ? "gt" :
  1750.       ((c_type == COMP_LT) ? "lt" : ((c_type == COMP_EQ) ? "eq" : "?")),
  1751.       (c_type == COMP_GT) ? " >" :
  1752.       ((c_type == COMP_LT) ? " <" : ((c_type == COMP_EQ) ? " =" : " ?")));
  1753.   printf ("%ld\n", our_pred->args.info.l_val);
  1754. #endif    /* DEBUG */
  1755.   return (true);
  1756. }
  1757.  
  1758. FILE *
  1759. open_output_file (path)
  1760.      char *path;
  1761. {
  1762.   FILE *f;
  1763.  
  1764.   if (!strcmp (path, "/dev/stderr"))
  1765.     return (stderr);
  1766.   else if (!strcmp (path, "/dev/stdout"))
  1767.     return (stdout);
  1768.   f = fopen (path, "w");
  1769.   if (f == NULL)
  1770.     error (1, errno, "%s", path);
  1771.   return (f);
  1772. }
  1773.