1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

Reworked the posix and w32 exechelpers.

This commit is contained in:
Werner Koch 2010-08-20 12:18:38 +00:00
parent be9c4748d0
commit 15330f36a7
13 changed files with 831 additions and 229 deletions

View file

@ -299,45 +299,95 @@ gnupg_create_outbound_pipe (int filedes[2])
}
static gpg_error_t
create_pipe_and_estream (int filedes[2], estream_t *r_fp,
gpg_err_source_t errsource)
{
gpg_error_t err;
if (pipe (filedes) == -1)
{
err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
filedes[0] = filedes[1] = -1;
*r_fp = NULL;
return err;
}
*r_fp = es_fdopen (filedes[0], "r");
if (!*r_fp)
{
err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
log_error (_("error creating a stream for a pipe: %s\n"),
gpg_strerror (err));
close (filedes[0]);
close (filedes[1]);
filedes[0] = filedes[1] = -1;
return err;
}
return 0;
}
/* Fork and exec the PGMNAME, see exechelp.h for details. */
gpg_error_t
gnupg_spawn_process (const char *pgmname, const char *argv[],
estream_t infile, estream_t outfile,
gpg_err_source_t errsource,
void (*preexec)(void), unsigned int flags,
estream_t *statusfile, pid_t *pid)
estream_t infp,
estream_t *r_outfp,
estream_t *r_errfp,
pid_t *pid)
{
gpg_error_t err;
int fd, fdout, rp[2];
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. */
*statusfile = NULL;
*pid = (pid_t)(-1);
if (r_outfp)
*r_outfp = NULL;
if (r_errfp)
*r_errfp = NULL;
*pid = (pid_t)(-1); /* Always required. */
if (infile)
if (infp)
{
es_fflush (infile);
es_rewind (infile);
fd = es_fileno (infile);
es_fflush (infp);
es_rewind (infp);
infd = es_fileno (infp);
if (infd == -1)
return gpg_err_make (errsource, GPG_ERR_INV_VALUE);
}
else
fd = -1;
if (outfile)
fdout = es_fileno (outfile);
else
fdout = -1;
if ((infile && fd == -1) || (outfile && fdout == -1))
log_fatal ("no file descriptor for file passed to gnupg_spawn_process\n");
if (pipe (rp) == -1)
if (r_outfp)
{
err = gpg_error_from_syserror ();
log_error (_("error creating a pipe: %s\n"), strerror (errno));
return err;
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;
}
}
#ifdef USE_GNU_PTH
*pid = pth_fork? pth_fork () : fork ();
#else
@ -345,33 +395,45 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
#endif
if (*pid == (pid_t)(-1))
{
err = gpg_error_from_syserror ();
log_error (_("error forking process: %s\n"), strerror (errno));
close (rp[0]);
close (rp[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);
/* Run child. */
do_exec (pgmname, argv, fd, fdout, rp[1], preexec);
es_fclose (outfp);
es_fclose (errfp);
do_exec (pgmname, argv, infd, outpipe[1], errpipe[1], preexec);
/*NOTREACHED*/
}
/* Parent. */
close (rp[1]);
/* This is the parent. */
if (outpipe[1] != -1)
close (outpipe[1]);
if (errpipe[1] != -1)
close (errpipe[1]);
*statusfile = es_fdopen (rp[0], "r");
if (!*statusfile)
{
err = gpg_error_from_syserror ();
log_error (_("can't fdopen pipe for reading: %s\n"), strerror (errno));
kill (*pid, SIGTERM);
*pid = (pid_t)(-1);
return err;
}
if (r_outfp)
*r_outfp = outfp;
if (r_errfp)
*r_errfp = errfp;
return 0;
}