diff options
Diffstat (limited to '')
| -rw-r--r-- | ChangeLog | 8 | ||||
| -rw-r--r-- | Makefile.am | 8 | ||||
| -rw-r--r-- | assuan/Makefile.am | 43 | ||||
| -rw-r--r-- | assuan/assuan-buffer.c | 247 | ||||
| -rw-r--r-- | assuan/assuan-connect.c | 129 | ||||
| -rw-r--r-- | assuan/assuan-defs.h | 110 | ||||
| -rw-r--r-- | assuan/assuan-handler.c | 431 | ||||
| -rw-r--r-- | assuan/assuan-listen.c | 86 | ||||
| -rw-r--r-- | assuan/assuan-pipe-server.c | 69 | ||||
| -rw-r--r-- | assuan/assuan-util.c | 98 | ||||
| -rw-r--r-- | assuan/assuan.h | 120 | ||||
| -rwxr-xr-x | assuan/mkerrors | 71 | ||||
| -rw-r--r-- | configure.ac | 8 | ||||
| -rw-r--r-- | gpgme/ChangeLog | 7 | ||||
| -rw-r--r-- | gpgme/Makefile.am | 5 | 
15 files changed, 1436 insertions, 4 deletions
@@ -1,5 +1,13 @@  2001-11-20  Marcus Brinkmann  <[email protected]> +	* Makefile.am (SUBDIRS): Support building the assuan library +	(currently if GPGSM_PATH is set).. +	* configure.ac: Support building the assuan library. +	* assuan: New directory, populated with the Assuan library +	(copied from the newpg repository). + +2001-11-20  Marcus Brinkmann  <[email protected]> +  	* configure.ac (NEED_GPGSM_VERSION): New variable.  Treat it  	similarly to NEED_GPGSM_VERSION.  	* acconfig.h: Likewise. diff --git a/Makefile.am b/Makefile.am index efe8c9ce..d9ef9645 100644 --- a/Makefile.am +++ b/Makefile.am @@ -21,6 +21,12 @@  EXTRA_DIST = README-alpha autogen.sh +if BUILD_ASSUAN +assuan = assuan +else +assuan = +endif +  if BUILD_BONOBO  bonobo = bonobo  else @@ -39,4 +45,4 @@ else  tests =   endif -SUBDIRS = jnlib gpgme ${tests} doc ${bonobo} ${complus} +SUBDIRS = ${assuan} jnlib gpgme ${tests} doc ${bonobo} ${complus} diff --git a/assuan/Makefile.am b/assuan/Makefile.am new file mode 100644 index 00000000..3c576900 --- /dev/null +++ b/assuan/Makefile.am @@ -0,0 +1,43 @@ +# 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 + +noinst_LIBRARIES = libassuan.a + + +#libassuan_a_LDFLAGS = +libassuan_a_SOURCES = \ +	assuan.h \ +	assuan-defs.h \ +	assuan-util.c \ +	assuan-errors.c \ +	assuan-buffer.c \ +	assuan-handler.c \ +	assuan-listen.c \ +	assuan-connect.c \ +	assuan-pipe-server.c  + + +assuan-errors.c : assuan.h +	$(srcdir)/mkerrors < $(srcdir)/assuan.h > assuan-errors.c diff --git a/assuan/assuan-buffer.c b/assuan/assuan-buffer.c new file mode 100644 index 00000000..912272f1 --- /dev/null +++ b/assuan/assuan-buffer.c @@ -0,0 +1,247 @@ +/* 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 <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <assert.h> + +#include "assuan-defs.h" + + +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 */ +} + +/* 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) +    { +      int n = read (fd, buf, nleft); +      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; +    } + +  return 0; +} + + +int +_assuan_read_line (ASSUAN_CONTEXT ctx) +{ +  char *line = ctx->inbound.line; +  int n, nread; +  int rc; +   +  if (ctx->inbound.eof) +    return -1; + +  rc = readline (ctx->inbound.fd, line, LINELENGTH, &nread, &ctx->inbound.eof); +  if (rc) +    return ASSUAN_Read_Error; +  if (!nread) +    { +      assert (ctx->inbound.eof); +      return -1;  +    } + +  for (n=nread-1; n>=0 ; n--) +    { +      if (line[n] == '\n') +        { +          if (n != nread-1) +            { +              fprintf (stderr, "DBG-assuan: %d bytes left over after read\n", +                       nread-1 - n); +              /* fixme: store them for the next read */ +            } +          if (n && line[n-1] == '\r') +            n--; +          line[n] = 0; +          ctx->inbound.linelen = n; +          return 0; +        } +    } + +  *line = 0; +  ctx->inbound.linelen = 0; +  return ctx->inbound.eof? ASSUAN_Line_Not_Terminated : ASSUAN_Line_Too_Long; +} + + + + +int  +_assuan_write_line (ASSUAN_CONTEXT ctx, const char *line ) +{ +  int rc; + +  /* fixme: we should do some kind of line buffering */ +  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) +        { +          *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) +    { +      *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; +} + + + + diff --git a/assuan/assuan-connect.c b/assuan/assuan-connect.c new file mode 100644 index 00000000..778b3a77 --- /dev/null +++ b/assuan/assuan-connect.c @@ -0,0 +1,129 @@ +/* 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 + */ + +#include <config.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <signal.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> + +#include "assuan-defs.h" + +/* 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.  */ +AssuanError +assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[]) +{ +  static int fixed_signals = 0; +  AssuanError err; +  int rp[2]; +  int wp[2]; +  int fd[2]; + +  if (!name || !argv || !argv[0]) +    return ASSUAN_General_Error; + +  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; +    } + +  fd[0] = rp[0];  /* Our inbound is read end of read pipe.  */ +  fd[1] = wp[1];  /* Our outbound is write end of write pipe.  */ + +  err = assuan_init_pipe_server (ctx, fd);  /* FIXME: Common code should be factored out.  */ +  if (err) +    { +      close (rp[0]); +      close (rp[1]); +      close (wp[0]); +      close (wp[1]); +      return err; +    } + +  (*ctx)->pid = fork (); +  if ((*ctx)->pid < 0) +    { +      close (rp[0]); +      close (rp[1]); +      close (wp[0]); +      close (wp[1]); +      assuan_deinit_pipe_server (*ctx);  /* FIXME: Common code should be factored out.  */ +      return ASSUAN_General_Error; +    } + +  if ((*ctx)->pid == 0) +    { +      close (rp[0]); +      close (wp[1]); +      if (rp[1] != STDOUT_FILENO) +	{ +	  dup2 (rp[1], STDOUT_FILENO);  /* Child's outbound is write end of read pipe.  */ +	  close (rp[1]); +	} +      if (wp[0] != STDIN_FILENO) +	{ +	  dup2 (wp[0], STDIN_FILENO);  /* Child's inbound is read end of write pipe.  */ +	  close (wp[0]); +	} +      execv (name, argv); +      _exit (1); +    } + +  close (rp[1]); +  close (wp[0]); +  _assuan_read_line (*ctx); /* FIXME: Handshake.  */ +  return 0; +} + +void +assuan_pipe_disconnect (ASSUAN_CONTEXT ctx) +{ +  _assuan_write_line (ctx, "BYE"); +  close (ctx->inbound.fd); +  close (ctx->outbound.fd); +  waitpid (ctx->pid, NULL, 0);  /* FIXME Check return value.  */ +  assuan_deinit_pipe_server (ctx); +} diff --git a/assuan/assuan-defs.h b/assuan/assuan-defs.h new file mode 100644 index 00000000..8723fd31 --- /dev/null +++ b/assuan/assuan-defs.h @@ -0,0 +1,110 @@ +/* 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 1002 /* 1000 + [CR,]LF */ + +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; +   +  void *user_pointer;  /* for assuan_[gs]et_pointer () */ + +  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 */ +  } 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.  */ + +  struct cmdtbl_s *cmdtbl; +  size_t cmdtbl_used; /* used entries */ +  size_t cmdtbl_size; /* allocated size of table */ + + +  int input_fd;   /* set by INPUT command */ +  int output_fd;  /* set by OUTPUT command */ + + + +}; + + +/*-- assuan-handler.c --*/ +int _assuan_register_std_commands (ASSUAN_CONTEXT ctx); + +/*-- assuan-buffer.c --*/ +int _assuan_write_line (ASSUAN_CONTEXT ctx, const char *line); +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-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)) + + +#endif /*ASSUAN_DEFS_H*/ + + + + + + + diff --git a/assuan/assuan-handler.c b/assuan/assuan-handler.c new file mode 100644 index 00000000..472206b0 --- /dev/null +++ b/assuan/assuan-handler.c @@ -0,0 +1,431 @@ +/* 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 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) +{ +  return set_error (ctx, Not_Implemented, NULL);  +} +   +static int +std_handler_bye (ASSUAN_CONTEXT ctx, char *line) +{ +  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) +{ +  return set_error (ctx, Not_Implemented, NULL);  +} +   +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); +  if (*endp) +    return set_error (ctx, Syntax_Error, "garbage found"); +  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; +  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; +  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 initializethis command */ +} std_cmd_table[] = { +  { "NOP",    ASSUAN_CMD_NOP,    std_handler_nop, 1 }, +  { "CANCEL", ASSUAN_CMD_CANCEL, std_handler_cancel, 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 }, +  { 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; +} + +/* 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); +} + + +/* 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) +    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); +} + + + + +/** + * 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 { +    /* Read the line but skip comments */ +    do +      { +        rc = _assuan_read_line (ctx); +        if (rc) +          return rc; +       +/*          fprintf (stderr, "DBG-assuan: got %d bytes `%s'\n", */ +/*                   ctx->inbound.linelen, ctx->inbound.line); */ +      } +    while ( *ctx->inbound.line == '#' || !ctx->inbound.linelen); + +    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; +      } +    /* Error handling */ +    if (!rc) +      { +        rc = _assuan_write_line (ctx, "OK"); +      } +    else if (rc == -1) +      { /* No error checking because the peer may have already disconnect */  +        _assuan_write_line (ctx, "OK  Bye, bye - hope to meet you again"); +      } +    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); +      } +  } while (!rc); + +  if (rc == -1) +    rc = 0; + +  return rc; +} + + +/* 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; +} + + +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/assuan/assuan-listen.c b/assuan/assuan-listen.c new file mode 100644 index 00000000..f8ccb270 --- /dev/null +++ b/assuan/assuan-listen.c @@ -0,0 +1,86 @@ +/* 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 "assuan-defs.h" + + + +/** + * 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. + **/ +int +assuan_accept (ASSUAN_CONTEXT ctx) +{ +  int rc; + +  if (!ctx) +    return ASSUAN_Invalid_Value; + +  /* fixme: cancel existing connection */ +  if (ctx->pipe_mode > 1) +    return -1; /* second invocation for pipemode -> terminate */ + +  if (!ctx->pipe_mode) +    { + +      /* fixme: wait for request */ +    } + +  /* send the hello */ +   +  rc = _assuan_write_line (ctx, +                           "OK Hello dear client - what can I do for you?"); +  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; +} + + diff --git a/assuan/assuan-pipe-server.c b/assuan/assuan-pipe-server.c new file mode 100644 index 00000000..018d05df --- /dev/null +++ b/assuan/assuan-pipe-server.c @@ -0,0 +1,69 @@ +/* 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" + + +int +assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2]) +{ +  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 = filedes[0]; +  ctx->outbound.fd = filedes[1]; + +  ctx->pipe_mode = 1; + +  rc = _assuan_register_std_commands (ctx); +  if (rc) +    xfree (ctx); +  else +    *r_ctx = ctx; +  return rc; +} + +void +assuan_deinit_pipe_server (ASSUAN_CONTEXT ctx) +{ +  xfree (ctx); +} + + + + + + + + + + + diff --git a/assuan/assuan-util.c b/assuan/assuan-util.c new file mode 100644 index 00000000..3eeee9ab --- /dev/null +++ b/assuan/assuan-util.c @@ -0,0 +1,98 @@ +/* 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" + + +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; +} + diff --git a/assuan/assuan.h b/assuan/assuan.h new file mode 100644 index 00000000..97462fb9 --- /dev/null +++ b/assuan/assuan.h @@ -0,0 +1,120 @@ +/* assuan.c - Definitions for the Assuna protocol + *	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_H +#define ASSUAN_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, + +  /* 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_Cert_Revoked = 301, +  ASSUAN_No_CRL_For_Cert = 302, +  ASSUNA_CRL_Too_Old = 303, + +} 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_DATA, +  ASSUAN_CMD_END, +  ASSUAN_CMD_INPUT, +  ASSUAN_CMD_OUTPUT, + +  ASSUAN_CMD_USER = 256  /* Other commands should be used with this offset*/ +} AssuanCommand; + + +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_process (ASSUAN_CONTEXT ctx); +FILE *assuan_get_data_fp (ASSUAN_CONTEXT ctx); +void assuan_write_status (ASSUAN_CONTEXT ctx, +                          const char *keyword, const char *text); + + +/*-- assuan-listen.c --*/ +int assuan_accept (ASSUAN_CONTEXT ctx); +int assuan_get_input_fd (ASSUAN_CONTEXT ctx); +int assuan_get_output_fd (ASSUAN_CONTEXT ctx); + + +/*-- assuan-pipe-server.c --*/ +int assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2]); +void assuan_deinit_pipe_server (ASSUAN_CONTEXT ctx); + + +/*-- assuan-connect.c --*/ +AssuanError assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, +                                 char *const argv[]); +void assuan_pipe_disconnect (ASSUAN_CONTEXT ctx); + +/*-- 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*) ); +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); + + +/*-- assuan-errors.c (built) --*/ +const char *assuan_strerror (AssuanError err); + + +#ifdef __cplusplus +} +#endif +#endif /*ASSUAN_H*/ diff --git a/assuan/mkerrors b/assuan/mkerrors new file mode 100755 index 00000000..13eabde7 --- /dev/null +++ b/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 diff --git a/configure.ac b/configure.ac index 55ab067f..bf3a5719 100644 --- a/configure.ac +++ b/configure.ac @@ -177,6 +177,9 @@ dnl  dnl Create config files   dnl +/* FIXME: Only build if supported.  */ +AM_CONDITIONAL(BUILD_ASSUAN, test "$GPGSM" != "no") +  AM_CONDITIONAL(BUILD_COMPLUS, test "$component_system" = "COM+")  AM_CONDITIONAL(BUILD_BONOBO,  test "$component_system" = "Bonobo") @@ -190,8 +193,9 @@ GPGME_CFLAGS=""  AC_SUBST(GPGME_LIBS)  AC_SUBST(GPGME_CFLAGS) -AC_CONFIG_FILES(Makefile jnlib/Makefile gpgme/Makefile tests/Makefile -		doc/Makefile bonobo/Makefile complus/Makefile) +AC_CONFIG_FILES(Makefile assuan/Makefile jnlib/Makefile gpgme/Makefile +		tests/Makefile doc/Makefile +		bonobo/Makefile complus/Makefile)  AC_CONFIG_FILES(gpgme/gpgme-config, chmod +x gpgme/gpgme-config)  AC_OUTPUT diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index b539b9f9..6e28bbfa 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,5 +1,11 @@  2001-11-20  Marcus Brinkmann  <[email protected]> +	* Makefile.am (libgpgme_la_INCLUDES): Remove obsolete directive. +	(AM_CPPFLAGS): New directive [BUILD_ASSUAN]. +	(libgpgme_la_LIBADD): Likewise. + +2001-11-20  Marcus Brinkmann  <[email protected]> +  	* version.c: Remove global variables lineno and  	tmp_engine_version.  	(version_handler): Removed. @@ -9,6 +15,7 @@  	* ops.h (_gpgme_get_program_version): Add prototype for  	_gpgme_get_program_version (we expect to use it elsewhere soon). +>>>>>>> 1.44  2001-11-18  Marcus Brinkmann  <[email protected]>  	* version.c (get_engine_info): If GnuPG is not available, return diff --git a/gpgme/Makefile.am b/gpgme/Makefile.am index 41b513cb..79155e3b 100644 --- a/gpgme/Makefile.am +++ b/gpgme/Makefile.am @@ -29,7 +29,10 @@ lib_LTLIBRARIES = libgpgme.la  libgpgme_la_LDFLAGS = -version-info \        @LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@ -libgpgme_la_INCLUDES = -I$(top_srcdir)/lib  +if BUILD_ASSUAN +AM_CPPFLAGS = -I$(top_srcdir)/assuan +libgpgme_la_LIBADD = -L../assuan -lassuan +endif  libgpgme_la_SOURCES = \  	gpgme.h types.h \  | 
