diff options
| author | Werner Koch <[email protected]> | 2001-12-13 15:04:36 +0000 | 
|---|---|---|
| committer | Werner Koch <[email protected]> | 2001-12-13 15:04:36 +0000 | 
| commit | 3de2384ea5ae8b542c0d6654ceca3b8f473d2f9f (patch) | |
| tree | aa13c8812fe6c65ca6db924dd7f0de6c5b70ec8a /assuan/assuan-connect.c | |
| parent | *** empty log message *** (diff) | |
| download | gpgme-3de2384ea5ae8b542c0d6654ceca3b8f473d2f9f.tar.gz gpgme-3de2384ea5ae8b542c0d6654ceca3b8f473d2f9f.zip  | |
Updated Assuan to the current version
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;  } + +  | 
