Updated Assuan to the current version
This commit is contained in:
parent
70720764e1
commit
3de2384ea5
@ -1,3 +1,46 @@
|
|||||||
|
2001-12-12 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
|
* assuan-connect.c (assuan_pipe_connect): Implemented the inital
|
||||||
|
handshake.
|
||||||
|
* assuan-client.c (read_from_server): Renamed to
|
||||||
|
(_assuan_read_from_server): this and made external.
|
||||||
|
|
||||||
|
* assuan-listen.c (assuan_set_hello_line): New.
|
||||||
|
(assuan_accept): Use a custom hello line is available.
|
||||||
|
|
||||||
|
* assuan-buffer.c (assuan_read_line): New.
|
||||||
|
(assuan_pending_line): New.
|
||||||
|
(_assuan_write_line): Renamed to ..
|
||||||
|
(assuan_write_line): this, made public and changed all callers.
|
||||||
|
|
||||||
|
2001-12-04 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
|
* assuan-connect.c (assuan_pipe_connect): Add more error reporting.
|
||||||
|
* assuan-client.c: New.
|
||||||
|
|
||||||
|
* assuan-inquire.c: New.
|
||||||
|
* assuan-handler.c (process_request): Check for nested invocations.
|
||||||
|
|
||||||
|
2001-11-27 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
|
* assuan-handler.c (assuan_register_input_notify): New.
|
||||||
|
(assuan_register_output_notify): New.
|
||||||
|
|
||||||
|
2001-11-26 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
|
* assuan.h: Added more status codes.
|
||||||
|
|
||||||
|
2001-11-25 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
|
* assuan-handler.c (assuan_register_bye_notify)
|
||||||
|
(assuan_register_reset_notify)
|
||||||
|
(assuan_register_cancel_notify): New and call them from the
|
||||||
|
standard handlers.
|
||||||
|
(assuan_process): Moved bulk of function to ..
|
||||||
|
(process_request): .. new.
|
||||||
|
(assuan_process_next): One shot version of above.
|
||||||
|
(assuan_get_active_fds): New.
|
||||||
|
|
||||||
2001-11-24 Werner Koch <wk@gnupg.org>
|
2001-11-24 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
* assuan-connect.c (assuan_get_pid): New.
|
* assuan-connect.c (assuan_get_pid): New.
|
||||||
|
@ -34,8 +34,10 @@ libassuan_a_SOURCES = \
|
|||||||
assuan-errors.c \
|
assuan-errors.c \
|
||||||
assuan-buffer.c \
|
assuan-buffer.c \
|
||||||
assuan-handler.c \
|
assuan-handler.c \
|
||||||
|
assuan-inquire.c \
|
||||||
assuan-listen.c \
|
assuan-listen.c \
|
||||||
assuan-connect.c \
|
assuan-connect.c \
|
||||||
|
assuan-client.c \
|
||||||
assuan-pipe-server.c
|
assuan-pipe-server.c
|
||||||
|
|
||||||
|
|
||||||
|
@ -123,16 +123,25 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx->inbound.attic.pending = 0;
|
||||||
for (n=0; n < nread; n++)
|
for (n=0; n < nread; n++)
|
||||||
{
|
{
|
||||||
if (line[n] == '\n')
|
if (line[n] == '\n')
|
||||||
{
|
{
|
||||||
if (n+1 < nread)
|
if (n+1 < nread)
|
||||||
{
|
{
|
||||||
|
char *s, *d;
|
||||||
|
int i;
|
||||||
|
|
||||||
n++;
|
n++;
|
||||||
/* we have to copy the rest because the handlers are
|
/* we have to copy the rest because the handlers are
|
||||||
allowed to modify the passed buffer */
|
allowed to modify the passed buffer */
|
||||||
memcpy (ctx->inbound.attic.line, line+n, nread-n);
|
for (d=ctx->inbound.attic.line, s=line+n, i=nread-n; i; i--)
|
||||||
|
{
|
||||||
|
if (*s=='\n')
|
||||||
|
ctx->inbound.attic.pending = 1;
|
||||||
|
*d++ = *s++;
|
||||||
|
}
|
||||||
ctx->inbound.attic.linelen = nread-n;
|
ctx->inbound.attic.linelen = nread-n;
|
||||||
n--;
|
n--;
|
||||||
}
|
}
|
||||||
@ -150,12 +159,43 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Read the next line from the client or server and return a pointer
|
||||||
|
to a buffer with holding that line. linelen returns the length of
|
||||||
|
the line. This buffer is valid until another read operation is
|
||||||
|
done on this buffer. The caller is allowed to modify this buffer.
|
||||||
|
He should only use the buffer if the function returns without an
|
||||||
|
error.
|
||||||
|
|
||||||
|
Returns: 0 on success or an assuan error code
|
||||||
|
See also: assuan_pending_line().
|
||||||
|
*/
|
||||||
|
AssuanError
|
||||||
|
assuan_read_line (ASSUAN_CONTEXT ctx, char **line, size_t *linelen)
|
||||||
|
{
|
||||||
|
if (!ctx)
|
||||||
|
return ASSUAN_Invalid_Value;
|
||||||
|
*line = ctx->inbound.line;
|
||||||
|
*linelen = ctx->inbound.linelen;
|
||||||
|
return _assuan_read_line (ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
/* Return true when a full line is pending for a read, without the need
|
||||||
_assuan_write_line (ASSUAN_CONTEXT ctx, const char *line )
|
for actual IO */
|
||||||
|
int
|
||||||
|
assuan_pending_line (ASSUAN_CONTEXT ctx)
|
||||||
|
{
|
||||||
|
return ctx && ctx->inbound.attic.pending;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AssuanError
|
||||||
|
assuan_write_line (ASSUAN_CONTEXT ctx, const char *line )
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
if (!ctx)
|
||||||
|
return ASSUAN_Invalid_Value;
|
||||||
|
|
||||||
/* fixme: we should do some kind of line buffering */
|
/* fixme: we should do some kind of line buffering */
|
||||||
rc = writen (ctx->outbound.fd, line, strlen(line));
|
rc = writen (ctx->outbound.fd, line, strlen(line));
|
||||||
@ -265,5 +305,50 @@ _assuan_cookie_write_flush (void *cookie)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* assuan_send_data:
|
||||||
|
* @ctx: An assuan context
|
||||||
|
* @buffer: Data to send or NULL to flush
|
||||||
|
* @length: length of the data to send/
|
||||||
|
*
|
||||||
|
* This function may be used by the server or the client to send data
|
||||||
|
* lines. The data will be escaped as required by the Assuan protocol
|
||||||
|
* and may get buffered until a line is full. To force sending the
|
||||||
|
* data out @buffer may be passed as NULL (in which case @length must
|
||||||
|
* also be 0); however when used by a client this flush operation does
|
||||||
|
* also send the terminating "END" command to terminate the reponse on
|
||||||
|
* a INQUIRE response. However, when assuan_transact() is used, this
|
||||||
|
* function takes care of sending END itself.
|
||||||
|
*
|
||||||
|
* Return value: 0 on success or an error code
|
||||||
|
**/
|
||||||
|
|
||||||
|
AssuanError
|
||||||
|
assuan_send_data (ASSUAN_CONTEXT ctx, const void *buffer, size_t length)
|
||||||
|
{
|
||||||
|
if (!ctx)
|
||||||
|
return ASSUAN_Invalid_Value;
|
||||||
|
if (!buffer && length)
|
||||||
|
return ASSUAN_Invalid_Value;
|
||||||
|
|
||||||
|
if (!buffer)
|
||||||
|
{ /* flush what we have */
|
||||||
|
_assuan_cookie_write_flush (ctx);
|
||||||
|
if (ctx->outbound.data.error)
|
||||||
|
return ctx->outbound.data.error;
|
||||||
|
if (!ctx->is_server)
|
||||||
|
return assuan_write_line (ctx, "END");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_assuan_cookie_write_data (ctx, buffer, length);
|
||||||
|
if (ctx->outbound.data.error)
|
||||||
|
return ctx->outbound.data.error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
180
assuan/assuan-client.c
Normal file
180
assuan/assuan-client.c
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
/* assuan-client.c - client functions
|
||||||
|
* Copyright (C) 2001 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GnuPG.
|
||||||
|
*
|
||||||
|
* GnuPG is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GnuPG is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "assuan-defs.h"
|
||||||
|
|
||||||
|
#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
|
||||||
|
*(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
|
||||||
|
#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
|
||||||
|
|
||||||
|
|
||||||
|
AssuanError
|
||||||
|
_assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off)
|
||||||
|
{
|
||||||
|
char *line;
|
||||||
|
int linelen;
|
||||||
|
AssuanError rc;
|
||||||
|
|
||||||
|
*okay = 0;
|
||||||
|
*off = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
rc = _assuan_read_line (ctx);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
line = ctx->inbound.line;
|
||||||
|
linelen = ctx->inbound.linelen;
|
||||||
|
}
|
||||||
|
while (*line == '#' || !linelen);
|
||||||
|
|
||||||
|
if (linelen >= 1
|
||||||
|
&& line[0] == 'D' && line[1] == ' ')
|
||||||
|
{
|
||||||
|
*okay = 2; /* data line */
|
||||||
|
*off = 2;
|
||||||
|
}
|
||||||
|
else if (linelen >= 2
|
||||||
|
&& line[0] == 'O' && line[1] == 'K'
|
||||||
|
&& (line[2] == '\0' || line[2] == ' '))
|
||||||
|
{
|
||||||
|
*okay = 1;
|
||||||
|
*off = 2;
|
||||||
|
}
|
||||||
|
else if (linelen >= 3
|
||||||
|
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
|
||||||
|
&& (line[3] == '\0' || line[3] == ' '))
|
||||||
|
{
|
||||||
|
*okay = 0;
|
||||||
|
*off = 3;
|
||||||
|
}
|
||||||
|
else if (linelen >= 7
|
||||||
|
&& line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
|
||||||
|
&& line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
|
||||||
|
&& line[6] == 'E'
|
||||||
|
&& (line[7] == '\0' || line[7] == ' '))
|
||||||
|
{
|
||||||
|
*okay = 3;
|
||||||
|
*off = 7;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rc = ASSUAN_Invalid_Response;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* assuan_transact:
|
||||||
|
* @ctx: The Assuan context
|
||||||
|
* @command: Coimmand line to be send to server
|
||||||
|
* @data_cb: Callback function for data lines
|
||||||
|
* @data_cb_arg: first argument passed to @data_cb
|
||||||
|
* @inquire_cb: Callback function for a inquire response
|
||||||
|
* @inquire_cb_arg: first argument passed to @inquire_cb
|
||||||
|
*
|
||||||
|
* FIXME: Write documentation
|
||||||
|
*
|
||||||
|
* Return value: 0 on success or error code. The error code may be
|
||||||
|
* the one one returned by the server in error lines or from the
|
||||||
|
* callback functions.
|
||||||
|
**/
|
||||||
|
AssuanError
|
||||||
|
assuan_transact (ASSUAN_CONTEXT ctx,
|
||||||
|
const char *command,
|
||||||
|
AssuanError (*data_cb)(void *, const void *, size_t),
|
||||||
|
void *data_cb_arg,
|
||||||
|
AssuanError (*inquire_cb)(void*, const char *),
|
||||||
|
void *inquire_cb_arg)
|
||||||
|
{
|
||||||
|
int rc, okay, off;
|
||||||
|
unsigned char *line;
|
||||||
|
int linelen;
|
||||||
|
|
||||||
|
rc = assuan_write_line (ctx, command);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
again:
|
||||||
|
rc = _assuan_read_from_server (ctx, &okay, &off);
|
||||||
|
if (rc)
|
||||||
|
return rc; /* error reading from server */
|
||||||
|
|
||||||
|
line = ctx->inbound.line + off;
|
||||||
|
linelen = ctx->inbound.linelen - off;
|
||||||
|
|
||||||
|
if (!okay)
|
||||||
|
{
|
||||||
|
rc = atoi (line);
|
||||||
|
if (rc < 100)
|
||||||
|
rc = ASSUAN_Server_Fault;
|
||||||
|
}
|
||||||
|
else if (okay == 2)
|
||||||
|
{
|
||||||
|
if (!data_cb)
|
||||||
|
rc = ASSUAN_No_Data_Callback;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned char *s, *d;
|
||||||
|
|
||||||
|
for (s=d=line; linelen; linelen--)
|
||||||
|
{
|
||||||
|
if (*s == '%' && linelen > 2)
|
||||||
|
{ /* handle escaping */
|
||||||
|
s++;
|
||||||
|
*d++ = xtoi_2 (s);
|
||||||
|
s += 2;
|
||||||
|
linelen -= 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*d++ = *s++;
|
||||||
|
}
|
||||||
|
*d = 0; /* add a hidden string terminator */
|
||||||
|
rc = data_cb (data_cb_arg, line, d - line);
|
||||||
|
if (!rc)
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (okay == 3)
|
||||||
|
{
|
||||||
|
if (!inquire_cb)
|
||||||
|
{
|
||||||
|
assuan_write_line (ctx, "END"); /* get out of inquire mode */
|
||||||
|
_assuan_read_from_server (ctx, &okay, &off); /* dummy read */
|
||||||
|
rc = ASSUAN_No_Inquire_Callback;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = inquire_cb (inquire_cb_arg, line);
|
||||||
|
if (!rc)
|
||||||
|
rc = assuan_send_data (ctx, NULL, 0); /* flush and send END */
|
||||||
|
if (!rc)
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
@ -18,17 +18,57 @@
|
|||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#include "assuan-defs.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 */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Connect to a server over a pipe, creating the assuan context and
|
/* Connect to a server over a pipe, creating the assuan context and
|
||||||
returning it in CTX. The server filename is NAME, the argument
|
returning it in CTX. The server filename is NAME, the argument
|
||||||
vector in ARGV. */
|
vector in ARGV. */
|
||||||
@ -41,8 +81,8 @@ assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[])
|
|||||||
int wp[2];
|
int wp[2];
|
||||||
int fd[2];
|
int fd[2];
|
||||||
|
|
||||||
if (!name || !argv || !argv[0])
|
if (!ctx || !name || !argv || !argv[0])
|
||||||
return ASSUAN_General_Error;
|
return ASSUAN_Invalid_Value;
|
||||||
|
|
||||||
if (!fixed_signals)
|
if (!fixed_signals)
|
||||||
{
|
{
|
||||||
@ -69,7 +109,7 @@ assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[])
|
|||||||
close (rp[1]);
|
close (rp[1]);
|
||||||
return ASSUAN_General_Error;
|
return ASSUAN_General_Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd[0] = rp[0]; /* Our inbound is read end of read pipe. */
|
fd[0] = rp[0]; /* Our inbound is read end of read pipe. */
|
||||||
fd[1] = wp[1]; /* Our outbound is write end of write pipe. */
|
fd[1] = wp[1]; /* Our outbound is write end of write pipe. */
|
||||||
|
|
||||||
@ -82,6 +122,7 @@ assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[])
|
|||||||
close (wp[1]);
|
close (wp[1]);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
(*ctx)->is_server = 0;
|
||||||
|
|
||||||
(*ctx)->pid = fork ();
|
(*ctx)->pid = fork ();
|
||||||
if ((*ctx)->pid < 0)
|
if ((*ctx)->pid < 0)
|
||||||
@ -96,32 +137,89 @@ assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[])
|
|||||||
|
|
||||||
if ((*ctx)->pid == 0)
|
if ((*ctx)->pid == 0)
|
||||||
{
|
{
|
||||||
close (rp[0]);
|
int i, n;
|
||||||
close (wp[1]);
|
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++)
|
||||||
|
{
|
||||||
|
if (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 (rp[1] != STDOUT_FILENO)
|
||||||
{
|
{
|
||||||
dup2 (rp[1], STDOUT_FILENO); /* Child's outbound is write end of read pipe. */
|
if (dup2 (rp[1], STDOUT_FILENO) == -1)
|
||||||
close (rp[1]);
|
{
|
||||||
}
|
LOGERROR1 ("dup2 failed in child: %s\n", strerror (errno));
|
||||||
|
_exit (4);
|
||||||
|
}
|
||||||
|
close (rp[1]);
|
||||||
|
}
|
||||||
if (wp[0] != STDIN_FILENO)
|
if (wp[0] != STDIN_FILENO)
|
||||||
{
|
{
|
||||||
dup2 (wp[0], STDIN_FILENO); /* Child's inbound is read end of write pipe. */
|
if (dup2 (wp[0], STDIN_FILENO) == -1)
|
||||||
close (wp[0]);
|
{
|
||||||
}
|
LOGERROR1 ("dup2 failed in child: %s\n", strerror (errno));
|
||||||
execv (name, argv);
|
_exit (4);
|
||||||
_exit (1);
|
}
|
||||||
|
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 (rp[1]);
|
||||||
close (wp[0]);
|
close (wp[0]);
|
||||||
_assuan_read_line (*ctx); /* FIXME: Handshake. */
|
|
||||||
return 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_pipe_disconnect (ASSUAN_CONTEXT ctx)
|
||||||
{
|
{
|
||||||
_assuan_write_line (ctx, "BYE");
|
assuan_write_line (ctx, "BYE");
|
||||||
close (ctx->inbound.fd);
|
close (ctx->inbound.fd);
|
||||||
close (ctx->outbound.fd);
|
close (ctx->outbound.fd);
|
||||||
waitpid (ctx->pid, NULL, 0); /* FIXME Check return value. */
|
waitpid (ctx->pid, NULL, 0); /* FIXME Check return value. */
|
||||||
@ -133,3 +231,5 @@ assuan_get_pid (ASSUAN_CONTEXT ctx)
|
|||||||
{
|
{
|
||||||
return ctx ? ctx->pid : -1;
|
return ctx ? ctx->pid : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,6 +35,10 @@ 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 is_server; /* set if this is context belongs to a server */
|
||||||
|
int in_inquire;
|
||||||
|
char *hello_line;
|
||||||
|
|
||||||
void *user_pointer; /* for assuan_[gs]et_pointer () */
|
void *user_pointer; /* for assuan_[gs]et_pointer () */
|
||||||
|
|
||||||
@ -48,6 +52,7 @@ struct assuan_context_s {
|
|||||||
struct {
|
struct {
|
||||||
char line[LINELENGTH];
|
char line[LINELENGTH];
|
||||||
int linelen ;
|
int linelen ;
|
||||||
|
int pending; /* i.e. at least one line is available in the attic */
|
||||||
} attic;
|
} attic;
|
||||||
} inbound;
|
} inbound;
|
||||||
|
|
||||||
@ -69,6 +74,12 @@ struct assuan_context_s {
|
|||||||
size_t cmdtbl_used; /* used entries */
|
size_t cmdtbl_used; /* used entries */
|
||||||
size_t cmdtbl_size; /* allocated size of table */
|
size_t cmdtbl_size; /* allocated size of table */
|
||||||
|
|
||||||
|
void (*bye_notify_fnc)(ASSUAN_CONTEXT);
|
||||||
|
void (*reset_notify_fnc)(ASSUAN_CONTEXT);
|
||||||
|
void (*cancel_notify_fnc)(ASSUAN_CONTEXT);
|
||||||
|
void (*input_notify_fnc)(ASSUAN_CONTEXT, const char *);
|
||||||
|
void (*output_notify_fnc)(ASSUAN_CONTEXT, const char *);
|
||||||
|
|
||||||
|
|
||||||
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 */
|
||||||
@ -82,12 +93,12 @@ struct assuan_context_s {
|
|||||||
int _assuan_register_std_commands (ASSUAN_CONTEXT ctx);
|
int _assuan_register_std_commands (ASSUAN_CONTEXT ctx);
|
||||||
|
|
||||||
/*-- assuan-buffer.c --*/
|
/*-- assuan-buffer.c --*/
|
||||||
int _assuan_write_line (ASSUAN_CONTEXT ctx, const char *line);
|
|
||||||
int _assuan_read_line (ASSUAN_CONTEXT ctx);
|
int _assuan_read_line (ASSUAN_CONTEXT ctx);
|
||||||
int _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size);
|
int _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size);
|
||||||
int _assuan_cookie_write_flush (void *cookie);
|
int _assuan_cookie_write_flush (void *cookie);
|
||||||
|
|
||||||
|
/*-- assuan-client.c --*/
|
||||||
|
AssuanError _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off);
|
||||||
|
|
||||||
|
|
||||||
/*-- assuan-util.c --*/
|
/*-- assuan-util.c --*/
|
||||||
|
@ -44,12 +44,16 @@ std_handler_nop (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
static int
|
static int
|
||||||
std_handler_cancel (ASSUAN_CONTEXT ctx, char *line)
|
std_handler_cancel (ASSUAN_CONTEXT ctx, char *line)
|
||||||
{
|
{
|
||||||
|
if (ctx->cancel_notify_fnc)
|
||||||
|
ctx->cancel_notify_fnc (ctx);
|
||||||
return set_error (ctx, Not_Implemented, NULL);
|
return set_error (ctx, Not_Implemented, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
std_handler_bye (ASSUAN_CONTEXT ctx, char *line)
|
std_handler_bye (ASSUAN_CONTEXT ctx, char *line)
|
||||||
{
|
{
|
||||||
|
if (ctx->bye_notify_fnc)
|
||||||
|
ctx->bye_notify_fnc (ctx);
|
||||||
return -1; /* pretty simple :-) */
|
return -1; /* pretty simple :-) */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +66,9 @@ std_handler_auth (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
static int
|
static int
|
||||||
std_handler_reset (ASSUAN_CONTEXT ctx, char *line)
|
std_handler_reset (ASSUAN_CONTEXT ctx, char *line)
|
||||||
{
|
{
|
||||||
return set_error (ctx, Not_Implemented, NULL);
|
if (ctx->reset_notify_fnc)
|
||||||
|
ctx->reset_notify_fnc (ctx);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -82,8 +88,9 @@ parse_cmd_input_output (ASSUAN_CONTEXT ctx, char *line, int *rfd)
|
|||||||
if (!digitp (*line))
|
if (!digitp (*line))
|
||||||
return set_error (ctx, Syntax_Error, "number required");
|
return set_error (ctx, Syntax_Error, "number required");
|
||||||
*rfd = strtoul (line, &endp, 10);
|
*rfd = strtoul (line, &endp, 10);
|
||||||
if (*endp)
|
/* remove that argument so that a notify handler won't see it */
|
||||||
return set_error (ctx, Syntax_Error, "garbage found");
|
memset (line, ' ', endp? (endp-line):strlen(line));
|
||||||
|
|
||||||
if (*rfd == ctx->inbound.fd)
|
if (*rfd == ctx->inbound.fd)
|
||||||
return set_error (ctx, Parameter_Conflict, "fd same as inbound fd");
|
return set_error (ctx, Parameter_Conflict, "fd same as inbound fd");
|
||||||
if (*rfd == ctx->outbound.fd)
|
if (*rfd == ctx->outbound.fd)
|
||||||
@ -101,6 +108,8 @@ std_handler_input (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
ctx->input_fd = fd;
|
ctx->input_fd = fd;
|
||||||
|
if (ctx->input_notify_fnc)
|
||||||
|
ctx->input_notify_fnc (ctx, line);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,6 +123,8 @@ std_handler_output (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
ctx->output_fd = fd;
|
ctx->output_fd = fd;
|
||||||
|
if (ctx->output_notify_fnc)
|
||||||
|
ctx->output_notify_fnc (ctx, line);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +139,7 @@ static struct {
|
|||||||
const char *name;
|
const char *name;
|
||||||
int cmd_id;
|
int cmd_id;
|
||||||
int (*handler)(ASSUAN_CONTEXT, char *line);
|
int (*handler)(ASSUAN_CONTEXT, char *line);
|
||||||
int always; /* always initializethis command */
|
int always; /* always initialize this command */
|
||||||
} 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 },
|
||||||
@ -220,6 +231,54 @@ assuan_register_command (ASSUAN_CONTEXT ctx,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
assuan_register_bye_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
|
||||||
|
{
|
||||||
|
if (!ctx)
|
||||||
|
return ASSUAN_Invalid_Value;
|
||||||
|
ctx->bye_notify_fnc = fnc;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
assuan_register_reset_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
|
||||||
|
{
|
||||||
|
if (!ctx)
|
||||||
|
return ASSUAN_Invalid_Value;
|
||||||
|
ctx->reset_notify_fnc = fnc;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
assuan_register_cancel_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
|
||||||
|
{
|
||||||
|
if (!ctx)
|
||||||
|
return ASSUAN_Invalid_Value;
|
||||||
|
ctx->cancel_notify_fnc = fnc;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
assuan_register_input_notify (ASSUAN_CONTEXT ctx,
|
||||||
|
void (*fnc)(ASSUAN_CONTEXT, const char *))
|
||||||
|
{
|
||||||
|
if (!ctx)
|
||||||
|
return ASSUAN_Invalid_Value;
|
||||||
|
ctx->input_notify_fnc = fnc;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
assuan_register_output_notify (ASSUAN_CONTEXT ctx,
|
||||||
|
void (*fnc)(ASSUAN_CONTEXT, const char *))
|
||||||
|
{
|
||||||
|
if (!ctx)
|
||||||
|
return ASSUAN_Invalid_Value;
|
||||||
|
ctx->output_notify_fnc = fnc;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Helper to register the standards commands */
|
/* Helper to register the standards commands */
|
||||||
int
|
int
|
||||||
_assuan_register_std_commands (ASSUAN_CONTEXT ctx)
|
_assuan_register_std_commands (ASSUAN_CONTEXT ctx)
|
||||||
@ -289,6 +348,61 @@ dispatch_command (ASSUAN_CONTEXT ctx, char *line, int linelen)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
process_request (ASSUAN_CONTEXT ctx)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (ctx->in_inquire)
|
||||||
|
return ASSUAN_Nested_Commands;
|
||||||
|
|
||||||
|
rc = _assuan_read_line (ctx);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
if (*ctx->inbound.line == '#' || !ctx->inbound.linelen)
|
||||||
|
return 0; /* comment line - ignore */
|
||||||
|
|
||||||
|
ctx->outbound.data.error = 0;
|
||||||
|
ctx->outbound.data.linelen = 0;
|
||||||
|
/* dispatch command and return reply */
|
||||||
|
rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen);
|
||||||
|
/* check from data write errors */
|
||||||
|
if (ctx->outbound.data.fp)
|
||||||
|
{ /* Flush the data lines */
|
||||||
|
fclose (ctx->outbound.data.fp);
|
||||||
|
ctx->outbound.data.fp = NULL;
|
||||||
|
if (!rc && ctx->outbound.data.error)
|
||||||
|
rc = ctx->outbound.data.error;
|
||||||
|
}
|
||||||
|
/* Error handling */
|
||||||
|
if (!rc)
|
||||||
|
{
|
||||||
|
rc = assuan_write_line (ctx, "OK");
|
||||||
|
}
|
||||||
|
else if (rc == -1)
|
||||||
|
{ /* No error checking because the peer may have already disconnect */
|
||||||
|
assuan_write_line (ctx, "OK closing connection");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char errline[256];
|
||||||
|
|
||||||
|
if (rc < 100)
|
||||||
|
sprintf (errline, "ERR %d server fault (%.50s)",
|
||||||
|
ASSUAN_Server_Fault, assuan_strerror (rc));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char *text = ctx->err_no == rc? ctx->err_str:NULL;
|
||||||
|
|
||||||
|
sprintf (errline, "ERR %d %.50s%s%.100s",
|
||||||
|
rc, assuan_strerror (rc), text? " - ":"", text?text:"");
|
||||||
|
}
|
||||||
|
rc = assuan_write_line (ctx, errline);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* assuan_process:
|
* assuan_process:
|
||||||
@ -307,55 +421,7 @@ assuan_process (ASSUAN_CONTEXT ctx)
|
|||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
/* Read the line but skip comments */
|
rc = process_request (ctx);
|
||||||
do
|
|
||||||
{
|
|
||||||
rc = _assuan_read_line (ctx);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
/* fprintf (stderr, "DBG-assuan: got %d bytes `%s'\n", */
|
|
||||||
/* ctx->inbound.linelen, ctx->inbound.line); */
|
|
||||||
}
|
|
||||||
while ( *ctx->inbound.line == '#' || !ctx->inbound.linelen);
|
|
||||||
|
|
||||||
ctx->outbound.data.error = 0;
|
|
||||||
ctx->outbound.data.linelen = 0;
|
|
||||||
/* dispatch command and return reply */
|
|
||||||
rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen);
|
|
||||||
/* check from data write errors */
|
|
||||||
if (ctx->outbound.data.fp)
|
|
||||||
{ /* Flush the data lines */
|
|
||||||
fclose (ctx->outbound.data.fp);
|
|
||||||
ctx->outbound.data.fp = NULL;
|
|
||||||
if (!rc && ctx->outbound.data.error)
|
|
||||||
rc = ctx->outbound.data.error;
|
|
||||||
}
|
|
||||||
/* Error handling */
|
|
||||||
if (!rc)
|
|
||||||
{
|
|
||||||
rc = _assuan_write_line (ctx, "OK");
|
|
||||||
}
|
|
||||||
else if (rc == -1)
|
|
||||||
{ /* No error checking because the peer may have already disconnect */
|
|
||||||
_assuan_write_line (ctx, "OK Bye, bye - hope to meet you again");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char errline[256];
|
|
||||||
|
|
||||||
if (rc < 100)
|
|
||||||
sprintf (errline, "ERR %d server fault (%.50s)",
|
|
||||||
ASSUAN_Server_Fault, assuan_strerror (rc));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const char *text = ctx->err_no == rc? ctx->err_str:NULL;
|
|
||||||
|
|
||||||
sprintf (errline, "ERR %d %.50s%s%.100s",
|
|
||||||
rc, assuan_strerror (rc), text? " - ":"", text?text:"");
|
|
||||||
}
|
|
||||||
rc = _assuan_write_line (ctx, errline);
|
|
||||||
}
|
|
||||||
} while (!rc);
|
} while (!rc);
|
||||||
|
|
||||||
if (rc == -1)
|
if (rc == -1)
|
||||||
@ -365,6 +431,65 @@ assuan_process (ASSUAN_CONTEXT ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* assuan_process_next:
|
||||||
|
* @ctx: Assuan context
|
||||||
|
*
|
||||||
|
* Same as assuan_process() but the user has to provide the outer
|
||||||
|
* loop. He should loop as long as the return code is zero and stop
|
||||||
|
* otherwise; -1 is regular end.
|
||||||
|
*
|
||||||
|
* See also: assuan_get_active_fds()
|
||||||
|
* Return value: -1 for end of server, 0 on success or an error code
|
||||||
|
**/
|
||||||
|
int
|
||||||
|
assuan_process_next (ASSUAN_CONTEXT ctx)
|
||||||
|
{
|
||||||
|
return process_request (ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* assuan_get_active_fds:
|
||||||
|
* @ctx: Assuan context
|
||||||
|
* @what: 0 for read fds, 1 for write fds
|
||||||
|
* @fdarray: Caller supplied array to store the FDs
|
||||||
|
* @fdarraysize: size of that array
|
||||||
|
*
|
||||||
|
* Return all active filedescriptors for the given context. This
|
||||||
|
* function can be used to select on the fds and call
|
||||||
|
* assuan_process_next() if there is an active one.
|
||||||
|
*
|
||||||
|
* Note, that write FDs are not yet supported.
|
||||||
|
*
|
||||||
|
* Return value: number of FDs active and put into @fdarray or -1 on
|
||||||
|
* error which is most likely a too small fdarray.
|
||||||
|
**/
|
||||||
|
int
|
||||||
|
assuan_get_active_fds (ASSUAN_CONTEXT ctx, int what,
|
||||||
|
int *fdarray, int fdarraysize)
|
||||||
|
{
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
if (ctx || fdarraysize < 2 || what < 0 || what > 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!what)
|
||||||
|
{
|
||||||
|
if (ctx->inbound.fd != -1)
|
||||||
|
fdarray[n++] = ctx->inbound.fd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ctx->outbound.fd != -1)
|
||||||
|
fdarray[n++] = ctx->outbound.fd;
|
||||||
|
if (ctx->outbound.data.fp)
|
||||||
|
fdarray[n++] = fileno (ctx->outbound.data.fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return a FP to be used for data output. The FILE pointer is valid
|
/* Return a FP to be used for data output. The FILE pointer is valid
|
||||||
until the end of a handler. So a close is not needed. Assuan does
|
until the end of a handler. So a close is not needed. Assuan does
|
||||||
all the buffering needed to insert the status line as well as the
|
all the buffering needed to insert the status line as well as the
|
||||||
@ -414,7 +539,7 @@ assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text)
|
|||||||
strcat (buffer, " ");
|
strcat (buffer, " ");
|
||||||
strcat (buffer, text);
|
strcat (buffer, text);
|
||||||
}
|
}
|
||||||
_assuan_write_line (ctx, buffer);
|
assuan_write_line (ctx, buffer);
|
||||||
}
|
}
|
||||||
else if ( (helpbuf = xtrymalloc (n)) )
|
else if ( (helpbuf = xtrymalloc (n)) )
|
||||||
{
|
{
|
||||||
@ -425,7 +550,7 @@ assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text)
|
|||||||
strcat (helpbuf, " ");
|
strcat (helpbuf, " ");
|
||||||
strcat (helpbuf, text);
|
strcat (helpbuf, text);
|
||||||
}
|
}
|
||||||
_assuan_write_line (ctx, helpbuf);
|
assuan_write_line (ctx, helpbuf);
|
||||||
xfree (helpbuf);
|
xfree (helpbuf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
220
assuan/assuan-inquire.c
Normal file
220
assuan/assuan-inquire.c
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
/* assuan-inquire.c - handle inquire stuff
|
||||||
|
* Copyright (C) 2001 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GnuPG.
|
||||||
|
*
|
||||||
|
* GnuPG is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GnuPG is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "assuan-defs.h"
|
||||||
|
|
||||||
|
#define digitp(a) ((a) >= '0' && (a) <= '9')
|
||||||
|
#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
|
||||||
|
*(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
|
||||||
|
#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
|
||||||
|
|
||||||
|
|
||||||
|
struct membuf {
|
||||||
|
size_t len;
|
||||||
|
size_t size;
|
||||||
|
char *buf;
|
||||||
|
int out_of_core;
|
||||||
|
int too_large;
|
||||||
|
size_t maxlen;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* A simple implemnation of a dynamic buffer. Use init_membuf() to
|
||||||
|
create a buffer, put_membuf to append bytes and get_membuf to
|
||||||
|
release and return the buffer. Allocation errors are detected but
|
||||||
|
only returned at the final get_membuf(), this helps not to clutter
|
||||||
|
the code with out of core checks. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_membuf (struct membuf *mb, int initiallen, size_t maxlen)
|
||||||
|
{
|
||||||
|
mb->len = 0;
|
||||||
|
mb->size = initiallen;
|
||||||
|
mb->out_of_core = 0;
|
||||||
|
mb->too_large = 0;
|
||||||
|
mb->maxlen = maxlen;
|
||||||
|
mb->buf = xtrymalloc (initiallen);
|
||||||
|
if (!mb->buf)
|
||||||
|
mb->out_of_core = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
put_membuf (struct membuf *mb, const void *buf, size_t len)
|
||||||
|
{
|
||||||
|
if (mb->out_of_core || mb->too_large)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mb->maxlen && mb->len + len > mb->maxlen)
|
||||||
|
{
|
||||||
|
mb->too_large = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mb->len + len >= mb->size)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
mb->size += len + 1024;
|
||||||
|
p = xtryrealloc (mb->buf, mb->size);
|
||||||
|
if (!p)
|
||||||
|
{
|
||||||
|
mb->out_of_core = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mb->buf = p;
|
||||||
|
}
|
||||||
|
memcpy (mb->buf + mb->len, buf, len);
|
||||||
|
mb->len += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
get_membuf (struct membuf *mb, size_t *len)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (mb->out_of_core || mb->too_large)
|
||||||
|
{
|
||||||
|
xfree (mb->buf);
|
||||||
|
mb->buf = NULL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = mb->buf;
|
||||||
|
*len = mb->len;
|
||||||
|
mb->buf = NULL;
|
||||||
|
mb->out_of_core = 1; /* don't allow a reuse */
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_membuf (struct membuf *mb)
|
||||||
|
{
|
||||||
|
xfree (mb->buf);
|
||||||
|
mb->buf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* assuan_inquire:
|
||||||
|
* @ctx: An assuan context
|
||||||
|
* @keyword: The keyword used for the inquire
|
||||||
|
* @r_buffer: Returns an allocated buffer
|
||||||
|
* @r_length: Returns the length of this buffer
|
||||||
|
* @maxlen: If no 0, the size limit of the inquired data.
|
||||||
|
*
|
||||||
|
* A Server may use this to Send an inquire
|
||||||
|
*
|
||||||
|
* Return value: 0 on success or an ASSUAN error code
|
||||||
|
**/
|
||||||
|
AssuanError
|
||||||
|
assuan_inquire (ASSUAN_CONTEXT ctx, const char *keyword,
|
||||||
|
char **r_buffer, size_t *r_length, size_t maxlen)
|
||||||
|
{
|
||||||
|
AssuanError rc;
|
||||||
|
struct membuf mb;
|
||||||
|
char cmdbuf[100];
|
||||||
|
unsigned char *line, *p;
|
||||||
|
int linelen;
|
||||||
|
|
||||||
|
if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf))
|
||||||
|
|| !r_buffer || !r_length )
|
||||||
|
return ASSUAN_Invalid_Value;
|
||||||
|
if (!ctx->is_server)
|
||||||
|
return ASSUAN_Not_A_Server;
|
||||||
|
if (ctx->in_inquire)
|
||||||
|
return ASSUAN_Nested_Commands;
|
||||||
|
|
||||||
|
ctx->in_inquire = 1;
|
||||||
|
init_membuf (&mb, maxlen? maxlen:1024, maxlen);
|
||||||
|
|
||||||
|
strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword);
|
||||||
|
rc = assuan_write_line (ctx, cmdbuf);
|
||||||
|
if (rc)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
rc = _assuan_read_line (ctx);
|
||||||
|
if (rc)
|
||||||
|
goto leave;
|
||||||
|
line = ctx->inbound.line;
|
||||||
|
linelen = ctx->inbound.linelen;
|
||||||
|
}
|
||||||
|
while (*line == '#' || !linelen);
|
||||||
|
if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
|
||||||
|
&& (!line[3] || line[3] == ' '))
|
||||||
|
break; /* END command received*/
|
||||||
|
if (line[0] != 'D' || line[1] != ' ')
|
||||||
|
{
|
||||||
|
rc = ASSUAN_Unexpected_Command;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
if (linelen < 3)
|
||||||
|
continue;
|
||||||
|
line += 2;
|
||||||
|
linelen -= 2;
|
||||||
|
|
||||||
|
p = line;
|
||||||
|
while (linelen)
|
||||||
|
{
|
||||||
|
for (;linelen && *p != '%'; linelen--, p++)
|
||||||
|
;
|
||||||
|
put_membuf (&mb, line, p-line);
|
||||||
|
if (linelen > 2)
|
||||||
|
{ /* handle escaping */
|
||||||
|
unsigned char tmp[1];
|
||||||
|
p++;
|
||||||
|
*tmp = xtoi_2 (p);
|
||||||
|
p += 2;
|
||||||
|
linelen -= 3;
|
||||||
|
put_membuf (&mb, tmp, 1);
|
||||||
|
}
|
||||||
|
line = p;
|
||||||
|
}
|
||||||
|
if (mb.too_large)
|
||||||
|
{
|
||||||
|
rc = ASSUAN_Too_Much_Data;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*r_buffer = get_membuf (&mb, r_length);
|
||||||
|
if (!*r_buffer)
|
||||||
|
rc = ASSUAN_Out_Of_Core;
|
||||||
|
|
||||||
|
leave:
|
||||||
|
free_membuf (&mb);
|
||||||
|
ctx->in_inquire = 0;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -25,6 +25,28 @@
|
|||||||
|
|
||||||
#include "assuan-defs.h"
|
#include "assuan-defs.h"
|
||||||
|
|
||||||
|
AssuanError
|
||||||
|
assuan_set_hello_line (ASSUAN_CONTEXT ctx, const char *line)
|
||||||
|
{
|
||||||
|
if (!ctx)
|
||||||
|
return ASSUAN_Invalid_Value;
|
||||||
|
if (!line)
|
||||||
|
{
|
||||||
|
xfree (ctx->hello_line);
|
||||||
|
ctx->hello_line = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *buf = xtrymalloc (3+strlen(line)+1);
|
||||||
|
if (!buf)
|
||||||
|
return ASSUAN_Out_Of_Core;
|
||||||
|
strcpy (buf, "OK ");
|
||||||
|
strcpy (buf+3, line);
|
||||||
|
xfree (ctx->hello_line);
|
||||||
|
ctx->hello_line = buf;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,7 +60,7 @@
|
|||||||
* Return value: 0 on success or an error if the connection could for
|
* Return value: 0 on success or an error if the connection could for
|
||||||
* some reason not be established.
|
* some reason not be established.
|
||||||
**/
|
**/
|
||||||
int
|
AssuanError
|
||||||
assuan_accept (ASSUAN_CONTEXT ctx)
|
assuan_accept (ASSUAN_CONTEXT ctx)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
@ -57,9 +79,8 @@ assuan_accept (ASSUAN_CONTEXT ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* send the hello */
|
/* send the hello */
|
||||||
|
rc = assuan_write_line (ctx, ctx->hello_line? ctx->hello_line
|
||||||
rc = _assuan_write_line (ctx,
|
: "OK Your orders please");
|
||||||
"OK Hello dear client - what can I do for you?");
|
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -70,6 +91,7 @@ assuan_accept (ASSUAN_CONTEXT ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
assuan_get_input_fd (ASSUAN_CONTEXT ctx)
|
assuan_get_input_fd (ASSUAN_CONTEXT ctx)
|
||||||
{
|
{
|
||||||
|
@ -35,6 +35,7 @@ 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;
|
||||||
|
|
||||||
@ -54,7 +55,11 @@ assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2])
|
|||||||
void
|
void
|
||||||
assuan_deinit_pipe_server (ASSUAN_CONTEXT ctx)
|
assuan_deinit_pipe_server (ASSUAN_CONTEXT ctx)
|
||||||
{
|
{
|
||||||
xfree (ctx);
|
if (ctx)
|
||||||
|
{
|
||||||
|
xfree (ctx->hello_line);
|
||||||
|
xfree (ctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -66,4 +71,3 @@ assuan_deinit_pipe_server (ASSUAN_CONTEXT ctx)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,6 +39,14 @@ typedef enum {
|
|||||||
ASSUAN_Timeout = 4,
|
ASSUAN_Timeout = 4,
|
||||||
ASSUAN_Read_Error = 5,
|
ASSUAN_Read_Error = 5,
|
||||||
ASSUAN_Write_Error = 6,
|
ASSUAN_Write_Error = 6,
|
||||||
|
ASSUAN_Problem_Starting_Server = 7,
|
||||||
|
ASSUAN_Not_A_Server = 8,
|
||||||
|
ASSUAN_Not_A_Client = 9,
|
||||||
|
ASSUAN_Nested_Commands = 10,
|
||||||
|
ASSUAN_Invalid_Response = 11,
|
||||||
|
ASSUAN_No_Data_Callback = 12,
|
||||||
|
ASSUAN_No_Inquire_Callback = 13,
|
||||||
|
ASSUAN_Connect_Failed = 14,
|
||||||
|
|
||||||
/* 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,
|
||||||
@ -53,10 +61,28 @@ typedef enum {
|
|||||||
ASSUAN_No_Input = 109,
|
ASSUAN_No_Input = 109,
|
||||||
ASSUAN_No_Output = 110,
|
ASSUAN_No_Output = 110,
|
||||||
ASSUAN_Canceled = 111,
|
ASSUAN_Canceled = 111,
|
||||||
|
ASSUAN_Unsupported_Algorithm = 112,
|
||||||
|
ASSUAN_Server_Resource_Problem = 113,
|
||||||
|
ASSUAN_Server_IO_Error = 114,
|
||||||
|
ASSUAN_Server_Bug = 115,
|
||||||
|
ASSUAN_No_Data_Available = 116,
|
||||||
|
ASSUAN_Invalid_Data = 117,
|
||||||
|
ASSUAN_Unexpected_Command = 118,
|
||||||
|
ASSUAN_Too_Much_Data = 119,
|
||||||
|
|
||||||
|
ASSUAN_Bad_Certificate = 201,
|
||||||
|
ASSUAN_Bad_Certificate_Path = 202,
|
||||||
|
ASSUAN_Missing_Certificate = 203,
|
||||||
|
ASSUAN_Bad_Signature = 204,
|
||||||
|
ASSUAN_No_Agent = 205,
|
||||||
|
ASSUAN_Agent_Error = 206,
|
||||||
|
ASSUAN_No_Public_Key = 207,
|
||||||
|
ASSUAN_No_Secret_Key = 208,
|
||||||
|
ASSUAN_Invalid_Name = 209,
|
||||||
|
|
||||||
ASSUAN_Cert_Revoked = 301,
|
ASSUAN_Cert_Revoked = 301,
|
||||||
ASSUAN_No_CRL_For_Cert = 302,
|
ASSUAN_No_CRL_For_Cert = 302,
|
||||||
ASSUNA_CRL_Too_Old = 303,
|
ASSUAN_CRL_Too_Old = 303,
|
||||||
|
|
||||||
} AssuanError;
|
} AssuanError;
|
||||||
|
|
||||||
@ -83,14 +109,30 @@ typedef struct assuan_context_s *ASSUAN_CONTEXT;
|
|||||||
int assuan_register_command (ASSUAN_CONTEXT ctx,
|
int assuan_register_command (ASSUAN_CONTEXT ctx,
|
||||||
int cmd_id, const char *cmd_string,
|
int cmd_id, const char *cmd_string,
|
||||||
int (*handler)(ASSUAN_CONTEXT, char *));
|
int (*handler)(ASSUAN_CONTEXT, char *));
|
||||||
|
int assuan_register_bye_notify (ASSUAN_CONTEXT ctx,
|
||||||
|
void (*fnc)(ASSUAN_CONTEXT));
|
||||||
|
int assuan_register_reset_notify (ASSUAN_CONTEXT ctx,
|
||||||
|
void (*fnc)(ASSUAN_CONTEXT));
|
||||||
|
int assuan_register_cancel_notify (ASSUAN_CONTEXT ctx,
|
||||||
|
void (*fnc)(ASSUAN_CONTEXT));
|
||||||
|
int assuan_register_input_notify (ASSUAN_CONTEXT ctx,
|
||||||
|
void (*fnc)(ASSUAN_CONTEXT, const char *));
|
||||||
|
int assuan_register_output_notify (ASSUAN_CONTEXT ctx,
|
||||||
|
void (*fnc)(ASSUAN_CONTEXT, const char *));
|
||||||
int assuan_process (ASSUAN_CONTEXT ctx);
|
int assuan_process (ASSUAN_CONTEXT ctx);
|
||||||
|
int assuan_process_next (ASSUAN_CONTEXT ctx);
|
||||||
|
int assuan_get_active_fds (ASSUAN_CONTEXT ctx, int what,
|
||||||
|
int *fdarray, int fdarraysize);
|
||||||
|
|
||||||
|
|
||||||
FILE *assuan_get_data_fp (ASSUAN_CONTEXT ctx);
|
FILE *assuan_get_data_fp (ASSUAN_CONTEXT ctx);
|
||||||
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);
|
||||||
|
|
||||||
|
|
||||||
/*-- assuan-listen.c --*/
|
/*-- assuan-listen.c --*/
|
||||||
int assuan_accept (ASSUAN_CONTEXT ctx);
|
AssuanError assuan_set_hello_line (ASSUAN_CONTEXT ctx, const char *line);
|
||||||
|
AssuanError assuan_accept (ASSUAN_CONTEXT ctx);
|
||||||
int assuan_get_input_fd (ASSUAN_CONTEXT ctx);
|
int assuan_get_input_fd (ASSUAN_CONTEXT ctx);
|
||||||
int assuan_get_output_fd (ASSUAN_CONTEXT ctx);
|
int assuan_get_output_fd (ASSUAN_CONTEXT ctx);
|
||||||
|
|
||||||
@ -106,6 +148,29 @@ AssuanError assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name,
|
|||||||
void assuan_pipe_disconnect (ASSUAN_CONTEXT ctx);
|
void assuan_pipe_disconnect (ASSUAN_CONTEXT ctx);
|
||||||
pid_t assuan_get_pid (ASSUAN_CONTEXT ctx);
|
pid_t assuan_get_pid (ASSUAN_CONTEXT ctx);
|
||||||
|
|
||||||
|
/*-- assuan-client.c --*/
|
||||||
|
AssuanError
|
||||||
|
assuan_transact (ASSUAN_CONTEXT ctx,
|
||||||
|
const char *command,
|
||||||
|
AssuanError (*data_cb)(void *, const void *, size_t),
|
||||||
|
void *data_cb_arg,
|
||||||
|
AssuanError (*inquire_cb)(void*, const char *),
|
||||||
|
void *inquire_cb_arg);
|
||||||
|
|
||||||
|
|
||||||
|
/*-- assuan-inquire.c --*/
|
||||||
|
AssuanError assuan_inquire (ASSUAN_CONTEXT ctx, const char *keyword,
|
||||||
|
char **r_buffer, size_t *r_length, size_t maxlen);
|
||||||
|
|
||||||
|
/*-- assuan-buffer.c --*/
|
||||||
|
AssuanError assuan_read_line (ASSUAN_CONTEXT ctx,
|
||||||
|
char **line, size_t *linelen);
|
||||||
|
int assuan_pending_line (ASSUAN_CONTEXT ctx);
|
||||||
|
AssuanError assuan_write_line (ASSUAN_CONTEXT ctx, const char *line );
|
||||||
|
AssuanError assuan_send_data (ASSUAN_CONTEXT ctx,
|
||||||
|
const void *buffer, size_t length);
|
||||||
|
|
||||||
|
|
||||||
/*-- assuan-util.c --*/
|
/*-- assuan-util.c --*/
|
||||||
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),
|
||||||
@ -123,3 +188,5 @@ const char *assuan_strerror (AssuanError err);
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif /*ASSUAN_H*/
|
#endif /*ASSUAN_H*/
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user