aboutsummaryrefslogtreecommitdiffstats
path: root/assuan/assuan-handler.c
diff options
context:
space:
mode:
authorMarcus Brinkmann <[email protected]>2009-10-20 15:39:15 +0000
committerMarcus Brinkmann <[email protected]>2009-10-20 15:39:15 +0000
commite782b1ab06a2d3325bc487c28ab678c95d9675b3 (patch)
tree87aacb82e59e4d7d8b60d2c55d66b12eed01af2e /assuan/assuan-handler.c
parentAdd new debug helper (diff)
downloadgpgme-e782b1ab06a2d3325bc487c28ab678c95d9675b3.tar.gz
gpgme-e782b1ab06a2d3325bc487c28ab678c95d9675b3.zip
2009-10-20 Marcus Brinkmann <[email protected]>
* configure.ac: Replace internal libassuan by external libassuan. * m4/libassuan.m4: New file. * Makefile.am (assuan): Remove variable. (SUBDIRS): Remove ${assuan}. * assuan/: Removed. src/ 2009-10-20 Marcus Brinkmann <[email protected]> * Makefile.am (assuan_cppflags, assuan_libobjs): Removed. (gpgsm_components): Move engine-assuan.c to ... (assuan_components): ... this new variable. (main_sources): Add this new variable. (AM_CPPFLAGS): Remove $(assuan_cppflags). (AM_CFLAGS): Add @LIBASSUAN_CFLAGS@. (libgpgme_la_DEPENDENCIES, libgpgme_pth_la_DEPENDENCIES) (libgpgme_glib_la_DEPENDENCIES, libgpgme_qt_la_DEPENDENCIES) (libgpgme_pthread_la_DEPENDENCIES): Remove $(assuan_libobjs). (libgpgme_la_LIBADD, libgpgme_pth_la_LIBADD) (libgpgme_glib_la_LIBADD, libgpgme_qt_la_LIBADD)) (libgpgme_pthread_la_LIBADD): Replace $(assuan_libobjs) by @LIBASSUAN_LIBS@. * priv-io.h [!HAVE_W32_SYSTEM]: Declare _gpgme_io_recvmsg, _gpgme_io_sendmsg, _gpgme_io_waitpid. * engine-backend.h: Define with [ENABLE_ASSUAN] instead of [ENABLE_GPGSM]. * posix-io.c (_gpgme_io_waitpid): Make non-static. * util.h (ENABLE_ASSUAN): Declar _gpgme_assuan_system_hooks, _gpgme_assuan_malloc_hooks, _gpgme_assuan_log_cb. * engine-gpgsm.c: Don't map assuan error codes. Use assuan_release instead of assuan_disconnect. (map_assuan_error): Remove function. (gpgsm_new): Use new assuan context interface. * engine-assuan.c: Use assuan_release instead of assuan_disconnect. (llass_new): Use new assuan context interface.
Diffstat (limited to 'assuan/assuan-handler.c')
-rw-r--r--assuan/assuan-handler.c915
1 files changed, 0 insertions, 915 deletions
diff --git a/assuan/assuan-handler.c b/assuan/assuan-handler.c
deleted file mode 100644
index f504abef..00000000
--- a/assuan/assuan-handler.c
+++ /dev/null
@@ -1,915 +0,0 @@
-/* assuan-handler.c - dispatch commands
- * Copyright (C) 2001, 2002, 2003, 2007 Free Software Foundation, Inc.
- *
- * This file is part of Assuan.
- *
- * Assuan is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Assuan 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-
-#include "assuan-defs.h"
-
-
-
-#define spacep(p) (*(p) == ' ' || *(p) == '\t')
-#define digitp(a) ((a) >= '0' && (a) <= '9')
-
-static int my_strcasecmp (const char *a, const char *b);
-
-
-#define PROCESS_DONE(ctx, rc) \
- ((ctx)->in_process_next ? assuan_process_done ((ctx), (rc)) : (rc))
-
-static int
-dummy_handler (assuan_context_t ctx, char *line)
-{
- return
- PROCESS_DONE (ctx, set_error (ctx, Server_Fault, "no handler registered"));
-}
-
-
-static int
-std_handler_nop (assuan_context_t ctx, char *line)
-{
- return PROCESS_DONE (ctx, 0); /* okay */
-}
-
-static int
-std_handler_cancel (assuan_context_t ctx, char *line)
-{
- if (ctx->cancel_notify_fnc)
- ctx->cancel_notify_fnc (ctx);
- return PROCESS_DONE (ctx, set_error (ctx, Not_Implemented, NULL));
-}
-
-static int
-std_handler_option (assuan_context_t ctx, char *line)
-{
- char *key, *value, *p;
-
- for (key=line; spacep (key); key++)
- ;
- if (!*key)
- return
- PROCESS_DONE (ctx, set_error (ctx, Syntax_Error, "argument required"));
- if (*key == '=')
- return
- PROCESS_DONE (ctx, set_error (ctx, Syntax_Error,
- "no option name given"));
- for (value=key; *value && !spacep (value) && *value != '='; value++)
- ;
- if (*value)
- {
- if (spacep (value))
- *value++ = 0; /* terminate key */
- for (; spacep (value); value++)
- ;
- if (*value == '=')
- {
- *value++ = 0; /* terminate key */
- for (; spacep (value); value++)
- ;
- if (!*value)
- return
- PROCESS_DONE (ctx, set_error (ctx, Syntax_Error,
- "option argument expected"));
- }
- if (*value)
- {
- for (p = value + strlen(value) - 1; p > value && spacep (p); p--)
- ;
- if (p > value)
- *++p = 0; /* strip trailing spaces */
- }
- }
-
- if (*key == '-' && key[1] == '-' && key[2])
- key += 2; /* the double dashes are optional */
- if (*key == '-')
- return PROCESS_DONE (ctx,
- set_error (ctx, Syntax_Error,
- "option should not begin with one dash"));
-
- if (ctx->option_handler_fnc)
- return PROCESS_DONE (ctx, ctx->option_handler_fnc (ctx, key, value));
- return PROCESS_DONE (ctx, 0);
-}
-
-static int
-std_handler_bye (assuan_context_t ctx, char *line)
-{
- if (ctx->bye_notify_fnc)
- ctx->bye_notify_fnc (ctx);
- assuan_close_input_fd (ctx);
- assuan_close_output_fd (ctx);
- return PROCESS_DONE (ctx, _assuan_error (-1)); /* pretty simple :-) */
-}
-
-static int
-std_handler_auth (assuan_context_t ctx, char *line)
-{
- return PROCESS_DONE (ctx, set_error (ctx, Not_Implemented, NULL));
-}
-
-static int
-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 PROCESS_DONE (ctx, 0);
-}
-
-static int
-std_handler_help (assuan_context_t ctx, char *line)
-{
- unsigned int i;
- char buf[ASSUAN_LINELENGTH];
-
- for (i = 0; i < ctx->cmdtbl_used; i++)
- {
- snprintf (buf, sizeof (buf), "# %s", ctx->cmdtbl[i].name);
- buf[ASSUAN_LINELENGTH - 1] = '\0';
- assuan_write_line (ctx, buf);
- }
-
- return PROCESS_DONE (ctx, 0);
-}
-
-
-static int
-std_handler_end (assuan_context_t ctx, char *line)
-{
- return PROCESS_DONE (ctx, set_error (ctx, Not_Implemented, NULL));
-}
-
-
-assuan_error_t
-assuan_command_parse_fd (assuan_context_t ctx, char *line, assuan_fd_t *rfd)
-{
- char *endp;
-
- if ((strncmp (line, "FD", 2) && strncmp (line, "fd", 2))
- || (line[2] != '=' && line[2] != '\0' && !spacep(&line[2])))
- return set_error (ctx, Syntax_Error, "FD[=<n>] expected");
- line += 2;
- if (*line == '=')
- {
- line ++;
- if (!digitp (*line))
- return set_error (ctx, Syntax_Error, "number required");
-#ifdef HAVE_W32_SYSTEM
- /* Fixme: For a W32/64bit system we will need to change the cast
- and the conversion fucntion. */
- *rfd = (void*)strtoul (line, &endp, 10);
-#else
- *rfd = strtoul (line, &endp, 10);
-#endif
- /* Remove that argument so that a notify handler won't see it. */
- memset (line, ' ', endp? (endp-line):strlen(line));
-
- if (*rfd == ctx->inbound.fd)
- return set_error (ctx, Parameter_Conflict, "fd same as inbound fd");
- if (*rfd == ctx->outbound.fd)
- return set_error (ctx, Parameter_Conflict, "fd same as outbound fd");
- return 0;
- }
- else
- /* Our peer has sent the file descriptor. */
- return assuan_receivefd (ctx, rfd);
-}
-
-
-/* Format is INPUT FD=<n> */
-static int
-std_handler_input (assuan_context_t ctx, char *line)
-{
- int rc;
- assuan_fd_t fd;
-
- rc = assuan_command_parse_fd (ctx, line, &fd);
- if (rc)
- return PROCESS_DONE (ctx, rc);
- ctx->input_fd = fd;
- if (ctx->input_notify_fnc)
- ctx->input_notify_fnc (ctx, line);
- return PROCESS_DONE (ctx, 0);
-}
-
-/* Format is OUTPUT FD=<n> */
-static int
-std_handler_output (assuan_context_t ctx, char *line)
-{
- int rc;
- assuan_fd_t fd;
-
- rc = assuan_command_parse_fd (ctx, line, &fd);
- if (rc)
- return PROCESS_DONE (ctx, rc);
- ctx->output_fd = fd;
- if (ctx->output_notify_fnc)
- ctx->output_notify_fnc (ctx, line);
- return PROCESS_DONE (ctx, 0);
-}
-
-
-
-
-
-/* This is a table with the standard commands and handler for them.
- The table is used to initialize a new context and associate strings
- with default handlers */
-static struct {
- const char *name;
- int (*handler)(assuan_context_t, char *line);
- int always; /* always initialize this command */
-} std_cmd_table[] = {
- { "NOP", std_handler_nop, 1 },
- { "CANCEL", std_handler_cancel, 1 },
- { "OPTION", std_handler_option, 1 },
- { "BYE", std_handler_bye, 1 },
- { "AUTH", std_handler_auth, 1 },
- { "RESET", std_handler_reset, 1 },
- { "END", std_handler_end, 1 },
- { "HELP", std_handler_help, 1 },
-
- { "INPUT", std_handler_input, 0 },
- { "OUTPUT", std_handler_output, 0 },
- { "OPTION", std_handler_option, 1 },
- { NULL, NULL, 0 }
-};
-
-
-/**
- * assuan_register_command:
- * @ctx: the server context
- * @cmd_name: A string with the command name
- * @handler: The handler function to be called or NULL to use a default
- * handler.
- *
- * Register a handler to be used for a given command. Note that
- * several default handlers are already regsitered with a new context.
- * This function however allows to override them.
- *
- * Return value: 0 on success or an error code
- **/
-int
-assuan_register_command (assuan_context_t ctx,
- const char *cmd_name,
- int (*handler)(assuan_context_t, char *))
-{
- int i;
- const char *s;
-
- if (cmd_name && !*cmd_name)
- cmd_name = NULL;
-
- if (!cmd_name)
- return _assuan_error (ASSUAN_Invalid_Value);
-
- if (!handler)
- { /* find a default handler. */
- for (i=0; (s=std_cmd_table[i].name) && strcmp (cmd_name, s); i++)
- ;
- if (!s)
- { /* Try again but case insensitive. */
- for (i=0; (s=std_cmd_table[i].name)
- && my_strcasecmp (cmd_name, s); i++)
- ;
- }
- if (s)
- handler = std_cmd_table[i].handler;
- if (!handler)
- handler = dummy_handler; /* Last resort is the dummy handler. */
- }
-
- if (!ctx->cmdtbl)
- {
- ctx->cmdtbl_size = 50;
- ctx->cmdtbl = xtrycalloc ( ctx->cmdtbl_size, sizeof *ctx->cmdtbl);
- if (!ctx->cmdtbl)
- return _assuan_error (ASSUAN_Out_Of_Core);
- ctx->cmdtbl_used = 0;
- }
- else if (ctx->cmdtbl_used >= ctx->cmdtbl_size)
- {
- struct cmdtbl_s *x;
-
- x = xtryrealloc ( ctx->cmdtbl, (ctx->cmdtbl_size+10) * sizeof *x);
- if (!x)
- return _assuan_error (ASSUAN_Out_Of_Core);
- ctx->cmdtbl = x;
- ctx->cmdtbl_size += 50;
- }
-
- ctx->cmdtbl[ctx->cmdtbl_used].name = cmd_name;
- ctx->cmdtbl[ctx->cmdtbl_used].handler = handler;
- ctx->cmdtbl_used++;
- return 0;
-}
-
-int
-assuan_register_post_cmd_notify (assuan_context_t ctx,
- void (*fnc)(assuan_context_t, int))
-{
- if (!ctx)
- return _assuan_error (ASSUAN_Invalid_Value);
- ctx->post_cmd_notify_fnc = fnc;
- return 0;
-}
-
-int
-assuan_register_bye_notify (assuan_context_t ctx,
- void (*fnc)(assuan_context_t))
-{
- if (!ctx)
- return _assuan_error (ASSUAN_Invalid_Value);
- ctx->bye_notify_fnc = fnc;
- return 0;
-}
-
-int
-assuan_register_reset_notify (assuan_context_t ctx,
- void (*fnc)(assuan_context_t))
-{
- if (!ctx)
- return _assuan_error (ASSUAN_Invalid_Value);
- ctx->reset_notify_fnc = fnc;
- return 0;
-}
-
-int
-assuan_register_cancel_notify (assuan_context_t ctx,
- void (*fnc)(assuan_context_t))
-{
- if (!ctx)
- return _assuan_error (ASSUAN_Invalid_Value);
- ctx->cancel_notify_fnc = fnc;
- return 0;
-}
-
-int
-assuan_register_option_handler (assuan_context_t ctx,
- int (*fnc)(assuan_context_t,
- const char*, const char*))
-{
- if (!ctx)
- return _assuan_error (ASSUAN_Invalid_Value);
- ctx->option_handler_fnc = fnc;
- return 0;
-}
-
-int
-assuan_register_input_notify (assuan_context_t ctx,
- void (*fnc)(assuan_context_t, const char *))
-{
- if (!ctx)
- return _assuan_error (ASSUAN_Invalid_Value);
- ctx->input_notify_fnc = fnc;
- return 0;
-}
-
-int
-assuan_register_output_notify (assuan_context_t ctx,
- void (*fnc)(assuan_context_t, const char *))
-{
- if (!ctx)
- return _assuan_error (ASSUAN_Invalid_Value);
- ctx->output_notify_fnc = fnc;
- return 0;
-}
-
-
-/* Helper to register the standards commands */
-int
-_assuan_register_std_commands (assuan_context_t ctx)
-{
- int i, rc;
-
- for (i=0; std_cmd_table[i].name; i++)
- {
- if (std_cmd_table[i].always)
- {
- rc = assuan_register_command (ctx, std_cmd_table[i].name, NULL);
- if (rc)
- return rc;
- }
- }
- return 0;
-}
-
-
-
-/* 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_t ctx, char *line, int linelen)
-{
- return set_error (ctx, Not_Implemented, NULL);
-}
-
-/* like ascii_strcasecmp but assume that B is already uppercase */
-static int
-my_strcasecmp (const char *a, const char *b)
-{
- if (a == b)
- return 0;
-
- for (; *a && *b; a++, b++)
- {
- if (((*a >= 'a' && *a <= 'z')? (*a&~0x20):*a) != *b)
- break;
- }
- return *a == *b? 0 : (((*a >= 'a' && *a <= 'z')? (*a&~0x20):*a) - *b);
-}
-
-
-/* Parse the line, break out the command, find it in the command
- 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_t ctx, char *line, int linelen)
-{
- char *p;
- const char *s;
- int shift, i;
-
- /* Note that as this function is invoked by assuan_process_next as
- well, we need to hide non-critical errors with PROCESS_DONE. */
-
- if (*line == 'D' && line[1] == ' ') /* divert to special handler */
- /* FIXME: Depending on the final implementation of
- handle_data_line, this may be wrong here. For example, if a
- user callback is invoked, and that callback is responsible for
- calling assuan_process_done, then this is wrong. */
- return PROCESS_DONE (ctx, handle_data_line (ctx, line+2, linelen-2));
-
- for (p=line; *p && *p != ' ' && *p != '\t'; p++)
- ;
- if (p==line)
- return PROCESS_DONE
- (ctx, set_error (ctx, Syntax_Error, "leading white-space"));
- if (*p)
- { /* Skip over leading WS after the keyword */
- *p++ = 0;
- while ( *p == ' ' || *p == '\t')
- p++;
- }
- shift = p - line;
-
- for (i=0; (s=ctx->cmdtbl[i].name); i++)
- {
- if (!strcmp (line, s))
- break;
- }
- if (!s)
- { /* and try case insensitive */
- for (i=0; (s=ctx->cmdtbl[i].name); i++)
- {
- if (!my_strcasecmp (line, s))
- break;
- }
- }
- if (!s)
- return PROCESS_DONE (ctx, set_error (ctx, Unknown_Command, NULL));
- line += shift;
- linelen -= shift;
-
-/* fprintf (stderr, "DBG-assuan: processing %s `%s'\n", s, line); */
- return ctx->cmdtbl[i].handler (ctx, line);
-}
-
-
-/* Call this to acknowledge the current command. */
-int
-assuan_process_done (assuan_context_t ctx, int rc)
-{
- if (!ctx->in_command)
- return _assuan_error (ASSUAN_General_Error);
-
- ctx->in_command = 0;
-
- /* Check for data write errors. */
- if (ctx->outbound.data.fp)
- {
- /* Flush the data lines. */
- fclose (ctx->outbound.data.fp);
- ctx->outbound.data.fp = NULL;
- if (!rc && ctx->outbound.data.error)
- rc = ctx->outbound.data.error;
- }
- else
- {
- /* Flush any data send without using the data FP. */
- assuan_send_data (ctx, NULL, 0);
- if (!rc && ctx->outbound.data.error)
- rc = ctx->outbound.data.error;
- }
-
- /* Error handling. */
- if (!rc)
- {
- rc = assuan_write_line (ctx, ctx->okay_line? ctx->okay_line : "OK");
- }
- else if (err_is_eof (rc))
- { /* No error checking because the peer may have already disconnect. */
- assuan_write_line (ctx, "OK closing connection");
- ctx->finish_handler (ctx);
- }
- else
- {
- char errline[300];
-
- if (rc < 100)
- sprintf (errline, "ERR %d server fault (%.50s)",
- _assuan_error (ASSUAN_Server_Fault), assuan_strerror (rc));
- else
- {
- const char *text = ctx->err_no == rc? ctx->err_str:NULL;
-
-#if defined(HAVE_W32_SYSTEM)
- unsigned int source, code;
- char ebuf[50];
- const char *esrc;
-
- source = ((rc >> 24) & 0xff);
- code = (rc & 0x00ffffff);
- if (source
- && !_assuan_gpg_strerror_r (rc, ebuf, sizeof ebuf)
- && (esrc=_assuan_gpg_strsource (rc)))
- {
- /* Assume this is an libgpg-error. */
- sprintf (errline, "ERR %d %.50s <%.30s>%s%.100s",
- rc, ebuf, esrc,
- text? " - ":"", text?text:"");
- }
- else
-#elif defined(__GNUC__) && defined(__ELF__)
- /* If we have weak symbol support we try to use the error
- strings from libgpg-error without creating a dependency.
- They are used for debugging purposes only, so there is no
- problem if they are not available. We need to make sure
- that we are using ELF because only this guarantees that
- weak symbol support is available in case GNU ld is not
- used. It seems that old gcc versions don't implement the
- weak attribute properly but it works with the weak
- pragma. */
-
- unsigned int source, code;
-
- int gpg_strerror_r (unsigned int err, char *buf, size_t buflen)
- __attribute__ ((weak));
- const char *gpg_strsource (unsigned int err)
- __attribute__ ((weak));
-#if __GNUC__ < 3
-#pragma weak gpg_strerror_r
-#pragma weak gpg_strsource
-#endif
-
- source = ((rc >> 24) & 0xff);
- code = (rc & 0x00ffffff);
- if (source && gpg_strsource && gpg_strerror_r)
- {
- /* Assume this is an libgpg-error. */
- char ebuf[50];
-
- gpg_strerror_r (rc, ebuf, sizeof ebuf );
- sprintf (errline, "ERR %d %.50s <%.30s>%s%.100s",
- rc,
- ebuf,
- gpg_strsource (rc),
- text? " - ":"", text?text:"");
- }
- else
-#endif /* __GNUC__ && __ELF__ */
- sprintf (errline, "ERR %d %.50s%s%.100s",
- rc, assuan_strerror (rc), text? " - ":"", text?text:"");
- }
- rc = assuan_write_line (ctx, errline);
- }
-
- if (ctx->post_cmd_notify_fnc)
- ctx->post_cmd_notify_fnc (ctx, rc);
-
- ctx->confidential = 0;
- if (ctx->okay_line)
- {
- xfree (ctx->okay_line);
- ctx->okay_line = NULL;
- }
-
- return rc;
-}
-
-
-static int
-process_next (assuan_context_t ctx)
-{
- int rc;
-
- /* What the next thing to do is depends on the current state.
- However, we will always first read the next line. The client is
- required to write full lines without blocking long after starting
- a partial line. */
- rc = _assuan_read_line (ctx);
- if (rc)
- return rc;
- if (*ctx->inbound.line == '#' || !ctx->inbound.linelen)
- /* Comment lines are ignored. */
- return 0;
-
- /* Now we have a line that really means something. It could be one
- of the following things: First, if we are not in a command
- already, it is the next command to dispatch. Second, if we are
- in a command, it can only be the response to an INQUIRE
- reply. */
-
- if (!ctx->in_command)
- {
- ctx->in_command = 1;
-
- ctx->outbound.data.error = 0;
- ctx->outbound.data.linelen = 0;
- /* Dispatch command and return reply. */
- ctx->in_process_next = 1;
- rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen);
- ctx->in_process_next = 0;
- }
- else if (ctx->in_inquire)
- {
- /* FIXME: Pick up the continuation. */
- rc = _assuan_inquire_ext_cb (ctx);
- }
- else
- {
- /* Should not happen. The client is sending data while we are
- in a command and not waiting for an inquire. We log an error
- and discard it. */
- _assuan_log_printf ("unexpected client data\n");
- rc = 0;
- }
-
- return rc;
-}
-
-
-/* This function should be invoked when the assuan connected FD is
- ready for reading. If the equivalent to EWOULDBLOCK is returned
- (this should be done by the command handler), assuan_process_next
- should be invoked the next time the connected FD is readable.
- Eventually, the caller will finish by invoking
- assuan_process_done. */
-int
-assuan_process_next (assuan_context_t ctx)
-{
- int rc;
-
- do
- {
- rc = process_next (ctx);
- }
- while (!rc && assuan_pending_line (ctx));
-
- return rc;
-}
-
-
-
-static int
-process_request (assuan_context_t ctx)
-{
- int rc;
-
- if (ctx->in_inquire)
- return _assuan_error (ASSUAN_Nested_Commands);
-
- do
- {
- rc = _assuan_read_line (ctx);
- }
- while (_assuan_error_is_eagain (rc));
- if (rc)
- return rc;
- if (*ctx->inbound.line == '#' || !ctx->inbound.linelen)
- return 0; /* comment line - ignore */
-
- ctx->in_command = 1;
- ctx->outbound.data.error = 0;
- ctx->outbound.data.linelen = 0;
- /* dispatch command and return reply */
- rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen);
-
- return assuan_process_done (ctx, rc);
-}
-
-/**
- * assuan_process:
- * @ctx: assuan context
- *
- * This function is used to handle the assuan protocol after a
- * connection has been established using assuan_accept(). This is the
- * main protocol handler.
- *
- * Return value: 0 on success or an error code if the assuan operation
- * failed. Note, that no error is returned for operational errors.
- **/
-int
-assuan_process (assuan_context_t ctx)
-{
- int rc;
-
- do {
- rc = process_request (ctx);
- } while (!rc);
-
- if (err_is_eof (rc))
- rc = 0;
-
- return rc;
-}
-
-
-/**
- * assuan_get_active_fds:
- * @ctx: Assuan context
- * @what: 0 for read fds, 1 for write fds
- * @fdarray: Caller supplied array to store the FDs
- * @fdarraysize: size of that array
- *
- * Return all active filedescriptors for the given context. This
- * function can be used to select on the fds and call
- * assuan_process_next() if there is an active one. The first fd in
- * the array is the one used for the command connection.
- *
- * Note, that write FDs are not yet supported.
- *
- * Return value: number of FDs active and put into @fdarray or -1 on
- * error which is most likely a too small fdarray.
- **/
-int
-assuan_get_active_fds (assuan_context_t ctx, int what,
- assuan_fd_t *fdarray, int fdarraysize)
-{
- int n = 0;
-
- if (!ctx || fdarraysize < 2 || what < 0 || what > 1)
- return -1;
-
- if (!what)
- {
- if (ctx->inbound.fd != ASSUAN_INVALID_FD)
- fdarray[n++] = ctx->inbound.fd;
- }
- else
- {
- if (ctx->outbound.fd != ASSUAN_INVALID_FD)
- fdarray[n++] = ctx->outbound.fd;
- if (ctx->outbound.data.fp)
-#ifdef HAVE_W32_SYSTEM
- fdarray[n++] = (void*)_get_osfhandle (fileno (ctx->outbound.data.fp));
-#else
- fdarray[n++] = fileno (ctx->outbound.data.fp);
-#endif
- }
-
- return n;
-}
-
-
-/* Two simple wrappers to make the expected function types match. */
-#ifdef HAVE_FUNOPEN
-static int
-fun1_cookie_write (void *cookie, const char *buffer, int orig_size)
-{
- return _assuan_cookie_write_data (cookie, buffer, orig_size);
-}
-#endif /*HAVE_FUNOPEN*/
-#ifdef HAVE_FOPENCOOKIE
-static ssize_t
-fun2_cookie_write (void *cookie, const char *buffer, size_t orig_size)
-{
- return _assuan_cookie_write_data (cookie, buffer, orig_size);
-}
-#endif /*HAVE_FOPENCOOKIE*/
-
-/* Return a FP to be used for data output. The FILE pointer is valid
- until the end of a handler. So a close is not needed. Assuan does
- all the buffering needed to insert the status line as well as the
- required line wappping and quoting for data lines.
-
- We use GNU's custom streams here. There should be an alternative
- implementaion for systems w/o a glibc, a simple implementation
- could use a child process */
-FILE *
-assuan_get_data_fp (assuan_context_t ctx)
-{
-#if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN)
- if (ctx->outbound.data.fp)
- return ctx->outbound.data.fp;
-
-#ifdef HAVE_FUNOPEN
- ctx->outbound.data.fp = funopen (ctx, 0, fun1_cookie_write,
- 0, _assuan_cookie_write_flush);
-#else
- ctx->outbound.data.fp = funopen (ctx, 0, fun2_cookie_write,
- 0, _assuan_cookie_write_flush);
-#endif
-
- ctx->outbound.data.error = 0;
- return ctx->outbound.data.fp;
-#else
- errno = ENOSYS;
- return NULL;
-#endif
-}
-
-
-/* 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_t ctx, const char *line)
-{
- if (!ctx)
- return _assuan_error (ASSUAN_Invalid_Value);
- if (!line)
- {
- xfree (ctx->okay_line);
- ctx->okay_line = NULL;
- }
- else
- {
- /* FIXME: we need to use gcry_is_secure() to test whether
- we should allocate the entire line in secure memory */
- char *buf = xtrymalloc (3+strlen(line)+1);
- if (!buf)
- return _assuan_error (ASSUAN_Out_Of_Core);
- strcpy (buf, "OK ");
- strcpy (buf+3, line);
- xfree (ctx->okay_line);
- ctx->okay_line = buf;
- }
- return 0;
-}
-
-
-
-assuan_error_t
-assuan_write_status (assuan_context_t ctx,
- const char *keyword, const char *text)
-{
- char buffer[256];
- char *helpbuf;
- size_t n;
- assuan_error_t ae;
-
- if ( !ctx || !keyword)
- return _assuan_error (ASSUAN_Invalid_Value);
- if (!text)
- text = "";
-
- n = 2 + strlen (keyword) + 1 + strlen (text) + 1;
- if (n < sizeof (buffer))
- {
- strcpy (buffer, "S ");
- strcat (buffer, keyword);
- if (*text)
- {
- strcat (buffer, " ");
- strcat (buffer, text);
- }
- ae = assuan_write_line (ctx, buffer);
- }
- else if ( (helpbuf = xtrymalloc (n)) )
- {
- strcpy (helpbuf, "S ");
- strcat (helpbuf, keyword);
- if (*text)
- {
- strcat (helpbuf, " ");
- strcat (helpbuf, text);
- }
- ae = assuan_write_line (ctx, helpbuf);
- xfree (helpbuf);
- }
- else
- ae = 0;
- return ae;
-}