コード例 #1
0
ファイル: exechelp-posix.c プロジェクト: cuidi/gnupg
/* Portable function to create a pipe.  Under Windows the read end is
   inheritable.  If R_FP is not NULL, an estream is created for the
   write end and stored at R_FP.  */
gpg_error_t
gnupg_create_outbound_pipe (int filedes[2], estream_t *r_fp, int nonblock)
{
  if (r_fp)
    return create_pipe_and_estream (filedes, r_fp, 1, nonblock);
  else
    return do_create_pipe (filedes);
}
コード例 #2
0
/* Fork and exec the PGMNAME, see exechelp.h for details.  */
gpg_error_t
gnupg_spawn_process (const char *pgmname, const char *argv[],
                     gpg_err_source_t errsource,
                     void (*preexec)(void), unsigned int flags,
                     estream_t infp,
                     estream_t *r_outfp,
                     estream_t *r_errfp,
                     pid_t *pid)
{
    gpg_error_t err;
    int infd = -1;
    int outpipe[2] = {-1, -1};
    int errpipe[2] = {-1, -1};
    estream_t outfp = NULL;
    estream_t errfp = NULL;

    (void)flags; /* Currently not used.  */

    if (r_outfp)
        *r_outfp = NULL;
    if (r_errfp)
        *r_errfp = NULL;
    *pid = (pid_t)(-1); /* Always required.  */

    if (infp)
    {
        es_fflush (infp);
        es_rewind (infp);
        infd = es_fileno (infp);
        if (infd == -1)
            return gpg_err_make (errsource, GPG_ERR_INV_VALUE);
    }

    if (r_outfp)
    {
        err = create_pipe_and_estream (outpipe, &outfp, errsource);
        if (err)
            return err;
    }

    if (r_errfp)
    {
        err = create_pipe_and_estream (errpipe, &errfp, errsource);
        if (err)
        {
            if (outfp)
                es_fclose (outfp);
            else if (outpipe[0] != -1)
                close (outpipe[0]);
            if (outpipe[1] != -1)
                close (outpipe[1]);
            return err;
        }
    }


    *pid = fork ();
    if (*pid == (pid_t)(-1))
    {
        err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
        log_error (_("error forking process: %s\n"), gpg_strerror (err));

        if (outfp)
            es_fclose (outfp);
        else if (outpipe[0] != -1)
            close (outpipe[0]);
        if (outpipe[1] != -1)
            close (outpipe[1]);

        if (errfp)
            es_fclose (errfp);
        else if (errpipe[0] != -1)
            close (errpipe[0]);
        if (errpipe[1] != -1)
            close (errpipe[1]);
        return err;
    }

    if (!*pid)
    {
        /* This is the child. */
        gcry_control (GCRYCTL_TERM_SECMEM);
        es_fclose (outfp);
        es_fclose (errfp);
        do_exec (pgmname, argv, infd, outpipe[1], errpipe[1], preexec);
        /*NOTREACHED*/
    }

    /* This is the parent. */
    if (outpipe[1] != -1)
        close (outpipe[1]);
    if (errpipe[1] != -1)
        close (errpipe[1]);

    if (r_outfp)
        *r_outfp = outfp;
    if (r_errfp)
        *r_errfp = errfp;

    return 0;
}
コード例 #3
0
ファイル: exechelp-posix.c プロジェクト: cuidi/gnupg
/* Fork and exec the PGMNAME, see exechelp.h for details.  */
gpg_error_t
gnupg_spawn_process (const char *pgmname, const char *argv[],
                     int *except, void (*preexec)(void), unsigned int flags,
                     estream_t *r_infp,
                     estream_t *r_outfp,
                     estream_t *r_errfp,
                     pid_t *pid)
{
  gpg_error_t err;
  int inpipe[2] = {-1, -1};
  int outpipe[2] = {-1, -1};
  int errpipe[2] = {-1, -1};
  estream_t infp = NULL;
  estream_t outfp = NULL;
  estream_t errfp = NULL;
  int nonblock = !!(flags & GNUPG_SPAWN_NONBLOCK);

  if (r_infp)
    *r_infp = NULL;
  if (r_outfp)
    *r_outfp = NULL;
  if (r_errfp)
    *r_errfp = NULL;
  *pid = (pid_t)(-1); /* Always required.  */

  if (r_infp)
    {
      err = create_pipe_and_estream (inpipe, &infp, 1, nonblock);
      if (err)
        return err;
    }

  if (r_outfp)
    {
      err = create_pipe_and_estream (outpipe, &outfp, 0, nonblock);
      if (err)
        {
          if (infp)
            es_fclose (infp);
          else if (inpipe[1] != -1)
            close (inpipe[1]);
          if (inpipe[0] != -1)
            close (inpipe[0]);

          return err;
        }
    }

  if (r_errfp)
    {
      err = create_pipe_and_estream (errpipe, &errfp, 0, nonblock);
      if (err)
        {
          if (infp)
            es_fclose (infp);
          else if (inpipe[1] != -1)
            close (inpipe[1]);
          if (inpipe[0] != -1)
            close (inpipe[0]);

          if (outfp)
            es_fclose (outfp);
          else if (outpipe[0] != -1)
            close (outpipe[0]);
          if (outpipe[1] != -1)
            close (outpipe[1]);

          return err;
        }
    }


  *pid = fork ();
  if (*pid == (pid_t)(-1))
    {
      err = my_error_from_syserror ();
      log_error (_("error forking process: %s\n"), gpg_strerror (err));

      if (infp)
        es_fclose (infp);
      else if (inpipe[1] != -1)
        close (inpipe[1]);
      if (inpipe[0] != -1)
        close (inpipe[0]);

      if (outfp)
        es_fclose (outfp);
      else if (outpipe[0] != -1)
        close (outpipe[0]);
      if (outpipe[1] != -1)
        close (outpipe[1]);

      if (errfp)
        es_fclose (errfp);
      else if (errpipe[0] != -1)
        close (errpipe[0]);
      if (errpipe[1] != -1)
        close (errpipe[1]);
      return err;
    }

  if (!*pid)
    {
      /* This is the child. */
      gcry_control (GCRYCTL_TERM_SECMEM);
      es_fclose (outfp);
      es_fclose (errfp);
      do_exec (pgmname, argv, inpipe[0], outpipe[1], errpipe[1],
               except, preexec);
      /*NOTREACHED*/
    }

  /* This is the parent. */
  if (inpipe[0] != -1)
    close (inpipe[0]);
  if (outpipe[1] != -1)
    close (outpipe[1]);
  if (errpipe[1] != -1)
    close (errpipe[1]);

  if (r_infp)
    *r_infp = infp;
  if (r_outfp)
    *r_outfp = outfp;
  if (r_errfp)
    *r_errfp = errfp;

  return 0;
}