summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2006-09-13 15:55:25 +0000
committerWerner Koch <wk@gnupg.org>2006-09-13 15:55:25 +0000
commit7a22110230b9f1e5b5a73c065571935df21ef9b1 (patch)
treeb312d30d17edc30dc7514dbc80a323f54ca71cf8 /src
parentd1210ab25c96e60fc439cfa9b50ec431642ada36 (diff)
downloadlibassuan-7a22110230b9f1e5b5a73c065571935df21ef9b1.tar.gz
More tweaks for descriptor passing.
gpg-connect-agent may now be used as a test program.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog24
-rw-r--r--src/assuan-buffer.c6
-rw-r--r--src/assuan-client.c2
-rw-r--r--src/assuan-defs.h1
-rw-r--r--src/assuan-handler.c76
-rw-r--r--src/assuan-listen.c1
-rw-r--r--src/assuan-pipe-connect.c38
-rw-r--r--src/assuan-pipe-server.c18
-rw-r--r--src/assuan-socket-connect.c38
-rw-r--r--src/assuan-socket-server.c70
-rw-r--r--src/assuan-uds.c34
-rw-r--r--src/assuan.h21
-rwxr-xr-xsrc/mkerrors4
13 files changed, 213 insertions, 120 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index fd4e3d3..04fb712 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,29 @@
+2006-09-13 Werner Koch <wk@g10code.com>
+
+ * assuan-client.c (assuan_transact): Need to map the error code.
+ * mkerrors: Need to map ASSUAN_No_Secret_Key.
+
+ * assuan-pipe-server.c (is_valid_socket): New.
+ (assuan_init_pipe_server): Use UDS with the environmet variable is
+ set and a valid descriptor is given. Ignore FILEDES in this case.
+
+ * assuan-socket-server.c (assuan_init_socket_server_ext): New.
+ Changed other init fucntions to make use of it.
+
+ * assuan-handler.c (assuan_command_parse_fd): Allow for lowercase
+ "fd".
+ (std_handler_reset): Close pending fds.
+ * assuan-uds.c (uds_receivefd): Fixed.
+ (_assuan_uds_close_fds): New.
+
+ * assuan-socket-connect.c (assuan_socket_connect_ext): New. Takes
+ all code of assuan_socket_connect plus an option to use sendmsg.
+ * assuan-pipe-connect.c (assuan_pipe_connect_ext): New arg FLAGS.
+
2006-09-12 Werner Koch <wk@g10code.com>
+ * assuan-buffer.c (_assuan_write_line): Also log the prefix.
+
* assuan-defs.h (DIM, DIMof): New.
* assuan-domain-server.c: Removed.
diff --git a/src/assuan-buffer.c b/src/assuan-buffer.c
index 57eba95..f7b45a3 100644
--- a/src/assuan-buffer.c
+++ b/src/assuan-buffer.c
@@ -269,7 +269,11 @@ _assuan_write_line (assuan_context_t ctx, const char *prefix,
if (ctx->confidential)
fputs ("[Confidential data not shown]", ctx->log_fp);
else
- _assuan_log_print_buffer (ctx->log_fp, line, len);
+ {
+ if (prefixlen)
+ _assuan_log_print_buffer (ctx->log_fp, prefix, prefixlen);
+ _assuan_log_print_buffer (ctx->log_fp, line, len);
+ }
putc ('\n', ctx->log_fp);
}
diff --git a/src/assuan-client.c b/src/assuan-client.c
index cf85ddf..f82abbd 100644
--- a/src/assuan-client.c
+++ b/src/assuan-client.c
@@ -160,7 +160,7 @@ assuan_transact (ASSUAN_CONTEXT ctx,
if (!okay)
{
- rc = atoi (line);
+ rc = _assuan_error (atoi (line));
if (rc < 100)
rc = ASSUAN_Server_Fault;
}
diff --git a/src/assuan-defs.h b/src/assuan-defs.h
index 1f908fb..93aca85 100644
--- a/src/assuan-defs.h
+++ b/src/assuan-defs.h
@@ -185,6 +185,7 @@ int _assuan_new_context (ASSUAN_CONTEXT *r_ctx);
void _assuan_release_context (ASSUAN_CONTEXT ctx);
/*-- assuan-uds.c --*/
+void _assuan_uds_close_fds (assuan_context_t ctx);
void _assuan_uds_deinit (assuan_context_t ctx);
void _assuan_init_uds_io (assuan_context_t ctx);
diff --git a/src/assuan-handler.c b/src/assuan-handler.c
index 0624305..bf00d1a 100644
--- a/src/assuan-handler.c
+++ b/src/assuan-handler.c
@@ -37,20 +37,20 @@ static int my_strcasecmp (const char *a, const char *b);
static int
-dummy_handler (ASSUAN_CONTEXT ctx, char *line)
+dummy_handler (assuan_context_t ctx, char *line)
{
return set_error (ctx, Server_Fault, "no handler registered");
}
static int
-std_handler_nop (ASSUAN_CONTEXT ctx, char *line)
+std_handler_nop (assuan_context_t ctx, char *line)
{
return 0; /* okay */
}
static int
-std_handler_cancel (ASSUAN_CONTEXT ctx, char *line)
+std_handler_cancel (assuan_context_t ctx, char *line)
{
if (ctx->cancel_notify_fnc)
ctx->cancel_notify_fnc (ctx);
@@ -58,7 +58,7 @@ std_handler_cancel (ASSUAN_CONTEXT ctx, char *line)
}
static int
-std_handler_option (ASSUAN_CONTEXT ctx, char *line)
+std_handler_option (assuan_context_t ctx, char *line)
{
char *key, *value, *p;
@@ -105,7 +105,7 @@ std_handler_option (ASSUAN_CONTEXT ctx, char *line)
}
static int
-std_handler_bye (ASSUAN_CONTEXT ctx, char *line)
+std_handler_bye (assuan_context_t ctx, char *line)
{
if (ctx->bye_notify_fnc)
ctx->bye_notify_fnc (ctx);
@@ -115,33 +115,35 @@ std_handler_bye (ASSUAN_CONTEXT ctx, char *line)
}
static int
-std_handler_auth (ASSUAN_CONTEXT ctx, char *line)
+std_handler_auth (assuan_context_t ctx, char *line)
{
return set_error (ctx, Not_Implemented, NULL);
}
static int
-std_handler_reset (ASSUAN_CONTEXT ctx, char *line)
+std_handler_reset (assuan_context_t ctx, char *line)
{
if (ctx->reset_notify_fnc)
ctx->reset_notify_fnc (ctx);
assuan_close_input_fd (ctx);
assuan_close_output_fd (ctx);
+ _assuan_uds_close_fds (ctx);
return 0;
}
static int
-std_handler_end (ASSUAN_CONTEXT ctx, char *line)
+std_handler_end (assuan_context_t ctx, char *line)
{
return set_error (ctx, Not_Implemented, NULL);
}
assuan_error_t
-assuan_command_parse_fd (ASSUAN_CONTEXT ctx, char *line, int *rfd)
+assuan_command_parse_fd (assuan_context_t ctx, char *line, int *rfd)
{
char *endp;
- if (strncmp (line, "FD", 2) != 0 || (line[2] != '=' && line[2] != '\0'))
+ if ( (strncmp (line, "FD", 2) && strncmp (line, "fd", 2))
+ || (line[2] != '=' && line[2] != '\0'))
return set_error (ctx, Syntax_Error, "FD[=<n>] expected");
line += 2;
if (*line == '=')
@@ -150,7 +152,7 @@ assuan_command_parse_fd (ASSUAN_CONTEXT ctx, char *line, int *rfd)
if (!digitp (*line))
return set_error (ctx, Syntax_Error, "number required");
*rfd = strtoul (line, &endp, 10);
- /* remove that argument so that a notify handler won't see it */
+ /* Remove that argument so that a notify handler won't see it. */
memset (line, ' ', endp? (endp-line):strlen(line));
if (*rfd == ctx->inbound.fd)
@@ -166,7 +168,7 @@ assuan_command_parse_fd (ASSUAN_CONTEXT ctx, char *line, int *rfd)
/* Format is INPUT FD=<n> */
static int
-std_handler_input (ASSUAN_CONTEXT ctx, char *line)
+std_handler_input (assuan_context_t ctx, char *line)
{
int rc, fd;
@@ -181,7 +183,7 @@ std_handler_input (ASSUAN_CONTEXT ctx, char *line)
/* Format is OUTPUT FD=<n> */
static int
-std_handler_output (ASSUAN_CONTEXT ctx, char *line)
+std_handler_output (assuan_context_t ctx, char *line)
{
int rc, fd;
@@ -203,7 +205,7 @@ std_handler_output (ASSUAN_CONTEXT ctx, char *line)
with default handlers */
static struct {
const char *name;
- int (*handler)(ASSUAN_CONTEXT, char *line);
+ int (*handler)(assuan_context_t, char *line);
int always; /* always initialize this command */
} std_cmd_table[] = {
{ "NOP", std_handler_nop, 1 },
@@ -235,9 +237,9 @@ static struct {
* Return value: 0 on success or an error code
**/
int
-assuan_register_command (ASSUAN_CONTEXT ctx,
+assuan_register_command (assuan_context_t ctx,
const char *cmd_name,
- int (*handler)(ASSUAN_CONTEXT, char *))
+ int (*handler)(assuan_context_t, char *))
{
int i;
const char *s;
@@ -290,7 +292,8 @@ assuan_register_command (ASSUAN_CONTEXT ctx,
}
int
-assuan_register_bye_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
+assuan_register_bye_notify (assuan_context_t ctx,
+ void (*fnc)(assuan_context_t))
{
if (!ctx)
return _assuan_error (ASSUAN_Invalid_Value);
@@ -299,7 +302,8 @@ assuan_register_bye_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
}
int
-assuan_register_reset_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
+assuan_register_reset_notify (assuan_context_t ctx,
+ void (*fnc)(assuan_context_t))
{
if (!ctx)
return _assuan_error (ASSUAN_Invalid_Value);
@@ -308,7 +312,8 @@ assuan_register_reset_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
}
int
-assuan_register_cancel_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
+assuan_register_cancel_notify (assuan_context_t ctx,
+ void (*fnc)(assuan_context_t))
{
if (!ctx)
return _assuan_error (ASSUAN_Invalid_Value);
@@ -317,8 +322,8 @@ assuan_register_cancel_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
}
int
-assuan_register_option_handler (ASSUAN_CONTEXT ctx,
- int (*fnc)(ASSUAN_CONTEXT,
+assuan_register_option_handler (assuan_context_t ctx,
+ int (*fnc)(assuan_context_t,
const char*, const char*))
{
if (!ctx)
@@ -328,8 +333,8 @@ assuan_register_option_handler (ASSUAN_CONTEXT ctx,
}
int
-assuan_register_input_notify (ASSUAN_CONTEXT ctx,
- void (*fnc)(ASSUAN_CONTEXT, const char *))
+assuan_register_input_notify (assuan_context_t ctx,
+ void (*fnc)(assuan_context_t, const char *))
{
if (!ctx)
return _assuan_error (ASSUAN_Invalid_Value);
@@ -338,8 +343,8 @@ assuan_register_input_notify (ASSUAN_CONTEXT ctx,
}
int
-assuan_register_output_notify (ASSUAN_CONTEXT ctx,
- void (*fnc)(ASSUAN_CONTEXT, const char *))
+assuan_register_output_notify (assuan_context_t ctx,
+ void (*fnc)(assuan_context_t, const char *))
{
if (!ctx)
return _assuan_error (ASSUAN_Invalid_Value);
@@ -350,7 +355,7 @@ assuan_register_output_notify (ASSUAN_CONTEXT ctx,
/* Helper to register the standards commands */
int
-_assuan_register_std_commands (ASSUAN_CONTEXT ctx)
+_assuan_register_std_commands (assuan_context_t ctx)
{
int i, rc;
@@ -371,7 +376,7 @@ _assuan_register_std_commands (ASSUAN_CONTEXT ctx)
/* Process the special data lines. The "D " has already been removed
from the line. As all handlers this function may modify the line. */
static int
-handle_data_line (ASSUAN_CONTEXT ctx, char *line, int linelen)
+handle_data_line (assuan_context_t ctx, char *line, int linelen)
{
return set_error (ctx, Not_Implemented, NULL);
}
@@ -395,7 +400,7 @@ my_strcasecmp (const char *a, const char *b)
table, remove leading and white spaces from the arguments, call the
handler with the argument line and return the error */
static int
-dispatch_command (ASSUAN_CONTEXT ctx, char *line, int linelen)
+dispatch_command (assuan_context_t ctx, char *line, int linelen)
{
char *p;
const char *s;
@@ -442,7 +447,7 @@ dispatch_command (ASSUAN_CONTEXT ctx, char *line, int linelen)
static int
-process_request (ASSUAN_CONTEXT ctx)
+process_request (assuan_context_t ctx)
{
int rc;
@@ -553,7 +558,7 @@ process_request (ASSUAN_CONTEXT ctx)
* failed. Note, that no error is returned for operational errors.
**/
int
-assuan_process (ASSUAN_CONTEXT ctx)
+assuan_process (assuan_context_t ctx)
{
int rc;
@@ -580,7 +585,7 @@ assuan_process (ASSUAN_CONTEXT ctx)
* Return value: -1 for end of server, 0 on success or an error code
**/
int
-assuan_process_next (ASSUAN_CONTEXT ctx)
+assuan_process_next (assuan_context_t ctx)
{
return process_request (ctx);
}
@@ -604,7 +609,7 @@ assuan_process_next (ASSUAN_CONTEXT ctx)
* error which is most likely a too small fdarray.
**/
int
-assuan_get_active_fds (ASSUAN_CONTEXT ctx, int what,
+assuan_get_active_fds (assuan_context_t ctx, int what,
int *fdarray, int fdarraysize)
{
int n = 0;
@@ -637,7 +642,7 @@ assuan_get_active_fds (ASSUAN_CONTEXT ctx, int what,
implementaion for systems w/o a glibc, a simple implementation
could use a child process */
FILE *
-assuan_get_data_fp (ASSUAN_CONTEXT ctx)
+assuan_get_data_fp (assuan_context_t ctx)
{
#if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN)
if (ctx->outbound.data.fp)
@@ -659,7 +664,7 @@ assuan_get_data_fp (ASSUAN_CONTEXT ctx)
/* Set the text used for the next OK reponse. This string is
automatically reset to NULL after the next command. */
assuan_error_t
-assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line)
+assuan_set_okay_line (assuan_context_t ctx, const char *line)
{
if (!ctx)
return _assuan_error (ASSUAN_Invalid_Value);
@@ -686,7 +691,8 @@ assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line)
assuan_error_t
-assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text)
+assuan_write_status (assuan_context_t ctx,
+ const char *keyword, const char *text)
{
char buffer[256];
char *helpbuf;
diff --git a/src/assuan-listen.c b/src/assuan-listen.c
index b81db84..04db68c 100644
--- a/src/assuan-listen.c
+++ b/src/assuan-listen.c
@@ -24,6 +24,7 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
+#include <errno.h>
#include "assuan-defs.h"
diff --git a/src/assuan-pipe-connect.c b/src/assuan-pipe-connect.c
index c3ceb53..5dd91cc 100644
--- a/src/assuan-pipe-connect.c
+++ b/src/assuan-pipe-connect.c
@@ -512,7 +512,7 @@ socketpair_connect (assuan_context_t *ctx,
_assuan_error (ASSUAN_Problem_Starting_Server),
name, strerror (errno));
errbuf[sizeof(errbuf)-1] = 0;
- writen (1, errbuf, strlen (errbuf));
+ writen (fds[1], errbuf, strlen (errbuf));
_exit (4);
}
#ifdef _ASSUAN_USE_DOUBLE_FORK
@@ -842,31 +842,41 @@ assuan_pipe_connect2 (assuan_context_t *ctx,
}
-/* Connect to a server over a 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.
+/* 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 specila environment variables are set. To let the caller
- detect whether the cild or the parent continues, the child returns
+ 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)
+ void *atforkvalue, unsigned int flags)
{
+ if ((flags & 1))
+ {
#ifdef HAVE_W32_SYSTEM
- return _assuan_error (ASSUAN_Not_Implemented);
+ return _assuan_error (ASSUAN_Not_Implemented);
#else
- return socketpair_connect (ctx, name, argv, fd_child_list,
- atfork, atforkvalue);
+ return socketpair_connect (ctx, name, argv, fd_child_list,
+ atfork, atforkvalue);
#endif
+ }
+ else
+ return pipe_connect (ctx, name, argv, fd_child_list, atfork, atforkvalue);
}
diff --git a/src/assuan-pipe-server.c b/src/assuan-pipe-server.c
index 509fc12..18f8cc5 100644
--- a/src/assuan-pipe-server.c
+++ b/src/assuan-pipe-server.c
@@ -22,6 +22,8 @@
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include <unistd.h>
#ifdef HAVE_W32_SYSTEM
#include <windows.h>
@@ -89,6 +91,18 @@ _assuan_new_context (ASSUAN_CONTEXT *r_ctx)
}
+/* Returns true if atoi(S) denotes a valid socket. */
+static int
+is_valid_socket (const char *s)
+{
+ struct stat buf;
+
+ if ( fstat (atoi (s), &buf ) )
+ return 0;
+ return S_ISSOCK (buf.st_mode);
+}
+
+
int
assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2])
{
@@ -112,7 +126,7 @@ assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2])
ctx->outbound.fd = _get_osfhandle (filedes[1]);
#else
s = getenv ("_assuan_connection_fd");
- if (!filedes && s && *s && atoi (s) >= 0 )
+ if (s && *s && is_valid_socket (s) )
{
/* Well, we are called with an bi-directional file
descriptor. Prepare for using sendmsg/recvmsg. In this
@@ -121,7 +135,7 @@ assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2])
_assuan_init_uds_io (ctx);
ctx->deinit_handler = _assuan_uds_deinit;
}
- else if (filedes)
+ else if (filedes && filedes[0] != -1 && filedes[1] != -1 )
{
/* Standard pipe server. */
ctx->inbound.fd = filedes[0];
diff --git a/src/assuan-socket-connect.c b/src/assuan-socket-connect.c
index 8df7812..5953f1c 100644
--- a/src/assuan-socket-connect.c
+++ b/src/assuan-socket-connect.c
@@ -55,7 +55,7 @@
static int
-do_finish (ASSUAN_CONTEXT ctx)
+do_finish (assuan_context_t ctx)
{
if (ctx->inbound.fd != -1)
{
@@ -67,22 +67,37 @@ do_finish (ASSUAN_CONTEXT ctx)
}
static void
-do_deinit (ASSUAN_CONTEXT ctx)
+do_deinit (assuan_context_t 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
become handy in the future. */
assuan_error_t
-assuan_socket_connect (ASSUAN_CONTEXT *r_ctx,
+assuan_socket_connect (assuan_context_t *r_ctx,
const char *name, pid_t server_pid)
{
+ return assuan_socket_connect_ext (r_ctx, name, server_pid, 0);
+}
+
+
+/* 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 ctx;
+ assuan_context_t ctx;
int fd;
struct sockaddr_un srvr_addr;
size_t len;
@@ -92,9 +107,9 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx,
return _assuan_error (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. To make things
- easier we allow an optional dirver prefix. */
+ /* 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;
@@ -107,10 +122,9 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx,
err = _assuan_new_context (&ctx);
if (err)
return err;
- ctx->deinit_handler = do_deinit;
+ 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)
{
@@ -138,7 +152,9 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx,
ctx->inbound.fd = fd;
ctx->outbound.fd = fd;
ctx->io = &io;
-
+ if ((flags&1))
+ _assuan_init_uds_io (ctx);
+
/* initial handshake */
{
int okay, off;
@@ -164,3 +180,5 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx,
*r_ctx = ctx;
return 0;
}
+
+
diff --git a/src/assuan-socket-server.c b/src/assuan-socket-server.c
index 91adb71..468826e 100644
--- a/src/assuan-socket-server.c
+++ b/src/assuan-socket-server.c
@@ -114,40 +114,25 @@ deinit_socket_server (assuan_context_t ctx)
int
assuan_init_socket_server (assuan_context_t *r_ctx, int listen_fd)
{
- assuan_context_t ctx;
- int rc;
-
- *r_ctx = NULL;
- ctx = xtrycalloc (1, sizeof *ctx);
- if (!ctx)
- return _assuan_error (ASSUAN_Out_Of_Core);
- ctx->is_server = 1;
- ctx->input_fd = -1;
- ctx->output_fd = -1;
-
- ctx->inbound.fd = -1;
- ctx->outbound.fd = -1;
-
- ctx->listen_fd = listen_fd;
- ctx->connected_fd = -1;
- ctx->deinit_handler = deinit_socket_server;
- ctx->accept_handler = accept_connection;
- ctx->finish_handler = finish_connection;
-
- ctx->io = &io;
-
- rc = _assuan_register_std_commands (ctx);
- if (rc)
- xfree (ctx);
- else
- *r_ctx = ctx;
- return rc;
+ return assuan_init_socket_server_ext (r_ctx, listen_fd, 0);
}
/* Initialize a server using the already accepted socket FD. */
int
assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd)
{
+ return assuan_init_socket_server_ext (r_ctx, fd, 2);
+}
+
+
+/*
+ Flag bits: 0 - use sendmsg/recvmsg to allow descriptor passing
+ 1 - FD has already been accepted.
+*/
+int
+assuan_init_socket_server_ext (assuan_context_t *r_ctx, int fd,
+ unsigned int flags)
+{
assuan_context_t ctx;
int rc;
@@ -156,21 +141,34 @@ assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd)
if (!ctx)
return _assuan_error (ASSUAN_Out_Of_Core);
ctx->is_server = 1;
- ctx->pipe_mode = 1; /* we want a second accept to indicate EOF */
+ if ((flags & 2))
+ ctx->pipe_mode = 1; /* We want a second accept to indicate EOF. */
ctx->input_fd = -1;
ctx->output_fd = -1;
ctx->inbound.fd = -1;
ctx->outbound.fd = -1;
- ctx->io = &io;
-
- ctx->listen_fd = -1;
- ctx->connected_fd = fd;
- ctx->deinit_handler = deinit_socket_server;
- ctx->accept_handler = accept_connection_bottom;
+ if ((flags & 2))
+ {
+ ctx->listen_fd = -1;
+ ctx->connected_fd = fd;
+ }
+ else
+ {
+ ctx->listen_fd = fd;
+ ctx->connected_fd = -1;
+ }
+ ctx->deinit_handler = (flags & 1)? _assuan_uds_deinit:deinit_socket_server;
+ ctx->accept_handler = ((flags & 2)
+ ? accept_connection_bottom
+ : accept_connection);
ctx->finish_handler = finish_connection;
+ ctx->io = &io;
+ if ((flags & 1))
+ _assuan_init_uds_io (ctx);
+
rc = _assuan_register_std_commands (ctx);
if (rc)
xfree (ctx);
@@ -178,5 +176,3 @@ assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd)
*r_ctx = ctx;
return rc;
}
-
-
diff --git a/src/assuan-uds.c b/src/assuan-uds.c
index 52988d4..c725392 100644
--- a/src/assuan-uds.c
+++ b/src/assuan-uds.c
@@ -45,7 +45,10 @@
#include "assuan-defs.h"
-/* Read from a unix domain socket using sendmsg. */
+/* Read from a unix domain socket using sendmsg.
+
+ FIXME: We don't need the buffering. It is a leftover from the time
+ when we used datagrams. */
static ssize_t
uds_reader (assuan_context_t ctx, void *buf, size_t buflen)
{
@@ -215,16 +218,19 @@ static assuan_error_t
uds_receivefd (assuan_context_t ctx, int *fd)
{
#ifndef HAVE_W32_SYSTEM
- if (!ctx->uds.pendingfds)
+ int i;
+
+ if (!ctx->uds.pendingfdscount)
{
_assuan_log_printf ("no pending file descriptors!\n");
return _assuan_error (ASSUAN_General_Error);
}
+ assert (ctx->uds.pendingfdscount <= DIM(ctx->uds.pendingfds));
*fd = ctx->uds.pendingfds[0];
- if (--ctx->uds.pendingfdscount)
- memmove (ctx->uds.pendingfds, ctx->uds.pendingfds + 1,
- ctx->uds.pendingfdscount * sizeof (int));
+ for (i=1; i < ctx->uds.pendingfdscount; i++)
+ ctx->uds.pendingfds[i-1] = ctx->uds.pendingfds[i];
+ ctx->uds.pendingfdscount--;
return 0;
#else
@@ -233,12 +239,21 @@ uds_receivefd (assuan_context_t ctx, int *fd)
}
-/* Deinitialize the unix domain socket I/O functions. */
+/* Close all pending fds. */
void
-_assuan_uds_deinit (assuan_context_t ctx)
+_assuan_uds_close_fds (assuan_context_t ctx)
{
int i;
+ for (i = 0; i < ctx->uds.pendingfdscount; i++)
+ _assuan_close (ctx->uds.pendingfds[i]);
+ ctx->uds.pendingfdscount = 0;
+}
+
+/* Deinitialize the unix domain socket I/O functions. */
+void
+_assuan_uds_deinit (assuan_context_t ctx)
+{
/* First call the finish_handler which should close descriptors etc. */
ctx->finish_handler (ctx);
@@ -249,13 +264,10 @@ _assuan_uds_deinit (assuan_context_t ctx)
xfree (ctx->uds.buffer);
}
- for (i = 0; i < ctx->uds.pendingfdscount; i++)
- _assuan_close (ctx->uds.pendingfds[i]);
- ctx->uds.pendingfdscount = 0;
+ _assuan_uds_close_fds (ctx);
}
-
/* Helper function to initialize a context for domain I/O. */
void
_assuan_init_uds_io (assuan_context_t ctx)
diff --git a/src/assuan.h b/src/assuan.h
index e16d821..8a22f90 100644
--- a/src/assuan.h
+++ b/src/assuan.h
@@ -91,10 +91,12 @@
#define assuan_init_socket_server _ASSUAN_PREFIX(assuan_init_socket_server)
#define assuan_init_connected_socket_server \
_ASSUAN_PREFIX(assuan_init_connected_socket_server)
+#define assuan_init_socket_server_ext \
+ _ASSUAN_PREFIX(assuan_init_socket_server-ext)
#define assuan_pipe_connect _ASSUAN_PREFIX(assuan_pipe_connect)
+#define assuan_pipe_connect_ext _ASSUAN_PREFIX(assuan_pipe_connect_ext)
#define assuan_socket_connect _ASSUAN_PREFIX(assuan_socket_connect)
-#define assuan_domain_connect _ASSUAN_PREFIX(assuan_domain_connect)
-#define assuan_init_domain_server _ASSUAN_PREFIX(assuan_init_domain_server)
+#define assuan_socket_connect_ext _ASSUAN_PREFIX(assuan_socket_connect_ext)
#define assuan_disconnect _ASSUAN_PREFIX(assuan_disconnect)
#define assuan_get_pid _ASSUAN_PREFIX(assuan_get_pid)
#define assuan_transact _ASSUAN_PREFIX(assuan_transact)
@@ -365,7 +367,8 @@ void assuan_deinit_server (assuan_context_t ctx);
/*-- assuan-socket-server.c --*/
int assuan_init_socket_server (assuan_context_t *r_ctx, int listen_fd);
int assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd);
-
+int assuan_init_socket_server_ext (assuan_context_t *r_ctx, int fd,
+ unsigned int flags);
/*-- assuan-pipe-connect.c --*/
assuan_error_t assuan_pipe_connect (assuan_context_t *ctx,
@@ -383,13 +386,17 @@ assuan_error_t assuan_pipe_connect_ext (assuan_context_t *ctx,
const char *const argv[],
int *fd_child_list,
void (*atfork) (void *, int),
- void *atforkvalue);
+ void *atforkvalue,
+ unsigned int flags);
/*-- assuan-socket-connect.c --*/
-assuan_error_t assuan_socket_connect (assuan_context_t *ctx, const char *name,
+assuan_error_t assuan_socket_connect (assuan_context_t *ctx,
+ const char *name,
pid_t server_pid);
-
-
+assuan_error_t assuan_socket_connect_ext (assuan_context_t *ctx,
+ const char *name,
+ pid_t server_pid,
+ unsigned int flags);
/*-- assuan-connect.c --*/
void assuan_disconnect (assuan_context_t ctx);
diff --git a/src/mkerrors b/src/mkerrors
index 552cb17..b5ab114 100755
--- a/src/mkerrors
+++ b/src/mkerrors
@@ -83,6 +83,7 @@ _assuan_error (int oldcode)
case ASSUAN_Unexpected_Command: n = 274; break;
case ASSUAN_Unknown_Command: n = 275; break;
case ASSUAN_Canceled: n = 277; break;
+ case ASSUAN_No_Secret_Key: n = 17; break;
case ASSUAN_Read_Error:
switch (errno)
@@ -119,8 +120,7 @@ _assuan_error (int oldcode)
case -1: n = 16383 /*GPG_ERR_EOF*/; break;
default:
- assert (!"unmapped error code used in libassuan!!");
- n = 257; /* Just in case someone compiled with NDEBUG. */
+ n = 257;
break;
}