int
assuan_init_pipe_server (assuan_context_t *r_ctx, int filedes[2])
{
  int rc;

  rc = _assuan_new_context (r_ctx);
  if (!rc)
    {
      assuan_context_t ctx = *r_ctx;
      const char *s;
      unsigned long ul;

      ctx->is_server = 1;
#ifdef HAVE_W32_SYSTEM
      /* MS Windows has so many different types of handle that one
         needs to tranlsate them at many place forth and back.  Also
         make sure that the file descriptors are in binary mode.  */
      setmode (filedes[0], O_BINARY);
      setmode (filedes[1], O_BINARY);
      ctx->inbound.fd  = (void*)_get_osfhandle (filedes[0]);
      ctx->outbound.fd = (void*)_get_osfhandle (filedes[1]);
#else
      s = getenv ("_assuan_connection_fd");
      if (s && *s && is_valid_socket (s) )
        {
          /* Well, we are called with an bi-directional file
             descriptor.  Prepare for using sendmsg/recvmsg.  In this
             case we ignore the passed file descriptors. */
          ctx->inbound.fd  = ctx->outbound.fd = atoi (s);
          _assuan_init_uds_io (ctx);
          ctx->deinit_handler = _assuan_uds_deinit;
        }
      else if (filedes && filedes[0] != ASSUAN_INVALID_FD 
               && filedes[1] != ASSUAN_INVALID_FD )
        {
          /* Standard pipe server. */
          ctx->inbound.fd  = filedes[0];
          ctx->outbound.fd = filedes[1];
        }
      else
        {
          _assuan_release_context (*r_ctx);
          *r_ctx = NULL;
          return ASSUAN_Problem_Starting_Server;
        }
#endif
      ctx->pipe_mode = 1;

      s = getenv ("_assuan_pipe_connect_pid");
      if (s && (ul=strtoul (s, NULL, 10)) && ul)
        ctx->pid = (pid_t)ul;
      else
        ctx->pid = (pid_t)-1;

    }
  return rc;
}
void
assuan_deinit_server(assuan_context_t ctx)
{
    if(ctx)
    {
        /* We use this function pointer to avoid linking other server
           when not needed but still allow for a generic deinit function.  */
        ctx->deinit_handler(ctx);
        ctx->deinit_handler = NULL;
        _assuan_release_context(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
   become handy in the future.  With flags set to 1 sendmsg and
   recvmesg are used. */
assuan_error_t
assuan_socket_connect_ext(assuan_context_t *r_ctx,
                          const char *name, pid_t server_pid,
                          unsigned int flags)
{
    static struct assuan_io io = { _assuan_simple_read,
               _assuan_simple_write
    };

    assuan_error_t err;
    assuan_context_t ctx;
    int fd;
    struct sockaddr_un srvr_addr;
    size_t len;
    const char *s;

    if(!r_ctx || !name)
        return _assuan_error(ASSUAN_Invalid_Value);
    *r_ctx = NULL;

    /* We require that the name starts with a slash, so that we
       eventually can reuse this function for other socket types.  To
       make things easier we allow an optional dirver prefix.  */
    s = name;
    if(*s && s[1] == ':')
        s += 2;
    if(*s != DIRSEP_C && *s != '/')
        return _assuan_error(ASSUAN_Invalid_Value);

    if(strlen(name) + 1 >= sizeof srvr_addr.sun_path)
        return _assuan_error(ASSUAN_Invalid_Value);

    err = _assuan_new_context(&ctx);
    if(err)
        return err;
    ctx->deinit_handler = ((flags & 1)) ? _assuan_uds_deinit :  do_deinit;
    ctx->finish_handler = do_finish;

    fd = _assuan_sock_new(PF_LOCAL, SOCK_STREAM, 0);
    if(fd == -1)
    {
        _assuan_log_printf("can't create socket: %s\n", strerror(errno));
        _assuan_release_context(ctx);
        return _assuan_error(ASSUAN_General_Error);
    }

    memset(&srvr_addr, 0, sizeof srvr_addr);
    srvr_addr.sun_family = AF_LOCAL;
    strncpy(srvr_addr.sun_path, name, sizeof(srvr_addr.sun_path) - 1);
    srvr_addr.sun_path[sizeof(srvr_addr.sun_path) - 1] = 0;
    len = SUN_LEN(&srvr_addr);


    if(_assuan_sock_connect(fd, (struct sockaddr *) &srvr_addr, len) == -1)
    {
        _assuan_log_printf("can't connect to `%s': %s\n",
                           name, strerror(errno));
        _assuan_release_context(ctx);
        _assuan_close(fd);
        return _assuan_error(ASSUAN_Connect_Failed);
    }

    ctx->inbound.fd = fd;
    ctx->outbound.fd = fd;
    ctx->io = &io;
    if((flags & 1))
        _assuan_init_uds_io(ctx);

    /* initial handshake */
    {
        int okay, off;

        err = _assuan_read_from_server(ctx, &okay, &off);
        if(err)
            _assuan_log_printf("can't connect to server: %s\n",
                               assuan_strerror(err));
        else if(okay != 1)
        {
            /*LOG ("can't connect to server: `");*/
            _assuan_log_sanitized_string(ctx->inbound.line);
            fprintf(assuan_get_assuan_log_stream(), "'\n");
            err = _assuan_error(ASSUAN_Connect_Failed);
        }
    }

    if(err)
    {
        assuan_disconnect(ctx);
    }
    else
        *r_ctx = ctx;
    return 0;
}