示例#1
0
bool
impl_pred_exec (const char *pathname,
		struct stat *stat_buf,
		struct predicate *pred_ptr)
{
  struct exec_val *execp = &pred_ptr->args.exec_vec;
  char *buf = NULL;
  const char *target;
  bool result;
  const bool local = is_exec_in_local_dir (pred_ptr->pred_func);
  char *prefix;
  size_t pfxlen;

  (void) stat_buf;
  if (local)
    {
      /* For -execdir/-okdir predicates, the parser did not fill in
	 the wd_for_exec member of sturct exec_val.  So for those
	 predicates, we do so now.
      */
      if (!record_exec_dir (execp))
	{
	  error (EXIT_FAILURE, errno,
		 _("Failed to save working directory in order to "
		   "run a command on %s"),
		 safely_quote_err_filename (0, pathname));
	  /*NOTREACHED*/
	}
      target = buf = base_name (state.rel_pathname);
      if ('/' == target[0])
	{
	  /* find / execdir ls -d {} \; */
	  prefix = NULL;
	  pfxlen = 0;
	}
      else
	{
	  prefix = "./";
	  pfxlen = 2u;
	}
    }
  else
    {
      /* For the others (-exec, -ok), the parser should
	 have set wd_for_exec to initial_wd, indicating
	 that the exec should take place from find's initial
	 working directory.
      */
      assert (execp->wd_for_exec == initial_wd);
      target = pathname;
      prefix = NULL;
      pfxlen = 0u;
    }

  if (execp->multiple)
    {
      /* Push the argument onto the current list.
       * The command may or may not be run at this point,
       * depending on the command line length limits.
       */
      bc_push_arg (&execp->ctl,
		   &execp->state,
		   target, strlen (target)+1,
		   prefix, pfxlen,
		   0);

      /* remember that there are pending execdirs. */
      if (execp->state.todo)
	state.execdirs_outstanding = true;

      /* POSIX: If the primary expression is punctuated by a plus
       * sign, the primary shall always evaluate as true
       */
      result = true;
    }
  else
    {
      int i;

      for (i=0; i<execp->num_args; ++i)
	{
	  bc_do_insert (&execp->ctl,
			&execp->state,
			execp->replace_vec[i],
			strlen (execp->replace_vec[i]),
			prefix, pfxlen,
			target, strlen (target),
			0);
	}

      /* Actually invoke the command. */
      bc_do_exec (&execp->ctl, &execp->state);
      if (WIFEXITED(execp->last_child_status))
	{
	  if (0 == WEXITSTATUS(execp->last_child_status))
	    result = true;	/* The child succeeded. */
	  else
	    result = false;
	}
      else
	{
	  result = false;
	}
    }
  if (buf)
    {
      assert (local);
      free (buf);
    }
  return result;
}
示例#2
0
void
bc_do_insert (const struct buildcmd_control *ctl,
              struct buildcmd_state *state,
              char *arg, size_t arglen,
              const char *prefix, size_t pfxlen,
              const char *linebuf, size_t lblen,
              int initial_args)
{
  /* Temporary copy of each arg with the replace pattern replaced by the
     real arg.  */
  static char *insertbuf;
  char *p;
  size_t bytes_left = ctl->arg_max - 1;    /* Bytes left on the command line.  */

  /* XXX: on systems lacking an upper limit for exec args, ctl->arg_max
   *      may have been set to LONG_MAX (see bc_get_arg_max()).  Hence
   *      this xmalloc call may be a bad idea, especially since we are
   *      adding 1 to it...
   */
  if (!insertbuf)
    insertbuf = xmalloc (ctl->arg_max + 1);
  p = insertbuf;

  do
    {
      size_t len;               /* Length in ARG before `replace_pat'.  */
      char *s = mbsstr (arg, ctl->replace_pat);
      if (s)
        {
          len = s - arg;
        }
      else
        {
          len = arglen;
        }
      
      if (bytes_left <= len)
        break;
      else
	bytes_left -= len;

      strncpy (p, arg, len);
      p += len;
      arg += len;
      arglen -= len;

      if (s)
        {
	  if (bytes_left <= (lblen + pfxlen))
	    break;
	  else
	    bytes_left -= (lblen + pfxlen);
	  
	  if (prefix)
	    {
	      strcpy (p, prefix);
	      p += pfxlen;
	    }
          strcpy (p, linebuf);
          p += lblen;

          arg += ctl->rplen;
          arglen -= ctl->rplen;
        }
    }
  while (*arg);
  if (*arg)
    error (1, 0, _("command too long"));
  *p++ = '\0';
  
  bc_push_arg (ctl, state,
	       insertbuf, p - insertbuf,
               NULL, 0,
               initial_args);
}