diff options
Diffstat (limited to 'branches/gpgme-0-3-branch/assuan')
17 files changed, 3401 insertions, 0 deletions
diff --git a/branches/gpgme-0-3-branch/assuan/ChangeLog b/branches/gpgme-0-3-branch/assuan/ChangeLog new file mode 100644 index 00000000..0cf53b89 --- /dev/null +++ b/branches/gpgme-0-3-branch/assuan/ChangeLog @@ -0,0 +1,221 @@ +2002-05-03 Werner Koch <[email protected]> + + * assuan-pipe-connect.c (assuan_pipe_connect2): New to extend + assuan_pipe_connect with some flags. Implemented a bitbucket for + stderr. + +2002-04-26 Werner Koch <[email protected]> + + * Makefile.am: Create libtool libraries + +2002-04-04 Werner Koch <[email protected]> + + * assuan-buffer.c (my_log_prefix): New. Use it for all i/o debug + output. + +2002-03-06 Werner Koch <[email protected]> + + * assuan-client.c (_assuan_read_from_server): Detect END. + (assuan_transact): Pass it to the data callback. + +2002-02-27 Werner Koch <[email protected]> + + * assuan-client.c (assuan_transact): Add 2 more arguments to + support status lines. Passing NULL yields the old behaviour. + + * assuan-handler.c (process_request): Flush data lines send + without using the data fp. + +2002-02-14 Werner Koch <[email protected]> + + * assuan-inquire.c (assuan_inquire): Check for a cancel command + and return ASSUAN_Canceled. Allow for non-data inquiry. + + * assuan.h: Add a few token specific error codes. + +2002-02-13 Werner Koch <[email protected]> + + * assuan-defs.h (assuan_context_s): New var CLIENT_PID. + * assuan-pipe-server.c (_assuan_new_context): set default value. + * assuan-socket-server.c (accept_connection): get the actual pid. + +2002-02-12 Werner Koch <[email protected]> + + * assuan-buffer.c (writen,readline) [USE_GNU_PT]: Use pth_read/write. + * assuan-socket-server.c (accept_connection) [USE_GNU_PTH]: Ditto. + +2002-02-01 Marcus Brinkmann <[email protected]> + + * Makefile.am (MOSTLYCLEANFILES): New variable. + +2002-01-23 Werner Koch <[email protected]> + + * assuan-socket-connect.c (LOGERRORX): and removed typo. + +2002-01-22 Marcus Brinkmann <[email protected]> + + * assuan-socket-connect.c (LOGERRORX): Reverse arguments to fputs. + +2002-01-21 Werner Koch <[email protected]> + + * assuan-connect.c: Move all except assuan_get_pid to... + * assuan-pipe-connect.c: this. + (assuan_pipe_disconnect): Removed. + (do_finish, do_deinit): New + (assuan_pipe_connect): and set them into the context. + * assuan-socket-connect.c: New. + + * assuan-util.c (_assuan_log_sanitized_string): New. + + * assuan-pipe-server.c (assuan_init_pipe_server): Factored most + code out to ... + (_assuan_new_context): new func. + (_assuan_release_context): New + * assuan-connect.c (assuan_pipe_connect): Use the new functions. + +2002-01-20 Werner Koch <[email protected]> + + * assuan.h: Added Invalid Option error code. + + * assuan-handler.c (std_handler_option): New. + (std_cmd_tbl): Add OPTION as standard command. + (assuan_register_option_handler): New. + (dispatch_command): Use case insensitive matching as a fallback. + (my_strcasecmp): New. + +2002-01-19 Werner Koch <[email protected]> + + * assuan-buffer.c (_assuan_read_line): Add output logging. + (assuan_write_line): Ditto. + (_assuan_cookie_write_data): Ditto. + (_assuan_cookie_write_flush): Ditto. + * assuan-util.c (_assuan_log_print_buffer): New. + (assuan_set_log_stream): New. + (assuan_begin_confidential): New. + (assuan_end_confidential): New. + + * assuan-defs.h: Add a few handler variables. + * assuan-pipe-server.c (assuan_deinit_pipe_server): Removed. + (deinit_pipe_server): New. + (assuan_deinit_server): New. Changed all callers to use this. + * assuan-listen.c (assuan_accept): Use the accept handler. + * assuan-handler.c (process_request): Use the close Handler. + * assuan-socket-server.c: New. + +2002-01-14 Werner Koch <[email protected]> + + * assuan-client.c (_assuan_read_from_server): Skip spaces after + the keyword. + +2002-01-03 Werner Koch <[email protected]> + + * assuan-handler.c (assuan_set_okay_line): New. + (process_request): And use it here. + +2002-01-02 Werner Koch <[email protected]> + + * assuan-inquire.c (init_membuf,put_membuf,get_membuf): Apply a + hidden 0 behind the buffer so that the buffer can be used as a + string in certain contexts. + +2001-12-14 Marcus Brinkmann <[email protected]> + + * assuan-connect.c (assuan_pipe_connect): New argument + FD_CHILD_LIST. Don't close those fds. + * assuan.h: Likewise for prototype. + +2001-12-14 Werner Koch <[email protected]> + + * assuan-listen.c (assuan_close_input_fd): New. + (assuan_close_output_fd): New. + * assuan-handler.c (std_handler_reset): Always close them after a + reset command. + (std_handler_bye): Likewise. + +2001-12-14 Marcus Brinkmann <[email protected]> + + * assuan-buffer.c (_assuan_read_line): New variable ATTICLEN, use + it to save the length of the attic line. + Rediddle the code a bit to make it more clear what happens. + +2001-12-14 Marcus Brinkmann <[email protected]> + + * assuan-defs.h (LINELENGTH): Define as ASSUAN_LINELENGTH. + assuan.h: Define ASSUAN_LINELENGTH. + +2001-12-13 Marcus Brinkmann <[email protected]> + + * assuan-buffer.c (assuan_read_line): Fix order of execution to + get correct return values. + +2001-12-13 Werner Koch <[email protected]> + + * assuan-handler.c (assuan_get_active_fds): Fixed silly bug, + pretty obvious that nobody ever tested this function. + +2001-12-12 Werner Koch <[email protected]> + + * assuan-connect.c (assuan_pipe_connect): Implemented the inital + handshake. + * assuan-client.c (read_from_server): Renamed to + (_assuan_read_from_server): this and made external. + + * assuan-listen.c (assuan_set_hello_line): New. + (assuan_accept): Use a custom hello line is available. + + * assuan-buffer.c (assuan_read_line): New. + (assuan_pending_line): New. + (_assuan_write_line): Renamed to .. + (assuan_write_line): this, made public and changed all callers. + +2001-12-04 Werner Koch <[email protected]> + + * assuan-connect.c (assuan_pipe_connect): Add more error reporting. + * assuan-client.c: New. + + * assuan-inquire.c: New. + * assuan-handler.c (process_request): Check for nested invocations. + +2001-11-27 Werner Koch <[email protected]> + + * assuan-handler.c (assuan_register_input_notify): New. + (assuan_register_output_notify): New. + +2001-11-26 Werner Koch <[email protected]> + + * assuan.h: Added more status codes. + +2001-11-25 Werner Koch <[email protected]> + + * assuan-handler.c (assuan_register_bye_notify) + (assuan_register_reset_notify) + (assuan_register_cancel_notify): New and call them from the + standard handlers. + (assuan_process): Moved bulk of function to .. + (process_request): .. new. + (assuan_process_next): One shot version of above. + (assuan_get_active_fds): New. + +2001-11-24 Werner Koch <[email protected]> + + * assuan-connect.c (assuan_get_pid): New. + + * assuan-buffer.c (_assuan_read_line): Deal with reads of more + than a line. + * assuan-defs.h: Add space in the context for this. + + + *********************************************************** + * Please note that Assuan is maintained as part of GnuPG. * + * You may find it source-copied in other packages. * + *********************************************************** + + Copyright 2001, 2002 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/branches/gpgme-0-3-branch/assuan/Makefile.am b/branches/gpgme-0-3-branch/assuan/Makefile.am new file mode 100644 index 00000000..8d11e15a --- /dev/null +++ b/branches/gpgme-0-3-branch/assuan/Makefile.am @@ -0,0 +1,49 @@ +# Assuan Makefile for test purposes +# Copyright (C) 2001 Free Software Foundation, Inc. +# +# This file is part of GnuPG. +# +# GnuPG is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# GnuPG 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +## Process this file with automake to produce Makefile.in + +EXTRA_DIST = mkerrors +INCLUDES = -I.. -I$(top_srcdir)/include +BUILT_SOURCES = assuan-errors.c +MOSTLYCLEANFILES = assuan-errors.c + +noinst_LTLIBRARIES = libassuan.la + + +#libassuan_a_LDFLAGS = +libassuan_la_SOURCES = \ + assuan.h \ + assuan-defs.h \ + assuan-util.c \ + assuan-errors.c \ + assuan-buffer.c \ + assuan-handler.c \ + assuan-inquire.c \ + assuan-listen.c \ + assuan-connect.c \ + assuan-client.c \ + assuan-pipe-server.c \ + assuan-socket-server.c \ + assuan-pipe-connect.c \ + assuan-socket-connect.c + + +assuan-errors.c : assuan.h + $(srcdir)/mkerrors < $(srcdir)/assuan.h > assuan-errors.c diff --git a/branches/gpgme-0-3-branch/assuan/README.1st b/branches/gpgme-0-3-branch/assuan/README.1st new file mode 100644 index 00000000..bb52959c --- /dev/null +++ b/branches/gpgme-0-3-branch/assuan/README.1st @@ -0,0 +1 @@ +Please don't modify it here but in the copy which comes with GnuPG.
\ No newline at end of file diff --git a/branches/gpgme-0-3-branch/assuan/assuan-buffer.c b/branches/gpgme-0-3-branch/assuan/assuan-buffer.c new file mode 100644 index 00000000..29f94794 --- /dev/null +++ b/branches/gpgme-0-3-branch/assuan/assuan-buffer.c @@ -0,0 +1,441 @@ +/* assuan-buffer.c - read and send data + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <assert.h> +#ifdef USE_GNU_PTH +# include <pth.h> +#endif +#include "assuan-defs.h" + +#ifdef HAVE_JNLIB_LOGGING +#include "../jnlib/logging.h" +#endif + + +static const char * +my_log_prefix (void) +{ +#ifdef HAVE_JNLIB_LOGGING + return log_get_prefix (NULL); +#else + return ""; +#endif +} + + +static int +writen ( int fd, const char *buffer, size_t length ) +{ + while (length) + { +#ifdef USE_GNU_PTH + int nwritten = pth_write (fd, buffer, length); +#else + int nwritten = write (fd, buffer, length); +#endif + + if (nwritten < 0) + { + if (errno == EINTR) + continue; + return -1; /* write error */ + } + length -= nwritten; + buffer += nwritten; + } + return 0; /* okay */ +} + +/* read an entire line */ +static int +readline (int fd, char *buf, size_t buflen, int *r_nread, int *eof) +{ + size_t nleft = buflen; + char *p; + + *eof = 0; + *r_nread = 0; + while (nleft > 0) + { +#ifdef USE_GNU_PTH + int n = pth_read (fd, buf, nleft); +#else + int n = read (fd, buf, nleft); +#endif + if (n < 0) + { + if (errno == EINTR) + continue; + return -1; /* read error */ + } + else if (!n) + { + *eof = 1; + break; /* allow incomplete lines */ + } + p = buf; + nleft -= n; + buf += n; + *r_nread += n; + + for (; n && *p != '\n'; n--, p++) + ; + if (n) + break; /* at least one full line available - that's enough for now */ + } + + return 0; +} + + +int +_assuan_read_line (ASSUAN_CONTEXT ctx) +{ + char *line = ctx->inbound.line; + int n, nread, atticlen; + int rc; + + if (ctx->inbound.eof) + return -1; + + atticlen = ctx->inbound.attic.linelen; + if (atticlen) + { + memcpy (line, ctx->inbound.attic.line, atticlen); + ctx->inbound.attic.linelen = 0; + for (n=0; n < atticlen && line[n] != '\n'; n++) + ; + if (n < atticlen) + { + rc = 0; /* found another line in the attic */ + nread = atticlen; + atticlen = 0; + } + else + { /* read the rest */ + assert (atticlen < LINELENGTH); + rc = readline (ctx->inbound.fd, line + atticlen, + LINELENGTH - atticlen, &nread, &ctx->inbound.eof); + } + } + else + rc = readline (ctx->inbound.fd, line, LINELENGTH, + &nread, &ctx->inbound.eof); + if (rc) + { + if (ctx->log_fp) + fprintf (ctx->log_fp, "%s[%p] <- [Error: %s]\n", + my_log_prefix (), ctx, strerror (errno)); + return ASSUAN_Read_Error; + } + if (!nread) + { + assert (ctx->inbound.eof); + if (ctx->log_fp) + fprintf (ctx->log_fp, "%s[%p] <- [EOF]\n", my_log_prefix (),ctx); + return -1; + } + + ctx->inbound.attic.pending = 0; + nread += atticlen; + for (n=0; n < nread; n++) + { + if (line[n] == '\n') + { + if (n+1 < nread) + { + char *s, *d; + int i; + + n++; + /* we have to copy the rest because the handlers are + allowed to modify the passed buffer */ + for (d=ctx->inbound.attic.line, s=line+n, i=nread-n; i; i--) + { + if (*s=='\n') + ctx->inbound.attic.pending = 1; + *d++ = *s++; + } + ctx->inbound.attic.linelen = nread-n; + n--; + } + if (n && line[n-1] == '\r') + n--; + line[n] = 0; + ctx->inbound.linelen = n; + if (ctx->log_fp) + { + fprintf (ctx->log_fp, "%s[%p] <- ", my_log_prefix (), ctx); + if (ctx->confidential) + fputs ("[Confidential data not shown]", ctx->log_fp); + else + _assuan_log_print_buffer (ctx->log_fp, + ctx->inbound.line, + ctx->inbound.linelen); + putc ('\n', ctx->log_fp); + } + return 0; + } + } + + if (ctx->log_fp) + fprintf (ctx->log_fp, "%s[%p] <- [Invalid line]\n", my_log_prefix (), ctx); + *line = 0; + ctx->inbound.linelen = 0; + return ctx->inbound.eof? ASSUAN_Line_Not_Terminated : ASSUAN_Line_Too_Long; +} + + +/* Read the next line from the client or server and return a pointer + to a buffer with holding that line. linelen returns the length of + the line. This buffer is valid until another read operation is + done on this buffer. The caller is allowed to modify this buffer. + He should only use the buffer if the function returns without an + error. + + Returns: 0 on success or an assuan error code + See also: assuan_pending_line(). +*/ +AssuanError +assuan_read_line (ASSUAN_CONTEXT ctx, char **line, size_t *linelen) +{ + AssuanError err; + + if (!ctx) + return ASSUAN_Invalid_Value; + + err = _assuan_read_line (ctx); + *line = ctx->inbound.line; + *linelen = ctx->inbound.linelen; + return err; +} + + +/* Return true when a full line is pending for a read, without the need + for actual IO */ +int +assuan_pending_line (ASSUAN_CONTEXT ctx) +{ + return ctx && ctx->inbound.attic.pending; +} + + +AssuanError +assuan_write_line (ASSUAN_CONTEXT ctx, const char *line ) +{ + int rc; + + if (!ctx) + return ASSUAN_Invalid_Value; + + /* fixme: we should do some kind of line buffering */ + if (ctx->log_fp) + { + fprintf (ctx->log_fp, "%s[%p] -> ", my_log_prefix (), ctx); + if (ctx->confidential) + fputs ("[Confidential data not shown]", ctx->log_fp); + else + _assuan_log_print_buffer (ctx->log_fp, + line, strlen (line)); + putc ('\n', ctx->log_fp); + } + + rc = writen (ctx->outbound.fd, line, strlen(line)); + if (rc) + rc = ASSUAN_Write_Error; + if (!rc) + { + rc = writen (ctx->outbound.fd, "\n", 1); + if (rc) + rc = ASSUAN_Write_Error; + } + + return rc; +} + + + +/* Write out the data in buffer as datalines with line wrapping and + percent escaping. This fucntion is used for GNU's custom streams */ +int +_assuan_cookie_write_data (void *cookie, const char *buffer, size_t size) +{ + ASSUAN_CONTEXT ctx = cookie; + char *line; + size_t linelen; + + if (ctx->outbound.data.error) + return 0; + + line = ctx->outbound.data.line; + linelen = ctx->outbound.data.linelen; + line += linelen; + while (size) + { + /* insert data line header */ + if (!linelen) + { + *line++ = 'D'; + *line++ = ' '; + linelen += 2; + } + + /* copy data, keep some space for the CRLF and to escape one character */ + while (size && linelen < LINELENGTH-2-2) + { + if (*buffer == '%' || *buffer == '\r' || *buffer == '\n') + { + sprintf (line, "%%%02X", *(unsigned char*)buffer); + line += 3; + linelen += 3; + buffer++; + } + else + { + *line++ = *buffer++; + linelen++; + } + size--; + } + + if (linelen >= LINELENGTH-2-2) + { + if (ctx->log_fp) + { + fprintf (ctx->log_fp, "%s[%p] -> ", my_log_prefix (), ctx); + if (ctx->confidential) + fputs ("[Confidential data not shown]", ctx->log_fp); + else + _assuan_log_print_buffer (ctx->log_fp, + ctx->outbound.data.line, + linelen); + putc ('\n', ctx->log_fp); + } + *line++ = '\n'; + linelen++; + if (writen (ctx->outbound.fd, ctx->outbound.data.line, linelen)) + { + ctx->outbound.data.error = ASSUAN_Write_Error; + return 0; + } + line = ctx->outbound.data.line; + linelen = 0; + } + } + + ctx->outbound.data.linelen = linelen; + return 0; +} + + +/* Write out any buffered data + This fucntion is used for GNU's custom streams */ +int +_assuan_cookie_write_flush (void *cookie) +{ + ASSUAN_CONTEXT ctx = cookie; + char *line; + size_t linelen; + + if (ctx->outbound.data.error) + return 0; + + line = ctx->outbound.data.line; + linelen = ctx->outbound.data.linelen; + line += linelen; + if (linelen) + { + if (ctx->log_fp) + { + fprintf (ctx->log_fp, "%s[%p] -> ", my_log_prefix (), ctx); + if (ctx->confidential) + fputs ("[Confidential data not shown]", ctx->log_fp); + else + _assuan_log_print_buffer (ctx->log_fp, + ctx->outbound.data.line, + linelen); + putc ('\n', ctx->log_fp); + } + *line++ = '\n'; + linelen++; + if (writen (ctx->outbound.fd, ctx->outbound.data.line, linelen)) + { + ctx->outbound.data.error = ASSUAN_Write_Error; + return 0; + } + ctx->outbound.data.linelen = 0; + } + return 0; +} + + +/** + * assuan_send_data: + * @ctx: An assuan context + * @buffer: Data to send or NULL to flush + * @length: length of the data to send/ + * + * This function may be used by the server or the client to send data + * lines. The data will be escaped as required by the Assuan protocol + * and may get buffered until a line is full. To force sending the + * data out @buffer may be passed as NULL (in which case @length must + * also be 0); however when used by a client this flush operation does + * also send the terminating "END" command to terminate the reponse on + * a INQUIRE response. However, when assuan_transact() is used, this + * function takes care of sending END itself. + * + * Return value: 0 on success or an error code + **/ + +AssuanError +assuan_send_data (ASSUAN_CONTEXT ctx, const void *buffer, size_t length) +{ + if (!ctx) + return ASSUAN_Invalid_Value; + if (!buffer && length) + return ASSUAN_Invalid_Value; + + if (!buffer) + { /* flush what we have */ + _assuan_cookie_write_flush (ctx); + if (ctx->outbound.data.error) + return ctx->outbound.data.error; + if (!ctx->is_server) + return assuan_write_line (ctx, "END"); + } + else + { + _assuan_cookie_write_data (ctx, buffer, length); + if (ctx->outbound.data.error) + return ctx->outbound.data.error; + } + + return 0; +} + + + + diff --git a/branches/gpgme-0-3-branch/assuan/assuan-client.c b/branches/gpgme-0-3-branch/assuan/assuan-client.c new file mode 100644 index 00000000..6c7a6e3e --- /dev/null +++ b/branches/gpgme-0-3-branch/assuan/assuan-client.c @@ -0,0 +1,225 @@ +/* assuan-client.c - client functions + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <assert.h> + +#include "assuan-defs.h" + +#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ + *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) +#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) + + +AssuanError +_assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off) +{ + char *line; + int linelen; + AssuanError rc; + + *okay = 0; + *off = 0; + do + { + rc = _assuan_read_line (ctx); + if (rc) + return rc; + line = ctx->inbound.line; + linelen = ctx->inbound.linelen; + } + while (*line == '#' || !linelen); + + if (linelen >= 1 + && line[0] == 'D' && line[1] == ' ') + { + *okay = 2; /* data line */ + *off = 2; + } + else if (linelen >= 1 + && line[0] == 'S' + && (line[1] == '\0' || line[1] == ' ')) + { + *okay = 4; + *off = 1; + while (line[*off] == ' ') + ++*off; + } + else if (linelen >= 2 + && line[0] == 'O' && line[1] == 'K' + && (line[2] == '\0' || line[2] == ' ')) + { + *okay = 1; + *off = 2; + while (line[*off] == ' ') + ++*off; + } + else if (linelen >= 3 + && line[0] == 'E' && line[1] == 'R' && line[2] == 'R' + && (line[3] == '\0' || line[3] == ' ')) + { + *okay = 0; + *off = 3; + while (line[*off] == ' ') + ++*off; + } + else if (linelen >= 7 + && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q' + && line[3] == 'U' && line[4] == 'I' && line[5] == 'R' + && line[6] == 'E' + && (line[7] == '\0' || line[7] == ' ')) + { + *okay = 3; + *off = 7; + while (line[*off] == ' ') + ++*off; + } + else if (linelen >= 3 + && line[0] == 'E' && line[1] == 'N' && line[2] == 'D' + && (line[3] == '\0' || line[3] == ' ')) + { + *okay = 5; /* end line */ + *off = 3; + } + else + rc = ASSUAN_Invalid_Response; + return rc; +} + + + +/** + * assuan_transact: + * @ctx: The Assuan context + * @command: Coimmand line to be send to server + * @data_cb: Callback function for data lines + * @data_cb_arg: first argument passed to @data_cb + * @inquire_cb: Callback function for a inquire response + * @inquire_cb_arg: first argument passed to @inquire_cb + * @status_cb: Callback function for a status response + * @status_cb_arg: first argument passed to @status_cb + * + * FIXME: Write documentation + * + * Return value: 0 on success or error code. The error code may be + * the one one returned by the server in error lines or from the + * callback functions. + **/ +AssuanError +assuan_transact (ASSUAN_CONTEXT ctx, + const char *command, + AssuanError (*data_cb)(void *, const void *, size_t), + void *data_cb_arg, + AssuanError (*inquire_cb)(void*, const char *), + void *inquire_cb_arg, + AssuanError (*status_cb)(void*, const char *), + void *status_cb_arg) +{ + int rc, okay, off; + unsigned char *line; + int linelen; + + rc = assuan_write_line (ctx, command); + if (rc) + return rc; + + again: + rc = _assuan_read_from_server (ctx, &okay, &off); + if (rc) + return rc; /* error reading from server */ + + line = ctx->inbound.line + off; + linelen = ctx->inbound.linelen - off; + + if (!okay) + { + rc = atoi (line); + if (rc < 100) + rc = ASSUAN_Server_Fault; + } + else if (okay == 2) + { + if (!data_cb) + rc = ASSUAN_No_Data_Callback; + else + { + unsigned char *s, *d; + + for (s=d=line; linelen; linelen--) + { + if (*s == '%' && linelen > 2) + { /* handle escaping */ + s++; + *d++ = xtoi_2 (s); + s += 2; + linelen -= 2; + } + else + *d++ = *s++; + } + *d = 0; /* add a hidden string terminator */ + rc = data_cb (data_cb_arg, line, d - line); + if (!rc) + goto again; + } + } + else if (okay == 3) + { + if (!inquire_cb) + { + assuan_write_line (ctx, "END"); /* get out of inquire mode */ + _assuan_read_from_server (ctx, &okay, &off); /* dummy read */ + rc = ASSUAN_No_Inquire_Callback; + } + else + { + rc = inquire_cb (inquire_cb_arg, line); + if (!rc) + rc = assuan_send_data (ctx, NULL, 0); /* flush and send END */ + if (!rc) + goto again; + } + } + else if (okay == 4) + { + if (status_cb) + rc = status_cb (status_cb_arg, line); + if (!rc) + goto again; + } + else if (okay == 5) + { + if (!data_cb) + rc = ASSUAN_No_Data_Callback; + else + { + rc = data_cb (data_cb_arg, NULL, 0); + if (!rc) + goto again; + } + } + + return rc; +} + diff --git a/branches/gpgme-0-3-branch/assuan/assuan-connect.c b/branches/gpgme-0-3-branch/assuan/assuan-connect.c new file mode 100644 index 00000000..49d4aac2 --- /dev/null +++ b/branches/gpgme-0-3-branch/assuan/assuan-connect.c @@ -0,0 +1,54 @@ +/* assuan-connect.c - Establish a connection (client) + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * 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" + +/* Disconnect and release the context CTX. */ +void +assuan_disconnect (ASSUAN_CONTEXT ctx) +{ + if (ctx) + { + assuan_write_line (ctx, "BYE"); + ctx->finish_handler (ctx); + ctx->deinit_handler (ctx); + ctx->deinit_handler = NULL; + _assuan_release_context (ctx); + } +} + +pid_t +assuan_get_pid (ASSUAN_CONTEXT ctx) +{ + return ctx ? ctx->pid : -1; +} diff --git a/branches/gpgme-0-3-branch/assuan/assuan-defs.h b/branches/gpgme-0-3-branch/assuan/assuan-defs.h new file mode 100644 index 00000000..6c502bf9 --- /dev/null +++ b/branches/gpgme-0-3-branch/assuan/assuan-defs.h @@ -0,0 +1,139 @@ +/* assuan-defs.c - Internal definitions to Assuan + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifndef ASSUAN_DEFS_H +#define ASSUAN_DEFS_H + +#include <sys/types.h> +#include "assuan.h" + +#define LINELENGTH ASSUAN_LINELENGTH + +struct cmdtbl_s { + const char *name; + int cmd_id; + int (*handler)(ASSUAN_CONTEXT, char *line); +}; + +struct assuan_context_s { + AssuanError err_no; + const char *err_str; + int os_errno; /* last system error number used with certain error codes*/ + + int confidential; + int is_server; /* set if this is context belongs to a server */ + int in_inquire; + char *hello_line; + char *okay_line; /* see assan_set_okay_line() */ + + void *user_pointer; /* for assuan_[gs]et_pointer () */ + + FILE *log_fp; + + struct { + int fd; + int eof; + char line[LINELENGTH]; + int linelen; /* w/o CR, LF - might not be the same as + strlen(line) due to embedded nuls. However a nul + is always written at this pos */ + struct { + char line[LINELENGTH]; + int linelen ; + int pending; /* i.e. at least one line is available in the attic */ + } attic; + } inbound; + + struct { + int fd; + struct { + FILE *fp; + char line[LINELENGTH]; + int linelen; + int error; + } data; + } outbound; + + int pipe_mode; /* We are in pipe mode, i.e. we can handle just one + connection and must terminate then */ + pid_t pid; /* In pipe mode, the pid of the child server process. + In socket mode, the pid of the server */ + int listen_fd; /* The fd we are listening on (used by socket servers) */ + + pid_t client_pid; /* for a socket server the PID of the client or -1 + if not available */ + + void (*deinit_handler)(ASSUAN_CONTEXT); + int (*accept_handler)(ASSUAN_CONTEXT); + int (*finish_handler)(ASSUAN_CONTEXT); + + struct cmdtbl_s *cmdtbl; + size_t cmdtbl_used; /* used entries */ + size_t cmdtbl_size; /* allocated size of table */ + + void (*bye_notify_fnc)(ASSUAN_CONTEXT); + void (*reset_notify_fnc)(ASSUAN_CONTEXT); + void (*cancel_notify_fnc)(ASSUAN_CONTEXT); + int (*option_handler_fnc)(ASSUAN_CONTEXT,const char*, const char*); + void (*input_notify_fnc)(ASSUAN_CONTEXT, const char *); + void (*output_notify_fnc)(ASSUAN_CONTEXT, const char *); + + int input_fd; /* set by INPUT command */ + int output_fd; /* set by OUTPUT command */ + +}; + + +/*-- assuan-pipe-server.c --*/ +int _assuan_new_context (ASSUAN_CONTEXT *r_ctx); +void _assuan_release_context (ASSUAN_CONTEXT ctx); + + +/*-- assuan-handler.c --*/ +int _assuan_register_std_commands (ASSUAN_CONTEXT ctx); + +/*-- assuan-buffer.c --*/ +int _assuan_read_line (ASSUAN_CONTEXT ctx); +int _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size); +int _assuan_cookie_write_flush (void *cookie); + +/*-- assuan-client.c --*/ +AssuanError _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off); + + +/*-- assuan-util.c --*/ +void *_assuan_malloc (size_t n); +void *_assuan_calloc (size_t n, size_t m); +void *_assuan_realloc (void *p, size_t n); +void _assuan_free (void *p); + +#define xtrymalloc(a) _assuan_malloc ((a)) +#define xtrycalloc(a,b) _assuan_calloc ((a),(b)) +#define xtryrealloc(a,b) _assuan_realloc((a),(b)) +#define xfree(a) _assuan_free ((a)) + +#define set_error(c,e,t) assuan_set_error ((c), ASSUAN_ ## e, (t)) + +void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length); +void _assuan_log_sanitized_string (const char *string); + + +#endif /*ASSUAN_DEFS_H*/ + diff --git a/branches/gpgme-0-3-branch/assuan/assuan-handler.c b/branches/gpgme-0-3-branch/assuan/assuan-handler.c new file mode 100644 index 00000000..69b34b4f --- /dev/null +++ b/branches/gpgme-0-3-branch/assuan/assuan-handler.c @@ -0,0 +1,688 @@ +/* assuan-handler.c - dispatch commands + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "assuan-defs.h" + +#define spacep(p) (*(p) == ' ' || *(p) == '\t') +#define digitp(a) ((a) >= '0' && (a) <= '9') + + +static int +dummy_handler (ASSUAN_CONTEXT ctx, char *line) +{ + return set_error (ctx, Server_Fault, "no handler registered"); +} + + +static int +std_handler_nop (ASSUAN_CONTEXT ctx, char *line) +{ + return 0; /* okay */ +} + +static int +std_handler_cancel (ASSUAN_CONTEXT ctx, char *line) +{ + if (ctx->cancel_notify_fnc) + ctx->cancel_notify_fnc (ctx); + return set_error (ctx, Not_Implemented, NULL); +} + +static int +std_handler_option (ASSUAN_CONTEXT ctx, char *line) +{ + char *key, *value, *p; + + for (key=line; spacep (key); key++) + ; + if (!*key) + return set_error (ctx, Syntax_Error, "argument required"); + if (*key == '=') + return 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 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 set_error (ctx, Syntax_Error, + "option should not begin with one dash"); + + if (ctx->option_handler_fnc) + return ctx->option_handler_fnc (ctx, key, value); + return 0; +} + +static int +std_handler_bye (ASSUAN_CONTEXT ctx, char *line) +{ + if (ctx->bye_notify_fnc) + ctx->bye_notify_fnc (ctx); + assuan_close_input_fd (ctx); + assuan_close_output_fd (ctx); + return -1; /* pretty simple :-) */ +} + +static int +std_handler_auth (ASSUAN_CONTEXT ctx, char *line) +{ + return set_error (ctx, Not_Implemented, NULL); +} + +static int +std_handler_reset (ASSUAN_CONTEXT ctx, char *line) +{ + if (ctx->reset_notify_fnc) + ctx->reset_notify_fnc (ctx); + assuan_close_input_fd (ctx); + assuan_close_output_fd (ctx); + return 0; +} + +static int +std_handler_end (ASSUAN_CONTEXT ctx, char *line) +{ + return set_error (ctx, Not_Implemented, NULL); +} + +static int +parse_cmd_input_output (ASSUAN_CONTEXT ctx, char *line, int *rfd) +{ + char *endp; + + if (strncmp (line, "FD=", 3)) + return set_error (ctx, Syntax_Error, "FD=<n> expected"); + line += 3; + 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 */ + 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; +} + +/* Format is INPUT FD=<n> */ +static int +std_handler_input (ASSUAN_CONTEXT ctx, char *line) +{ + int rc, fd; + + rc = parse_cmd_input_output (ctx, line, &fd); + if (rc) + return rc; + ctx->input_fd = fd; + if (ctx->input_notify_fnc) + ctx->input_notify_fnc (ctx, line); + return 0; +} + +/* Format is OUTPUT FD=<n> */ +static int +std_handler_output (ASSUAN_CONTEXT ctx, char *line) +{ + int rc, fd; + + rc = parse_cmd_input_output (ctx, line, &fd); + if (rc) + return rc; + ctx->output_fd = fd; + if (ctx->output_notify_fnc) + ctx->output_notify_fnc (ctx, line); + return 0; +} + + + + + +/* This is a table with the standard commands and handler for them. + The table is used to initialize a new context and assuciate strings + and handlers with cmd_ids */ +static struct { + const char *name; + int cmd_id; + int (*handler)(ASSUAN_CONTEXT, char *line); + int always; /* always initialize this command */ +} std_cmd_table[] = { + { "NOP", ASSUAN_CMD_NOP, std_handler_nop, 1 }, + { "CANCEL", ASSUAN_CMD_CANCEL, std_handler_cancel, 1 }, + { "OPTION", ASSUAN_CMD_OPTION, std_handler_option, 1 }, + { "BYE", ASSUAN_CMD_BYE, std_handler_bye, 1 }, + { "AUTH", ASSUAN_CMD_AUTH, std_handler_auth, 1 }, + { "RESET", ASSUAN_CMD_RESET, std_handler_reset, 1 }, + { "END", ASSUAN_CMD_END, std_handler_end, 1 }, + + { "INPUT", ASSUAN_CMD_INPUT, std_handler_input }, + { "OUTPUT", ASSUAN_CMD_OUTPUT, std_handler_output }, + { "OPTION", ASSUAN_CMD_OPTION, std_handler_option, 1 }, + { NULL } +}; + + +/** + * assuan_register_command: + * @ctx: the server context + * @cmd_id: An ID value for the command + * @cmd_name: A string with the command name + * @handler: The handler function to be called + * + * Register a handler to be used for a given command. + * + * The @cmd_name must be %NULL or an empty string for all @cmd_ids + * below %ASSUAN_CMD_USER because predefined values are used. + * + * Return value: + **/ +int +assuan_register_command (ASSUAN_CONTEXT ctx, + int cmd_id, const char *cmd_name, + int (*handler)(ASSUAN_CONTEXT, char *)) +{ + int i; + + if (cmd_name && !*cmd_name) + cmd_name = NULL; + + if (cmd_id < ASSUAN_CMD_USER) + { + if (cmd_name) + return ASSUAN_Invalid_Value; /* must be NULL for these values*/ + + for (i=0; std_cmd_table[i].name; i++) + { + if (std_cmd_table[i].cmd_id == cmd_id) + { + cmd_name = std_cmd_table[i].name; + if (!handler) + handler = std_cmd_table[i].handler; + break; + } + } + if (!std_cmd_table[i].name) + return ASSUAN_Invalid_Value; /* not a pre-registered one */ + } + + if (!handler) + handler = dummy_handler; + + if (!cmd_name) + return ASSUAN_Invalid_Value; + +/* fprintf (stderr, "DBG-assuan: registering %d as `%s'\n", cmd_id, cmd_name); */ + + if (!ctx->cmdtbl) + { + ctx->cmdtbl_size = 50; + ctx->cmdtbl = xtrycalloc ( ctx->cmdtbl_size, sizeof *ctx->cmdtbl); + if (!ctx->cmdtbl) + return 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_Out_Of_Core; + ctx->cmdtbl = x; + ctx->cmdtbl_size += 50; + } + + ctx->cmdtbl[ctx->cmdtbl_used].name = cmd_name; + ctx->cmdtbl[ctx->cmdtbl_used].cmd_id = cmd_id; + ctx->cmdtbl[ctx->cmdtbl_used].handler = handler; + ctx->cmdtbl_used++; + return 0; +} + +int +assuan_register_bye_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT)) +{ + if (!ctx) + return ASSUAN_Invalid_Value; + ctx->bye_notify_fnc = fnc; + return 0; +} + +int +assuan_register_reset_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT)) +{ + if (!ctx) + return ASSUAN_Invalid_Value; + ctx->reset_notify_fnc = fnc; + return 0; +} + +int +assuan_register_cancel_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT)) +{ + if (!ctx) + return ASSUAN_Invalid_Value; + ctx->cancel_notify_fnc = fnc; + return 0; +} + +int +assuan_register_option_handler (ASSUAN_CONTEXT ctx, + int (*fnc)(ASSUAN_CONTEXT, + const char*, const char*)) +{ + if (!ctx) + return ASSUAN_Invalid_Value; + ctx->option_handler_fnc = fnc; + return 0; +} + +int +assuan_register_input_notify (ASSUAN_CONTEXT ctx, + void (*fnc)(ASSUAN_CONTEXT, const char *)) +{ + if (!ctx) + return ASSUAN_Invalid_Value; + ctx->input_notify_fnc = fnc; + return 0; +} + +int +assuan_register_output_notify (ASSUAN_CONTEXT ctx, + void (*fnc)(ASSUAN_CONTEXT, const char *)) +{ + if (!ctx) + return ASSUAN_Invalid_Value; + ctx->output_notify_fnc = fnc; + return 0; +} + + +/* Helper to register the standards commands */ +int +_assuan_register_std_commands (ASSUAN_CONTEXT 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].cmd_id, + NULL, 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 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, all the + handler with the argument line and return the error */ +static int +dispatch_command (ASSUAN_CONTEXT ctx, char *line, int linelen) +{ + char *p; + const char *s; + int shift, i; + + if (*line == 'D' && line[1] == ' ') /* divert to special handler */ + return handle_data_line (ctx, line+2, linelen-2); + + for (p=line; *p && *p != ' ' && *p != '\t'; p++) + ; + if (p==line) + return set_error (ctx, Invalid_Command, "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 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); +} + + + + +static int +process_request (ASSUAN_CONTEXT ctx) +{ + int rc; + + if (ctx->in_inquire) + return ASSUAN_Nested_Commands; + + rc = _assuan_read_line (ctx); + if (rc) + return rc; + if (*ctx->inbound.line == '#' || !ctx->inbound.linelen) + return 0; /* comment line - ignore */ + + 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); + /* check from 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 w/o 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 (rc == -1) + { /* No error checking because the peer may have already disconnect */ + assuan_write_line (ctx, "OK closing connection"); + ctx->finish_handler (ctx); + } + else + { + char errline[256]; + + if (rc < 100) + sprintf (errline, "ERR %d server fault (%.50s)", + ASSUAN_Server_Fault, assuan_strerror (rc)); + else + { + const char *text = ctx->err_no == rc? ctx->err_str:NULL; + + sprintf (errline, "ERR %d %.50s%s%.100s", + rc, assuan_strerror (rc), text? " - ":"", text?text:""); + } + rc = assuan_write_line (ctx, errline); + } + + ctx->confidential = 0; + if (ctx->okay_line) + { + xfree (ctx->okay_line); + ctx->okay_line = NULL; + } + return rc; +} + +/** + * assuan_process: + * @ctx: assuan context + * + * This fucntion 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 ctx) +{ + int rc; + + do { + rc = process_request (ctx); + } while (!rc); + + if (rc == -1) + rc = 0; + + return rc; +} + + +/** + * assuan_process_next: + * @ctx: Assuan context + * + * Same as assuan_process() but the user has to provide the outer + * loop. He should loop as long as the return code is zero and stop + * otherwise; -1 is regular end. + * + * See also: assuan_get_active_fds() + * Return value: -1 for end of server, 0 on success or an error code + **/ +int +assuan_process_next (ASSUAN_CONTEXT ctx) +{ + return process_request (ctx); +} + + +/** + * 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 ctx, int what, + int *fdarray, int fdarraysize) +{ + int n = 0; + + if (!ctx || fdarraysize < 2 || what < 0 || what > 1) + return -1; + + if (!what) + { + if (ctx->inbound.fd != -1) + fdarray[n++] = ctx->inbound.fd; + } + else + { + if (ctx->outbound.fd != -1) + fdarray[n++] = ctx->outbound.fd; + if (ctx->outbound.data.fp) + fdarray[n++] = fileno (ctx->outbound.data.fp); + } + + return n; +} + +/* 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 ctx) +{ + cookie_io_functions_t cookie_fnc; + + if (ctx->outbound.data.fp) + return ctx->outbound.data.fp; + + cookie_fnc.read = NULL; + cookie_fnc.write = _assuan_cookie_write_data; + cookie_fnc.seek = NULL; + cookie_fnc.close = _assuan_cookie_write_flush; + + ctx->outbound.data.fp = fopencookie (ctx, "wb", cookie_fnc); + ctx->outbound.data.error = 0; + return ctx->outbound.data.fp; +} + + +/* Set the text used for the next OK reponse. This string is + automatically reset to NULL after the next command. */ +AssuanError +assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line) +{ + if (!ctx) + return 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_Out_Of_Core; + strcpy (buf, "OK "); + strcpy (buf+3, line); + xfree (ctx->okay_line); + ctx->okay_line = buf; + } + return 0; +} + + + +void +assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text) +{ + char buffer[256]; + char *helpbuf; + size_t n; + + if ( !ctx || !keyword) + return; + 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); + } + assuan_write_line (ctx, buffer); + } + else if ( (helpbuf = xtrymalloc (n)) ) + { + strcpy (helpbuf, "S "); + strcat (helpbuf, keyword); + if (*text) + { + strcat (helpbuf, " "); + strcat (helpbuf, text); + } + assuan_write_line (ctx, helpbuf); + xfree (helpbuf); + } +} diff --git a/branches/gpgme-0-3-branch/assuan/assuan-inquire.c b/branches/gpgme-0-3-branch/assuan/assuan-inquire.c new file mode 100644 index 00000000..2bac1303 --- /dev/null +++ b/branches/gpgme-0-3-branch/assuan/assuan-inquire.c @@ -0,0 +1,239 @@ +/* assuan-inquire.c - handle inquire stuff + * Copyright (C) 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "assuan-defs.h" + +#define digitp(a) ((a) >= '0' && (a) <= '9') +#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ + *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) +#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) + + +struct membuf { + size_t len; + size_t size; + char *buf; + int out_of_core; + int too_large; + size_t maxlen; +}; + + + +/* A simple implemnation of a dynamic buffer. Use init_membuf() to + create a buffer, put_membuf to append bytes and get_membuf to + release and return the buffer. Allocation errors are detected but + only returned at the final get_membuf(), this helps not to clutter + the code with out of core checks. */ + +static void +init_membuf (struct membuf *mb, int initiallen, size_t maxlen) +{ + mb->len = 0; + mb->size = initiallen; + mb->out_of_core = 0; + mb->too_large = 0; + mb->maxlen = maxlen; + /* we need to allocate one byte more for get_membuf */ + mb->buf = xtrymalloc (initiallen+1); + if (!mb->buf) + mb->out_of_core = 1; +} + +static void +put_membuf (struct membuf *mb, const void *buf, size_t len) +{ + if (mb->out_of_core || mb->too_large) + return; + + if (mb->maxlen && mb->len + len > mb->maxlen) + { + mb->too_large = 1; + return; + } + + if (mb->len + len >= mb->size) + { + char *p; + + mb->size += len + 1024; + /* we need to allocate one byte more for get_membuf */ + p = xtryrealloc (mb->buf, mb->size+1); + if (!p) + { + mb->out_of_core = 1; + return; + } + mb->buf = p; + } + memcpy (mb->buf + mb->len, buf, len); + mb->len += len; +} + +static void * +get_membuf (struct membuf *mb, size_t *len) +{ + char *p; + + if (mb->out_of_core || mb->too_large) + { + xfree (mb->buf); + mb->buf = NULL; + return NULL; + } + + mb->buf[mb->len] = 0; /* there is enough space for the hidden eos */ + p = mb->buf; + *len = mb->len; + mb->buf = NULL; + mb->out_of_core = 1; /* don't allow a reuse */ + return p; +} + +static void +free_membuf (struct membuf *mb) +{ + xfree (mb->buf); + mb->buf = NULL; +} + + +/** + * assuan_inquire: + * @ctx: An assuan context + * @keyword: The keyword used for the inquire + * @r_buffer: Returns an allocated buffer + * @r_length: Returns the length of this buffer + * @maxlen: If not 0, the size limit of the inquired data. + * + * A Server may use this to Send an inquire. r_buffer, r_length and + * maxlen may all be NULL/0 to indicate that no real data is expected. + * + * Return value: 0 on success or an ASSUAN error code + **/ +AssuanError +assuan_inquire (ASSUAN_CONTEXT ctx, const char *keyword, + char **r_buffer, size_t *r_length, size_t maxlen) +{ + AssuanError rc; + struct membuf mb; + char cmdbuf[100]; + unsigned char *line, *p; + int linelen; + int nodataexpected; + + if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf))) + return ASSUAN_Invalid_Value; + nodataexpected = !r_buffer && !r_length && !maxlen; + if (!nodataexpected && (!r_buffer || !r_length)) + return ASSUAN_Invalid_Value; + if (!ctx->is_server) + return ASSUAN_Not_A_Server; + if (ctx->in_inquire) + return ASSUAN_Nested_Commands; + + ctx->in_inquire = 1; + if (nodataexpected) + memset (&mb, 0, sizeof mb); /* avoid compiler warnings */ + else + init_membuf (&mb, maxlen? maxlen:1024, maxlen); + + strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword); + rc = assuan_write_line (ctx, cmdbuf); + if (rc) + goto leave; + + for (;;) + { + do + { + rc = _assuan_read_line (ctx); + if (rc) + goto leave; + line = ctx->inbound.line; + linelen = ctx->inbound.linelen; + } + while (*line == '#' || !linelen); + if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D' + && (!line[3] || line[3] == ' ')) + break; /* END command received*/ + if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N') + { + rc = ASSUAN_Canceled; + goto leave; + } + if (line[0] != 'D' || line[1] != ' ' || nodataexpected) + { + rc = ASSUAN_Unexpected_Command; + goto leave; + } + if (linelen < 3) + continue; + line += 2; + linelen -= 2; + + p = line; + while (linelen) + { + for (;linelen && *p != '%'; linelen--, p++) + ; + put_membuf (&mb, line, p-line); + if (linelen > 2) + { /* handle escaping */ + unsigned char tmp[1]; + p++; + *tmp = xtoi_2 (p); + p += 2; + linelen -= 3; + put_membuf (&mb, tmp, 1); + } + line = p; + } + if (mb.too_large) + { + rc = ASSUAN_Too_Much_Data; + goto leave; + } + } + + if (!nodataexpected) + { + *r_buffer = get_membuf (&mb, r_length); + if (!*r_buffer) + rc = ASSUAN_Out_Of_Core; + } + + leave: + if (!nodataexpected) + free_membuf (&mb); + ctx->in_inquire = 0; + return rc; +} + + + + + + diff --git a/branches/gpgme-0-3-branch/assuan/assuan-listen.c b/branches/gpgme-0-3-branch/assuan/assuan-listen.c new file mode 100644 index 00000000..db63ad2b --- /dev/null +++ b/branches/gpgme-0-3-branch/assuan/assuan-listen.c @@ -0,0 +1,132 @@ +/* assuan-listen.c - Wait for a connection (server) + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "assuan-defs.h" + +AssuanError +assuan_set_hello_line (ASSUAN_CONTEXT ctx, const char *line) +{ + if (!ctx) + return ASSUAN_Invalid_Value; + if (!line) + { + xfree (ctx->hello_line); + ctx->hello_line = NULL; + } + else + { + char *buf = xtrymalloc (3+strlen(line)+1); + if (!buf) + return ASSUAN_Out_Of_Core; + strcpy (buf, "OK "); + strcpy (buf+3, line); + xfree (ctx->hello_line); + ctx->hello_line = buf; + } + return 0; +} + + +/** + * assuan_accept: + * @ctx: context + * + * Cancel any existing connectiion and wait for a connection from a + * client. The initial handshake is performed which may include an + * initial authentication or encryption negotiation. + * + * Return value: 0 on success or an error if the connection could for + * some reason not be established. + **/ +AssuanError +assuan_accept (ASSUAN_CONTEXT ctx) +{ + int rc; + + if (!ctx) + return ASSUAN_Invalid_Value; + + if (ctx->pipe_mode > 1) + return -1; /* second invocation for pipemode -> terminate */ + ctx->finish_handler (ctx); + + rc = ctx->accept_handler (ctx); + if (rc) + return rc; + + /* send the hello */ + rc = assuan_write_line (ctx, ctx->hello_line? ctx->hello_line + : "OK Your orders please"); + if (rc) + return rc; + + if (ctx->pipe_mode) + ctx->pipe_mode = 2; + + return 0; +} + + + +int +assuan_get_input_fd (ASSUAN_CONTEXT ctx) +{ + return ctx? ctx->input_fd : -1; +} + + +int +assuan_get_output_fd (ASSUAN_CONTEXT ctx) +{ + return ctx? ctx->output_fd : -1; +} + + +/* Close the fd descriptor set by the command INPUT FD=n. We handle + this fd inside assuan so that we can do some initial checks */ +AssuanError +assuan_close_input_fd (ASSUAN_CONTEXT ctx) +{ + if (!ctx || ctx->input_fd == -1) + return ASSUAN_Invalid_Value; + close (ctx->input_fd); + ctx->input_fd = -1; + return 0; +} + +/* Close the fd descriptor set by the command OUTPUT FD=n. We handle + this fd inside assuan so that we can do some initial checks */ +AssuanError +assuan_close_output_fd (ASSUAN_CONTEXT ctx) +{ + if (!ctx || ctx->output_fd == -1) + return ASSUAN_Invalid_Value; + + close (ctx->output_fd); + ctx->output_fd = -1; + return 0; +} + diff --git a/branches/gpgme-0-3-branch/assuan/assuan-pipe-connect.c b/branches/gpgme-0-3-branch/assuan/assuan-pipe-connect.c new file mode 100644 index 00000000..6614dab9 --- /dev/null +++ b/branches/gpgme-0-3-branch/assuan/assuan-pipe-connect.c @@ -0,0 +1,298 @@ +/* assuan-pipe-connect.c - Establish a pipe connection (client) + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * 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 <sys/stat.h> +#include <fcntl.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 */ +} + + +static int +do_finish (ASSUAN_CONTEXT ctx) +{ + if (ctx->inbound.fd != -1) + { + close (ctx->inbound.fd); + ctx->inbound.fd = -1; + } + if (ctx->outbound.fd != -1) + { + close (ctx->outbound.fd); + ctx->outbound.fd = -1; + } + if (ctx->pid != -1) + { + waitpid (ctx->pid, NULL, 0); /* FIXME Check return value. */ + ctx->pid = -1; + } + return 0; +} + +static void +do_deinit (ASSUAN_CONTEXT ctx) +{ + do_finish (ctx); +} + + + +/* 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. FD_CHILD_LIST is a -1 terminated list of file + descriptors not to close in the child. */ +AssuanError +assuan_pipe_connect2 (ASSUAN_CONTEXT *ctx, const char *name, + char *const argv[], int *fd_child_list, + unsigned int connect_flags) +{ + static int fixed_signals = 0; + AssuanError err; + int rp[2]; + int wp[2]; + + if (!ctx || !name || !argv || !argv[0]) + return ASSUAN_Invalid_Value; + + if (!fixed_signals) + { + struct sigaction act; + + sigaction (SIGPIPE, NULL, &act); + if (act.sa_handler == SIG_DFL) + { + act.sa_handler = SIG_IGN; + sigemptyset (&act.sa_mask); + act.sa_flags = 0; + sigaction (SIGPIPE, &act, NULL); + } + fixed_signals = 1; + /* FIXME: This is not MT safe */ + } + + if (pipe (rp) < 0) + return ASSUAN_General_Error; + + if (pipe (wp) < 0) + { + close (rp[0]); + close (rp[1]); + return ASSUAN_General_Error; + } + + err = _assuan_new_context (ctx); + if (err) + { + close (rp[0]); + close (rp[1]); + close (wp[0]); + close (wp[1]); + return err; + } + (*ctx)->pipe_mode = 1; + (*ctx)->inbound.fd = rp[0]; /* Our inbound is read end of read pipe. */ + (*ctx)->outbound.fd = wp[1]; /* Our outbound is write end of write pipe. */ + (*ctx)->deinit_handler = do_deinit; + (*ctx)->finish_handler = do_finish; + + (*ctx)->pid = fork (); + if ((*ctx)->pid < 0) + { + close (rp[0]); + close (rp[1]); + close (wp[0]); + close (wp[1]); + _assuan_release_context (*ctx); + return ASSUAN_General_Error; + } + + if ((*ctx)->pid == 0) + { + 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++) + { + int *fdp = fd_child_list; + + if (fdp) + { + while (*fdp != -1 && *fdp != i) + fdp++; + } + + if (!(fdp && *fdp != -1) + && 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) + { + 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) + { + if (dup2 (wp[0], STDIN_FILENO) == -1) + { + LOGERROR1 ("dup2 failed in child: %s\n", strerror (errno)); + _exit (4); + } + close (wp[0]); + } + + if ((connect_flags & 1)) + { /* dup stderr to /dev/null so that the application output + won't get clobbered with output from the backend */ + int fdzero = open ("/dev/null", O_WRONLY); + if (fdzero == -1) + { + LOGERROR1 ("can't open `/dev/null': %s\n", strerror (errno)); + _exit (4); + } + if (dup2 (fdzero, 2) == -1) + { + LOGERROR1 ("dup2(dev/null, 2) failed: %s\n", strerror (errno)); + _exit (4); + } + close (fdzero); + } + + 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]); + + /* 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) + { + assuan_disconnect (*ctx); + *ctx = NULL; + } + + return err; +} + +AssuanError +assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[], + int *fd_child_list) +{ + return assuan_pipe_connect2 (ctx, name, argv, fd_child_list, 0); +} + + + + + + + + + + + + + + + + diff --git a/branches/gpgme-0-3-branch/assuan/assuan-pipe-server.c b/branches/gpgme-0-3-branch/assuan/assuan-pipe-server.c new file mode 100644 index 00000000..5c5d1248 --- /dev/null +++ b/branches/gpgme-0-3-branch/assuan/assuan-pipe-server.c @@ -0,0 +1,124 @@ +/* assuan-pipe-server.c - Assuan server working over a pipe + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdlib.h> +#include <stdio.h> + +#include "assuan-defs.h" + +static void +deinit_pipe_server (ASSUAN_CONTEXT ctx) +{ + /* nothing to do for this simple server */ +} + +static int +accept_connection (ASSUAN_CONTEXT ctx) +{ + /* This is a NOP for a pipe server */ + return 0; +} + +static int +finish_connection (ASSUAN_CONTEXT ctx) +{ + /* This is a NOP for a pipe server */ + return 0; +} + + +/* Create a new context. Note that the handlers are set up for a pipe + server/client - this wau we don't need extra dummy functions */ +int +_assuan_new_context (ASSUAN_CONTEXT *r_ctx) +{ + ASSUAN_CONTEXT ctx; + int rc; + + *r_ctx = NULL; + ctx = xtrycalloc (1, sizeof *ctx); + if (!ctx) + return ASSUAN_Out_Of_Core; + ctx->input_fd = -1; + ctx->output_fd = -1; + + ctx->inbound.fd = -1; + ctx->outbound.fd = -1; + + ctx->listen_fd = -1; + ctx->client_pid = (pid_t)-1; + /* use the pipe server handler as a default */ + ctx->deinit_handler = deinit_pipe_server; + ctx->accept_handler = accept_connection; + ctx->finish_handler = finish_connection; + + rc = _assuan_register_std_commands (ctx); + if (rc) + xfree (ctx); + else + *r_ctx = ctx; + return rc; +} + + + +int +assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2]) +{ + int rc; + + rc = _assuan_new_context (r_ctx); + if (!rc) + { + ASSUAN_CONTEXT ctx = *r_ctx; + + ctx->is_server = 1; + ctx->inbound.fd = filedes[0]; + ctx->outbound.fd = filedes[1]; + ctx->pipe_mode = 1; + } + return rc; +} + + +void +_assuan_release_context (ASSUAN_CONTEXT ctx) +{ + if (ctx) + { + xfree (ctx->hello_line); + xfree (ctx->okay_line); + xfree (ctx); + } +} + +void +assuan_deinit_server (ASSUAN_CONTEXT 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); + } +} diff --git a/branches/gpgme-0-3-branch/assuan/assuan-socket-connect.c b/branches/gpgme-0-3-branch/assuan/assuan-socket-connect.c new file mode 100644 index 00000000..748a91ff --- /dev/null +++ b/branches/gpgme-0-3-branch/assuan/assuan-socket-connect.c @@ -0,0 +1,150 @@ +/* assuan-socket-connect.c - Assuan socket based client + * Copyright (C) 2002 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdlib.h> +#include <stddef.h> +#include <stdio.h> +#include <errno.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> + +#include "assuan-defs.h" + +#ifdef HAVE_JNLIB_LOGGING +#include "../jnlib/logging.h" +#define LOGERROR(a) log_error ((a)) +#define LOGERROR1(a,b) log_error ((a), (b)) +#define LOGERROR2(a,b,c) log_error ((a), (b), (c)) +#define LOGERRORX(a) log_printf ((a)) +#else +#define LOGERROR(a) fprintf (stderr, (a)) +#define LOGERROR1(a,b) fprintf (stderr, (a), (b)) +#define LOGERROR2(a,b,c) fprintf (stderr, (a), (b), (c)) +#define LOGERRORX(a) fputs ((a), stderr) +#endif + + + +static int +do_finish (ASSUAN_CONTEXT ctx) +{ + if (ctx->inbound.fd != -1) + { + close (ctx->inbound.fd); + } + ctx->inbound.fd = -1; + ctx->outbound.fd = -1; + return 0; +} + +static void +do_deinit (ASSUAN_CONTEXT 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 + becode handy in future. */ +AssuanError +assuan_socket_connect (ASSUAN_CONTEXT *r_ctx, + const char *name, pid_t server_pid) +{ + AssuanError err; + ASSUAN_CONTEXT ctx; + int fd; + struct sockaddr_un srvr_addr; + size_t len; + + if (!r_ctx || !name) + return 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 */ + if (*name != '/') + return ASSUAN_Invalid_Value; + if (strlen (name)+1 >= sizeof srvr_addr.sun_path) + return ASSUAN_Invalid_Value; + + err = _assuan_new_context (&ctx); + if (err) + return err; + ctx->pid = server_pid; /* save it in case we need it later */ + ctx->deinit_handler = do_deinit; + ctx->finish_handler = do_finish; + + fd = socket (AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) + { + LOGERROR1 ("can't create socket: %s\n", strerror (errno)); + _assuan_release_context (ctx); + return ASSUAN_General_Error; + } + + memset (&srvr_addr, 0, sizeof srvr_addr ); + srvr_addr.sun_family = AF_UNIX; + strcpy (srvr_addr.sun_path, name); + len = (offsetof (struct sockaddr_un, sun_path) + + strlen (srvr_addr.sun_path) + 1); + + if (connect (fd, (struct sockaddr*)&srvr_addr, len) == -1) + { + LOGERROR2 ("can't connect to `%s': %s\n", name, strerror (errno)); + _assuan_release_context (ctx); + close (fd ); + return ASSUAN_Connect_Failed; + } + + ctx->inbound.fd = fd; + ctx->outbound.fd = fd; + + /* 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) + { + LOGERROR ("can't connect server: `"); + _assuan_log_sanitized_string (ctx->inbound.line); + LOGERRORX ("'\n"); + err = ASSUAN_Connect_Failed; + } + } + + if (err) + { + assuan_disconnect (ctx); + } + else + *r_ctx = ctx; + return 0; +} + + diff --git a/branches/gpgme-0-3-branch/assuan/assuan-socket-server.c b/branches/gpgme-0-3-branch/assuan/assuan-socket-server.c new file mode 100644 index 00000000..39dd84a1 --- /dev/null +++ b/branches/gpgme-0-3-branch/assuan/assuan-socket-server.c @@ -0,0 +1,139 @@ +/* assuan-socket-server.c - Assuan socket based server + * Copyright (C) 2002 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#ifdef USE_GNU_PTH +# include <pth.h> +#endif + +#include "assuan-defs.h" + +static int +accept_connection (ASSUAN_CONTEXT ctx) +{ + int fd; + struct sockaddr_un clnt_addr; + size_t len = sizeof clnt_addr; + + ctx->client_pid = (pid_t)-1; +#ifdef USE_GNU_PTH + fd = pth_accept (ctx->listen_fd, (struct sockaddr*)&clnt_addr, &len ); +#else + fd = accept (ctx->listen_fd, (struct sockaddr*)&clnt_addr, &len ); +#endif + if (fd == -1) + { + ctx->os_errno = errno; + return ASSUAN_Accept_Failed; + } + +#ifdef HAVE_SO_PEERCRED + { + struct ucred cr; + int cl = sizeof cr; + + if ( !getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl) ) + ctx->client_pid = cr.pid; + } +#endif + + ctx->inbound.fd = fd; + ctx->inbound.eof = 0; + ctx->inbound.linelen = 0; + ctx->inbound.attic.linelen = 0; + ctx->inbound.attic.pending = 0; + + ctx->outbound.fd = fd; + ctx->outbound.data.linelen = 0; + ctx->outbound.data.error = 0; + + ctx->confidential = 0; + + return 0; +} + +static int +finish_connection (ASSUAN_CONTEXT ctx) +{ + if (ctx->inbound.fd != -1) + { + close (ctx->inbound.fd); + } + ctx->inbound.fd = -1; + ctx->outbound.fd = -1; + return 0; +} + + +static void +deinit_socket_server (ASSUAN_CONTEXT ctx) +{ + finish_connection (ctx); +} + + + +/* Initialize a server for the socket LISTEN_FD which has already be + put into listen mode */ +int +assuan_init_socket_server (ASSUAN_CONTEXT *r_ctx, int listen_fd) +{ + ASSUAN_CONTEXT ctx; + int rc; + + *r_ctx = NULL; + ctx = xtrycalloc (1, sizeof *ctx); + if (!ctx) + return 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->deinit_handler = deinit_socket_server; + ctx->accept_handler = accept_connection; + ctx->finish_handler = finish_connection; + + rc = _assuan_register_std_commands (ctx); + if (rc) + xfree (ctx); + else + *r_ctx = ctx; + return rc; +} + + + + + + + + + + diff --git a/branches/gpgme-0-3-branch/assuan/assuan-util.c b/branches/gpgme-0-3-branch/assuan/assuan-util.c new file mode 100644 index 00000000..4153ef8d --- /dev/null +++ b/branches/gpgme-0-3-branch/assuan/assuan-util.c @@ -0,0 +1,196 @@ +/* assuan-util.c - Utility functions for Assuan + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "assuan-defs.h" + +#ifdef HAVE_JNLIB_LOGGING +#include "../jnlib/logging.h" +#endif + + +static void *(*alloc_func)(size_t n) = malloc; +static void *(*realloc_func)(void *p, size_t n) = realloc; +static void (*free_func)(void*) = free; + + + +void +assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n), + void *(*new_realloc_func)(void *p, size_t n), + void (*new_free_func)(void*) ) +{ + alloc_func = new_alloc_func; + realloc_func = new_realloc_func; + free_func = new_free_func; +} + +void * +_assuan_malloc (size_t n) +{ + return alloc_func (n); +} + +void * +_assuan_realloc (void *a, size_t n) +{ + return realloc_func (a, n); +} + +void * +_assuan_calloc (size_t n, size_t m) +{ + void *p = _assuan_malloc (n*m); + if (p) + memset (p, 0, n* m); + return p; +} + +void +_assuan_free (void *p) +{ + if (p) + free_func (p); +} + + + +/* Store the error in the context so that the error sending function + can take out a descriptive text. Inside the assuan code, use the + macro set_error instead of this function. */ +int +assuan_set_error (ASSUAN_CONTEXT ctx, int err, const char *text) +{ + ctx->err_no = err; + ctx->err_str = text; + return err; +} + +void +assuan_set_pointer (ASSUAN_CONTEXT ctx, void *pointer) +{ + if (ctx) + ctx->user_pointer = pointer; +} + +void * +assuan_get_pointer (ASSUAN_CONTEXT ctx) +{ + return ctx? ctx->user_pointer : NULL; +} + + +void +assuan_set_log_stream (ASSUAN_CONTEXT ctx, FILE *fp) +{ + if (ctx) + { + if (ctx->log_fp) + fflush (ctx->log_fp); + ctx->log_fp = fp; + } +} + + +void +assuan_begin_confidential (ASSUAN_CONTEXT ctx) +{ + if (ctx) + { + ctx->confidential = 1; + } +} + +void +assuan_end_confidential (ASSUAN_CONTEXT ctx) +{ + if (ctx) + { + ctx->confidential = 0; + } +} + +void +_assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length) +{ + const unsigned char *s; + int n; + + for (n=length,s=buffer; n; n--, s++) + { + if (*s < ' ' || (*s >= 0x7f && *s <= 0xa0)) + break; + } + s = buffer; + if (!n && *s != '[') + fwrite (buffer, length, 1, fp); + else + { + putc ('[', fp); + for (n=0; n < length; n++, s++) + fprintf (fp, " %02x", *s); + putc (' ', fp); + putc (']', fp); + } +} + + +/* print a user supplied string after filtering out potential bad + characters*/ +void +_assuan_log_sanitized_string (const char *string) +{ + const unsigned char *s = string; +#ifdef HAVE_JNLIB_LOGGING + FILE *fp = log_get_stream (); +#else + FILE *fp = stderr; +#endif + + for (; *s; s++) + { + if (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)) + { + putc ('\\', fp); + if (*s == '\n') + putc ('n', fp); + else if (*s == '\r') + putc ('r', fp); + else if (*s == '\f') + putc ('f', fp); + else if (*s == '\v') + putc ('v', fp); + else if (*s == '\b') + putc ('b', fp); + else if (!*s) + putc ('0', fp); + else + fprintf (fp, "x%02x", *s ); + } + else + putc (*s, fp); + } +} + + diff --git a/branches/gpgme-0-3-branch/assuan/assuan.h b/branches/gpgme-0-3-branch/assuan/assuan.h new file mode 100644 index 00000000..e18c46e6 --- /dev/null +++ b/branches/gpgme-0-3-branch/assuan/assuan.h @@ -0,0 +1,234 @@ +/* assuan.c - Definitions for the Assuna protocol + * Copyright (C) 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifndef ASSUAN_H +#define ASSUAN_H + +#include <stdio.h> +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#if 0 + } +#endif +#endif + +typedef enum { + ASSUAN_No_Error = 0, + ASSUAN_General_Error = 1, + ASSUAN_Out_Of_Core = 2, + ASSUAN_Invalid_Value = 3, + ASSUAN_Timeout = 4, + ASSUAN_Read_Error = 5, + ASSUAN_Write_Error = 6, + ASSUAN_Problem_Starting_Server = 7, + ASSUAN_Not_A_Server = 8, + ASSUAN_Not_A_Client = 9, + ASSUAN_Nested_Commands = 10, + ASSUAN_Invalid_Response = 11, + ASSUAN_No_Data_Callback = 12, + ASSUAN_No_Inquire_Callback = 13, + ASSUAN_Connect_Failed = 14, + ASSUAN_Accept_Failed = 15, + + /* error codes above 99 are meant as status codes */ + ASSUAN_Not_Implemented = 100, + ASSUAN_Server_Fault = 101, + ASSUAN_Invalid_Command = 102, + ASSUAN_Unknown_Command = 103, + ASSUAN_Syntax_Error = 104, + ASSUAN_Parameter_Error = 105, + ASSUAN_Parameter_Conflict = 106, + ASSUAN_Line_Too_Long = 107, + ASSUAN_Line_Not_Terminated = 108, + ASSUAN_No_Input = 109, + ASSUAN_No_Output = 110, + ASSUAN_Canceled = 111, + ASSUAN_Unsupported_Algorithm = 112, + ASSUAN_Server_Resource_Problem = 113, + ASSUAN_Server_IO_Error = 114, + ASSUAN_Server_Bug = 115, + ASSUAN_No_Data_Available = 116, + ASSUAN_Invalid_Data = 117, + ASSUAN_Unexpected_Command = 118, + ASSUAN_Too_Much_Data = 119, + ASSUAN_Inquire_Unknown = 120, + ASSUAN_Inquire_Error = 121, + ASSUAN_Invalid_Option = 122, + ASSUAN_Invalid_Index = 123, + ASSUAN_Unexpected_Status = 124, + ASSUAN_Unexpected_Data = 125, + ASSUAN_Invalid_Status = 126, + + ASSUAN_Not_Confirmed = 128, + + ASSUAN_Bad_Certificate = 201, + ASSUAN_Bad_Certificate_Path = 202, + ASSUAN_Missing_Certificate = 203, + ASSUAN_Bad_Signature = 204, + ASSUAN_No_Agent = 205, + ASSUAN_Agent_Error = 206, + ASSUAN_No_Public_Key = 207, + ASSUAN_No_Secret_Key = 208, + ASSUAN_Invalid_Name = 209, + + ASSUAN_Cert_Revoked = 301, + ASSUAN_No_CRL_For_Cert = 302, + ASSUAN_CRL_Too_Old = 303, + ASSUAN_Not_Trusted = 304, + + ASSUAN_Card_Error = 401, + ASSUAN_Invalid_Card = 402, + ASSUAN_No_PKCS15_App = 403, + ASSUAN_Card_Not_Present = 404, + ASSUAN_Invalid_Id = 405 + +} AssuanError; + +/* This is a list of pre-registered ASSUAN commands */ +typedef enum { + ASSUAN_CMD_NOP = 0, + ASSUAN_CMD_CANCEL, /* cancel the current request */ + ASSUAN_CMD_BYE, + ASSUAN_CMD_AUTH, + ASSUAN_CMD_RESET, + ASSUAN_CMD_OPTION, + ASSUAN_CMD_DATA, + ASSUAN_CMD_END, + ASSUAN_CMD_INPUT, + ASSUAN_CMD_OUTPUT, + + ASSUAN_CMD_USER = 256 /* Other commands should be used with this offset*/ +} AssuanCommand; + +#define ASSUAN_LINELENGTH 1002 /* 1000 + [CR,]LF */ + +struct assuan_context_s; +typedef struct assuan_context_s *ASSUAN_CONTEXT; + +/*-- assuan-handler.c --*/ +int assuan_register_command (ASSUAN_CONTEXT ctx, + int cmd_id, const char *cmd_string, + int (*handler)(ASSUAN_CONTEXT, char *)); +int assuan_register_bye_notify (ASSUAN_CONTEXT ctx, + void (*fnc)(ASSUAN_CONTEXT)); +int assuan_register_reset_notify (ASSUAN_CONTEXT ctx, + void (*fnc)(ASSUAN_CONTEXT)); +int assuan_register_cancel_notify (ASSUAN_CONTEXT ctx, + void (*fnc)(ASSUAN_CONTEXT)); +int assuan_register_input_notify (ASSUAN_CONTEXT ctx, + void (*fnc)(ASSUAN_CONTEXT, const char *)); +int assuan_register_output_notify (ASSUAN_CONTEXT ctx, + void (*fnc)(ASSUAN_CONTEXT, const char *)); + +int assuan_register_option_handler (ASSUAN_CONTEXT ctx, + int (*fnc)(ASSUAN_CONTEXT, + const char*, const char*)); + +int assuan_process (ASSUAN_CONTEXT ctx); +int assuan_process_next (ASSUAN_CONTEXT ctx); +int assuan_get_active_fds (ASSUAN_CONTEXT ctx, int what, + int *fdarray, int fdarraysize); + + +FILE *assuan_get_data_fp (ASSUAN_CONTEXT ctx); +AssuanError assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line); +void assuan_write_status (ASSUAN_CONTEXT ctx, + const char *keyword, const char *text); + + +/*-- assuan-listen.c --*/ +AssuanError assuan_set_hello_line (ASSUAN_CONTEXT ctx, const char *line); +AssuanError assuan_accept (ASSUAN_CONTEXT ctx); +int assuan_get_input_fd (ASSUAN_CONTEXT ctx); +int assuan_get_output_fd (ASSUAN_CONTEXT ctx); +AssuanError assuan_close_input_fd (ASSUAN_CONTEXT ctx); +AssuanError assuan_close_output_fd (ASSUAN_CONTEXT ctx); + + +/*-- assuan-pipe-server.c --*/ +int assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2]); +void assuan_deinit_server (ASSUAN_CONTEXT ctx); + +/*-- assuan-socket-server.c --*/ +int assuan_init_socket_server (ASSUAN_CONTEXT *r_ctx, int listen_fd); + + +/*-- assuan-pipe-connect.c --*/ +AssuanError assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, + char *const argv[], int *fd_child_list); +AssuanError assuan_pipe_connect2 (ASSUAN_CONTEXT *ctx, const char *name, + char *const argv[], int *fd_child_list, + unsigned int connect_flags); + +/*-- assuan-socket-connect.c --*/ +AssuanError assuan_socket_connect (ASSUAN_CONTEXT *ctx, const char *name, + pid_t server_pid); + +/*-- assuan-connect.c --*/ +void assuan_disconnect (ASSUAN_CONTEXT ctx); +pid_t assuan_get_pid (ASSUAN_CONTEXT ctx); + +/*-- assuan-client.c --*/ +AssuanError +assuan_transact (ASSUAN_CONTEXT ctx, + const char *command, + AssuanError (*data_cb)(void *, const void *, size_t), + void *data_cb_arg, + AssuanError (*inquire_cb)(void*, const char *), + void *inquire_cb_arg, + AssuanError (*status_cb)(void*, const char *), + void *status_cb_arg); + + +/*-- assuan-inquire.c --*/ +AssuanError assuan_inquire (ASSUAN_CONTEXT ctx, const char *keyword, + char **r_buffer, size_t *r_length, size_t maxlen); + +/*-- assuan-buffer.c --*/ +AssuanError assuan_read_line (ASSUAN_CONTEXT ctx, + char **line, size_t *linelen); +int assuan_pending_line (ASSUAN_CONTEXT ctx); +AssuanError assuan_write_line (ASSUAN_CONTEXT ctx, const char *line ); +AssuanError assuan_send_data (ASSUAN_CONTEXT ctx, + const void *buffer, size_t length); + + +/*-- assuan-util.c --*/ +void assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n), + void *(*new_realloc_func)(void *p, size_t n), + void (*new_free_func)(void*) ); +void assuan_set_log_stream (ASSUAN_CONTEXT ctx, FILE *fp); +int assuan_set_error (ASSUAN_CONTEXT ctx, int err, const char *text); +void assuan_set_pointer (ASSUAN_CONTEXT ctx, void *pointer); +void *assuan_get_pointer (ASSUAN_CONTEXT ctx); + +void assuan_begin_confidential (ASSUAN_CONTEXT ctx); +void assuan_end_confidential (ASSUAN_CONTEXT ctx); + +/*-- assuan-errors.c (built) --*/ +const char *assuan_strerror (AssuanError err); + + +#ifdef __cplusplus +} +#endif +#endif /*ASSUAN_H*/ diff --git a/branches/gpgme-0-3-branch/assuan/mkerrors b/branches/gpgme-0-3-branch/assuan/mkerrors new file mode 100755 index 00000000..13eabde7 --- /dev/null +++ b/branches/gpgme-0-3-branch/assuan/mkerrors @@ -0,0 +1,71 @@ +#!/bin/sh +# mkerrors - Extract error strings from assuan.h +# and create C source for assuan_strerror +# Copyright (C) 2001 Free Software Foundation, Inc. +# +# This file is part of GnuPG. +# +# GnuPG is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# GnuPG 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +cat <<EOF +/* Generated automatically by mkerrors */ +/* Do not edit! */ + +#include <stdio.h> +#include "assuan.h" + +/** + * assuan_strerror: + * @err: Error code + * + * This function returns a textual representaion of the given + * errorcode. If this is an unknown value, a string with the value + * is returned (Beware: it is hold in a static buffer). + * + * Return value: String with the error description. + **/ +const char * +assuan_strerror (AssuanError err) +{ + const char *s; + static char buf[25]; + + switch (err) + { +EOF + +awk ' +/ASSUAN_No_Error/ { okay=1 } +!okay {next} +/}/ { exit 0 } +/ASSUAN_[A-Za-z_]*/ { print_code($1) } + + +function print_code( s ) +{ +printf " case %s: s=\"", s ; +gsub(/_/, " ", s ); +printf "%s\"; break;\n", tolower(substr(s,8)); +} +' + +cat <<EOF + default: sprintf (buf, "ec=%d", err ); s=buf; break; + } + + return s; +} + +EOF
\ No newline at end of file |