diff options
| author | Marcus Brinkmann <[email protected]> | 2006-09-19 14:01:54 +0000 | 
|---|---|---|
| committer | Marcus Brinkmann <[email protected]> | 2006-09-19 14:01:54 +0000 | 
| commit | 9e09d93de83fe1160689acb36b082c02ccb52716 (patch) | |
| tree | 807126be9dd89fe2850ad748de978de0c5d3b340 /assuan/assuan-pipe-connect.c | |
| parent | 2006-07-29 Marcus Brinkmann <[email protected]> (diff) | |
| download | gpgme-9e09d93de83fe1160689acb36b082c02ccb52716.tar.gz gpgme-9e09d93de83fe1160689acb36b082c02ccb52716.zip | |
assuan/
	Update to current version.
2006-09-19  Marcus Brinkmann  <[email protected]>
	* configure.ac: Turn stpcpy into a replacement function.
	Check for unistd.h and add setenv as replacement function.
gpgme/
2006-09-19  Marcus Brinkmann  <[email protected]>
	* setenv.c: New file.
Diffstat (limited to 'assuan/assuan-pipe-connect.c')
| -rw-r--r-- | assuan/assuan-pipe-connect.c | 702 | 
1 files changed, 486 insertions, 216 deletions
| diff --git a/assuan/assuan-pipe-connect.c b/assuan/assuan-pipe-connect.c index ecedb166..8ee9c748 100644 --- a/assuan/assuan-pipe-connect.c +++ b/assuan/assuan-pipe-connect.c @@ -1,5 +1,5 @@  /* assuan-pipe-connect.c - Establish a pipe connection (client)  - *	Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2005, 2006 Free Software Foundation, Inc.   *   * This file is part of Assuan.   * @@ -15,7 +15,8 @@   *   * You should have received a copy of the GNU Lesser General Public   * License along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA  + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA.    */  #ifdef HAVE_CONFIG_H @@ -38,6 +39,19 @@  #include "assuan-defs.h" +/* Hacks for Slowaris.  */ +#ifndef PF_LOCAL +# ifdef PF_UNIX +#  define PF_LOCAL PF_UNIX +# else +#  define PF_LOCAL AF_UNIX +# endif +#endif +#ifndef AF_LOCAL +# define AF_LOCAL AF_UNIX +#endif + +  #ifdef _POSIX_OPEN_MAX  #define MAX_OPEN_FDS _POSIX_OPEN_MAX  #else @@ -111,6 +125,8 @@ do_finish (assuan_context_t ctx)    if (ctx->inbound.fd != -1)      {        _assuan_close (ctx->inbound.fd); +      if (ctx->inbound.fd == ctx->outbound.fd) +        ctx->outbound.fd = -1;        ctx->inbound.fd = -1;      }    if (ctx->outbound.fd != -1) @@ -123,7 +139,7 @@ do_finish (assuan_context_t ctx)  #ifndef HAVE_W32_SYSTEM  #ifndef _ASSUAN_USE_DOUBLE_FORK        if (!ctx->flags.no_waitpid) -        waitpid (ctx->pid, NULL, 0);  +        _assuan_waitpid (ctx->pid, NULL, 0);         ctx->pid = -1;  #endif  #endif /*!HAVE_W32_SYSTEM*/ @@ -138,6 +154,402 @@ do_deinit (assuan_context_t ctx)  } +/* Helper for pipe_connect. */ +static assuan_error_t +initial_handshake (assuan_context_t *ctx) +{ +  int okay, off; +  assuan_error_t err; +   +  err = _assuan_read_from_server (*ctx, &okay, &off); +  if (err) +    _assuan_log_printf ("can't connect server: %s\n", +                        assuan_strerror (err)); +  else if (okay != 1) +    { +      _assuan_log_printf ("can't connect server: `%s'\n", +                          (*ctx)->inbound.line); +      err = _assuan_error (ASSUAN_Connect_Failed); +    } + +  if (err) +    { +      assuan_disconnect (*ctx); +      *ctx = NULL; +    } +  return err; +} + + +#ifndef HAVE_W32_SYSTEM +#define pipe_connect pipe_connect_unix +/* Unix version of the pipe connection code.  We use an extra macro to +   make ChangeLog entries easier. */ +static assuan_error_t +pipe_connect_unix (assuan_context_t *ctx, +                   const char *name, const char *const argv[], +                   int *fd_child_list, +                   void (*atfork) (void *opaque, int reserved), +                   void *atforkvalue) +{ +  assuan_error_t err; +  int rp[2]; +  int wp[2]; +  char mypidstr[50]; + +  if (!ctx || !name || !argv || !argv[0]) +    return _assuan_error (ASSUAN_Invalid_Value); + +  fix_signals (); + +  sprintf (mypidstr, "%lu", (unsigned long)getpid ()); + +  if (pipe (rp) < 0) +    return _assuan_error (ASSUAN_General_Error); +   +  if (pipe (wp) < 0) +    { +      close (rp[0]); +      close (rp[1]); +      return _assuan_error (ASSUAN_General_Error); +    } + +  err = _assuan_new_context (ctx); +  if (err) +    { +      close (rp[0]); +      close (rp[1]); +      close (wp[0]); +      close (wp[1]); +      return err; +    } +  (*ctx)->pipe_mode = 1; +  (*ctx)->inbound.fd  = rp[0];  /* Our inbound is read end of read pipe. */ +  (*ctx)->outbound.fd = wp[1];  /* Our outbound is write end of write pipe. */ +  (*ctx)->deinit_handler = do_deinit; +  (*ctx)->finish_handler = do_finish; + +  /* FIXME: For GPGME we should better use _gpgme_io_spawn.  The PID +     stored here is actually soon useless.  */ +  (*ctx)->pid = fork (); +  if ((*ctx)->pid < 0) +    { +      close (rp[0]); +      close (rp[1]); +      close (wp[0]); +      close (wp[1]); +      _assuan_release_context (*ctx);  +      return _assuan_error (ASSUAN_General_Error); +    } + +  if ((*ctx)->pid == 0) +    { +#ifdef _ASSUAN_USE_DOUBLE_FORK       +      pid_t pid; + +      if ((pid = fork ()) == 0) +#endif +	{ +          int i, n; +          char errbuf[512]; +          int *fdp; +           +          if (atfork) +            atfork (atforkvalue, 0); + +          /* Dup handles to stdin/stdout. */ +          if (rp[1] != STDOUT_FILENO) +            { +              if (dup2 (rp[1], STDOUT_FILENO) == -1) +                { +                  _assuan_log_printf ("dup2 failed in child: %s\n", +                                      strerror (errno)); +                  _exit (4); +                } +            } +          if (wp[0] != STDIN_FILENO) +            { +              if (dup2 (wp[0], STDIN_FILENO) == -1) +                { +                  _assuan_log_printf ("dup2 failed in child: %s\n", +                                      strerror (errno)); +                  _exit (4); +                } +            } + +          /* Dup stderr to /dev/null unless it is in the list of FDs to be +             passed to the child. */ +          fdp = fd_child_list; +          if (fdp) +            { +              for (; *fdp != -1 && *fdp != STDERR_FILENO; fdp++) +                ; +            } +          if (!fdp || *fdp == -1) +            { +              int fd = open ("/dev/null", O_WRONLY); +              if (fd == -1) +                { +                  _assuan_log_printf ("can't open `/dev/null': %s\n", +                                      strerror (errno)); +                  _exit (4); +                } +              if (dup2 (fd, STDERR_FILENO) == -1) +                { +                  _assuan_log_printf ("dup2(dev/null, 2) failed: %s\n", +                                      strerror (errno)); +                  _exit (4); +                } +            } + + +          /* Close all files which will not be duped and are not in the +             fd_child_list. */ +          n = sysconf (_SC_OPEN_MAX); +          if (n < 0) +            n = MAX_OPEN_FDS; +          for (i=0; i < n; i++) +            { +              if ( i == STDIN_FILENO || i == STDOUT_FILENO +                   || i == STDERR_FILENO) +                continue; +              fdp = fd_child_list; +              if (fdp) +                { +                  while (*fdp != -1 && *fdp != i) +                    fdp++; +                } + +              if (!(fdp && *fdp != -1)) +                close(i); +            } +          errno = 0; + +          /* We store our parents pid in the environment so that the +             execed assuan server is able to read the actual pid of the +             client.  The server can't use getppid because it might have +             been double forked before the assuan server has been +             initialized. */ +          setenv ("_assuan_pipe_connect_pid", mypidstr, 1); + +          /* Make sure that we never pass a connection fd variable +             when using a simple pipe.  */ +          unsetenv ("_assuan_connection_fd"); + +          execv (name, (char *const *) argv);  +          /* oops - use the pipe to tell the parent about it */ +          snprintf (errbuf, sizeof(errbuf)-1, +                    "ERR %d can't exec `%s': %.50s\n", +                    _assuan_error (ASSUAN_Problem_Starting_Server), +                    name, strerror (errno)); +          errbuf[sizeof(errbuf)-1] = 0; +          writen (1, errbuf, strlen (errbuf)); +          _exit (4); +        } +#ifdef _ASSUAN_USE_DOUBLE_FORK +      if (pid == -1) +	_exit (1); +      else +	_exit (0); +#endif +    } + +#ifdef _ASSUAN_USE_DOUBLE_FORK +  _assuan_waitpid ((*ctx)->pid, NULL, 0); +  (*ctx)->pid = -1; +#endif + +  close (rp[1]); +  close (wp[0]); + +  return initial_handshake (ctx); +} +#endif /*!HAVE_W32_SYSTEM*/ + + +#ifndef HAVE_W32_SYSTEM +/* This function is similar to pipe_connect but uses a socketpair and +   sets the I/O up to use sendmsg/recvmsg. */ +static assuan_error_t +socketpair_connect (assuan_context_t *ctx, +                    const char *name, const char *const argv[], +                    int *fd_child_list, +                    void (*atfork) (void *opaque, int reserved), +                    void *atforkvalue) +{ +  assuan_error_t err; +  int fds[2]; +  char mypidstr[50]; + +  if (!ctx +      || (name && (!argv || !argv[0])) +      || (!name && argv)) +    return _assuan_error (ASSUAN_Invalid_Value); + +  fix_signals (); + +  sprintf (mypidstr, "%lu", (unsigned long)getpid ()); + +  if ( socketpair (AF_LOCAL, SOCK_STREAM, 0, fds) ) +    { +      _assuan_log_printf ("socketpair failed: %s\n", strerror (errno)); +      return _assuan_error (ASSUAN_General_Error); +    } +   +  err = _assuan_new_context (ctx); +  if (err) +    { +      close (fds[0]); +      close (fds[1]); +      return err; +    } +  (*ctx)->pipe_mode = 1; +  (*ctx)->inbound.fd  = fds[0];  +  (*ctx)->outbound.fd = fds[0];  +  _assuan_init_uds_io (*ctx); +  (*ctx)->deinit_handler = _assuan_uds_deinit; +  (*ctx)->finish_handler = do_finish; + +  (*ctx)->pid = fork (); +  if ((*ctx)->pid < 0) +    { +      close (fds[0]); +      close (fds[1]); +      _assuan_release_context (*ctx);  +      *ctx = NULL; +      return _assuan_error (ASSUAN_General_Error); +    } + +  if ((*ctx)->pid == 0) +    { +#ifdef _ASSUAN_USE_DOUBLE_FORK       +      pid_t pid; + +      if ((pid = fork ()) == 0) +#endif +	{ +          int fd, i, n; +          char errbuf[512]; +          int *fdp; +           +          if (atfork) +            atfork (atforkvalue, 0); + +          /* Connect stdin and stdout to /dev/null. */ +          fd = open ("/dev/null", O_RDONLY); +          if (fd == -1 || dup2 (fd, STDIN_FILENO) == -1) +            { +              _assuan_log_printf ("dup2(dev/null) failed: %s\n", +                                  strerror (errno)); +              _exit (4); +            } +          fd = open ("/dev/null", O_WRONLY); +          if (fd == -1 || dup2 (fd, STDOUT_FILENO) == -1) +            { +              _assuan_log_printf ("dup2(dev/null) failed: %s\n", +                                  strerror (errno)); +              _exit (4); +            } + +          /* Dup stderr to /dev/null unless it is in the list of FDs to be +             passed to the child. */ +          fdp = fd_child_list; +          if (fdp) +            { +              for (; *fdp != -1 && *fdp != STDERR_FILENO; fdp++) +                ; +            } +          if (!fdp || *fdp == -1) +            { +              fd = open ("/dev/null", O_WRONLY); +              if (fd == -1 || dup2 (fd, STDERR_FILENO) == -1) +                { +                  _assuan_log_printf ("dup2(dev/null) failed: %s\n", +                                      strerror (errno)); +                  _exit (4); +                } +            } + + +          /* Close all files which will not be duped, are not in the +             fd_child_list and are not the connection fd. */ +          n = sysconf (_SC_OPEN_MAX); +          if (n < 0) +            n = MAX_OPEN_FDS; +          for (i=0; i < n; i++) +            { +              if ( i == STDIN_FILENO || i == STDOUT_FILENO +                   || i == STDERR_FILENO || i == fds[1]) +                continue; +              fdp = fd_child_list; +              if (fdp) +                { +                  while (*fdp != -1 && *fdp != i) +                    fdp++; +                } + +              if (!(fdp && *fdp != -1)) +                close(i); +            } +          errno = 0; + +          /* We store our parents pid in the environment so that the +             execed assuan server is able to read the actual pid of the +             client.  The server can't use getppid becuase it might have +             been double forked before the assuan server has been +             initialized. */ +          setenv ("_assuan_pipe_connect_pid", mypidstr, 1); + +          /* Now set the environment variable used to convey the +             connection's file descriptor. */ +          sprintf (mypidstr, "%d", fds[1]); +          if (setenv ("_assuan_connection_fd", mypidstr, 1)) +            { +              _assuan_log_printf ("setenv failed: %s\n", strerror (errno)); +              _exit (4); +            } + +          if (!name && !argv) +            { +              /* No name and no args given, thus we don't do an exec +                 but continue the forked process.  */ +              _assuan_release_context (*ctx); +              *ctx = NULL; +              return 0; +            } + +          execv (name, (char *const *) argv);  +          /* oops - use the pipe to tell the parent about it */ +          snprintf (errbuf, sizeof(errbuf)-1, +                    "ERR %d can't exec `%s': %.50s\n", +                    _assuan_error (ASSUAN_Problem_Starting_Server), +                    name, strerror (errno)); +          errbuf[sizeof(errbuf)-1] = 0; +          writen (fds[1], errbuf, strlen (errbuf)); +          _exit (4); +        } +#ifdef _ASSUAN_USE_DOUBLE_FORK +      if (pid == -1) +	_exit (1); +      else +	_exit (0); +#endif +    } + + +#ifdef _ASSUAN_USE_DOUBLE_FORK +  _assuan_waitpid ((*ctx)->pid, NULL, 0); +  (*ctx)->pid = -1; +#endif + +  close (fds[1]); +   +  return initial_handshake (ctx); +} +#endif /*!HAVE_W32_SYSTEM*/ + + +  #ifdef HAVE_W32_SYSTEM  /* Build a command line for use with W32's CreateProcess.  On success     CMDLINE gets the address of a newly allocated string.  */ @@ -236,21 +648,16 @@ create_inheritable_pipe (int filedes[2], int for_write)  #endif /*HAVE_W32_SYSTEM*/ -/* Connect to a server over a pipe, creating the assuan context and -   returning it in CTX.  The server filename is NAME, the argument -   vector in ARGV.  FD_CHILD_LIST is a -1 terminated list of file -   descriptors not to close in the child.  ATFORK is called in the -   child right after the fork; ATFORKVALUE is passed as the first -   argument and 0 is passed as the second argument. The ATFORK -   function should only act if the second value is 0. */ -assuan_error_t -assuan_pipe_connect2 (assuan_context_t *ctx, -                      const char *name, const char *const argv[], -                      int *fd_child_list, -                      void (*atfork) (void *opaque, int reserved), -                      void *atforkvalue) -{  #ifdef HAVE_W32_SYSTEM +#define pipe_connect pipe_connect_w32 +/* W32 version of the pipe connection code. */ +static assuan_error_t +pipe_connect_w32 (assuan_context_t *ctx, +                  const char *name, const char *const argv[], +                  int *fd_child_list, +                  void (*atfork) (void *opaque, int reserved), +                  void *atforkvalue) +{    assuan_error_t err;    int rp[2];    int wp[2]; @@ -269,7 +676,7 @@ assuan_pipe_connect2 (assuan_context_t *ctx,    HANDLE nullfd = INVALID_HANDLE_VALUE;    if (!ctx || !name || !argv || !argv[0]) -    return ASSUAN_Invalid_Value; +    return _assuan_error (ASSUAN_Invalid_Value);    fix_signals (); @@ -277,13 +684,13 @@ assuan_pipe_connect2 (assuan_context_t *ctx,    /* Build the command line.  */    if (build_w32_commandline (argv, &cmdline)) -    return ASSUAN_Out_Of_Core; +    return _assuan_error (ASSUAN_Out_Of_Core);    /* Create thew two pipes. */    if (create_inheritable_pipe (rp, 0))      {        xfree (cmdline); -      return ASSUAN_General_Error; +      return _assuan_error (ASSUAN_General_Error);      }    if (create_inheritable_pipe (wp, 1)) @@ -291,7 +698,7 @@ assuan_pipe_connect2 (assuan_context_t *ctx,        CloseHandle (fd_to_handle (rp[0]));        CloseHandle (fd_to_handle (rp[1]));        xfree (cmdline); -      return ASSUAN_General_Error; +      return _assuan_error (ASSUAN_General_Error);      } @@ -303,7 +710,7 @@ assuan_pipe_connect2 (assuan_context_t *ctx,        CloseHandle (fd_to_handle (wp[0]));        CloseHandle (fd_to_handle (wp[1]));        xfree (cmdline); -      return ASSUAN_General_Error; +      return _assuan_error (ASSUAN_General_Error);      }    (*ctx)->pipe_mode = 1; @@ -390,7 +797,7 @@ assuan_pipe_connect2 (assuan_context_t *ctx,          CloseHandle (nullfd);        xfree (cmdline);        _assuan_release_context (*ctx);  -      return ASSUAN_General_Error; +      return _assuan_error (ASSUAN_General_Error);      }    xfree (cmdline);    cmdline = NULL; @@ -413,200 +820,11 @@ assuan_pipe_connect2 (assuan_context_t *ctx,    (*ctx)->pid = 0;  /* We don't use the PID. */    CloseHandle (pi.hProcess); /* We don't need to wait for the process. */ -#else /*!HAVE_W32_SYSTEM*/ -  assuan_error_t err; -  int rp[2]; -  int wp[2]; -  char mypidstr[50]; - -  if (!ctx || !name || !argv || !argv[0]) -    return ASSUAN_Invalid_Value; - -  fix_signals (); - -  sprintf (mypidstr, "%lu", (unsigned long)getpid ()); - -  if (pipe (rp) < 0) -    return ASSUAN_General_Error; - -  if (pipe (wp) < 0) -    { -      close (rp[0]); -      close (rp[1]); -      return ASSUAN_General_Error; -    } -   -  err = _assuan_new_context (ctx); -  if (err) -    { -      close (rp[0]); -      close (rp[1]); -      close (wp[0]); -      close (wp[1]); -      return err; -    } -  (*ctx)->pipe_mode = 1; -  (*ctx)->inbound.fd  = rp[0];  /* Our inbound is read end of read pipe. */ -  (*ctx)->outbound.fd = wp[1];  /* Our outbound is write end of write pipe. */ -  (*ctx)->deinit_handler = do_deinit; -  (*ctx)->finish_handler = do_finish; - -  /* FIXME: For GPGME we should better use _gpgme_io_spawn.  The PID -     stored here is actually soon useless.  */ -  (*ctx)->pid = fork (); -  if ((*ctx)->pid < 0) -    { -      close (rp[0]); -      close (rp[1]); -      close (wp[0]); -      close (wp[1]); -      _assuan_release_context (*ctx);  -      return ASSUAN_General_Error; -    } - -  if ((*ctx)->pid == 0) -    { -#ifdef _ASSUAN_USE_DOUBLE_FORK       -      pid_t pid; - -      if ((pid = fork ()) == 0) -#endif -	{ -          int i, n; -          char errbuf[512]; -          int *fdp; -           -          if (atfork) -            atfork (atforkvalue, 0); - -          /* Dup handles to stdin/stdout. */ -          if (rp[1] != STDOUT_FILENO) -            { -              if (dup2 (rp[1], STDOUT_FILENO) == -1) -                { -                  _assuan_log_printf ("dup2 failed in child: %s\n", -                                      strerror (errno)); -                  _exit (4); -                } -            } -          if (wp[0] != STDIN_FILENO) -            { -              if (dup2 (wp[0], STDIN_FILENO) == -1) -                { -                  _assuan_log_printf ("dup2 failed in child: %s\n", -                                      strerror (errno)); -                  _exit (4); -                } -            } - -          /* Dup stderr to /dev/null unless it is in the list of FDs to be -             passed to the child. */ -          fdp = fd_child_list; -          if (fdp) -            { -              for (; *fdp != -1 && *fdp != STDERR_FILENO; fdp++) -                ; -            } -          if (!fdp || *fdp == -1) -            { -              int fd = open ("/dev/null", O_WRONLY); -              if (fd == -1) -                { -                  _assuan_log_printf ("can't open `/dev/null': %s\n", -                                      strerror (errno)); -                  _exit (4); -                } -              if (dup2 (fd, STDERR_FILENO) == -1) -                { -                  _assuan_log_printf ("dup2(dev/null, 2) failed: %s\n", -                                      strerror (errno)); -                  _exit (4); -                } -            } - - -          /* Close all files which will not be duped and are not in the -             fd_child_list. */ -          n = sysconf (_SC_OPEN_MAX); -          if (n < 0) -            n = MAX_OPEN_FDS; -          for (i=0; i < n; i++) -            { -              if ( i == STDIN_FILENO || i == STDOUT_FILENO -                   || i == STDERR_FILENO) -                continue; -              fdp = fd_child_list; -              if (fdp) -                { -                  while (*fdp != -1 && *fdp != i) -                    fdp++; -                } - -              if (!(fdp && *fdp != -1)) -                close(i); -            } -          errno = 0; - -          /* We store our parents pid in the environment so that the -             execed assuan server is able to read the actual pid of the -             client.  The server can't use getppid becuase it might have -             been double forked before the assuan server has been -             initialized. */ -          setenv ("_assuan_pipe_connect_pid", mypidstr, 1); - -          execv (name, (char *const *) argv);  -          /* oops - use the pipe to tell the parent about it */ -          snprintf (errbuf, sizeof(errbuf)-1, -                    "ERR %d can't exec `%s': %.50s\n", -                    ASSUAN_Problem_Starting_Server, name, strerror (errno)); -          errbuf[sizeof(errbuf)-1] = 0; -          writen (1, errbuf, strlen (errbuf)); -          _exit (4); -        } -#ifdef _ASSUAN_USE_DOUBLE_FORK -      if (pid == -1) -	_exit (1); -      else -	_exit (0); -#endif -    } - -#ifdef _ASSUAN_USE_DOUBLE_FORK -  waitpid ((*ctx)->pid, NULL, 0); -  (*ctx)->pid = -1; -#endif - -  close (rp[1]); -  close (wp[0]); - -#endif /*!HAVE_W32_SYSTEM*/ - -  /* initial handshake */ -  { -    int okay, off; - -    err = _assuan_read_from_server (*ctx, &okay, &off); -    if (err) -      _assuan_log_printf ("can't connect server: %s\n", -                          assuan_strerror (err)); -    else if (okay != 1) -      { -	_assuan_log_printf ("can't connect server: `%s'\n", -                            (*ctx)->inbound.line); -	err = ASSUAN_Connect_Failed; -      } -  } - -  if (err) -    { -      assuan_disconnect (*ctx); -      *ctx = NULL; -    } - -  return err; +  return initial_handshake (ctx);  } +#endif /*HAVE_W32_SYSTEM*/ - +  /* Connect to a server over a pipe, creating the assuan context and     returning it in CTX.  The server filename is NAME, the argument     vector in ARGV.  FD_CHILD_LIST is a -1 terminated list of file @@ -615,5 +833,57 @@ assuan_error_t  assuan_pipe_connect (assuan_context_t *ctx, const char *name,  		     const char *const argv[], int *fd_child_list)  { -  return assuan_pipe_connect2 (ctx, name, argv, fd_child_list, NULL, NULL); +  return pipe_connect (ctx, name, argv, fd_child_list, NULL, NULL); +} + + + +assuan_error_t +assuan_pipe_connect2 (assuan_context_t *ctx, +                      const char *name, const char *const argv[], +                      int *fd_child_list, +                      void (*atfork) (void *opaque, int reserved), +                      void *atforkvalue) +{ +  return pipe_connect (ctx, name, argv, fd_child_list, atfork, atforkvalue); +} + + +/* Connect to a server over a full-duplex socket (i.e. created by +   socketpair), creating the assuan context and returning it in CTX. +   The server filename is NAME, the argument vector in ARGV. +   FD_CHILD_LIST is a -1 terminated list of file descriptors not to +   close in the child.  ATFORK is called in the child right after the +   fork; ATFORKVALUE is passed as the first argument and 0 is passed +   as the second argument. The ATFORK function should only act if the +   second value is 0. + +   For now FLAGS may either take the value 0 to behave like +   assuan_pipe_connect2 or 1 to enable the described full-duplex +   socket behaviour. + +   If NAME as well as ARGV are NULL, no exec is done but the same +   process is continued.  However all file descriptors are closed and +   some special environment variables are set. To let the caller +   detect whether the child or the parent continues, the child returns +   a CTX of NULL. */ +assuan_error_t +assuan_pipe_connect_ext (assuan_context_t *ctx, +                         const char *name, const char *const argv[], +                         int *fd_child_list, +                         void (*atfork) (void *opaque, int reserved), +                         void *atforkvalue, unsigned int flags) +{ +  if ((flags & 1)) +    { +#ifdef HAVE_W32_SYSTEM +      return _assuan_error (ASSUAN_Not_Implemented); +#else +      return socketpair_connect (ctx, name, argv, fd_child_list, +                                 atfork, atforkvalue); +#endif +    } +  else +    return pipe_connect (ctx, name, argv, fd_child_list, atfork, atforkvalue);  } + | 
