Update to current version in newpg module.

This commit is contained in:
Marcus Brinkmann 2002-01-22 16:29:12 +00:00
parent e70c184235
commit b863cea7d7
23 changed files with 1371 additions and 308 deletions

View File

@ -1,3 +1,69 @@
2002-01-22 Marcus Brinkmann <marcus@g10code.de>
* assuan-socket-connect.c (LOGERRORX): Reverse arguments to fputs.
2002-01-21 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* 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 <wk@gnupg.org>
* assuan-client.c (_assuan_read_from_server): Skip spaces after
the keyword.
2002-01-03 Werner Koch <wk@gnupg.org>
* assuan-handler.c (assuan_set_okay_line): New.
(process_request): And use it here.
2002-01-02 Werner Koch <wk@gnupg.org>
* 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 <marcus@g10code.de> 2001-12-14 Marcus Brinkmann <marcus@g10code.de>
* assuan-connect.c (assuan_pipe_connect): New argument * assuan-connect.c (assuan_pipe_connect): New argument
@ -90,7 +156,7 @@
* You may find it source-copied in other packages. * * 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 This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without unlimited permission to copy and/or distribute it, with or without

View File

@ -38,7 +38,10 @@ libassuan_a_SOURCES = \
assuan-listen.c \ assuan-listen.c \
assuan-connect.c \ assuan-connect.c \
assuan-client.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 assuan-errors.c : assuan.h

View File

@ -20,6 +20,7 @@
#include <config.h> #include <config.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
@ -119,10 +120,17 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
rc = readline (ctx->inbound.fd, line, LINELENGTH, rc = readline (ctx->inbound.fd, line, LINELENGTH,
&nread, &ctx->inbound.eof); &nread, &ctx->inbound.eof);
if (rc) 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) if (!nread)
{ {
assert (ctx->inbound.eof); assert (ctx->inbound.eof);
if (ctx->log_fp)
fprintf (ctx->log_fp, "%p <- [EOF]\n", ctx);
return -1; return -1;
} }
@ -153,10 +161,23 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
n--; n--;
line[n] = 0; line[n] = 0;
ctx->inbound.linelen = n; 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; return 0;
} }
} }
if (ctx->log_fp)
fprintf (ctx->log_fp, "%p <- [Invalid line]\n", ctx);
*line = 0; *line = 0;
ctx->inbound.linelen = 0; ctx->inbound.linelen = 0;
return ctx->inbound.eof? ASSUAN_Line_Not_Terminated : ASSUAN_Line_Too_Long; 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; return ASSUAN_Invalid_Value;
/* fixme: we should do some kind of line buffering */ /* 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)); rc = writen (ctx->outbound.fd, line, strlen(line));
if (rc) if (rc)
rc = ASSUAN_Write_Error; 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 (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'; *line++ = '\n';
linelen++; linelen++;
if (writen (ctx->outbound.fd, ctx->outbound.data.line, linelen)) if (writen (ctx->outbound.fd, ctx->outbound.data.line, linelen))
@ -300,6 +343,17 @@ _assuan_cookie_write_flush (void *cookie)
line += linelen; line += linelen;
if (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'; *line++ = '\n';
linelen++; linelen++;
if (writen (ctx->outbound.fd, ctx->outbound.data.line, linelen)) if (writen (ctx->outbound.fd, ctx->outbound.data.line, linelen))

View File

@ -63,6 +63,8 @@ _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off)
{ {
*okay = 1; *okay = 1;
*off = 2; *off = 2;
while (line[*off] == ' ')
++*off;
} }
else if (linelen >= 3 else if (linelen >= 3
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R' && 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; *okay = 0;
*off = 3; *off = 3;
while (line[*off] == ' ')
++*off;
} }
else if (linelen >= 7 else if (linelen >= 7
&& line[0] == 'I' && line[1] == 'N' && line[2] == 'Q' && 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; *okay = 3;
*off = 7; *off = 7;
while (line[*off] == ' ')
++*off;
} }
else else
rc = ASSUAN_Invalid_Response; rc = ASSUAN_Invalid_Response;

View File

@ -33,208 +33,18 @@
#include "assuan-defs.h" #include "assuan-defs.h"
#ifdef _POSIX_OPEN_MAX /* Disconnect and release the context CTX. */
#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 */
}
/* 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 void
assuan_pipe_disconnect (ASSUAN_CONTEXT ctx) assuan_disconnect (ASSUAN_CONTEXT ctx)
{ {
assuan_write_line (ctx, "BYE"); if (ctx)
close (ctx->inbound.fd); {
close (ctx->outbound.fd); assuan_write_line (ctx, "BYE");
waitpid (ctx->pid, NULL, 0); /* FIXME Check return value. */ ctx->finish_handler (ctx);
assuan_deinit_pipe_server (ctx); ctx->deinit_handler (ctx);
ctx->deinit_handler = NULL;
_assuan_release_context (ctx);
}
} }
pid_t pid_t
@ -242,5 +52,3 @@ assuan_get_pid (ASSUAN_CONTEXT ctx)
{ {
return ctx ? ctx->pid : -1; return ctx ? ctx->pid : -1;
} }

View File

@ -35,13 +35,18 @@ struct cmdtbl_s {
struct assuan_context_s { struct assuan_context_s {
AssuanError err_no; AssuanError err_no;
const char *err_str; 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 is_server; /* set if this is context belongs to a server */
int in_inquire; int in_inquire;
char *hello_line; char *hello_line;
char *okay_line; /* see assan_set_okay_line() */
void *user_pointer; /* for assuan_[gs]et_pointer () */ void *user_pointer; /* for assuan_[gs]et_pointer () */
FILE *log_fp;
struct { struct {
int fd; int fd;
int eof; 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 int pipe_mode; /* We are in pipe mode, i.e. we can handle just one
connection and must terminate then */ 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; struct cmdtbl_s *cmdtbl;
size_t cmdtbl_used; /* used entries */ size_t cmdtbl_used; /* used entries */
@ -77,6 +88,7 @@ struct assuan_context_s {
void (*bye_notify_fnc)(ASSUAN_CONTEXT); void (*bye_notify_fnc)(ASSUAN_CONTEXT);
void (*reset_notify_fnc)(ASSUAN_CONTEXT); void (*reset_notify_fnc)(ASSUAN_CONTEXT);
void (*cancel_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 (*input_notify_fnc)(ASSUAN_CONTEXT, const char *);
void (*output_notify_fnc)(ASSUAN_CONTEXT, const char *); void (*output_notify_fnc)(ASSUAN_CONTEXT, const char *);
@ -84,11 +96,14 @@ struct assuan_context_s {
int input_fd; /* set by INPUT command */ int input_fd; /* set by INPUT command */
int output_fd; /* set by OUTPUT 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 --*/ /*-- assuan-handler.c --*/
int _assuan_register_std_commands (ASSUAN_CONTEXT ctx); int _assuan_register_std_commands (ASSUAN_CONTEXT ctx);
@ -114,6 +129,9 @@ void _assuan_free (void *p);
#define set_error(c,e,t) assuan_set_error ((c), ASSUAN_ ## e, (t)) #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*/ #endif /*ASSUAN_DEFS_H*/

View File

@ -25,6 +25,7 @@
#include "assuan-defs.h" #include "assuan-defs.h"
#define spacep(p) (*(p) == ' ' || *(p) == '\t')
#define digitp(a) ((a) >= '0' && (a) <= '9') #define digitp(a) ((a) >= '0' && (a) <= '9')
@ -49,6 +50,53 @@ std_handler_cancel (ASSUAN_CONTEXT ctx, char *line)
return set_error (ctx, Not_Implemented, NULL); 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 static int
std_handler_bye (ASSUAN_CONTEXT ctx, char *line) std_handler_bye (ASSUAN_CONTEXT ctx, char *line)
{ {
@ -147,6 +195,7 @@ static struct {
} std_cmd_table[] = { } std_cmd_table[] = {
{ "NOP", ASSUAN_CMD_NOP, std_handler_nop, 1 }, { "NOP", ASSUAN_CMD_NOP, std_handler_nop, 1 },
{ "CANCEL", ASSUAN_CMD_CANCEL, std_handler_cancel, 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 }, { "BYE", ASSUAN_CMD_BYE, std_handler_bye, 1 },
{ "AUTH", ASSUAN_CMD_AUTH, std_handler_auth, 1 }, { "AUTH", ASSUAN_CMD_AUTH, std_handler_auth, 1 },
{ "RESET", ASSUAN_CMD_RESET, std_handler_reset, 1 }, { "RESET", ASSUAN_CMD_RESET, std_handler_reset, 1 },
@ -154,6 +203,7 @@ static struct {
{ "INPUT", ASSUAN_CMD_INPUT, std_handler_input }, { "INPUT", ASSUAN_CMD_INPUT, std_handler_input },
{ "OUTPUT", ASSUAN_CMD_OUTPUT, std_handler_output }, { "OUTPUT", ASSUAN_CMD_OUTPUT, std_handler_output },
{ "OPTION", ASSUAN_CMD_OPTION, std_handler_option, 1 },
{ NULL } { NULL }
}; };
@ -262,6 +312,17 @@ assuan_register_cancel_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
return 0; return 0;
} }
int
assuan_register_option_handler (ASSUAN_CONTEXT ctx,
int (*fnc)(ASSUAN_CONTEXT,
const char*, const char*))
{
if (!ctx)
return ASSUAN_Invalid_Value;
ctx->option_handler_fnc = fnc;
return 0;
}
int int
assuan_register_input_notify (ASSUAN_CONTEXT ctx, assuan_register_input_notify (ASSUAN_CONTEXT ctx,
void (*fnc)(ASSUAN_CONTEXT, const char *)) 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); 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 /* Parse the line, break out the command, find it in the command
table, remove leading and white spaces from the arguments, all the 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; shift = p - line;
for (i=0; (s=ctx->cmdtbl[i].name); i++) 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) if (!s)
return set_error (ctx, Unknown_Command, NULL); return set_error (ctx, Unknown_Command, NULL);
line += shift; line += shift;
@ -382,17 +467,18 @@ process_request (ASSUAN_CONTEXT ctx)
/* Error handling */ /* Error handling */
if (!rc) if (!rc)
{ {
rc = assuan_write_line (ctx, "OK"); rc = assuan_write_line (ctx, ctx->okay_line? ctx->okay_line : "OK");
} }
else if (rc == -1) else if (rc == -1)
{ /* No error checking because the peer may have already disconnect */ { /* No error checking because the peer may have already disconnect */
assuan_write_line (ctx, "OK closing connection"); assuan_write_line (ctx, "OK closing connection");
ctx->finish_handler (ctx);
} }
else else
{ {
char errline[256]; char errline[256];
if (rc < 100) if (rc < 100)
sprintf (errline, "ERR %d server fault (%.50s)", sprintf (errline, "ERR %d server fault (%.50s)",
ASSUAN_Server_Fault, assuan_strerror (rc)); ASSUAN_Server_Fault, assuan_strerror (rc));
else else
@ -405,6 +491,12 @@ process_request (ASSUAN_CONTEXT ctx)
rc = assuan_write_line (ctx, errline); rc = assuan_write_line (ctx, errline);
} }
ctx->confidential = 0;
if (ctx->okay_line)
{
xfree (ctx->okay_line);
ctx->okay_line = NULL;
}
return rc; 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 void
assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text) assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text)
{ {

View File

@ -1,5 +1,5 @@
/* assuan-inquire.c - handle inquire stuff /* 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. * 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->out_of_core = 0;
mb->too_large = 0; mb->too_large = 0;
mb->maxlen = maxlen; 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) if (!mb->buf)
mb->out_of_core = 1; mb->out_of_core = 1;
} }
@ -78,7 +79,8 @@ put_membuf (struct membuf *mb, const void *buf, size_t len)
char *p; char *p;
mb->size += len + 1024; 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) if (!p)
{ {
mb->out_of_core = 1; mb->out_of_core = 1;
@ -102,6 +104,7 @@ get_membuf (struct membuf *mb, size_t *len)
return NULL; return NULL;
} }
mb->buf[mb->len] = 0; /* there is enough space for the hidden eos */
p = mb->buf; p = mb->buf;
*len = mb->len; *len = mb->len;
mb->buf = NULL; mb->buf = NULL;

View File

@ -69,15 +69,13 @@ assuan_accept (ASSUAN_CONTEXT ctx)
if (!ctx) if (!ctx)
return ASSUAN_Invalid_Value; return ASSUAN_Invalid_Value;
/* fixme: cancel existing connection */
if (ctx->pipe_mode > 1) if (ctx->pipe_mode > 1)
return -1; /* second invocation for pipemode -> terminate */ return -1; /* second invocation for pipemode -> terminate */
ctx->finish_handler (ctx);
if (!ctx->pipe_mode) rc = ctx->accept_handler (ctx);
{ if (rc)
return rc;
/* fixme: wait for request */
}
/* send the hello */ /* send the hello */
rc = assuan_write_line (ctx, ctx->hello_line? ctx->hello_line rc = assuan_write_line (ctx, ctx->hello_line? ctx->hello_line

View File

@ -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;
}

View File

@ -24,9 +24,31 @@
#include "assuan-defs.h" #include "assuan-defs.h"
static void
deinit_pipe_server (ASSUAN_CONTEXT ctx)
{
/* nothing to do for this simple server */
}
static int
accept_connection (ASSUAN_CONTEXT ctx)
{
/* This is a NOP for a pipe server */
return 0;
}
static int
finish_connection (ASSUAN_CONTEXT ctx)
{
/* This is a NOP for a pipe server */
return 0;
}
/* Create a new context. Note that the handlers are set up for a pipe
server/client - this wau we don't need extra dummy functions */
int int
assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2]) _assuan_new_context (ASSUAN_CONTEXT *r_ctx)
{ {
ASSUAN_CONTEXT ctx; ASSUAN_CONTEXT ctx;
int rc; int rc;
@ -35,14 +57,17 @@ assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2])
ctx = xtrycalloc (1, sizeof *ctx); ctx = xtrycalloc (1, sizeof *ctx);
if (!ctx) if (!ctx)
return ASSUAN_Out_Of_Core; return ASSUAN_Out_Of_Core;
ctx->is_server = 1;
ctx->input_fd = -1; ctx->input_fd = -1;
ctx->output_fd = -1; ctx->output_fd = -1;
ctx->inbound.fd = filedes[0]; ctx->inbound.fd = -1;
ctx->outbound.fd = filedes[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); rc = _assuan_register_std_commands (ctx);
if (rc) if (rc)
@ -52,22 +77,47 @@ assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2])
return rc; 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 void
assuan_deinit_pipe_server (ASSUAN_CONTEXT ctx) _assuan_release_context (ASSUAN_CONTEXT ctx)
{ {
if (ctx) if (ctx)
{ {
xfree (ctx->hello_line); xfree (ctx->hello_line);
xfree (ctx->okay_line);
xfree (ctx); 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);
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -25,6 +25,10 @@
#include "assuan-defs.h" #include "assuan-defs.h"
#ifdef HAVE_JNLIB_LOGGING
#include "../jnlib/logging.h"
#endif
static void *(*alloc_func)(size_t n) = malloc; static void *(*alloc_func)(size_t n) = malloc;
static void *(*realloc_func)(void *p, size_t n) = realloc; 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; 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);
}
}

View File

@ -1,5 +1,5 @@
/* assuan.c - Definitions for the Assuna protocol /* 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. * This file is part of GnuPG.
* *
@ -47,6 +47,7 @@ typedef enum {
ASSUAN_No_Data_Callback = 12, ASSUAN_No_Data_Callback = 12,
ASSUAN_No_Inquire_Callback = 13, ASSUAN_No_Inquire_Callback = 13,
ASSUAN_Connect_Failed = 14, ASSUAN_Connect_Failed = 14,
ASSUAN_Accept_Failed = 15,
/* error codes above 99 are meant as status codes */ /* error codes above 99 are meant as status codes */
ASSUAN_Not_Implemented = 100, ASSUAN_Not_Implemented = 100,
@ -69,6 +70,9 @@ typedef enum {
ASSUAN_Invalid_Data = 117, ASSUAN_Invalid_Data = 117,
ASSUAN_Unexpected_Command = 118, ASSUAN_Unexpected_Command = 118,
ASSUAN_Too_Much_Data = 119, ASSUAN_Too_Much_Data = 119,
ASSUAN_Inquire_Unknown = 120,
ASSUAN_Inquire_Error = 121,
ASSUAN_Invalid_Option = 122,
ASSUAN_Bad_Certificate = 201, ASSUAN_Bad_Certificate = 201,
ASSUAN_Bad_Certificate_Path = 202, ASSUAN_Bad_Certificate_Path = 202,
@ -83,6 +87,7 @@ typedef enum {
ASSUAN_Cert_Revoked = 301, ASSUAN_Cert_Revoked = 301,
ASSUAN_No_CRL_For_Cert = 302, ASSUAN_No_CRL_For_Cert = 302,
ASSUAN_CRL_Too_Old = 303, ASSUAN_CRL_Too_Old = 303,
ASSUAN_Not_Trusted = 304,
} AssuanError; } AssuanError;
@ -93,6 +98,7 @@ typedef enum {
ASSUAN_CMD_BYE, ASSUAN_CMD_BYE,
ASSUAN_CMD_AUTH, ASSUAN_CMD_AUTH,
ASSUAN_CMD_RESET, ASSUAN_CMD_RESET,
ASSUAN_CMD_OPTION,
ASSUAN_CMD_DATA, ASSUAN_CMD_DATA,
ASSUAN_CMD_END, ASSUAN_CMD_END,
ASSUAN_CMD_INPUT, ASSUAN_CMD_INPUT,
@ -120,6 +126,11 @@ int assuan_register_input_notify (ASSUAN_CONTEXT ctx,
void (*fnc)(ASSUAN_CONTEXT, const char *)); void (*fnc)(ASSUAN_CONTEXT, const char *));
int assuan_register_output_notify (ASSUAN_CONTEXT ctx, int assuan_register_output_notify (ASSUAN_CONTEXT ctx,
void (*fnc)(ASSUAN_CONTEXT, const char *)); 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 (ASSUAN_CONTEXT ctx);
int assuan_process_next (ASSUAN_CONTEXT ctx); int assuan_process_next (ASSUAN_CONTEXT ctx);
int assuan_get_active_fds (ASSUAN_CONTEXT ctx, int what, 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); 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, void assuan_write_status (ASSUAN_CONTEXT ctx,
const char *keyword, const char *text); const char *keyword, const char *text);
@ -142,13 +154,21 @@ AssuanError assuan_close_output_fd (ASSUAN_CONTEXT ctx);
/*-- assuan-pipe-server.c --*/ /*-- assuan-pipe-server.c --*/
int assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2]); 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, AssuanError assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name,
char *const argv[], int *fd_child_list); 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); pid_t assuan_get_pid (ASSUAN_CONTEXT ctx);
/*-- assuan-client.c --*/ /*-- 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 assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),
void *(*new_realloc_func)(void *p, size_t n), void *(*new_realloc_func)(void *p, size_t n),
void (*new_free_func)(void*) ); 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); int assuan_set_error (ASSUAN_CONTEXT ctx, int err, const char *text);
void assuan_set_pointer (ASSUAN_CONTEXT ctx, void *pointer); void assuan_set_pointer (ASSUAN_CONTEXT ctx, void *pointer);
void *assuan_get_pointer (ASSUAN_CONTEXT ctx); 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) --*/ /*-- assuan-errors.c (built) --*/
const char *assuan_strerror (AssuanError err); const char *assuan_strerror (AssuanError err);

View File

@ -5,6 +5,22 @@
unconditionally. unconditionally.
Reported by Jose Carlos Garcia Sogo <jsogo@debian.org>. Reported by Jose Carlos Garcia Sogo <jsogo@debian.org>.
2002-01-19 Werner Koch <wk@gnupg.org>
* logging.c (log_get_stream): New.
2001-12-05 Werner Koch <wk@gnupg.org>
* 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 <wk@gnupg.org>
* strlist.c, strlist.h: New. Taken from pgnupg/util/strgutil.c
2001-08-30 Werner Koch <wk@gnupg.org> 2001-08-30 Werner Koch <wk@gnupg.org>
* logging.c (log_printf): Don't pass NULL instead of arg_ptr. * logging.c (log_printf): Don't pass NULL instead of arg_ptr.

View File

@ -26,11 +26,14 @@ noinst_LIBRARIES = libjnlib.a
#libjnlib_a_LDFLAGS = #libjnlib_a_LDFLAGS =
libjnlib_a_SOURCES = libjnlib-config.h \ libjnlib_a_SOURCES = \
xmalloc.c xmalloc.h \ libjnlib-config.h \
stringhelp.c stringhelp.h \ stringhelp.c stringhelp.h \
argparse.c argparse.h \ strlist.c strlist.h \
logging.c logging.h \ argparse.c argparse.h \
types.h mischelp.h logging.c logging.h \
dotlock.c dotlock.h \
types.h mischelp.h
# xmalloc.c xmalloc.h

View File

@ -900,7 +900,7 @@ strusage( int level )
switch( level ) { switch( level ) {
case 11: p = "foo"; break; case 11: p = "foo"; break;
case 13: p = "0.0"; 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 = case 15: p =
"This program comes with ABSOLUTELY NO WARRANTY.\n" "This program comes with ABSOLUTELY NO WARRANTY.\n"
"This is free software, and you are welcome to redistribute it\n" "This is free software, and you are welcome to redistribute it\n"

View File

@ -26,11 +26,9 @@
#ifndef LIBJNLIB_CONFIG_H #ifndef LIBJNLIB_CONFIG_H
#define LIBJNLIB_CONFIG_H #define LIBJNLIB_CONFIG_H
#include "xmalloc.h" #include <gcrypt.h> /* gcry_malloc & Cie. */
#include "logging.h" #include "logging.h"
#ifdef USE_SIMPLE_GETTEXT #ifdef USE_SIMPLE_GETTEXT
int set_gettext_file( const char *filename ); int set_gettext_file( const char *filename );
const char *gettext( const char *msgid ); const char *gettext( const char *msgid );
@ -58,11 +56,11 @@
#endif /* !USE_SIMPLE_GETTEXT */ #endif /* !USE_SIMPLE_GETTEXT */
#define jnlib_xmalloc(a) xmalloc( (a) ) #define jnlib_xmalloc(a) gcry_xmalloc( (a) )
#define jnlib_xcalloc(a,b) xcalloc( (a), (b) ) #define jnlib_xcalloc(a,b) gcry_xcalloc( (a), (b) )
#define jnlib_xrealloc(a,n) xrealloc( (a), (n) ) #define jnlib_xrealloc(a,n) gcry_xrealloc( (a), (n) )
#define jnlib_xstrdup(a) xstrdup( (a) ) #define jnlib_xstrdup(a) gcry_xstrdup( (a) )
#define jnlib_free(a) free( (a) ) #define jnlib_free(a) gcry_free( (a) )
#define jnlib_log_debug log_debug #define jnlib_log_debug log_debug
#define jnlib_log_info log_info #define jnlib_log_info log_info
@ -73,3 +71,5 @@
#endif /*LIBJNUTIL_CONFIG_H*/ #endif /*LIBJNUTIL_CONFIG_H*/

View File

@ -31,26 +31,23 @@
#include <stdarg.h> #include <stdarg.h>
#include <errno.h> #include <errno.h>
#include <time.h> #include <time.h>
#include <sys/types.h>
#include <unistd.h>
#ifdef __MINGW32__ #ifdef __MINGW32__
#include <io.h> #include <io.h>
#endif #endif
#define JNLIB_NEED_LOG_LOGV 1
#include "libjnlib-config.h" #include "libjnlib-config.h"
#include "logging.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 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 missing_lf;
static int errorcount; static int errorcount;
@ -95,61 +92,93 @@ log_set_file( const char *name )
if( logstream && logstream != stderr ) if( logstream && logstream != stderr )
fclose( logstream ); fclose( logstream );
logstream = fp; logstream = fp;
use_time = fp != stderr;
missing_lf = 0; 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 int
log_get_fd() log_get_fd()
{ {
return fileno(logstream?logstream:stderr); return fileno(logstream?logstream:stderr);
} }
FILE *
log_get_stream ()
{
return logstream?logstream:stderr;
}
static void static void
do_logv( int level, const char *fmt, va_list arg_ptr ) do_logv( int level, const char *fmt, va_list arg_ptr )
{ {
if( !logstream ) if (!logstream)
logstream = stderr; logstream = stderr;
if( missing_lf && level != MY_LOG_CONT ) if (missing_lf && level != JNLIB_LOG_CONT)
putc('\n', logstream ); putc('\n', logstream );
missing_lf = 0; missing_lf = 0;
if( use_time && level != MY_LOG_CONT ) { if (level != JNLIB_LOG_CONT)
/* Note this does not work for multiple line logging as we would { /* Note this does not work for multiple line logging as we would
* need to print to a buffer first */ * need to print to a buffer first */
struct tm *tp; if (with_time)
time_t atime = time(NULL); {
struct tm *tp;
time_t atime = time (NULL);
tp = localtime( &atime ); tp = localtime (&atime);
fprintf( logstream, "%04d-%02d-%02d %02d:%02d:%02d ", fprintf (logstream, "%04d-%02d-%02d %02d:%02d:%02d ",
1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday, 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
tp->tm_hour, tp->tm_min, tp->tm_sec ); 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 ) { switch (level)
case MY_LOG_BEGIN: break; {
case MY_LOG_CONT: break; case JNLIB_LOG_BEGIN: break;
case MY_LOG_INFO: break; case JNLIB_LOG_CONT: break;
case MY_LOG_WARN: break; case JNLIB_LOG_INFO: break;
case MY_LOG_ERROR: break; case JNLIB_LOG_WARN: break;
case MY_LOG_FATAL: fputs("Fatal: ",logstream ); break; case JNLIB_LOG_ERROR: break;
case MY_LOG_BUG: fputs("Ohhhh jeeee: ", logstream); break; case JNLIB_LOG_FATAL: fputs("Fatal: ",logstream ); break;
case MY_LOG_DEBUG: fputs("DBG: ", logstream ); break; case JNLIB_LOG_BUG: fputs("Ohhhh jeeee: ", logstream); break;
default: fprintf(logstream,"[Unknown log level %d]: ", level ); break; case JNLIB_LOG_DEBUG: fputs("DBG: ", logstream ); break;
default: fprintf(logstream,"[Unknown log level %d]: ", level ); break;
} }
if( fmt ) { if (fmt)
vfprintf(logstream,fmt,arg_ptr) ; {
if( *fmt && fmt[strlen(fmt)-1] != '\n' ) vfprintf(logstream,fmt,arg_ptr) ;
missing_lf = 1; if (*fmt && fmt[strlen(fmt)-1] != '\n')
missing_lf = 1;
} }
if( level == MY_LOG_FATAL ) if (level == JNLIB_LOG_FATAL)
exit(2); exit(2);
if( level == MY_LOG_BUG ) if (level == JNLIB_LOG_BUG)
abort(); abort();
} }
static void 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 void
log_info( const char *fmt, ... ) log_info( const char *fmt, ... )
@ -170,7 +204,7 @@ log_info( const char *fmt, ... )
va_list arg_ptr ; va_list arg_ptr ;
va_start( arg_ptr, fmt ) ; 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); va_end(arg_ptr);
} }
@ -180,7 +214,7 @@ log_error( const char *fmt, ... )
va_list arg_ptr ; va_list arg_ptr ;
va_start( arg_ptr, fmt ) ; 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); va_end(arg_ptr);
/* protect against counter overflow */ /* protect against counter overflow */
if( errorcount < 30000 ) if( errorcount < 30000 )
@ -194,7 +228,7 @@ log_fatal( const char *fmt, ... )
va_list arg_ptr ; va_list arg_ptr ;
va_start( arg_ptr, fmt ) ; 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); va_end(arg_ptr);
abort(); /* never called, bugs it makes the compiler happy */ abort(); /* never called, bugs it makes the compiler happy */
} }
@ -205,7 +239,7 @@ log_bug( const char *fmt, ... )
va_list arg_ptr ; va_list arg_ptr ;
va_start( arg_ptr, fmt ) ; 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); va_end(arg_ptr);
abort(); /* never called, but it makes the compiler happy */ abort(); /* never called, but it makes the compiler happy */
} }
@ -216,7 +250,7 @@ log_debug( const char *fmt, ... )
va_list arg_ptr ; va_list arg_ptr ;
va_start( arg_ptr, fmt ) ; 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); va_end(arg_ptr);
} }
@ -227,16 +261,35 @@ log_printf (const char *fmt, ...)
va_list arg_ptr; va_list arg_ptr;
va_start (arg_ptr, fmt); 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); 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 ) #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
void void
bug_at( const char *file, int line, const char *func ) 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 ); ("... this is a bug (%s:%d:%s)\n"), file, line, func );
abort(); /* never called, but it makes the compiler happy */ abort(); /* never called, but it makes the compiler happy */
} }
@ -244,7 +297,7 @@ bug_at( const char *file, int line, const char *func )
void void
bug_at( const char *file, int line ) 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); _("you found a bug ... (%s:%d)\n"), file, line);
abort(); /* never called, but it makes the compiler happy */ abort(); /* never called, but it makes the compiler happy */
} }

View File

@ -24,9 +24,12 @@
#include <stdio.h> #include <stdio.h>
#include "mischelp.h" #include "mischelp.h"
int log_get_errorcount (int clear); int log_get_errorcount (int clear);
void log_set_file( const char *name ); void log_set_file( const char *name );
void log_set_prefix (const char *text, unsigned int flags);
int log_get_fd(void); int log_get_fd(void);
FILE *log_get_stream (void);
#ifdef JNLIB_GCC_M_FUNCTION #ifdef JNLIB_GCC_M_FUNCTION
void bug_at( const char *file, int line, const char *func ) JNLIB_GCC_A_NR; 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__ ) # define BUG() bug_at( __FILE__ , __LINE__ )
#endif #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_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_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_error( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2);
void log_info( 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_debug( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2);
void log_printf( 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*/ #endif /*LIBJNLIB_LOGGING_H*/

133
jnlib/strlist.c Normal file
View File

@ -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;
}

43
jnlib/strlist.h Normal file
View File

@ -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*/