Example #1
0
int execute (const char *name,
             const char **argv,
             const char *input,
             const char *output,
             const char **errmsg,
             int *waitstatus)
{
    int errnum;

    if(input != NULL || output != NULL) {
        *errmsg = "execute input/output NYI";
        return -1;
    }

    struct pex_obj *pex = pex_init(0, name, NULL);
    if (pex == NULL) {
        *errmsg = "pex_init failed";
        return -1;
    }

    *errmsg = pex_run(pex, PEX_LAST, name, (char * const *)argv, output, NULL, &errnum);
    if (*errmsg != NULL || !pex_get_status(pex, 1, waitstatus)) {
        if (&errmsg == NULL) {
            *errmsg = "can't get program status";
        }
        pex_free(pex);
        return -1;
    }

    pex_free(pex);
    return 0;
}
Example #2
0
int
pexecute (const char *program, char * const *argv, const char *pname,
	  const char *temp_base, char **errmsg_fmt, char **errmsg_arg,
	  int flags)
{
  const char *errmsg;
  int err;

  if ((flags & PEXECUTE_FIRST) != 0)
    {
      if (pex != NULL)
	{
	  *errmsg_fmt = (char *) "pexecute already in progress";
	  *errmsg_arg = NULL;
	  return -1;
	}
      pex = pex_init (PEX_USE_PIPES, pname, temp_base);
      idx = 0;
    }
  else
    {
      if (pex == NULL)
	{
	  *errmsg_fmt = (char *) "pexecute not in progress";
	  *errmsg_arg = NULL;
	  return -1;
	}
    }

  errmsg = pex_run (pex,
		    (((flags & PEXECUTE_LAST) != 0 ? PEX_LAST : 0)
		     | ((flags & PEXECUTE_SEARCH) != 0 ? PEX_SEARCH : 0)),
		    program, argv, NULL, NULL, &err);
  if (errmsg != NULL)
    {
      *errmsg_fmt = (char *) errmsg;
      *errmsg_arg = NULL;
      return -1;
    }

  /* Instead of a PID, we just return a one-based index into the
     status values.  We avoid zero just because the old pexecute would
     never return it.  */
  return ++idx;
}
Example #3
0
struct pex_obj *
collect_execute (const char *prog, char **argv, const char *outname,
		 const char *errname, int flags, bool use_atfile)
{
  struct pex_obj *pex;
  const char *errmsg;
  int err;
  char *response_arg = NULL;
  char *response_argv[3];

  if (use_atfile && argv[0] != NULL)
    {
      /* If using @file arguments, create a temporary file and put the
         contents of argv into it.  Then change argv to an array corresponding
         to a single argument @FILE, where FILE is the temporary filename.  */

      char **current_argv = argv + 1;
      char *argv0 = argv[0];
      int status;
      FILE *f;

      /* Note: we assume argv contains at least one element; this is
         checked above.  */

      response_file = make_temp_file ("");

      f = fopen (response_file, "w");

      if (f == NULL)
        fatal_error (input_location, "could not open response file %s",
		     response_file);

      status = writeargv (current_argv, f);

      if (status)
        fatal_error (input_location, "could not write to response file %s",
		     response_file);

      status = fclose (f);

      if (EOF == status)
        fatal_error (input_location, "could not close response file %s",
		     response_file);

      response_arg = concat ("@", response_file, NULL);
      response_argv[0] = argv0;
      response_argv[1] = response_arg;
      response_argv[2] = NULL;

      argv = response_argv;
    }

  if (verbose || debug)
    {
      char **p_argv;
      const char *str;

      if (argv[0])
	fprintf (stderr, "%s", argv[0]);
      else
	notice ("[cannot find %s]", prog);

      for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++)
	fprintf (stderr, " %s", str);

      fprintf (stderr, "\n");
    }

  fflush (stdout);
  fflush (stderr);

  /* If we cannot find a program we need, complain error.  Do this here
     since we might not end up needing something that we could not find.  */

  if (argv[0] == 0)
    fatal_error (input_location, "cannot find '%s'", prog);

  pex = pex_init (0, "collect2", NULL);
  if (pex == NULL)
    fatal_error (input_location, "pex_init failed: %m");

  errmsg = pex_run (pex, flags, argv[0], argv, outname,
		    errname, &err);
  if (errmsg != NULL)
    {
      if (err != 0)
	{
	  errno = err;
	  fatal_error (input_location, "%s: %m", _(errmsg));
	}
      else
	fatal_error (input_location, errmsg);
    }

  free (response_arg);

  return pex;
}
/* CYG_PATH is a pointer to a Cygwin path.  This function converts the
   Cygwin path to a Windows path, storing the result in
   WIN32_PATH.  Returns true if the conversion was successful; false
   otherwise.  */
int
cygpath (const char *cyg_path, char win32_path[MAX_PATH + 1])
{
  bool ok;
  bool retrying;
  
  /* Special-case the empty path.  cygpath cannot handle the empty
     path correctly.  It ignores the empty line, waiting for a
     non-empty line, which in turn causes an application using this
     function to appear stuck.  */
  if (cyg_path[0] == '\0')
    {
      win32_path[0] = '\0';
      return true;
    }
  
  retrying = false;

 retry:
  if (!cygpath_initialized) 
    {
      const char *argv[] = { "cygpath", "-w", "-f", "-", NULL };
      const char *cygpath_path;
      const char *log;
      int err;

      /* If we are unable to invoke cygpath, we do not want to try
	 again.  So, we set the initialized flag at this point; if
	 errors occur during the invocation, it will remain set.  */
      cygpath_initialized = 1;
      /* Check to see if the user wants cygpath support.  */
      cygpath_path = getenv ("CYGPATH");
      if (!cygpath_path)
	/* The user doesn't need to support Cygwin paths.  */
	goto error;
      /* If debugging, open the log file.  */
      log = getenv ("CSL_DEBUG_CYGPATH");
      if (log && log[0])
	{
	  /* The log file is opened for "append" so that multiple
	     processes (perhaps invoked from "make") can share it.  */
	  cygpath_log = fopen (log, "a");
	  if (cygpath_log)
	    cygpath_log_msg ("begin");
	}
      /* If the environment variable is set to a non-empty string, use
	 that string as the path to cygpath.  */ 
      if (cygpath_path[0] != '\0')
	argv[0] = cygpath_path;
      /* Create the pex object.  */
      cygpath_pex = pex_init (PEX_SEARCH | PEX_USE_PIPES, 
			      "cygpath", NULL);
      if (!cygpath_pex)
	goto error;
      /* Get the FILE we will use to write to the child.  */
      cygpath_in = pex_input_pipe (cygpath_pex, /*binary=*/0);
      if (!cygpath_in)
	goto error;
      /* Start the child process.  */
      if (pex_run (cygpath_pex, PEX_SEARCH | PEX_USE_PIPES, 
		   argv[0], (char**) argv, 
		   NULL, NULL,
		   &err) != NULL)
	goto error;
      /* Get the FILE we will use to read from the child.  */
      cygpath_out = pex_read_output (cygpath_pex, /*binary=*/1);
      if (!cygpath_out)
	goto error;
    }
  else if (!cygpath_pex) 
    /* We previously tried to use cygpath, but something went wrong.  */
    return false;

  /* Write CYG_PATH to the child, on a line by itself.  */
  cygpath_log_msg_arg ("-> %s", cyg_path);
  if (fprintf (cygpath_in, "%s\n", cyg_path) < 0)
    {
      cygpath_perror ("write failed");
      goto error;
    }
  /* Flush the output.  (We cannot set the stream into line-buffered
     mode with setvbuf because Windows treats _IOLBF as a synonym for
     _IOFBF.)  */
  if (fflush (cygpath_in))
    cygpath_perror ("flush failed");
  /* Read the output.  */
  ok = true;
  while (1)
    {
      size_t pathlen;
      if (!fgets (win32_path, MAX_PATH, cygpath_out))
	{
	  if (ferror (cygpath_out))
	    cygpath_perror ("read failed");
	  else
	    {
	      cygpath_log_msg ("error: EOF");
	      /* Unfortunately, cygpath sometimes crashes for no
		 apparent reason.  We give it two chances... */
	      if (!retrying)
		{
		  retrying = true;
		  cygpath_log_msg ("retrying");
		  cygpath_close ();
		  cygpath_initialized = 0;
		  goto retry;
		}
	    }
	  goto error;
	}
      pathlen = strlen (win32_path);
      if (pathlen == 0 && ok)
	/* This isn't a well-formed response from cygpath.  */
	goto error;
      if (win32_path[pathlen - 1] == '\n')
	{
	  win32_path[pathlen - 1] = '\0';
	  cygpath_log_msg_arg ("<- %s", win32_path);
	  break;
	}
      /* We didn't reach the end of the line.  There's no point in
	 trying to use this output, since we know the length of
	 paths are limited to MAX_PATH characters, but we read the
	 entire line so that we are still in sync with
	 cygpath.  */
      ok = false;
      if (cygpath_log)
	cygpath_log_msg_arg ("error: invalid response: %s",
			     win32_path);
    }
  
  return ok;
  
 error:
  cygpath_close();
  return false;
}
static void
exec_lto_wrapper (char *argv[])
{
  int t, i;
  int status;
  char *at_args;
  FILE *args;
  FILE *wrapper_output;
  char *new_argv[3];
  struct pex_obj *pex;
  const char *errmsg;

  /* Write argv to a file to avoid a command line that is too long. */
  arguments_file_name = make_temp_file ("");
  check (arguments_file_name, LDPL_FATAL,
         "Failed to generate a temorary file name");

  args = fopen (arguments_file_name, "w");
  check (args, LDPL_FATAL, "could not open arguments file");

  t = writeargv (&argv[1], args);
  check (t == 0, LDPL_FATAL, "could not write arguments");
  t = fclose (args);
  check (t == 0, LDPL_FATAL, "could not close arguments file");

  at_args = concat ("@", arguments_file_name, NULL);
  check (at_args, LDPL_FATAL, "could not allocate");

  for (i = 1; argv[i]; i++)
    {
      char *a = argv[i];
      if (a[0] == '-' && a[1] == 'v' && a[2] == '\0')
	{
	  for (i = 0; argv[i]; i++)
	    fprintf (stderr, "%s ", argv[i]);
	  fprintf (stderr, "\n");
	  break;
	}
    }

  new_argv[0] = argv[0];
  new_argv[1] = at_args;
  new_argv[2] = NULL;

  if (debug)
    {
      for (i = 0; new_argv[i]; i++)
	fprintf (stderr, "%s ", new_argv[i]);
      fprintf (stderr, "\n");
    }


  pex = pex_init (PEX_USE_PIPES, "lto-wrapper", NULL);
  check (pex != NULL, LDPL_FATAL, "could not pex_init lto-wrapper");

  errmsg = pex_run (pex, 0, new_argv[0], new_argv, NULL, NULL, &t);
  check (errmsg == NULL, LDPL_FATAL, "could not run lto-wrapper");
  check (t == 0, LDPL_FATAL, "could not run lto-wrapper");

  wrapper_output = pex_read_output (pex, 0);
  check (wrapper_output, LDPL_FATAL, "could not read lto-wrapper output");

  add_output_files (wrapper_output);

  t = pex_get_status (pex, 1, &status);
  check (t == 1, LDPL_FATAL, "could not get lto-wrapper exit status");
  check (WIFEXITED (status) && WEXITSTATUS (status) == 0, LDPL_FATAL,
         "lto-wrapper failed");

  pex_free (pex);

  free (at_args);
}