diff options
| author | Marcus Brinkmann <[email protected]> | 2002-01-22 16:29:12 +0000 | 
|---|---|---|
| committer | Marcus Brinkmann <[email protected]> | 2002-01-22 16:29:12 +0000 | 
| commit | b863cea7d70e32d0b0bcd84f87f5350818722242 (patch) | |
| tree | 92bb4b2448f5b2eb5651a730b47e3a71f8f438ce | |
| parent | Remove obsolete item. (diff) | |
| download | gpgme-b863cea7d70e32d0b0bcd84f87f5350818722242.tar.gz gpgme-b863cea7d70e32d0b0bcd84f87f5350818722242.zip  | |
Update to current version in newpg module.
Diffstat (limited to '')
| -rw-r--r-- | assuan/ChangeLog | 68 | ||||
| -rw-r--r-- | assuan/Makefile.am | 5 | ||||
| -rw-r--r-- | assuan/assuan-buffer.c | 56 | ||||
| -rw-r--r-- | assuan/assuan-client.c | 6 | ||||
| -rw-r--r-- | assuan/assuan-connect.c | 210 | ||||
| -rw-r--r-- | assuan/assuan-defs.h | 22 | ||||
| -rw-r--r-- | assuan/assuan-handler.c | 129 | ||||
| -rw-r--r-- | assuan/assuan-inquire.c | 9 | ||||
| -rw-r--r-- | assuan/assuan-listen.c | 10 | ||||
| -rw-r--r-- | assuan/assuan-pipe-connect.c | 269 | ||||
| -rw-r--r-- | assuan/assuan-pipe-server.c | 80 | ||||
| -rw-r--r-- | assuan/assuan-socket-connect.c | 150 | ||||
| -rw-r--r-- | assuan/assuan-socket-server.c | 121 | ||||
| -rw-r--r-- | assuan/assuan-util.c | 98 | ||||
| -rw-r--r-- | assuan/assuan.h | 31 | ||||
| -rw-r--r-- | jnlib/ChangeLog | 16 | ||||
| -rw-r--r-- | jnlib/Makefile.am | 17 | ||||
| -rw-r--r-- | jnlib/argparse.c | 2 | ||||
| -rw-r--r-- | jnlib/libjnlib-config.h | 16 | ||||
| -rw-r--r-- | jnlib/logging.c | 163 | ||||
| -rw-r--r-- | jnlib/logging.h | 27 | ||||
| -rw-r--r-- | jnlib/strlist.c | 133 | ||||
| -rw-r--r-- | jnlib/strlist.h | 43 | 
23 files changed, 1372 insertions, 309 deletions
diff --git a/assuan/ChangeLog b/assuan/ChangeLog index dbf5f43e..76cd68e3 100644 --- a/assuan/ChangeLog +++ b/assuan/ChangeLog @@ -1,3 +1,69 @@ +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 @@ -90,7 +156,7 @@       * You may find it source-copied in other packages.        *       ***********************************************************	 - Copyright 2001 Free Software Foundation, Inc. + 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 diff --git a/assuan/Makefile.am b/assuan/Makefile.am index bc14e8f6..7508dce2 100644 --- a/assuan/Makefile.am +++ b/assuan/Makefile.am @@ -38,7 +38,10 @@ libassuan_a_SOURCES = \  	assuan-listen.c \  	assuan-connect.c \  	assuan-client.c \ -	assuan-pipe-server.c  +	assuan-pipe-server.c \ +	assuan-socket-server.c \ +	assuan-pipe-connect.c \ +	assuan-socket-connect.c   assuan-errors.c : assuan.h diff --git a/assuan/assuan-buffer.c b/assuan/assuan-buffer.c index 399d11db..bd088174 100644 --- a/assuan/assuan-buffer.c +++ b/assuan/assuan-buffer.c @@ -20,6 +20,7 @@  #include <config.h>  #include <stdlib.h> +#include <string.h>  #include <stdio.h>  #include <errno.h>  #include <unistd.h> @@ -119,10 +120,17 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)      rc = readline (ctx->inbound.fd, line, LINELENGTH,                     &nread, &ctx->inbound.eof);    if (rc) -    return ASSUAN_Read_Error; +    { +      if (ctx->log_fp) +        fprintf (ctx->log_fp, "%p <- [Error: %s]\n", +                 ctx, strerror (errno));  +      return ASSUAN_Read_Error; +    }    if (!nread)      {        assert (ctx->inbound.eof); +      if (ctx->log_fp) +        fprintf (ctx->log_fp, "%p <- [EOF]\n", ctx);         return -1;       } @@ -153,10 +161,23 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)              n--;            line[n] = 0;            ctx->inbound.linelen = n; +          if (ctx->log_fp) +            { +              fprintf (ctx->log_fp, "%p <- ", 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, "%p <- [Invalid line]\n", ctx);    *line = 0;    ctx->inbound.linelen = 0;    return ctx->inbound.eof? ASSUAN_Line_Not_Terminated : ASSUAN_Line_Too_Long; @@ -206,6 +227,17 @@ assuan_write_line (ASSUAN_CONTEXT ctx, const char *line )      return ASSUAN_Invalid_Value;    /* fixme: we should do some kind of line buffering */ +  if (ctx->log_fp) +    { +      fprintf (ctx->log_fp, "%p -> ", 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; @@ -266,6 +298,17 @@ _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size)        if (linelen >= LINELENGTH-2-2)          { +          if (ctx->log_fp) +            { +              fprintf (ctx->log_fp, "%p -> ", 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)) @@ -300,6 +343,17 @@ _assuan_cookie_write_flush (void *cookie)    line += linelen;    if (linelen)      { +      if (ctx->log_fp) +        { +          fprintf (ctx->log_fp, "%p -> ", 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)) diff --git a/assuan/assuan-client.c b/assuan/assuan-client.c index a555cf33..d56357dc 100644 --- a/assuan/assuan-client.c +++ b/assuan/assuan-client.c @@ -63,6 +63,8 @@ _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off)      {        *okay = 1;        *off = 2; +      while (line[*off] == ' ') +        ++*off;      }    else if (linelen >= 3             && line[0] == 'E' && line[1] == 'R' && line[2] == 'R' @@ -70,6 +72,8 @@ _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off)      {        *okay = 0;        *off = 3; +      while (line[*off] == ' ') +        ++*off;      }      else if (linelen >= 7             && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q' @@ -79,6 +83,8 @@ _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off)      {        *okay = 3;        *off = 7; +      while (line[*off] == ' ') +        ++*off;      }    else      rc = ASSUAN_Invalid_Response; diff --git a/assuan/assuan-connect.c b/assuan/assuan-connect.c index 613b54a1..49d4aac2 100644 --- a/assuan/assuan-connect.c +++ b/assuan/assuan-connect.c @@ -33,208 +33,18 @@  #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 ) +/* Disconnect and release the context CTX. */ +void +assuan_disconnect (ASSUAN_CONTEXT ctx)  { -  while (length) +  if (ctx)      { -      int nwritten = write (fd, buffer, length); -       -      if (nwritten < 0) -        { -          if (errno == EINTR) -            continue; -          return -1; /* write error */ -        } -      length -= nwritten; -      buffer += nwritten; +      assuan_write_line (ctx, "BYE"); +      ctx->finish_handler (ctx); +      ctx->deinit_handler (ctx); +      ctx->deinit_handler = NULL; +      _assuan_release_context (ctx);      } -  return 0;  /* okay */ -} - - - -/* 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_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[], -		     int *fd_child_list) -{ -  static int fixed_signals = 0; -  AssuanError err; -  int rp[2]; -  int wp[2]; -  int fd[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; -    } -   -  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)->is_server = 0; - -  (*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) -    { -      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]); -        } - -      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) -    { -      if ((*ctx)->pid != -1) -        waitpid ((*ctx)->pid, NULL, 0);  /* FIXME Check return value.  */ -      assuan_deinit_pipe_server (*ctx);  /* FIXME: Common code should be factored out.  */ -    } - -  return err; -} - -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);  }  pid_t @@ -242,5 +52,3 @@ assuan_get_pid (ASSUAN_CONTEXT ctx)  {    return ctx ? ctx->pid : -1;  } - - diff --git a/assuan/assuan-defs.h b/assuan/assuan-defs.h index ecabd382..7d55aabd 100644 --- a/assuan/assuan-defs.h +++ b/assuan/assuan-defs.h @@ -35,13 +35,18 @@ struct cmdtbl_s {  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; @@ -68,7 +73,13 @@ struct assuan_context_s {    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.  */ +  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) */ + +  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 */ @@ -77,6 +88,7 @@ struct assuan_context_s {    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 *); @@ -84,9 +96,12 @@ struct assuan_context_s {    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 --*/ @@ -114,6 +129,9 @@ void  _assuan_free (void *p);  #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/assuan/assuan-handler.c b/assuan/assuan-handler.c index a82bd537..1c8aded7 100644 --- a/assuan/assuan-handler.c +++ b/assuan/assuan-handler.c @@ -25,6 +25,7 @@  #include "assuan-defs.h" +#define spacep(p)  (*(p) == ' ' || *(p) == '\t')  #define digitp(a) ((a) >= '0' && (a) <= '9') @@ -48,6 +49,53 @@ std_handler_cancel (ASSUAN_CONTEXT ctx, char *line)      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) @@ -147,6 +195,7 @@ static struct {  } 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 }, @@ -154,6 +203,7 @@ static struct {    { "INPUT",  ASSUAN_CMD_INPUT,  std_handler_input },    { "OUTPUT", ASSUAN_CMD_OUTPUT, std_handler_output }, +  { "OPTION", ASSUAN_CMD_OPTION, std_handler_option, 1 },    { NULL }  }; @@ -263,6 +313,17 @@ assuan_register_cancel_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))  }  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 *))  { @@ -312,6 +373,20 @@ 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 @@ -339,8 +414,18 @@ dispatch_command (ASSUAN_CONTEXT ctx, char *line, int linelen)    shift = p - line;    for (i=0; (s=ctx->cmdtbl[i].name); i++) -    if (!strcmp (line, s)) -      break; +    { +      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; @@ -382,17 +467,18 @@ process_request (ASSUAN_CONTEXT ctx)    /* Error handling */    if (!rc)      { -      rc = assuan_write_line (ctx, "OK"); +      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) +        if (rc < 100)          sprintf (errline, "ERR %d server fault (%.50s)",                   ASSUAN_Server_Fault, assuan_strerror (rc));        else @@ -405,6 +491,12 @@ process_request (ASSUAN_CONTEXT ctx)        rc = assuan_write_line (ctx, errline);      } +  ctx->confidential = 0; +  if (ctx->okay_line) +    { +      xfree (ctx->okay_line); +      ctx->okay_line = NULL; +    }    return rc;  } @@ -522,6 +614,35 @@ assuan_get_data_fp (ASSUAN_CONTEXT ctx)  } +/* Set the text used for the next OK reponse.  This string is +   automatically reset to NULL after the next command. */ +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)  { diff --git a/assuan/assuan-inquire.c b/assuan/assuan-inquire.c index 8fec77ef..933091e1 100644 --- a/assuan/assuan-inquire.c +++ b/assuan/assuan-inquire.c @@ -1,5 +1,5 @@  /* assuan-inquire.c - handle inquire stuff - *	Copyright (C) 2001 Free Software Foundation, Inc. + *	Copyright (C) 2001, 2002 Free Software Foundation, Inc.   *   * This file is part of GnuPG.   * @@ -56,7 +56,8 @@ init_membuf (struct membuf *mb, int initiallen, size_t maxlen)    mb->out_of_core = 0;    mb->too_large = 0;    mb->maxlen = maxlen; -  mb->buf = xtrymalloc (initiallen); +  /* we need to allocate one byte more for get_membuf */ +  mb->buf = xtrymalloc (initiallen+1);    if (!mb->buf)        mb->out_of_core = 1;  } @@ -78,7 +79,8 @@ put_membuf (struct membuf *mb, const void *buf, size_t len)        char *p;        mb->size += len + 1024; -      p = xtryrealloc (mb->buf, mb->size); +      /* we need to allocate one byte more for get_membuf */ +      p = xtryrealloc (mb->buf, mb->size+1);        if (!p)          {            mb->out_of_core = 1; @@ -102,6 +104,7 @@ get_membuf (struct membuf *mb, size_t *len)        return NULL;      } +  mb->buf[mb->len] = 0; /* there is enough space for the hidden eos */    p = mb->buf;    *len = mb->len;    mb->buf = NULL; diff --git a/assuan/assuan-listen.c b/assuan/assuan-listen.c index 57fe4b66..db63ad2b 100644 --- a/assuan/assuan-listen.c +++ b/assuan/assuan-listen.c @@ -69,15 +69,13 @@ assuan_accept (ASSUAN_CONTEXT ctx)    if (!ctx)      return ASSUAN_Invalid_Value; -  /* fixme: cancel existing connection */    if (ctx->pipe_mode > 1)      return -1; /* second invocation for pipemode -> terminate */ +  ctx->finish_handler (ctx); -  if (!ctx->pipe_mode) -    { - -      /* fixme: wait for request */ -    } +  rc = ctx->accept_handler (ctx); +  if (rc) +    return rc;    /* send the hello */    rc = assuan_write_line (ctx, ctx->hello_line? ctx->hello_line diff --git a/assuan/assuan-pipe-connect.c b/assuan/assuan-pipe-connect.c new file mode 100644 index 00000000..ccfc1f01 --- /dev/null +++ b/assuan/assuan-pipe-connect.c @@ -0,0 +1,269 @@ +/* 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 "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_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[], +		     int *fd_child_list) +{ +  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]); +        } + +      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; +} + + + + + + + + + + + + + + diff --git a/assuan/assuan-pipe-server.c b/assuan/assuan-pipe-server.c index 2a9b829a..d15f54f5 100644 --- a/assuan/assuan-pipe-server.c +++ b/assuan/assuan-pipe-server.c @@ -24,9 +24,31 @@  #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_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2]) +_assuan_new_context (ASSUAN_CONTEXT *r_ctx)  {    ASSUAN_CONTEXT ctx;    int rc; @@ -35,14 +57,17 @@ assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2])    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 = filedes[0]; -  ctx->outbound.fd = filedes[1]; +  ctx->inbound.fd = -1; +  ctx->outbound.fd = -1; -  ctx->pipe_mode = 1; +  ctx->listen_fd = -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) @@ -52,22 +77,47 @@ assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2])    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_deinit_pipe_server (ASSUAN_CONTEXT ctx) +_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/assuan/assuan-socket-connect.c b/assuan/assuan-socket-connect.c new file mode 100644 index 00000000..6602b827 --- /dev/null +++ b/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), stderror) +#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/assuan/assuan-socket-server.c b/assuan/assuan-socket-server.c new file mode 100644 index 00000000..6ad6455e --- /dev/null +++ b/assuan/assuan-socket-server.c @@ -0,0 +1,121 @@ +/* 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> + +#include "assuan-defs.h" + +static int +accept_connection (ASSUAN_CONTEXT ctx) +{ +  int fd; +  struct sockaddr_un clnt_addr; +  size_t len = sizeof clnt_addr; + +  fd = accept (ctx->listen_fd, (struct sockaddr*)&clnt_addr, &len ); +  if (fd == -1) +    { +      ctx->os_errno = errno; +      return ASSUAN_Accept_Failed; +    } + +  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/assuan/assuan-util.c b/assuan/assuan-util.c index 3eeee9ab..4153ef8d 100644 --- a/assuan/assuan-util.c +++ b/assuan/assuan-util.c @@ -25,6 +25,10 @@  #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; @@ -96,3 +100,97 @@ 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/assuan/assuan.h b/assuan/assuan.h index cddc98cb..5971d81b 100644 --- a/assuan/assuan.h +++ b/assuan/assuan.h @@ -1,5 +1,5 @@  /* assuan.c - Definitions for the Assuna protocol - *	Copyright (C) 2001 Free Software Foundation, Inc. + *	Copyright (C) 2001, 2002 Free Software Foundation, Inc.   *   * This file is part of GnuPG.   * @@ -47,6 +47,7 @@ typedef enum {    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, @@ -69,6 +70,9 @@ typedef enum {    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_Bad_Certificate = 201,    ASSUAN_Bad_Certificate_Path = 202, @@ -83,6 +87,7 @@ typedef enum {    ASSUAN_Cert_Revoked = 301,    ASSUAN_No_CRL_For_Cert = 302,    ASSUAN_CRL_Too_Old = 303, +  ASSUAN_Not_Trusted = 304,  } AssuanError; @@ -93,6 +98,7 @@ typedef enum {    ASSUAN_CMD_BYE,    ASSUAN_CMD_AUTH,    ASSUAN_CMD_RESET, +  ASSUAN_CMD_OPTION,    ASSUAN_CMD_DATA,    ASSUAN_CMD_END,    ASSUAN_CMD_INPUT, @@ -120,6 +126,11 @@ 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, @@ -127,6 +138,7 @@ int assuan_get_active_fds (ASSUAN_CONTEXT ctx, int what,  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); @@ -142,13 +154,21 @@ 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_pipe_server (ASSUAN_CONTEXT ctx); +void assuan_deinit_server (ASSUAN_CONTEXT ctx); +/*-- assuan-socket-server.c --*/ +int assuan_init_socket_server (ASSUAN_CONTEXT *r_ctx, int listen_fd); -/*-- assuan-connect.c --*/ + +/*-- assuan-pipe-connect.c --*/  AssuanError assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name,                                   char *const argv[], int *fd_child_list); -void assuan_pipe_disconnect (ASSUAN_CONTEXT ctx); +/*-- 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 --*/ @@ -178,10 +198,13 @@ AssuanError assuan_send_data (ASSUAN_CONTEXT ctx,  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); diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 1d750bfa..b5f723cf 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -5,6 +5,22 @@  	unconditionally.  	Reported by Jose Carlos Garcia Sogo <[email protected]>. +2002-01-19  Werner Koch  <[email protected]> + +	* logging.c (log_get_stream): New. + +2001-12-05  Werner Koch  <[email protected]> + +	* logging.c (log_set_prefix): New. +	(do_logv): Include prefix and pid only if enabled. Print time only +	when explicitly enabled. +	(log_logv): New.   +	* logging.h: Include log_logv() only when requested. + +2001-11-06  Werner Koch  <[email protected]> + +	* strlist.c, strlist.h: New. Taken from pgnupg/util/strgutil.c +  2001-08-30  Werner Koch  <[email protected]>  	* logging.c (log_printf): Don't pass NULL instead of arg_ptr. diff --git a/jnlib/Makefile.am b/jnlib/Makefile.am index 1049f3c2..515a49a6 100644 --- a/jnlib/Makefile.am +++ b/jnlib/Makefile.am @@ -26,11 +26,14 @@ noinst_LIBRARIES = libjnlib.a  #libjnlib_a_LDFLAGS = -libjnlib_a_SOURCES = libjnlib-config.h	       \ -		     xmalloc.c xmalloc.h       \ -		     stringhelp.c stringhelp.h \ -		     argparse.c argparse.h     \ -		     logging.c logging.h       \ -		     types.h mischelp.h - +libjnlib_a_SOURCES = \ +	libjnlib-config.h \ +	stringhelp.c stringhelp.h \ +	strlist.c strlist.h \ +	argparse.c argparse.h \ +	logging.c logging.h  \ +	dotlock.c dotlock.h  \ +	types.h mischelp.h + +#		     xmalloc.c xmalloc.h        diff --git a/jnlib/argparse.c b/jnlib/argparse.c index ba635585..0e353e4d 100644 --- a/jnlib/argparse.c +++ b/jnlib/argparse.c @@ -900,7 +900,7 @@ strusage( int level )      switch( level ) {        case 11: p = "foo"; break;        case 13: p = "0.0"; break; -      case 14: p = "Copyright (C) 2000 Free Software Foundation, Inc."; break; +      case 14: p = "Copyright (C) 2001 Free Software Foundation, Inc."; break;        case 15: p =  "This program comes with ABSOLUTELY NO WARRANTY.\n"  "This is free software, and you are welcome to redistribute it\n" diff --git a/jnlib/libjnlib-config.h b/jnlib/libjnlib-config.h index de8e6a47..ec31d356 100644 --- a/jnlib/libjnlib-config.h +++ b/jnlib/libjnlib-config.h @@ -26,11 +26,9 @@  #ifndef LIBJNLIB_CONFIG_H  #define LIBJNLIB_CONFIG_H -#include "xmalloc.h" +#include <gcrypt.h> /* gcry_malloc & Cie. */  #include "logging.h" - -  #ifdef USE_SIMPLE_GETTEXT    int set_gettext_file( const char *filename );    const char *gettext( const char *msgid ); @@ -58,11 +56,11 @@  #endif /* !USE_SIMPLE_GETTEXT */ -#define jnlib_xmalloc(a)    xmalloc( (a) ) -#define jnlib_xcalloc(a,b)  xcalloc( (a), (b) ) -#define jnlib_xrealloc(a,n) xrealloc( (a), (n) ) -#define jnlib_xstrdup(a)    xstrdup( (a) ) -#define jnlib_free(a)	    free( (a) ) +#define jnlib_xmalloc(a)    gcry_xmalloc( (a) ) +#define jnlib_xcalloc(a,b)  gcry_xcalloc( (a), (b) ) +#define jnlib_xrealloc(a,n) gcry_xrealloc( (a), (n) ) +#define jnlib_xstrdup(a)    gcry_xstrdup( (a) ) +#define jnlib_free(a)	    gcry_free( (a) )  #define jnlib_log_debug    log_debug  #define jnlib_log_info	   log_info @@ -73,3 +71,5 @@  #endif /*LIBJNUTIL_CONFIG_H*/ + + diff --git a/jnlib/logging.c b/jnlib/logging.c index 69b94b1b..2e0d53ae 100644 --- a/jnlib/logging.c +++ b/jnlib/logging.c @@ -31,26 +31,23 @@  #include <stdarg.h>  #include <errno.h>  #include <time.h> +#include <sys/types.h> +#include <unistd.h>  #ifdef __MINGW32__    #include <io.h>  #endif +#define JNLIB_NEED_LOG_LOGV 1  #include "libjnlib-config.h"  #include "logging.h" -enum my_log_levels { -    MY_LOG_BEGIN,  /* only print the timestamp if configured */ -    MY_LOG_CONT, -    MY_LOG_INFO, -    MY_LOG_WARN, -    MY_LOG_ERROR, -    MY_LOG_FATAL, -    MY_LOG_BUG, -    MY_LOG_DEBUG -};  static FILE *logstream; -static int use_time; +static char prefix_buffer[80]; +static int with_time; +static int with_prefix; +static int with_pid; +  static int missing_lf;  static int errorcount; @@ -95,61 +92,93 @@ log_set_file( const char *name )      if( logstream && logstream != stderr )  	fclose( logstream );      logstream = fp; -    use_time = fp != stderr;      missing_lf = 0;  } +void +log_set_prefix (const char *text, unsigned int flags) +{ +  if (text) +    { +      strncpy (prefix_buffer, text, sizeof (prefix_buffer)-1); +      prefix_buffer[sizeof (prefix_buffer)-1] = 0; +    } +   +  with_prefix = (flags & 1); +  with_time = (flags & 2); +  with_pid  = (flags & 4); +} +  int  log_get_fd()  {      return fileno(logstream?logstream:stderr);  } -static void -do_logv( int level, const char *fmt, va_list arg_ptr ) +FILE * +log_get_stream ()  { -    if( !logstream ) -	logstream = stderr; - -    if( missing_lf && level != MY_LOG_CONT ) -	putc('\n', logstream ); -    missing_lf = 0; +    return logstream?logstream:stderr; +} -    if( use_time && level != MY_LOG_CONT ) { -	/* Note this does not work for multiple line logging as we would -	 * need to print to a buffer first */ -	struct tm *tp; -	time_t atime = time(NULL); -	tp = localtime( &atime ); -	fprintf( logstream, "%04d-%02d-%02d %02d:%02d:%02d ", -		    1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday, -			 tp->tm_hour, tp->tm_min, tp->tm_sec ); +static void +do_logv( int level, const char *fmt, va_list arg_ptr ) +{ +  if (!logstream) +    logstream = stderr; + +  if (missing_lf && level != JNLIB_LOG_CONT) +    putc('\n', logstream ); +  missing_lf = 0; + +  if (level != JNLIB_LOG_CONT) +    { /* Note this does not work for multiple line logging as we would +       * need to print to a buffer first */ +      if (with_time) +        { +          struct tm *tp; +          time_t atime = time (NULL); +           +          tp = localtime (&atime); +          fprintf (logstream, "%04d-%02d-%02d %02d:%02d:%02d ", +                   1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday, +                   tp->tm_hour, tp->tm_min, tp->tm_sec ); +        } +      if (with_prefix) +        fputs (prefix_buffer, logstream); +      if (with_pid) +        fprintf (logstream, "[%u]", (unsigned int)getpid ()); +      if (!with_time) +        putc (':', logstream); +      putc (' ', logstream);      } -    switch ( level ) { -      case MY_LOG_BEGIN: break; -      case MY_LOG_CONT: break; -      case MY_LOG_INFO: break; -      case MY_LOG_WARN: break; -      case MY_LOG_ERROR: break; -      case MY_LOG_FATAL: fputs("Fatal: ",logstream ); break; -      case MY_LOG_BUG: fputs("Ohhhh jeeee: ", logstream); break; -      case MY_LOG_DEBUG: fputs("DBG: ", logstream ); break; -      default: fprintf(logstream,"[Unknown log level %d]: ", level ); break; +  switch (level) +    { +    case JNLIB_LOG_BEGIN: break; +    case JNLIB_LOG_CONT: break; +    case JNLIB_LOG_INFO: break; +    case JNLIB_LOG_WARN: break; +    case JNLIB_LOG_ERROR: break; +    case JNLIB_LOG_FATAL: fputs("Fatal: ",logstream ); break; +    case JNLIB_LOG_BUG: fputs("Ohhhh jeeee: ", logstream); break; +    case JNLIB_LOG_DEBUG: fputs("DBG: ", logstream ); break; +    default: fprintf(logstream,"[Unknown log level %d]: ", level ); break;      } -    if( fmt ) { -	vfprintf(logstream,fmt,arg_ptr) ; -	if( *fmt && fmt[strlen(fmt)-1] != '\n' ) -	    missing_lf = 1; +  if (fmt) +    { +      vfprintf(logstream,fmt,arg_ptr) ; +      if (*fmt && fmt[strlen(fmt)-1] != '\n') +        missing_lf = 1;      } -    if( level == MY_LOG_FATAL ) -	exit(2); -    if( level == MY_LOG_BUG ) -	abort(); +  if (level == JNLIB_LOG_FATAL) +    exit(2); +  if (level == JNLIB_LOG_BUG) +    abort();  }  static void @@ -163,6 +192,11 @@ do_log( int level, const char *fmt, ... )  } +void +log_logv (int level, const char *fmt, va_list arg_ptr) +{ +  do_logv (level, fmt, arg_ptr); +}  void  log_info( const char *fmt, ... ) @@ -170,7 +204,7 @@ log_info( const char *fmt, ... )      va_list arg_ptr ;      va_start( arg_ptr, fmt ) ; -    do_logv( MY_LOG_INFO, fmt, arg_ptr ); +    do_logv( JNLIB_LOG_INFO, fmt, arg_ptr );      va_end(arg_ptr);  } @@ -180,7 +214,7 @@ log_error( const char *fmt, ... )      va_list arg_ptr ;      va_start( arg_ptr, fmt ) ; -    do_logv( MY_LOG_ERROR, fmt, arg_ptr ); +    do_logv( JNLIB_LOG_ERROR, fmt, arg_ptr );      va_end(arg_ptr);      /* protect against counter overflow */      if( errorcount < 30000 ) @@ -194,7 +228,7 @@ log_fatal( const char *fmt, ... )      va_list arg_ptr ;      va_start( arg_ptr, fmt ) ; -    do_logv( MY_LOG_FATAL, fmt, arg_ptr ); +    do_logv( JNLIB_LOG_FATAL, fmt, arg_ptr );      va_end(arg_ptr);      abort(); /* never called, bugs it makes the compiler happy */  } @@ -205,7 +239,7 @@ log_bug( const char *fmt, ... )      va_list arg_ptr ;      va_start( arg_ptr, fmt ) ; -    do_logv( MY_LOG_BUG, fmt, arg_ptr ); +    do_logv( JNLIB_LOG_BUG, fmt, arg_ptr );      va_end(arg_ptr);      abort(); /* never called, but it makes the compiler happy */  } @@ -216,7 +250,7 @@ log_debug( const char *fmt, ... )      va_list arg_ptr ;      va_start( arg_ptr, fmt ) ; -    do_logv( MY_LOG_DEBUG, fmt, arg_ptr ); +    do_logv( JNLIB_LOG_DEBUG, fmt, arg_ptr );      va_end(arg_ptr);  } @@ -227,16 +261,35 @@ log_printf (const char *fmt, ...)    va_list arg_ptr;    va_start (arg_ptr, fmt); -  do_logv (fmt ? MY_LOG_CONT : MY_LOG_BEGIN, fmt, arg_ptr); +  do_logv (fmt ? JNLIB_LOG_CONT : JNLIB_LOG_BEGIN, fmt, arg_ptr);    va_end (arg_ptr);  } +/* Print a hexdump of BUFFER.  With TEXT of NULL print just the raw +   dump, with TEXT just an empty string, print a trailing linefeed, +   otherwise print an entire debug line. */ +void +log_printhex (const char *text, const void *buffer, size_t length) +{ +  if (text && *text) +    log_debug ("%s ", text); +  if (length) +    { +      const unsigned char *p = buffer; +      log_printf ("%02X", *p); +      for (length--, p++; length--; p++) +        log_printf (" %02X", *p); +    } +  if (text) +    log_printf ("\n"); +} +  #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )  void  bug_at( const char *file, int line, const char *func )  { -    do_log( MY_LOG_BUG, +    do_log( JNLIB_LOG_BUG,  	     ("... this is a bug (%s:%d:%s)\n"), file, line, func );      abort(); /* never called, but it makes the compiler happy */  } @@ -244,7 +297,7 @@ bug_at( const char *file, int line, const char *func )  void  bug_at( const char *file, int line )  { -    do_log( MY_LOG_BUG, +    do_log( JNLIB_LOG_BUG,  	     _("you found a bug ... (%s:%d)\n"), file, line);      abort(); /* never called, but it makes the compiler happy */  } diff --git a/jnlib/logging.h b/jnlib/logging.h index 83158f0b..7b7b8c8a 100644 --- a/jnlib/logging.h +++ b/jnlib/logging.h @@ -24,9 +24,12 @@  #include <stdio.h>  #include "mischelp.h" +  int  log_get_errorcount (int clear);  void log_set_file( const char *name ); +void log_set_prefix (const char *text, unsigned int flags);  int  log_get_fd(void); +FILE *log_get_stream (void);  #ifdef JNLIB_GCC_M_FUNCTION    void bug_at( const char *file, int line, const char *func ) JNLIB_GCC_A_NR; @@ -36,12 +39,36 @@ int  log_get_fd(void);  # define BUG() bug_at( __FILE__ , __LINE__ )  #endif +/* To avoid mandatory inclusion of stdarg and other stuff, do it only +   if explicitly requested to do so. */ +#ifdef JNLIB_NEED_LOG_LOGV +#include <stdarg.h> +enum jnlib_log_levels { +    JNLIB_LOG_BEGIN, +    JNLIB_LOG_CONT, +    JNLIB_LOG_INFO, +    JNLIB_LOG_WARN, +    JNLIB_LOG_ERROR, +    JNLIB_LOG_FATAL, +    JNLIB_LOG_BUG, +    JNLIB_LOG_DEBUG +}; +void log_logv (int level, const char *fmt, va_list arg_ptr); +#endif /*JNLIB_NEED_LOG_LOGV*/ + +  void log_bug( const char *fmt, ... )	JNLIB_GCC_A_NR_PRINTF(1,2);  void log_fatal( const char *fmt, ... )	JNLIB_GCC_A_NR_PRINTF(1,2);  void log_error( const char *fmt, ... )	JNLIB_GCC_A_PRINTF(1,2);  void log_info( const char *fmt, ... )	JNLIB_GCC_A_PRINTF(1,2);  void log_debug( const char *fmt, ... )	JNLIB_GCC_A_PRINTF(1,2);  void log_printf( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); +void log_printhex (const char *text, const void *buffer, size_t length);  #endif /*LIBJNLIB_LOGGING_H*/ + + + + + diff --git a/jnlib/strlist.c b/jnlib/strlist.c new file mode 100644 index 00000000..7cbaf5e0 --- /dev/null +++ b/jnlib/strlist.c @@ -0,0 +1,133 @@ +/* strlist.c -  string helpers + *	Copyright (C) 1998, 2000, 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 <stdarg.h> +#include <ctype.h> + +#include "libjnlib-config.h" +#include "strlist.h" + + +void +free_strlist( STRLIST sl ) +{ +    STRLIST sl2; + +    for(; sl; sl = sl2 ) { +	sl2 = sl->next; +	jnlib_free(sl); +    } +} + + +STRLIST +add_to_strlist( STRLIST *list, const char *string ) +{ +    STRLIST sl; + +    sl = jnlib_xmalloc( sizeof *sl + strlen(string)); +    sl->flags = 0; +    strcpy(sl->d, string); +    sl->next = *list; +    *list = sl; +    return sl; +} + +#if 0 +/**************** + * same as add_to_strlist() but if is_utf8 is *not* set a conversion + * to UTF8 is done + */ +STRLIST +add_to_strlist2( STRLIST *list, const char *string, int is_utf8 ) +{ +    STRLIST sl; + +    if( is_utf8 ) +	sl = add_to_strlist( list, string ); +    else { +	char *p = native_to_utf8( string ); +	sl = add_to_strlist( list, p ); +	m_free( p ); +    } +    return sl; +} +#endif + +STRLIST +append_to_strlist( STRLIST *list, const char *string ) +{ +    STRLIST r, sl; + +    sl = jnlib_xmalloc( sizeof *sl + strlen(string)); +    sl->flags = 0; +    strcpy(sl->d, string); +    sl->next = NULL; +    if( !*list ) +	*list = sl; +    else { +	for( r = *list; r->next; r = r->next ) +	    ; +	r->next = sl; +    } +    return sl; +} + +#if 0 +STRLIST +append_to_strlist2( STRLIST *list, const char *string, int is_utf8 ) +{ +    STRLIST sl; + +    if( is_utf8 ) +	sl = append_to_strlist( list, string ); +    else { +	char *p = native_to_utf8( string ); +	sl = append_to_strlist( list, p ); +	m_free( p ); +    } +    return sl; +} +#endif + +STRLIST +strlist_prev( STRLIST head, STRLIST node ) +{ +    STRLIST n; + +    for(n=NULL; head && head != node; head = head->next ) +	n = head; +    return n; +} + +STRLIST +strlist_last( STRLIST node ) +{ +    if( node ) +	for( ; node->next ; node = node->next ) +	    ; +    return node; +} + + + diff --git a/jnlib/strlist.h b/jnlib/strlist.h new file mode 100644 index 00000000..53c0bc75 --- /dev/null +++ b/jnlib/strlist.h @@ -0,0 +1,43 @@ +/* strlist.h + *	Copyright (C) 1998, 2000, 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 LIBJNLIB_STRLIST_H +#define LIBJNLIB_STRLIST_H + +struct string_list { +  struct string_list *next; +  unsigned int flags; +  char d[1]; +}; +typedef struct string_list *STRLIST; + + +void    free_strlist( STRLIST sl ); +STRLIST add_to_strlist( STRLIST *list, const char *string ); +STRLIST add_to_strlist2( STRLIST *list, const char *string, int is_utf8 ); +STRLIST append_to_strlist( STRLIST *list, const char *string ); +STRLIST append_to_strlist2( STRLIST *list, const char *string, int is_utf8 ); +STRLIST strlist_prev( STRLIST head, STRLIST node ); +STRLIST strlist_last( STRLIST node ); + +#define FREE_STRLIST(a) do { free_strlist((a)); (a) = NULL ; } while(0) + + +#endif /*LIBJNLIB_STRLIST_H*/  | 
