diff options
Diffstat (limited to 'assuan/assuan-connect.c')
-rw-r--r-- | assuan/assuan-connect.c | 136 |
1 files changed, 118 insertions, 18 deletions
diff --git a/assuan/assuan-connect.c b/assuan/assuan-connect.c index 37d42625..683c7f06 100644 --- a/assuan/assuan-connect.c +++ b/assuan/assuan-connect.c @@ -18,17 +18,57 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ +#ifdef HAVE_CONFIG_H #include <config.h> +#endif + #include <stdlib.h> #include <stdio.h> #include <string.h> #include <signal.h> #include <unistd.h> +#include <errno.h> #include <sys/types.h> #include <sys/wait.h> #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. */ @@ -41,8 +81,8 @@ assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[]) int wp[2]; int fd[2]; - if (!name || !argv || !argv[0]) - return ASSUAN_General_Error; + if (!ctx || !name || !argv || !argv[0]) + return ASSUAN_Invalid_Value; if (!fixed_signals) { @@ -69,7 +109,7 @@ assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[]) 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. */ @@ -82,6 +122,7 @@ assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[]) close (wp[1]); return err; } + (*ctx)->is_server = 0; (*ctx)->pid = fork (); if ((*ctx)->pid < 0) @@ -96,32 +137,89 @@ assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[]) if ((*ctx)->pid == 0) { - close (rp[0]); - close (wp[1]); + 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++) + { + if (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) - { - dup2 (rp[1], STDOUT_FILENO); /* Child's outbound is write end of read pipe. */ - close (rp[1]); - } + { + 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) - { - dup2 (wp[0], STDIN_FILENO); /* Child's inbound is read end of write pipe. */ - close (wp[0]); - } - execv (name, argv); - _exit (1); + { + 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]); - _assuan_read_line (*ctx); /* FIXME: Handshake. */ - return 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_pipe_server (*ctx); /* FIXME: Common code should be factored out. */ + } + + return err; } void assuan_pipe_disconnect (ASSUAN_CONTEXT ctx) { - _assuan_write_line (ctx, "BYE"); + assuan_write_line (ctx, "BYE"); close (ctx->inbound.fd); close (ctx->outbound.fd); waitpid (ctx->pid, NULL, 0); /* FIXME Check return value. */ @@ -133,3 +231,5 @@ assuan_get_pid (ASSUAN_CONTEXT ctx) { return ctx ? ctx->pid : -1; } + + |