diff --git a/assuan/ChangeLog b/assuan/ChangeLog index d12aceef3..a96c6c7c3 100644 --- a/assuan/ChangeLog +++ b/assuan/ChangeLog @@ -1,3 +1,20 @@ +2002-01-21 Werner Koch + + * assuan-connect.c: Move all except assuan_get_pid to... + * assuan-pipe-connect.c: this. + (assuan_pipe_disconnect): Removed. + (do_finish, do_deinit): New + (assuan_pipe_connect): and set them into the context. + * assuan-socket-connect.c: New. + + * assuan-util.c (_assuan_log_sanitized_string): New. + + * assuan-pipe-server.c (assuan_init_pipe_server): Factored most + code out to ... + (_assuan_new_context): new func. + (_assuan_release_context): New + * assuan-connect.c (assuan_pipe_connect): Use the new functions. + 2002-01-20 Werner Koch * assuan.h: Added Invalid Option error code. diff --git a/assuan/Makefile.am b/assuan/Makefile.am index c4d117e09..7508dce24 100644 --- a/assuan/Makefile.am +++ b/assuan/Makefile.am @@ -39,7 +39,9 @@ libassuan_a_SOURCES = \ assuan-connect.c \ assuan-client.c \ assuan-pipe-server.c \ - assuan-socket-server.c + assuan-socket-server.c \ + assuan-pipe-connect.c \ + assuan-socket-connect.c assuan-errors.c : assuan.h diff --git a/assuan/assuan-connect.c b/assuan/assuan-connect.c index 53b742fc9..49d4aac23 100644 --- a/assuan/assuan-connect.c +++ b/assuan/assuan-connect.c @@ -33,208 +33,18 @@ #include "assuan-defs.h" -#ifdef _POSIX_OPEN_MAX -#define MAX_OPEN_FDS _POSIX_OPEN_MAX -#else -#define MAX_OPEN_FDS 20 -#endif - -#ifdef HAVE_JNLIB_LOGGING -#include "../jnlib/logging.h" -#define LOGERROR1(a,b) log_error ((a), (b)) -#else -#define LOGERROR1(a,b) fprintf (stderr, (a), (b)) -#endif - - - -static int -writen ( int fd, const char *buffer, size_t length ) -{ - while (length) - { - int nwritten = write (fd, buffer, length); - - if (nwritten < 0) - { - if (errno == EINTR) - continue; - return -1; /* write error */ - } - length -= nwritten; - buffer += nwritten; - } - return 0; /* okay */ -} - - - -/* 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. */ -AssuanError -assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[], - int *fd_child_list) -{ - static int fixed_signals = 0; - AssuanError err; - int rp[2]; - int wp[2]; - int fd[2]; - - if (!ctx || !name || !argv || !argv[0]) - return ASSUAN_Invalid_Value; - - if (!fixed_signals) - { - struct sigaction act; - - sigaction (SIGPIPE, NULL, &act); - if (act.sa_handler == SIG_DFL) - { - act.sa_handler = SIG_IGN; - sigemptyset (&act.sa_mask); - act.sa_flags = 0; - sigaction (SIGPIPE, &act, NULL); - } - fixed_signals = 1; - /* FIXME: This is not MT safe */ - } - - if (pipe (rp) < 0) - return ASSUAN_General_Error; - - if (pipe (wp) < 0) - { - close (rp[0]); - close (rp[1]); - return ASSUAN_General_Error; - } - - fd[0] = rp[0]; /* Our inbound is read end of read pipe. */ - fd[1] = wp[1]; /* Our outbound is write end of write pipe. */ - - err = assuan_init_pipe_server (ctx, fd); /* FIXME: Common code should be factored out. */ - if (err) - { - close (rp[0]); - close (rp[1]); - close (wp[0]); - close (wp[1]); - return err; - } - (*ctx)->is_server = 0; - - (*ctx)->pid = fork (); - if ((*ctx)->pid < 0) - { - close (rp[0]); - close (rp[1]); - close (wp[0]); - close (wp[1]); - assuan_deinit_server (*ctx); /* FIXME: Common code should be factored out. */ - return ASSUAN_General_Error; - } - - if ((*ctx)->pid == 0) - { - int i, n; - char errbuf[512]; -#ifdef HAVE_JNLIB_LOGGING - int log_fd = log_get_fd (); -#endif - /* close all files which will not be duped but keep stderr - and log_stream for now */ - n = sysconf (_SC_OPEN_MAX); - if (n < 0) - n = MAX_OPEN_FDS; - for (i=0; i < n; i++) - { - int *fdp = fd_child_list; - - if (fdp) - { - while (*fdp != -1 && *fdp != i) - fdp++; - } - - if (!(fdp && *fdp != -1) - && i != fileno (stderr) -#ifdef HAVE_JNLIB_LOGGING - && i != log_fd -#endif - && i != rp[1] && i != wp[0]) - close(i); - } - errno = 0; - - /* Dup handles and to stdin/stdout and exec */ - if (rp[1] != STDOUT_FILENO) - { - if (dup2 (rp[1], STDOUT_FILENO) == -1) - { - LOGERROR1 ("dup2 failed in child: %s\n", strerror (errno)); - _exit (4); - } - close (rp[1]); - } - if (wp[0] != STDIN_FILENO) - { - if (dup2 (wp[0], STDIN_FILENO) == -1) - { - LOGERROR1 ("dup2 failed in child: %s\n", strerror (errno)); - _exit (4); - } - close (wp[0]); - } - - execv (name, 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); - } - - close (rp[1]); - close (wp[0]); - - /* initial handshake */ - { - int okay, off; - - err = _assuan_read_from_server (*ctx, &okay, &off); - if (err) - { - LOGERROR1 ("can't connect server: %s\n", assuan_strerror (err)); - } - else if (okay != 1) - { - LOGERROR1 ("can't connect server: `%s'\n", (*ctx)->inbound.line); - err = ASSUAN_Connect_Failed; - } - } - - if (err) - { - if ((*ctx)->pid != -1) - waitpid ((*ctx)->pid, NULL, 0); /* FIXME Check return value. */ - assuan_deinit_server (*ctx); /* FIXME: Common code should be factored out. */ - } - - return err; -} - +/* Disconnect and release the context CTX. */ void -assuan_pipe_disconnect (ASSUAN_CONTEXT ctx) +assuan_disconnect (ASSUAN_CONTEXT ctx) { - assuan_write_line (ctx, "BYE"); - close (ctx->inbound.fd); - close (ctx->outbound.fd); - waitpid (ctx->pid, NULL, 0); /* FIXME Check return value. */ - assuan_deinit_server (ctx); + if (ctx) + { + assuan_write_line (ctx, "BYE"); + ctx->finish_handler (ctx); + ctx->deinit_handler (ctx); + ctx->deinit_handler = NULL; + _assuan_release_context (ctx); + } } pid_t @@ -242,5 +52,3 @@ assuan_get_pid (ASSUAN_CONTEXT ctx) { return ctx ? ctx->pid : -1; } - - diff --git a/assuan/assuan-defs.h b/assuan/assuan-defs.h index c14b40991..7d55aabd9 100644 --- a/assuan/assuan-defs.h +++ b/assuan/assuan-defs.h @@ -73,7 +73,8 @@ struct assuan_context_s { int pipe_mode; /* We are in pipe mode, i.e. we can handle just one connection and must terminate then */ - pid_t pid; /* In pipe mode, the pid of the child server process. */ + pid_t pid; /* In pipe mode, the pid of the child server process. + In socket mode, the pid of the server */ int listen_fd; /* The fd we are listening on (used by socket servers) */ void (*deinit_handler)(ASSUAN_CONTEXT); @@ -98,6 +99,11 @@ struct assuan_context_s { }; +/*-- assuan-pipe-server.c --*/ +int _assuan_new_context (ASSUAN_CONTEXT *r_ctx); +void _assuan_release_context (ASSUAN_CONTEXT ctx); + + /*-- assuan-handler.c --*/ int _assuan_register_std_commands (ASSUAN_CONTEXT ctx); @@ -124,6 +130,7 @@ void _assuan_free (void *p); #define set_error(c,e,t) assuan_set_error ((c), ASSUAN_ ## e, (t)) void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length); +void _assuan_log_sanitized_string (const char *string); #endif /*ASSUAN_DEFS_H*/ diff --git a/assuan/assuan-pipe-connect.c b/assuan/assuan-pipe-connect.c new file mode 100644 index 000000000..ccfc1f016 --- /dev/null +++ b/assuan/assuan-pipe-connect.c @@ -0,0 +1,269 @@ +/* assuan-pipe-connect.c - Establish a pipe connection (client) + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU 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 + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "assuan-defs.h" + +#ifdef _POSIX_OPEN_MAX +#define MAX_OPEN_FDS _POSIX_OPEN_MAX +#else +#define MAX_OPEN_FDS 20 +#endif + +#ifdef HAVE_JNLIB_LOGGING +#include "../jnlib/logging.h" +#define LOGERROR1(a,b) log_error ((a), (b)) +#else +#define LOGERROR1(a,b) fprintf (stderr, (a), (b)) +#endif + + + +static int +writen ( int fd, const char *buffer, size_t length ) +{ + while (length) + { + int nwritten = write (fd, buffer, length); + + if (nwritten < 0) + { + if (errno == EINTR) + continue; + return -1; /* write error */ + } + length -= nwritten; + buffer += nwritten; + } + return 0; /* okay */ +} + + +static int +do_finish (ASSUAN_CONTEXT ctx) +{ + if (ctx->inbound.fd != -1) + { + close (ctx->inbound.fd); + ctx->inbound.fd = -1; + } + if (ctx->outbound.fd != -1) + { + close (ctx->outbound.fd); + ctx->outbound.fd = -1; + } + if (ctx->pid != -1) + { + waitpid (ctx->pid, NULL, 0); /* FIXME Check return value. */ + ctx->pid = -1; + } + return 0; +} + +static void +do_deinit (ASSUAN_CONTEXT ctx) +{ + do_finish (ctx); +} + + + +/* 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. */ +AssuanError +assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[], + int *fd_child_list) +{ + static int fixed_signals = 0; + AssuanError err; + int rp[2]; + int wp[2]; + + if (!ctx || !name || !argv || !argv[0]) + return ASSUAN_Invalid_Value; + + if (!fixed_signals) + { + struct sigaction act; + + sigaction (SIGPIPE, NULL, &act); + if (act.sa_handler == SIG_DFL) + { + act.sa_handler = SIG_IGN; + sigemptyset (&act.sa_mask); + act.sa_flags = 0; + sigaction (SIGPIPE, &act, NULL); + } + fixed_signals = 1; + /* FIXME: This is not MT safe */ + } + + 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; + + (*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) + { + int i, n; + char errbuf[512]; +#ifdef HAVE_JNLIB_LOGGING + int log_fd = log_get_fd (); +#endif + /* close all files which will not be duped but keep stderr + and log_stream for now */ + n = sysconf (_SC_OPEN_MAX); + if (n < 0) + n = MAX_OPEN_FDS; + for (i=0; i < n; i++) + { + int *fdp = fd_child_list; + + if (fdp) + { + while (*fdp != -1 && *fdp != i) + fdp++; + } + + if (!(fdp && *fdp != -1) + && i != fileno (stderr) +#ifdef HAVE_JNLIB_LOGGING + && i != log_fd +#endif + && i != rp[1] && i != wp[0]) + close(i); + } + errno = 0; + + /* Dup handles and to stdin/stdout and exec */ + if (rp[1] != STDOUT_FILENO) + { + if (dup2 (rp[1], STDOUT_FILENO) == -1) + { + LOGERROR1 ("dup2 failed in child: %s\n", strerror (errno)); + _exit (4); + } + close (rp[1]); + } + if (wp[0] != STDIN_FILENO) + { + if (dup2 (wp[0], STDIN_FILENO) == -1) + { + LOGERROR1 ("dup2 failed in child: %s\n", strerror (errno)); + _exit (4); + } + close (wp[0]); + } + + execv (name, 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); + } + + close (rp[1]); + close (wp[0]); + + /* initial handshake */ + { + int okay, off; + + err = _assuan_read_from_server (*ctx, &okay, &off); + if (err) + { + LOGERROR1 ("can't connect server: %s\n", assuan_strerror (err)); + } + else if (okay != 1) + { + LOGERROR1 ("can't connect server: `%s'\n", (*ctx)->inbound.line); + err = ASSUAN_Connect_Failed; + } + } + + if (err) + { + assuan_disconnect (*ctx); + *ctx = NULL; + } + + return err; +} + + + + + + + + + + + + + + diff --git a/assuan/assuan-pipe-server.c b/assuan/assuan-pipe-server.c index c283a925f..d15f54f5a 100644 --- a/assuan/assuan-pipe-server.c +++ b/assuan/assuan-pipe-server.c @@ -45,8 +45,10 @@ finish_connection (ASSUAN_CONTEXT ctx) } +/* Create a new context. Note that the handlers are set up for a pipe + server/client - this wau we don't need extra dummy functions */ int -assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2]) +_assuan_new_context (ASSUAN_CONTEXT *r_ctx) { ASSUAN_CONTEXT ctx; int rc; @@ -55,15 +57,14 @@ assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2]) ctx = xtrycalloc (1, sizeof *ctx); if (!ctx) return ASSUAN_Out_Of_Core; - ctx->is_server = 1; ctx->input_fd = -1; ctx->output_fd = -1; - ctx->inbound.fd = filedes[0]; - ctx->outbound.fd = filedes[1]; + ctx->inbound.fd = -1; + ctx->outbound.fd = -1; - ctx->pipe_mode = 1; ctx->listen_fd = -1; + /* use the pipe server handler as a default */ ctx->deinit_handler = deinit_pipe_server; ctx->accept_handler = accept_connection; ctx->finish_handler = finish_connection; @@ -77,6 +78,37 @@ assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2]) } + +int +assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2]) +{ + int rc; + + rc = _assuan_new_context (r_ctx); + if (!rc) + { + ASSUAN_CONTEXT ctx = *r_ctx; + + ctx->is_server = 1; + ctx->inbound.fd = filedes[0]; + ctx->outbound.fd = filedes[1]; + ctx->pipe_mode = 1; + } + return rc; +} + + +void +_assuan_release_context (ASSUAN_CONTEXT ctx) +{ + if (ctx) + { + xfree (ctx->hello_line); + xfree (ctx->okay_line); + xfree (ctx); + } +} + void assuan_deinit_server (ASSUAN_CONTEXT ctx) { @@ -86,16 +118,6 @@ assuan_deinit_server (ASSUAN_CONTEXT ctx) when not needed but still allow for a generic deinit function */ ctx->deinit_handler (ctx); ctx->deinit_handler = NULL; - xfree (ctx->hello_line); - xfree (ctx->okay_line); - xfree (ctx); + _assuan_release_context (ctx); } } - - - - - - - - diff --git a/assuan/assuan-socket-connect.c b/assuan/assuan-socket-connect.c new file mode 100644 index 000000000..9cdefdfc9 --- /dev/null +++ b/assuan/assuan-socket-connect.c @@ -0,0 +1,150 @@ +/* assuan-socket-connect.c - Assuan socket based client + * Copyright (C) 2002 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU 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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "assuan-defs.h" + +#ifdef HAVE_JNLIB_LOGGING +#include "../jnlib/logging.h" +#define LOGERROR(a) log_error ((a)) +#define LOGERROR1(a,b) log_error ((a), (b)) +#define LOGERROR2(a,b,c) log_error ((a), (b), (c)) +#define LOGERRORX(a) log_printf ((a)) +#else +#define LOGERROR(a) fprintf (stderr, (a)) +#define LOGERROR1(a,b) fprintf (stderr, (a), (b)) +#define LOGERROR2(a,b,c) fprintf (stderr, (a), (b), (c)) +#define LOGERRORX(a) fputs (stderr, (a)) +#endif + + + +static int +do_finish (ASSUAN_CONTEXT ctx) +{ + if (ctx->inbound.fd != -1) + { + close (ctx->inbound.fd); + } + ctx->inbound.fd = -1; + ctx->outbound.fd = -1; + return 0; +} + +static void +do_deinit (ASSUAN_CONTEXT ctx) +{ + do_finish (ctx); +} + + + +/* Make a connection to the Unix domain socket NAME and return a new + Assuan context in CTX. SERVER_PID is currently not used but may + becode handy in future. */ +AssuanError +assuan_socket_connect (ASSUAN_CONTEXT *r_ctx, + const char *name, pid_t server_pid) +{ + AssuanError err; + ASSUAN_CONTEXT ctx; + int fd; + struct sockaddr_un srvr_addr; + size_t len; + + if (!r_ctx || !name) + return ASSUAN_Invalid_Value; + *r_ctx = NULL; + + /* we require that the name starts with a slash, so that we can + alter reuse this function for other socket types */ + if (*name != '/') + return ASSUAN_Invalid_Value; + if (strlen (name)+1 >= sizeof srvr_addr.sun_path) + return ASSUAN_Invalid_Value; + + err = _assuan_new_context (&ctx); + if (err) + return err; + ctx->pid = server_pid; /* save it in case we need it later */ + ctx->deinit_handler = do_deinit; + ctx->finish_handler = do_finish; + + fd = socket (AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) + { + LOGERROR1 ("can't create socket: %s\n", strerror (errno)); + _assuan_release_context (ctx); + return ASSUAN_General_Error; + } + + memset (&srvr_addr, 0, sizeof srvr_addr ); + srvr_addr.sun_family = AF_UNIX; + strcpy (srvr_addr.sun_path, name); + len = (offsetof (struct sockaddr_un, sun_path) + + strlen (srvr_addr.sun_path) + 1); + + if (connect (fd, (struct sockaddr*)&srvr_addr, len) == -1) + { + LOGERROR2 ("can't connect to `%s': %s\n", name, strerror (errno)); + _assuan_release_context (ctx); + close (fd ); + return ASSUAN_Connect_Failed; + } + + ctx->inbound.fd = fd; + ctx->outbound.fd = fd; + + /* initial handshake */ + { + int okay, off; + + err = _assuan_read_from_server (ctx, &okay, &off); + if (err) + { + LOGERROR1 ("can't connect server: %s\n", assuan_strerror (err)); + } + else if (okay != 1) + { + LOGERROR ("can't connect server: `"); + _assuan_log_sanitized_string (ctx->inbound.line); + LOGERRORX ("'\n"); + err = ASSUAN_Connect_Failed; + } + } + + if (err) + { + assuan_disconnect (ctx); + } + else + *r_ctx = ctx; + return 0; +} + + diff --git a/assuan/assuan-util.c b/assuan/assuan-util.c index 96cd68d4e..4153ef8db 100644 --- a/assuan/assuan-util.c +++ b/assuan/assuan-util.c @@ -25,6 +25,10 @@ #include "assuan-defs.h" +#ifdef HAVE_JNLIB_LOGGING +#include "../jnlib/logging.h" +#endif + static void *(*alloc_func)(size_t n) = malloc; static void *(*realloc_func)(void *p, size_t n) = realloc; @@ -150,3 +154,43 @@ _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length) putc (']', fp); } } + + +/* print a user supplied string after filtering out potential bad + characters*/ +void +_assuan_log_sanitized_string (const char *string) +{ + const unsigned char *s = string; +#ifdef HAVE_JNLIB_LOGGING + FILE *fp = log_get_stream (); +#else + FILE *fp = stderr; +#endif + + for (; *s; s++) + { + if (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)) + { + putc ('\\', fp); + if (*s == '\n') + putc ('n', fp); + else if (*s == '\r') + putc ('r', fp); + else if (*s == '\f') + putc ('f', fp); + else if (*s == '\v') + putc ('v', fp); + else if (*s == '\b') + putc ('b', fp); + else if (!*s) + putc ('0', fp); + else + fprintf (fp, "x%02x", *s ); + } + else + putc (*s, fp); + } +} + + diff --git a/assuan/assuan.h b/assuan/assuan.h index 31d6fbd32..5971d81b8 100644 --- a/assuan/assuan.h +++ b/assuan/assuan.h @@ -1,5 +1,5 @@ /* assuan.c - Definitions for the Assuna protocol - * Copyright (C) 2001 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -160,10 +160,15 @@ void assuan_deinit_server (ASSUAN_CONTEXT ctx); int assuan_init_socket_server (ASSUAN_CONTEXT *r_ctx, int listen_fd); -/*-- assuan-connect.c --*/ +/*-- assuan-pipe-connect.c --*/ AssuanError assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[], int *fd_child_list); -void assuan_pipe_disconnect (ASSUAN_CONTEXT ctx); +/*-- assuan-socket-connect.c --*/ +AssuanError assuan_socket_connect (ASSUAN_CONTEXT *ctx, const char *name, + pid_t server_pid); + +/*-- assuan-connect.c --*/ +void assuan_disconnect (ASSUAN_CONTEXT ctx); pid_t assuan_get_pid (ASSUAN_CONTEXT ctx); /*-- assuan-client.c --*/