home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / f / find12as.zip / PARSER.C < prev    next >
C/C++ Source or Header  |  1992-02-22  |  26KB  |  1,064 lines

  1. /* The Parsers and associated routines for Find.
  2.    Copyright (C) 1987, 1990 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 1, 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. /* MS-DOS port (c) 1990 by Thorsten Ohl, ohl@gnu.ai.mit.edu
  19.    This port is also distributed under the terms of the
  20.    GNU General Public License as published by the
  21.    Free Software Foundation.
  22.  
  23.    Please note that this file is not identical to the
  24.    original GNU release, you should have received this
  25.    code as patch to the official release.
  26.  
  27.    $Header: e:/gnu/find/RCS/parser.c 1.2.0.3 90/09/23 16:09:45 tho Exp $
  28.  */
  29.  
  30. #include <stdio.h>
  31. #include <sys/types.h>
  32. #include <sys/stat.h>
  33. #include <pwd.h>
  34. #ifndef MSDOS
  35. #include <grp.h>
  36. #endif /* not MSDOS */
  37. #include <time.h>
  38. #ifndef USG
  39. #include <strings.h>
  40. #else
  41. #include <string.h>
  42. #define index strchr
  43. #define rindex strrchr
  44. #endif
  45. #include "modechange.h"
  46. #include "defs.h"
  47.  
  48. #ifndef S_IFLNK
  49. #define lstat stat
  50. #endif
  51.  
  52. #ifdef MSDOS
  53.  
  54. static boolean parse_atime (PARSE_ARGS);
  55. static boolean parse_ctime (PARSE_ARGS);
  56. static boolean parse_depth (PARSE_ARGS);
  57. static boolean parse_exec (PARSE_ARGS);
  58. static boolean parse_fulldays (PARSE_ARGS);
  59. static boolean parse_fstype (PARSE_ARGS);
  60. static boolean parse_group (PARSE_ARGS);
  61. static boolean parse_inum (PARSE_ARGS);
  62. static boolean parse_links (PARSE_ARGS);
  63. static boolean parse_ls (PARSE_ARGS);
  64. static boolean parse_mtime (PARSE_ARGS);
  65. static boolean parse_name (PARSE_ARGS);
  66. static boolean parse_negate (PARSE_ARGS);
  67. static boolean parse_newer (PARSE_ARGS);
  68. static boolean parse_nogroup (PARSE_ARGS);
  69. static boolean parse_nouser (PARSE_ARGS);
  70. static boolean parse_ok (PARSE_ARGS);
  71. static boolean parse_or (PARSE_ARGS);
  72. static boolean parse_perm (PARSE_ARGS);
  73. static boolean parse_permmask (PARSE_ARGS);
  74. static boolean parse_prune (PARSE_ARGS);
  75. static boolean parse_regex (PARSE_ARGS);
  76. static boolean parse_size (PARSE_ARGS);
  77. static boolean parse_type (PARSE_ARGS);
  78. static boolean parse_user (PARSE_ARGS);
  79. static boolean parse_version (PARSE_ARGS);
  80. static boolean parse_xdev (PARSE_ARGS);
  81.  
  82. #else /* not MSDOS */
  83.  
  84. /* no parse_and */
  85. boolean parse_atime ();
  86. boolean parse_close ();
  87. boolean parse_ctime ();
  88. boolean parse_depth ();
  89. boolean parse_exec ();
  90. boolean parse_fstype ();
  91. boolean parse_fulldays ();
  92. boolean parse_group ();
  93. boolean parse_inum ();
  94. boolean parse_links ();
  95. boolean parse_ls ();
  96. boolean parse_mtime ();
  97. boolean parse_name ();
  98. boolean parse_negate ();
  99. boolean parse_newer ();
  100. boolean parse_nogroup ();
  101. boolean parse_nouser ();
  102. boolean parse_ok ();
  103. boolean parse_open ();
  104. boolean parse_or ();
  105. boolean parse_perm ();
  106. boolean parse_permmask ();
  107. boolean parse_print ();
  108. boolean parse_prune ();
  109. boolean parse_regex ();
  110. boolean parse_size ();
  111. boolean parse_type ();
  112. boolean parse_user ();
  113. boolean parse_version ();
  114. boolean parse_xdev ();
  115.  
  116. boolean pred_and ();
  117. boolean pred_atime ();
  118. boolean pred_close ();
  119. boolean pred_ctime ();
  120. /* no pred_depth */
  121. boolean pred_exec ();
  122. boolean pred_fstype ();
  123. /* no pred_fulldays */
  124. boolean pred_group ();
  125. boolean pred_inum ();
  126. boolean pred_links ();
  127. boolean pred_ls ();
  128. boolean pred_mtime ();
  129. boolean pred_name ();
  130. boolean pred_negate ();
  131. boolean pred_newer ();
  132. boolean pred_nogroup ();
  133. boolean pred_nouser ();
  134. boolean pred_ok ();
  135. boolean pred_open ();
  136. boolean pred_or ();
  137. boolean pred_perm ();
  138. boolean pred_permmask ();
  139. boolean pred_print ();
  140. boolean pred_prune ();
  141. boolean pred_regex ();
  142. boolean pred_size ();
  143. boolean pred_type ();
  144. boolean pred_user ();
  145. /* no pred_version */
  146. /* no pred_xdev */
  147.  
  148. #endif /* not MSDOS */
  149.  
  150. long atol ();
  151. struct group *getgrnam ();
  152. struct passwd *getpwnam ();
  153. struct tm *localtime ();
  154. void endgrent ();
  155. void endpwent ();
  156.  
  157. boolean get_num ();
  158. boolean insert_exec_ok ();
  159. boolean insert_num ();
  160. boolean insert_time ();
  161. char *find_pred_name ();
  162. void read_mtab ();
  163.  
  164. #ifdef    DEBUG
  165. char *find_pred_name ();
  166. #endif    /* DEBUG */
  167.  
  168. struct parser_table_t
  169. {
  170.   char *parser_name;
  171. #ifdef MSDOS
  172.   PARSE_FCT parser_func;
  173. #else
  174.   PFB parser_func;
  175. #endif
  176. };
  177.  
  178. struct parser_table_t parse_table[] =
  179. {
  180.   {"!", parse_negate},
  181.   {"(", parse_open},
  182.   {")", parse_close},
  183. #ifdef UNIMPLEMENTED_UNIX
  184.   {"a", parse_and},        /* do-nothing */
  185. #endif
  186.   {"atime", parse_atime},
  187. #ifdef UNIMPLEMENTED_UNIX
  188.   {"cpio", parse_cpio},
  189. #endif
  190.   {"ctime", parse_ctime},
  191.   {"depth", parse_depth},
  192.   {"exec", parse_exec},
  193.   {"fulldays", parse_fulldays},    /* nonstandard */
  194.   {"fstype", parse_fstype},
  195.   {"group", parse_group},
  196.   {"inum", parse_inum},        /* nonstandard, Unix */
  197.   {"links", parse_links},
  198.   {"ls", parse_ls},        /* nonstandard, Unix */
  199.   {"mtime", parse_mtime},
  200.   {"name", parse_name},
  201. #ifdef UNIMPLEMENTED_UNIX
  202.   {"ncpio", parse_ncpio},
  203. #endif
  204.   {"newer", parse_newer},
  205.   {"nogroup", parse_nogroup},
  206.   {"nouser", parse_nouser},
  207.   {"o", parse_or},
  208.   {"or", parse_or},        /* nonstandard */
  209.   {"ok", parse_ok},
  210.   {"perm", parse_perm},
  211.   {"permmask", parse_permmask},    /* nonstandard */
  212.   {"print", parse_print},
  213.   {"prune", parse_prune},
  214.   {"regex", parse_regex},    /* nonstandard */
  215.   {"size", parse_size},
  216.   {"type", parse_type},
  217.   {"user", parse_user},
  218.   {"version", parse_version},
  219.   {"xdev", parse_xdev},
  220.   {0, 0}
  221. };
  222.  
  223. /* Return a pointer to the parser function to invoke for predicate
  224.    SEARCH_NAME.
  225.    Return NULL if SEARCH_NAME is not a valid predicate name. */
  226.  
  227.  
  228. #ifdef MSDOS
  229. PARSE_FCT
  230. #else
  231. PFB
  232. #endif
  233. find_parser (search_name)
  234.      char *search_name;
  235. {
  236.   int i;
  237.  
  238.   if (*search_name == '-')
  239.     search_name++;
  240.   for (i = 0; parse_table[i].parser_name != 0; i++)
  241.     if (strcmp (parse_table[i].parser_name, search_name) == 0)
  242.       return (parse_table[i].parser_func);
  243.   return (NULL);
  244. }
  245.  
  246. /* The parsers are responsible to continue scanning ARGV for
  247.    their arguments.  Each parser knows what is and isn't
  248.    allowed for itself.
  249.    
  250.    ARGV is the argument array.
  251.    *ARG_PTR is the index to start at in ARGV,
  252.    updated to point beyond the last element consumed.
  253.  
  254.    The predicate structure is updated with the new information. */
  255.  
  256. boolean
  257. parse_atime (argv, arg_ptr)
  258.      char *argv[];
  259.      int *arg_ptr;
  260. {
  261.   return (insert_time (argv, arg_ptr, pred_atime));
  262. }
  263.  
  264. boolean
  265. parse_close (argv, arg_ptr)
  266.      char *argv[];
  267.      int *arg_ptr;
  268. {
  269.   struct pred_struct *our_pred;
  270.  
  271.   our_pred = get_new_pred ();
  272.   our_pred->pred_func = pred_close;
  273. #ifdef    DEBUG
  274.   our_pred->p_name = find_pred_name (pred_close);
  275. #endif    /* DEBUG */
  276.   our_pred->p_type = CLOSE_PAREN;
  277.   our_pred->p_prec = NO_PREC;
  278.   return (true);
  279. }
  280.  
  281. boolean
  282. parse_ctime (argv, arg_ptr)
  283.      char *argv[];
  284.      int *arg_ptr;
  285. {
  286.   return (insert_time (argv, arg_ptr, pred_ctime));
  287. }
  288.  
  289. boolean
  290. parse_depth (argv, arg_ptr)
  291.      char *argv[];
  292.      int *arg_ptr;
  293. {
  294.   do_dir_first = false;
  295.   return (true);
  296. }
  297.  
  298. boolean
  299. parse_exec (argv, arg_ptr)
  300.      char *argv[];
  301.      int *arg_ptr;
  302. {
  303.   return (insert_exec_ok (pred_exec, argv, arg_ptr));
  304. }
  305.  
  306. boolean
  307. parse_fulldays (argv, arg_ptr)
  308.      char *argv[];
  309.      int *arg_ptr;
  310. {
  311.   struct tm *local;
  312.  
  313.   if (full_days == false)
  314.     {
  315.       cur_day_start += DAYSECS;
  316.       local = localtime (&cur_day_start);
  317.       cur_day_start -= local->tm_sec + local->tm_min * 60
  318.     + local->tm_hour * 3600;
  319.       full_days = true;
  320.     }
  321.   return (true);
  322. }
  323.  
  324. boolean
  325. parse_fstype (argv, arg_ptr)
  326.      char *argv[];
  327.      int *arg_ptr;
  328. {
  329.   struct pred_struct *our_pred;
  330.  
  331.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  332.     return (false);
  333.   our_pred = insert_victim (pred_fstype);
  334.   our_pred->args.str = argv[*arg_ptr];
  335.   (*arg_ptr)++;
  336.   read_mtab ();
  337.   return (true);
  338. }
  339.  
  340. boolean
  341. parse_group (argv, arg_ptr)
  342.      char *argv[];
  343.      int *arg_ptr;
  344. {
  345.   struct group *cur_gr;
  346.   struct pred_struct *our_pred;
  347.   int gid, gid_len;
  348.  
  349.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  350.     return (false);
  351.   cur_gr = getgrnam (argv[*arg_ptr]);
  352.   endgrent ();
  353.   if (cur_gr != NULL)
  354.     gid = cur_gr->gr_gid;
  355.   else
  356.     {
  357.       gid_len = strspn (argv[*arg_ptr], "0123456789");
  358.       if ((gid_len == 0) || (argv[*arg_ptr][gid_len] != '\0'))
  359.     return (false);
  360.       gid = atoi (argv[*arg_ptr]);
  361.     }
  362.   our_pred = insert_victim (pred_group);
  363.   our_pred->args.gid = (short) gid;
  364.   (*arg_ptr)++;
  365.   return (true);
  366. }
  367.  
  368. boolean
  369. parse_inum (argv, arg_ptr)
  370.      char *argv[];
  371.      int *arg_ptr;
  372. {
  373.   return (insert_num (argv, arg_ptr, pred_inum));
  374. }
  375.  
  376. boolean
  377. parse_links (argv, arg_ptr)
  378.      char *argv[];
  379.      int *arg_ptr;
  380. {
  381.   return (insert_num (argv, arg_ptr, pred_links));
  382. }
  383.  
  384. boolean
  385. parse_ls (argv, arg_ptr)
  386.      char *argv[];
  387.      int *arg_ptr;
  388. {
  389.   struct pred_struct *our_pred;
  390.  
  391.   our_pred = insert_victim (pred_ls);
  392.   our_pred->side_effects = true;
  393.   return (true);
  394. }
  395.  
  396. boolean
  397. parse_mtime (argv, arg_ptr)
  398.      char *argv[];
  399.      int *arg_ptr;
  400. {
  401.   return (insert_time (argv, arg_ptr, pred_mtime));
  402. }
  403.  
  404. boolean
  405. parse_name (argv, arg_ptr)
  406.      char *argv[];
  407.      int *arg_ptr;
  408. {
  409.   struct pred_struct *our_pred;
  410.  
  411.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  412.     return (false);
  413.   our_pred = insert_victim (pred_name);
  414.   our_pred->args.str = argv[*arg_ptr];
  415.   (*arg_ptr)++;
  416.   return (true);
  417. }
  418.  
  419. boolean
  420. parse_negate (argv, arg_ptr)
  421.      char *argv[];
  422.      int *arg_ptr;
  423. {
  424.   struct pred_struct *our_pred;
  425.  
  426.   our_pred = get_new_pred_chk_op ();
  427.   our_pred->pred_func = pred_negate;
  428. #ifdef    DEBUG
  429.   our_pred->p_name = find_pred_name (pred_negate);
  430. #endif    /* DEBUG */
  431.   our_pred->p_type = UNI_OP;
  432.   our_pred->p_prec = NEGATE_PREC;
  433.   return (true);
  434. }
  435.  
  436. boolean
  437. parse_newer (argv, arg_ptr)
  438.      char *argv[];
  439.      int *arg_ptr;
  440. {
  441.   struct pred_struct *our_pred;
  442.   struct stat stat_newer;
  443.  
  444.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  445.     return (false);
  446.   if (lstat (argv[*arg_ptr], &stat_newer))
  447.     error (1, errno, "%s", argv[*arg_ptr]);
  448.   our_pred = insert_victim (pred_newer);
  449.   our_pred->args.time = stat_newer.st_mtime;
  450.   (*arg_ptr)++;
  451.   return (true);
  452. }
  453.  
  454. boolean
  455. parse_nogroup (argv, arg_ptr)
  456.      char *argv[];
  457.      int *arg_ptr;
  458. {
  459.   struct pred_struct *our_pred;
  460.  
  461.   our_pred = insert_victim (pred_nogroup);
  462.   return (true);
  463. }
  464.  
  465. boolean
  466. parse_nouser (argv, arg_ptr)
  467.      char *argv[];
  468.      int *arg_ptr;
  469. {
  470.   struct pred_struct *our_pred;
  471.  
  472.   our_pred = insert_victim (pred_nouser);
  473.   return (true);
  474. }
  475.  
  476. boolean
  477. parse_ok (argv, arg_ptr)
  478.      char *argv[];
  479.      int *arg_ptr;
  480. {
  481.   boolean insert_exec_ok ();
  482.  
  483.   return (insert_exec_ok (pred_ok, argv, arg_ptr));
  484. }
  485.  
  486. boolean
  487. parse_open (argv, arg_ptr)
  488.      char *argv[];
  489.      int *arg_ptr;
  490. {
  491.   struct pred_struct *our_pred;
  492.  
  493.   our_pred = get_new_pred_chk_op ();
  494.   our_pred->pred_func = pred_open;
  495. #ifdef    DEBUG
  496.   our_pred->p_name = find_pred_name (pred_open);
  497. #endif    /* DEBUG */
  498.   our_pred->p_type = OPEN_PAREN;
  499.   our_pred->p_prec = NO_PREC;
  500.   return (true);
  501. }
  502.  
  503. boolean
  504. parse_or (argv, arg_ptr)
  505.      char *argv[];
  506.      int *arg_ptr;
  507. {
  508.   struct pred_struct *our_pred;
  509.  
  510.   our_pred = get_new_pred ();
  511.   our_pred->pred_func = pred_or;
  512. #ifdef    DEBUG
  513.   our_pred->p_name = find_pred_name (pred_or);
  514. #endif    /* DEBUG */
  515.   our_pred->p_type = BI_OP;
  516.   our_pred->p_prec = OR_PREC;
  517.   return (true);
  518. }
  519.  
  520. boolean
  521. parse_perm (argv, arg_ptr)
  522.      char *argv[];
  523.      int *arg_ptr;
  524. {
  525.   unsigned long perm_val;
  526.   int mode_start = 0;
  527.   struct mode_change *change;
  528.   struct pred_struct *our_pred;
  529.  
  530.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  531.     return (false);
  532.   if (argv[*arg_ptr][0] == '-')
  533.     mode_start = 1;
  534.   
  535.   change = mode_compile (argv[*arg_ptr] + mode_start, MODE_MASK_PLUS);
  536.   if (change == MODE_INVALID)
  537.     error (1, 0, "invalid mode `%s'", argv[*arg_ptr]);
  538.   else if (change == MODE_MEMORY_EXHAUSTED)
  539.     error (1, 0, "virtual memory exhausted");
  540.   perm_val = mode_adjust (0, change);
  541.   mode_free (change);
  542.  
  543.   our_pred = insert_victim (pred_perm);
  544.   if (mode_start)
  545.     /* Set magic flag to compare suid, sgid, sticky bits as well;
  546.        also, true if at least the given bits are set. */
  547.     our_pred->args.perm = (perm_val & 07777) | 010000;
  548.   else
  549.     our_pred->args.perm = perm_val & 0777;
  550.   (*arg_ptr)++;
  551.   return (true);
  552. }
  553.  
  554. boolean
  555. parse_permmask (argv, arg_ptr)
  556.      char *argv[];
  557.      int *arg_ptr;
  558. {
  559.   unsigned long mask_val;
  560.   struct mode_change *change;
  561.   struct pred_struct *our_pred;
  562.  
  563.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  564.     return (false);
  565.  
  566.   change = mode_compile (argv[*arg_ptr], MODE_MASK_PLUS);
  567.   if (change == MODE_INVALID)
  568.     error (1, 0, "invalid mode mask `%s'", argv[*arg_ptr]);
  569.   else if (change == MODE_MEMORY_EXHAUSTED)
  570.     error (1, 0, "virtual memory exhausted");
  571.   mask_val = mode_adjust (0, change);
  572.   mode_free (change);
  573.  
  574.   our_pred = insert_victim (pred_permmask);
  575.   our_pred->args.perm = mask_val;
  576.   (*arg_ptr)++;
  577.   return (true);
  578. }
  579.  
  580. boolean
  581. parse_print (argv, arg_ptr)
  582.      char *argv[];
  583.      int *arg_ptr;
  584. {
  585.   struct pred_struct *our_pred;
  586.  
  587.   our_pred = insert_victim (pred_print);
  588.   /* -print has the side effect of printing.  This prevents us
  589.      from doing undesired multiple printing when the user has
  590.      already specified -print. */
  591.   our_pred->side_effects = true;
  592.   return (true);
  593. }
  594.  
  595. boolean
  596. parse_prune (argv, arg_ptr)
  597.      char *argv[];
  598.      int *arg_ptr;
  599. {
  600.   struct pred_struct *our_pred;
  601.  
  602.   our_pred = insert_victim (pred_prune);
  603.   return (true);
  604. }
  605.  
  606. boolean
  607. parse_regex (argv, arg_ptr)
  608.      char *argv[];
  609.      int *arg_ptr;
  610. {
  611.   struct pred_struct *our_pred;
  612.   struct re_pattern_buffer *re;
  613.   char *error_message;
  614.  
  615.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  616.     return (false);
  617.   our_pred = insert_victim (pred_regex);
  618.   re = (struct re_pattern_buffer *)
  619.     xmalloc (sizeof (struct re_pattern_buffer));
  620.   our_pred->args.regex = re;
  621.   re->allocated = 100;
  622. #ifdef MSDOS
  623.   re->buffer = xmalloc ((size_t) re->allocated);
  624. #else /* not MSDOS */
  625.   re->buffer = xmalloc (re->allocated);
  626. #endif /* not MSDOS */
  627.   re->fastmap = NULL;
  628.   re->translate = NULL;
  629.   error_message = re_compile_pattern (argv[*arg_ptr], strlen (argv[*arg_ptr]),
  630.                       re);
  631.   if (error_message)
  632.     error (1, 0, "%s", error_message);
  633.   (*arg_ptr)++;
  634.   return (true);
  635. }
  636.  
  637. boolean
  638. parse_size (argv, arg_ptr)
  639.      char *argv[];
  640.      int *arg_ptr;
  641. {
  642.   struct pred_struct *our_pred;
  643.   unsigned long num;
  644.   short c_type;
  645.   boolean blk;
  646.   int len;
  647.  
  648.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  649.     return (false);
  650.   len = strlen (argv[*arg_ptr]);
  651.   if (len == 0)
  652.     error (1, 0, "invalid null argument to -size");
  653.   switch (argv[*arg_ptr][len - 1])
  654.     {
  655.     case 'c':
  656.       blk = false;
  657.       argv[*arg_ptr][len - 1] = '\0';
  658.       break;
  659.  
  660.     case '0':
  661.     case '1':
  662.     case '2':
  663.     case '3':
  664.     case '4':
  665.     case '5':
  666.     case '6':
  667.     case '7':
  668.     case '8':
  669.     case '9':
  670.       blk = true;
  671.       break;
  672.  
  673.     default:
  674.       error (1, 0, "invalid -size type `%c'", argv[*arg_ptr][len - 1]);
  675.     }
  676.   if (!get_num (argv[*arg_ptr], &num, &c_type))
  677.     return (false);
  678.   our_pred = insert_victim (pred_size);
  679.   our_pred->args.size.kind = c_type;
  680.   our_pred->args.size.block = blk;
  681.   our_pred->args.size.size = num;
  682.   (*arg_ptr)++;
  683.   return (true);
  684. }
  685.  
  686. boolean
  687. parse_type (argv, arg_ptr)
  688.      char *argv[];
  689.      int *arg_ptr;
  690. {
  691.   unsigned long type_cell;
  692.   struct pred_struct *our_pred;
  693.  
  694.   if ((argv == NULL) || (argv[*arg_ptr] == NULL)
  695.       || (strlen (argv[*arg_ptr]) != 1))
  696.     return (false);
  697.   switch (argv[*arg_ptr][0])
  698.     {
  699. #ifdef S_IFBLK
  700.     case 'b':            /* block special */
  701.       type_cell = S_IFBLK;
  702.       break;
  703. #endif
  704.     case 'c':            /* character special */
  705.       type_cell = S_IFCHR;
  706.       break;
  707.     case 'd':            /* directory */
  708.       type_cell = S_IFDIR;
  709.       break;
  710.     case 'f':            /* regular file */
  711.       type_cell = S_IFREG;
  712.       break;
  713. #ifdef S_IFLNK
  714.     case 'l':            /* symbolic link */
  715.       type_cell = S_IFLNK;
  716.       break;
  717. #endif
  718. #ifdef S_IFIFO
  719.     case 'p':            /* pipe */
  720.       type_cell = S_IFIFO;
  721.       break;
  722. #endif
  723. #ifdef S_IFSOCK
  724.     case 's':            /* socket */
  725.       type_cell = S_IFSOCK;
  726.       break;
  727. #endif
  728.     default:            /* none of the above ... nuke em */
  729.       return (false);
  730.     }
  731.   our_pred = insert_victim (pred_type);
  732.   our_pred->args.type = type_cell;
  733.   (*arg_ptr)++;            /* move on to next argument */
  734.   return (true);
  735. }
  736.  
  737. boolean
  738. parse_user (argv, arg_ptr)
  739.      char *argv[];
  740.      int *arg_ptr;
  741. {
  742.   struct passwd *cur_pwd;
  743.   struct pred_struct *our_pred;
  744.   int uid, uid_len;
  745.  
  746.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  747.     return (false);
  748.   cur_pwd = getpwnam (argv[*arg_ptr]);
  749.   endpwent ();
  750.   if (cur_pwd != NULL)
  751.     uid = cur_pwd->pw_uid;
  752.   else
  753.     {
  754.       uid_len = strspn (argv[*arg_ptr], "0123456789");
  755.       if ((uid_len == 0) || (argv[*arg_ptr][uid_len] != '\0'))
  756.     return (false);
  757.       uid = atoi (argv[*arg_ptr]);
  758.     }
  759.   our_pred = insert_victim (pred_user);
  760.   our_pred->args.uid = (short) uid;
  761.   (*arg_ptr)++;
  762.   return (true);
  763. }
  764.  
  765. boolean
  766. parse_version (argv, arg_ptr)
  767.      char *argv[];
  768.      int *arg_ptr;
  769. {
  770.   extern char *version_string;
  771.  
  772.   fprintf (stderr, "%s", version_string);
  773.   return true;
  774. }
  775.  
  776. boolean
  777. parse_xdev (argv, arg_ptr)
  778.      char *argv[];
  779.      int *arg_ptr;
  780. {
  781.   stay_on_filesystem = true;
  782.   return true;
  783. }
  784.  
  785. boolean
  786. insert_exec_ok (func, argv, arg_ptr)
  787.      boolean (*func) ();
  788.      char *argv[];
  789.      int *arg_ptr;
  790. {
  791.   int start, end;        /* Indexes in ARGV of start & end of cmd. */
  792.   int num_paths;        /* Number of "{}" insertions to do. */
  793.   int path_pos;            /* Index in array of "{}" insertions. */
  794.   int vec_pos;            /* Index in array of arg words. */
  795.   struct pred_struct *our_pred;
  796.  
  797.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  798.     return (false);
  799.   start = *arg_ptr;
  800.   for (end = start, num_paths = 0;
  801.        (argv[end] != NULL)
  802.        && ((argv[end][0] != ';') || (argv[end][1] != '\0'));
  803.        end++)
  804.     if (strcmp (argv[end], "{}") == 0)
  805.       num_paths++;
  806.   /* Fail if no command given or no semicolon found. */
  807.   if ((end == start) || (argv[end] == NULL))
  808.     {
  809.       *arg_ptr = end;
  810.       return (false);
  811.     }
  812.   our_pred = insert_victim (func);
  813.   our_pred->side_effects = true;
  814.   our_pred->args.exec_vec.path_loc =
  815.     (short *) xmalloc (sizeof (short) * (num_paths + 1));
  816.   our_pred->args.exec_vec.vec =
  817.     (char **) xmalloc (sizeof (char *) * (end - start + 1));
  818.   for (end = start, path_pos = vec_pos = 0;
  819.        (argv[end] != NULL)
  820.        && ((argv[end][0] != ';') || (argv[end][1] != '\0'));
  821.        end++)
  822.     {
  823.       if (strcmp (argv[end], "{}") == 0)
  824.     our_pred->args.exec_vec.path_loc[path_pos++] = vec_pos;
  825.       our_pred->args.exec_vec.vec[vec_pos++] = argv[end];
  826.     }
  827.   our_pred->args.exec_vec.path_loc[path_pos] = -1;
  828.   our_pred->args.exec_vec.vec[vec_pos] = NULL;
  829.   if (argv[end] == NULL)
  830.     *arg_ptr = end;
  831.   else
  832.     *arg_ptr = end + 1;
  833.   return (true);
  834. }
  835.  
  836. /* Get a number of days and comparison type.
  837.    STR is the ASCII representation.
  838.    Set *NUM_DAYS to the number of days, taken as being from
  839.    the current moment (or possibly midnight).  Thus the sense of the
  840.    comparison type appears to be reversed.
  841.    Set *COMP_TYPE to the kind of comparison that is requested.
  842.  
  843.    Return true if all okay, false if input error.
  844.  
  845.    Used by -atime, -ctime and -mtime (parsers) to
  846.    get the appropriate information for a time predicate processor. */
  847.  
  848. boolean
  849. get_num_days (str, num_days, comp_type)
  850.      char *str;
  851.      unsigned long *num_days;
  852.      enum comparison_type *comp_type;
  853. {
  854.   int len_days;            /* length of field */
  855.  
  856.   if (str == NULL)
  857.     return (false);
  858.   switch (str[0])
  859.     {
  860.     case '+':
  861.       *comp_type = COMP_LT;
  862.       str++;
  863.       break;
  864.     case '-':
  865.       *comp_type = COMP_GT;
  866.       str++;
  867.       break;
  868.     case '0':
  869.     case '1':
  870.     case '2':
  871.     case '3':
  872.     case '4':
  873.     case '5':
  874.     case '6':
  875.     case '7':
  876.     case '8':
  877.     case '9':
  878.       *comp_type = COMP_EQ;
  879.       break;
  880.     default:
  881.       return (false);
  882.     }
  883.  
  884.   /* We know the first char has been reasonable.  Find the
  885.      number of days to play with. */
  886.   len_days = strspn (str, "0123456789");
  887.   if ((len_days == 0) || (str[len_days] != '\0'))
  888.     return (false);
  889.   *num_days = (unsigned long) atol (str);
  890.   return (true);
  891. }
  892.  
  893. /* Insert a time predicate PRED.
  894.    ARGV is a pointer to the argument array.
  895.    ARG_PTR is a pointer to an index into the array, incremented if
  896.    all went well.
  897.  
  898.    Return true if input is valid, false if not.
  899.  
  900.    A new predicate node is assigned, along with an argument node
  901.    obtained with malloc.
  902.  
  903.    Used by -atime, -ctime, and -mtime parsers. */
  904.  
  905. boolean
  906. insert_time (argv, arg_ptr, pred)
  907.      char *argv[];
  908.      int *arg_ptr;
  909. #ifdef MSDOS
  910.      PRED_FCT pred;
  911. #else
  912.      PFB pred;
  913. #endif
  914. {
  915.   struct pred_struct *our_pred;
  916.   unsigned long num_days;
  917.   enum comparison_type c_type;
  918.  
  919.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  920.     return (false);
  921.   if (!get_num_days (argv[*arg_ptr], &num_days, &c_type))
  922.     return (false);
  923.   our_pred = insert_victim (pred);
  924.   our_pred->args.info.kind = c_type;
  925.   our_pred->args.info.l_val = cur_day_start - num_days * DAYSECS
  926.     + ((c_type == COMP_GT) ? DAYSECS - 1 : 0);
  927.   (*arg_ptr)++;
  928. #ifdef    DEBUG
  929.   printf ("inserting %s\n", our_pred->p_name);
  930.   printf ("    type: %s    %s  ",
  931.       (c_type == COMP_GT) ? "gt" :
  932.       ((c_type == COMP_LT) ? "lt" : ((c_type == COMP_EQ) ? "eq" : "?")),
  933.       (c_type == COMP_GT) ? " >" :
  934.       ((c_type == COMP_LT) ? " <" : ((c_type == COMP_EQ) ? ">=" : " ?")));
  935.   printf ("%ld %s", our_pred->args.info.l_val,
  936.       ctime (&our_pred->args.info.l_val));
  937.   if (c_type == COMP_EQ)
  938.     {
  939.       our_pred->args.info.l_val += DAYSECS;
  940.       printf ("                 <  %ld %s", our_pred->args.info.l_val,
  941.           ctime (&our_pred->args.info.l_val));
  942.       our_pred->args.info.l_val -= DAYSECS;
  943.     }
  944. #endif    /* DEBUG */
  945.   return (true);
  946. }
  947.  
  948. /* Get a number with comparision information.
  949.    The sense of the comparision information is 'normal'; that is,
  950.    '+' looks for inums or links > than the number and '-' less than.
  951.    
  952.    STR is the ASCII representation of the number.
  953.    Set *NUM to the number.
  954.    Set *COMP_TYPE to the kind of comparison that is requested.
  955.  
  956.    Return true if all okay, false if input error.
  957.  
  958.    Used by the -inum and -links predicate parsers. */
  959.  
  960. boolean
  961. get_num (str, num, comp_type)
  962.      char *str;
  963.      unsigned long *num;
  964.      short *comp_type;
  965. {
  966.   int len_num;            /* length of field */
  967.  
  968.   if (str == NULL)
  969.     return (false);
  970.   switch (str[0])
  971.     {
  972.     case '+':
  973.       *comp_type = COMP_GT;
  974.       str++;
  975.       break;
  976.     case '-':
  977.       *comp_type = COMP_LT;
  978.       str++;
  979.       break;
  980.     case '0':
  981.     case '1':
  982.     case '2':
  983.     case '3':
  984.     case '4':
  985.     case '5':
  986.     case '6':
  987.     case '7':
  988.     case '8':
  989.     case '9':
  990.       *comp_type = COMP_EQ;
  991.       break;
  992.     default:
  993.       return (false);
  994.     }
  995.  
  996.   /* We know the first char has been reasonable.  Find the number of
  997.      days to play with. */
  998.   len_num = strspn (str, "0123456789");
  999.   if ((len_num == 0) || (str[len_num] != '\0'))
  1000.     return (false);
  1001.   *num = (unsigned long) atol (str);
  1002.   return (true);
  1003. }
  1004.  
  1005. /* Insert a number predicate.
  1006.    ARGV is a pointer to the argument array.
  1007.    *ARG_PTR is an index into ARGV, incremented if all went well.
  1008.    *PRED is the predicate processor to insert.
  1009.  
  1010.    Return true if input is valid, false if error.
  1011.    
  1012.    A new predicate node is assigned, along with an argument node
  1013.    obtained with malloc.
  1014.  
  1015.    Used by -inum and -links parsers. */
  1016.  
  1017. boolean
  1018. insert_num (argv, arg_ptr, pred)
  1019.      char *argv[];
  1020.      int *arg_ptr;
  1021. #ifdef MSDOS
  1022.      PRED_FCT pred;
  1023. #else
  1024.      PFB pred;
  1025. #endif
  1026. {
  1027.   struct pred_struct *our_pred;
  1028.   unsigned long num;
  1029.   short c_type;
  1030.  
  1031.   if ((argv == NULL) || (argv[*arg_ptr] == NULL))
  1032.     return (false);
  1033.   if (!get_num (argv[*arg_ptr], &num, &c_type))
  1034.     return (false);
  1035.   our_pred = insert_victim (pred);
  1036.   our_pred->args.info.kind = c_type;
  1037.   our_pred->args.info.l_val = num;
  1038.   (*arg_ptr)++;
  1039. #ifdef    DEBUG
  1040.   printf ("inserting %s\n", our_pred->p_name);
  1041.   printf ("    type: %s    %s  ",
  1042.       (c_type == COMP_GT) ? "gt" :
  1043.       ((c_type == COMP_LT) ? "lt" : ((c_type == COMP_EQ) ? "eq" : "?")),
  1044.       (c_type == COMP_GT) ? " >" :
  1045.       ((c_type == COMP_LT) ? " <" : ((c_type == COMP_EQ) ? " =" : " ?")));
  1046.   printf ("%ld\n", our_pred->args.info.l_val);
  1047. #endif    /* DEBUG */
  1048.   return (true);
  1049. }
  1050.  
  1051. #ifdef STRSPN_MISSING
  1052. int
  1053. strspn (str, class)
  1054.      char *str, *class;
  1055. {
  1056.   register char *cl = class;
  1057.   register char *st = str;
  1058.  
  1059.   while (index (class, *st))
  1060.     ++st;
  1061.   return st - str;
  1062. }
  1063. #endif
  1064.