assuan/
Update to current version. 2006-09-19 Marcus Brinkmann <marcus@g10code.de> * configure.ac: Turn stpcpy into a replacement function. Check for unistd.h and add setenv as replacement function. gpgme/ 2006-09-19 Marcus Brinkmann <marcus@g10code.de> * setenv.c: New file.
This commit is contained in:
parent
426fd0cc08
commit
9e09d93de8
@ -1,3 +1,8 @@
|
|||||||
|
2006-09-19 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
|
* configure.ac: Turn stpcpy into a replacement function.
|
||||||
|
Check for unistd.h and add setenv as replacement function.
|
||||||
|
|
||||||
2006-07-29 Marcus Brinkmann <marcus@g10code.de>
|
2006-07-29 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
* configure.ac: Check for network libraries and set NETLIBS.
|
* configure.ac: Check for network libraries and set NETLIBS.
|
||||||
|
168
assuan/ChangeLog
168
assuan/ChangeLog
@ -1,3 +1,171 @@
|
|||||||
|
2006-09-19 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
|
* assuan.h (assuan_init_socket_server_ext)
|
||||||
|
[_ASSUAN_EXT_SYM_PREFIX]: Fix typo in macro.
|
||||||
|
|
||||||
|
2006-09-19 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* assuan-defs.h (putc_unlocked): Add prototype.
|
||||||
|
|
||||||
|
* assuan-socket-server.c (accept_connection): Made LEN a socklen_t.
|
||||||
|
|
||||||
|
* assuan.h: Replaced assuan error code enum by simple defines and
|
||||||
|
made assuan_error_t an int.
|
||||||
|
* mkerrors: Changed parser accordingly.
|
||||||
|
|
||||||
|
2006-09-19 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
|
* assuan-pipe-connect.c: Add hacks for Slowaris.
|
||||||
|
* assuan-socket.c: Likewise here.
|
||||||
|
|
||||||
|
* assuan.h (enum): Avoid trailing comma in enumerator list. Ugh.
|
||||||
|
|
||||||
|
* mkerrors (_assuan_error): Change return type to assuan_error_t.
|
||||||
|
* assuan-buffer.c (_assuan_read_line): Change return type to
|
||||||
|
assuan_error_t. Map returned value of -1.
|
||||||
|
(_assuan_write_line): Change type of RC to assuan_error_t.
|
||||||
|
* assuan-defs.h (_assuan_read_line, _assuan_error): Likewise for
|
||||||
|
prototypes.
|
||||||
|
|
||||||
|
* assuan-defs.h (unsetenv): Define correctly.
|
||||||
|
|
||||||
|
2006-09-14 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* assuan-io.c (_assuan_waitpid): New. Changed all waitpid calls
|
||||||
|
to this.
|
||||||
|
|
||||||
|
* assuan.h (_ASSUAN_DEPRECATED): New internal macro.
|
||||||
|
(assuan_pipe_connect2): Declare deprecated.
|
||||||
|
(assuan_init_connected_socket_server): Declare deprecated.
|
||||||
|
|
||||||
|
* assuan-connect.c (assuan_get_peercred): New.
|
||||||
|
* assuan-socket-server.c (accept_connection_bottom): Save uid and gid.
|
||||||
|
|
||||||
|
2006-09-13 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* assuan-client.c (assuan_transact): Need to map the error code.
|
||||||
|
* mkerrors: Need to map ASSUAN_No_Secret_Key.
|
||||||
|
|
||||||
|
* assuan-pipe-server.c (is_valid_socket): New.
|
||||||
|
(assuan_init_pipe_server): Use UDS with the environmet variable is
|
||||||
|
set and a valid descriptor is given. Ignore FILEDES in this case.
|
||||||
|
|
||||||
|
* assuan-socket-server.c (assuan_init_socket_server_ext): New.
|
||||||
|
Changed other init fucntions to make use of it.
|
||||||
|
|
||||||
|
* assuan-handler.c (assuan_command_parse_fd): Allow for lowercase
|
||||||
|
"fd".
|
||||||
|
(std_handler_reset): Close pending fds.
|
||||||
|
* assuan-uds.c (uds_receivefd): Fixed.
|
||||||
|
(_assuan_uds_close_fds): New.
|
||||||
|
|
||||||
|
* assuan-socket-connect.c (assuan_socket_connect_ext): New. Takes
|
||||||
|
all code of assuan_socket_connect plus an option to use sendmsg.
|
||||||
|
* assuan-pipe-connect.c (assuan_pipe_connect_ext): New arg FLAGS.
|
||||||
|
|
||||||
|
2006-09-12 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* assuan-buffer.c (_assuan_write_line): Also log the prefix.
|
||||||
|
|
||||||
|
* assuan-defs.h (DIM, DIMof): New.
|
||||||
|
|
||||||
|
* assuan-domain-server.c: Removed.
|
||||||
|
* assuan-domain-connect.c: Renamed to ..
|
||||||
|
* assuan-uds.c: this.
|
||||||
|
(domain_reader, domain_writer, domain_sendfd, domain_receivefd)
|
||||||
|
(assuan_domain_connect, _assuan_domain_init): Removed.
|
||||||
|
(uds_reader, uds_writer, uds_sendfd, uds_receivefd)
|
||||||
|
(_assuan_init_uds_io): New.
|
||||||
|
(_assuan_uds_deinit): New.
|
||||||
|
|
||||||
|
* assuan-io.c (_assuan_simple_sendmsg, _assuan_simple_recvmsg): New.
|
||||||
|
(my_pth_fdmode, my_pth_select): New.
|
||||||
|
|
||||||
|
2006-09-11 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* assuan-pipe-server.c (assuan_init_pipe_server): Allow for
|
||||||
|
FILEDES to be NULL and try to start as a socketpair server in this
|
||||||
|
case.
|
||||||
|
|
||||||
|
* assuan-pipe-connect.c (assuan_pipe_connect2): Split up into two
|
||||||
|
functions (unix and w32) for clarity.
|
||||||
|
(pipe_connect_unix): This is the new fucntion. Add USE_CMSG flag.
|
||||||
|
(pipe_connect_w32): Ditto.
|
||||||
|
(initial_handshake): Factored out code.
|
||||||
|
(socketpair_connect): New.
|
||||||
|
(assuan_pipe_connect_ext): New.
|
||||||
|
(do_finish): Handle case if outbound and inbound fd are the same.
|
||||||
|
This is to support socketpairs.
|
||||||
|
|
||||||
|
2006-09-10 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* assuan-util.c (_assuan_log_print_buffer)
|
||||||
|
(_assuan_log_sanitized_string,assuan_set_log_stream): Moved to ..
|
||||||
|
* assuan-logging.c: .. here.
|
||||||
|
(_assuan_log_print_buffer): Only print the leading bytes in hex
|
||||||
|
log mode unless the new env variable ASSUAN_FULL_LOGGING has been
|
||||||
|
set.
|
||||||
|
(_assuan_set_default_log_stream): Test this env variable.
|
||||||
|
|
||||||
|
2006-09-06 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* assuan.h (_ASSUAN_ONLY_GPG_ERRORS): New.
|
||||||
|
|
||||||
|
* assuan-handler.c (dispatch_command): Use Syntax_Error instead of
|
||||||
|
Invalid_Command.
|
||||||
|
|
||||||
|
* assuan-domain-connect.c: Changed alloc malloc/free/realloc to
|
||||||
|
xtrymalloc et al.
|
||||||
|
(read_int, write_int): Make args void pointers.
|
||||||
|
(domain_receivefd): Take care of realloc shrinking failure.
|
||||||
|
|
||||||
|
* assuan-buffer.c (_assuan_read_line, _assuan_write_line)
|
||||||
|
(assuan_write_line, _assuan_cookie_write_data)
|
||||||
|
(_assuan_cookie_write_flush): Print the inbound fd instead of the
|
||||||
|
address of the context when logging I/0. This makes it more
|
||||||
|
readable.
|
||||||
|
|
||||||
|
2006-09-05 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* assuan-defs.h (err_code, err_is_eof): New.
|
||||||
|
|
||||||
|
* mkerrors (_assuan_error): New. Wrapped all error code
|
||||||
|
assignments in a call to this.
|
||||||
|
(assuan_strerror): Map gpg-style error codes back. Also print a
|
||||||
|
string for the old EOF code.
|
||||||
|
(assuan_set_assuan_err_source): New.
|
||||||
|
|
||||||
|
* assuan-logging.c (_assuan_log_printf): Do not change ERRNO and
|
||||||
|
print the pid.
|
||||||
|
|
||||||
|
* assuan-domain-connect.c (domain_reader): Replaced plain printf
|
||||||
|
by assuan_log function.
|
||||||
|
|
||||||
|
2005-10-24 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* putc_unlocked.c, memrchr.c, isascii.c, funopen.c: Changed
|
||||||
|
distribution terms to LGPL. This are small and trivial files so
|
||||||
|
there are no obstacles of doing so.
|
||||||
|
* assuan-socket.c: Likewise, the stated GPL was not intended.
|
||||||
|
|
||||||
|
2005-10-08 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
|
* assuan-defs.h (setenv, unsetenv, clearenv) [!HAVE_SETENV]:
|
||||||
|
Define to _assuan_*.
|
||||||
|
* setenv.c: Include "assuan-defs.h".
|
||||||
|
(__add_to_environ): Make static.
|
||||||
|
|
||||||
|
2005-10-07 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
|
* assuan-defs.h (memrchr) [!HAVE_MEMRCHR]: New prototype.
|
||||||
|
(stpcpy) [!HAVE_STPCPY]: Likewise.
|
||||||
|
* stpcpy.c: New LGPL'ed file from the GNU C Library.
|
||||||
|
* setenv.c: New file.
|
||||||
|
* assuan-domain-connect.c (read_int): New function.
|
||||||
|
(write_int): New function.
|
||||||
|
(domain_reader): Use read_int.
|
||||||
|
(domain_sendfd): Use write_int.
|
||||||
|
|
||||||
2005-10-01 Marcus Brinkmann <marcus@g10code.de>
|
2005-10-01 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
* assuan.h (assuan_pipe_connect, assuan_pipe_connect2): Make type
|
* assuan.h (assuan_pipe_connect, assuan_pipe_connect2): Make type
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Lesser General Public
|
# You should have received a copy of the GNU Lesser General Public
|
||||||
# License along with this program; if not, write to the Free Software
|
# License along with this program; if not, write to the Free Software
|
||||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
## Process this file with automake to produce Makefile.in
|
## Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
@ -44,12 +44,11 @@ libassuan_la_SOURCES = \
|
|||||||
assuan-socket-server.c \
|
assuan-socket-server.c \
|
||||||
assuan-pipe-connect.c \
|
assuan-pipe-connect.c \
|
||||||
assuan-socket-connect.c \
|
assuan-socket-connect.c \
|
||||||
assuan-socket.c \
|
assuan-uds.c \
|
||||||
funopen.c \
|
funopen.c \
|
||||||
assuan-io.c \
|
assuan-io.c \
|
||||||
assuan-domain-connect.c \
|
assuan-logging.c \
|
||||||
assuan-domain-server.c \
|
assuan-socket.c
|
||||||
assuan-logging.c
|
|
||||||
|
|
||||||
assuan-errors.c : assuan.h
|
assuan-errors.c : assuan.h mkerrors
|
||||||
$(srcdir)/mkerrors < $(srcdir)/assuan.h > assuan-errors.c
|
$(srcdir)/mkerrors < $(srcdir)/assuan.h > assuan-errors.c
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this program; if not, write to the Free Software
|
* License along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
* USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@ -30,8 +31,11 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "assuan-defs.h"
|
#include "assuan-defs.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Extended version of write(2) to guarantee that all bytes are
|
||||||
|
written. Returns 0 on success or -1 and ERRNO on failure. */
|
||||||
static int
|
static int
|
||||||
writen (ASSUAN_CONTEXT ctx, const char *buffer, size_t length)
|
writen (assuan_context_t ctx, const char *buffer, size_t length)
|
||||||
{
|
{
|
||||||
while (length)
|
while (length)
|
||||||
{
|
{
|
||||||
@ -49,9 +53,11 @@ writen (ASSUAN_CONTEXT ctx, const char *buffer, size_t length)
|
|||||||
return 0; /* okay */
|
return 0; /* okay */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read an entire line. */
|
/* Read an entire line. Returns 0 on success or -1 and ERRNo on
|
||||||
|
failure. EOF is indictated by setting the integer at address
|
||||||
|
R_EOF. */
|
||||||
static int
|
static int
|
||||||
readline (ASSUAN_CONTEXT ctx, char *buf, size_t buflen,
|
readline (assuan_context_t ctx, char *buf, size_t buflen,
|
||||||
int *r_nread, int *r_eof)
|
int *r_nread, int *r_eof)
|
||||||
{
|
{
|
||||||
size_t nleft = buflen;
|
size_t nleft = buflen;
|
||||||
@ -88,8 +94,9 @@ readline (ASSUAN_CONTEXT ctx, char *buf, size_t buflen,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
/* Function returns an Assuan error. */
|
||||||
_assuan_read_line (ASSUAN_CONTEXT ctx)
|
assuan_error_t
|
||||||
|
_assuan_read_line (assuan_context_t ctx)
|
||||||
{
|
{
|
||||||
char *line = ctx->inbound.line;
|
char *line = ctx->inbound.line;
|
||||||
int nread, atticlen;
|
int nread, atticlen;
|
||||||
@ -97,7 +104,7 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
|
|||||||
char *endp = 0;
|
char *endp = 0;
|
||||||
|
|
||||||
if (ctx->inbound.eof)
|
if (ctx->inbound.eof)
|
||||||
return -1;
|
return _assuan_error (-1);
|
||||||
|
|
||||||
atticlen = ctx->inbound.attic.linelen;
|
atticlen = ctx->inbound.attic.linelen;
|
||||||
if (atticlen)
|
if (atticlen)
|
||||||
@ -128,19 +135,20 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
|
|||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
if (ctx->log_fp)
|
if (ctx->log_fp)
|
||||||
fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [Error: %s]\n",
|
fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [Error: %s]\n",
|
||||||
assuan_get_assuan_log_prefix (),
|
assuan_get_assuan_log_prefix (),
|
||||||
(unsigned int)getpid (), ctx, strerror (errno));
|
(unsigned int)getpid (), ctx->inbound.fd,
|
||||||
return ASSUAN_Read_Error;
|
strerror (errno));
|
||||||
|
return _assuan_error (ASSUAN_Read_Error);
|
||||||
}
|
}
|
||||||
if (!nread)
|
if (!nread)
|
||||||
{
|
{
|
||||||
assert (ctx->inbound.eof);
|
assert (ctx->inbound.eof);
|
||||||
if (ctx->log_fp)
|
if (ctx->log_fp)
|
||||||
fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [EOF]\n",
|
fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [EOF]\n",
|
||||||
assuan_get_assuan_log_prefix (),
|
assuan_get_assuan_log_prefix (),
|
||||||
(unsigned int)getpid (), ctx);
|
(unsigned int)getpid (), ctx->inbound.fd);
|
||||||
return -1;
|
return _assuan_error (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->inbound.attic.pending = 0;
|
ctx->inbound.attic.pending = 0;
|
||||||
@ -170,9 +178,9 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
|
|||||||
ctx->inbound.linelen = endp - line;
|
ctx->inbound.linelen = endp - line;
|
||||||
if (ctx->log_fp)
|
if (ctx->log_fp)
|
||||||
{
|
{
|
||||||
fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- ",
|
fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- ",
|
||||||
assuan_get_assuan_log_prefix (),
|
assuan_get_assuan_log_prefix (),
|
||||||
(unsigned int)getpid (), ctx);
|
(unsigned int)getpid (), ctx->inbound.fd);
|
||||||
if (ctx->confidential)
|
if (ctx->confidential)
|
||||||
fputs ("[Confidential data not shown]", ctx->log_fp);
|
fputs ("[Confidential data not shown]", ctx->log_fp);
|
||||||
else
|
else
|
||||||
@ -186,13 +194,14 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (ctx->log_fp)
|
if (ctx->log_fp)
|
||||||
fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [Invalid line]\n",
|
fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [Invalid line]\n",
|
||||||
assuan_get_assuan_log_prefix (),
|
assuan_get_assuan_log_prefix (),
|
||||||
(unsigned int)getpid (), ctx);
|
(unsigned int)getpid (), ctx->inbound.fd);
|
||||||
*line = 0;
|
*line = 0;
|
||||||
ctx->inbound.linelen = 0;
|
ctx->inbound.linelen = 0;
|
||||||
return ctx->inbound.eof ? ASSUAN_Line_Not_Terminated
|
return _assuan_error (ctx->inbound.eof
|
||||||
: ASSUAN_Line_Too_Long;
|
? ASSUAN_Line_Not_Terminated
|
||||||
|
: ASSUAN_Line_Too_Long);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,12 +216,12 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
|
|||||||
See also: assuan_pending_line().
|
See also: assuan_pending_line().
|
||||||
*/
|
*/
|
||||||
assuan_error_t
|
assuan_error_t
|
||||||
assuan_read_line (ASSUAN_CONTEXT ctx, char **line, size_t *linelen)
|
assuan_read_line (assuan_context_t ctx, char **line, size_t *linelen)
|
||||||
{
|
{
|
||||||
assuan_error_t err;
|
assuan_error_t err;
|
||||||
|
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
|
|
||||||
err = _assuan_read_line (ctx);
|
err = _assuan_read_line (ctx);
|
||||||
*line = ctx->inbound.line;
|
*line = ctx->inbound.line;
|
||||||
@ -224,7 +233,7 @@ assuan_read_line (ASSUAN_CONTEXT ctx, char **line, size_t *linelen)
|
|||||||
/* Return true if a full line is buffered (i.e. an entire line may be
|
/* Return true if a full line is buffered (i.e. an entire line may be
|
||||||
read without any I/O). */
|
read without any I/O). */
|
||||||
int
|
int
|
||||||
assuan_pending_line (ASSUAN_CONTEXT ctx)
|
assuan_pending_line (assuan_context_t ctx)
|
||||||
{
|
{
|
||||||
return ctx && ctx->inbound.attic.pending;
|
return ctx && ctx->inbound.attic.pending;
|
||||||
}
|
}
|
||||||
@ -234,17 +243,17 @@ assuan_error_t
|
|||||||
_assuan_write_line (assuan_context_t ctx, const char *prefix,
|
_assuan_write_line (assuan_context_t ctx, const char *prefix,
|
||||||
const char *line, size_t len)
|
const char *line, size_t len)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
assuan_error_t rc = 0;
|
||||||
size_t prefixlen = prefix? strlen (prefix):0;
|
size_t prefixlen = prefix? strlen (prefix):0;
|
||||||
|
|
||||||
/* Make sure that the line is short enough. */
|
/* Make sure that the line is short enough. */
|
||||||
if (len + prefixlen + 2 > ASSUAN_LINELENGTH)
|
if (len + prefixlen + 2 > ASSUAN_LINELENGTH)
|
||||||
{
|
{
|
||||||
if (ctx->log_fp)
|
if (ctx->log_fp)
|
||||||
fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> "
|
fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> "
|
||||||
"[supplied line too long -truncated]\n",
|
"[supplied line too long -truncated]\n",
|
||||||
assuan_get_assuan_log_prefix (),
|
assuan_get_assuan_log_prefix (),
|
||||||
(unsigned int)getpid (), ctx);
|
(unsigned int)getpid (), ctx->inbound.fd);
|
||||||
if (prefixlen > 5)
|
if (prefixlen > 5)
|
||||||
prefixlen = 5;
|
prefixlen = 5;
|
||||||
if (len > ASSUAN_LINELENGTH - prefixlen - 2)
|
if (len > ASSUAN_LINELENGTH - prefixlen - 2)
|
||||||
@ -254,13 +263,17 @@ _assuan_write_line (assuan_context_t ctx, const char *prefix,
|
|||||||
/* Fixme: we should do some kind of line buffering. */
|
/* Fixme: we should do some kind of line buffering. */
|
||||||
if (ctx->log_fp)
|
if (ctx->log_fp)
|
||||||
{
|
{
|
||||||
fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ",
|
fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ",
|
||||||
assuan_get_assuan_log_prefix (),
|
assuan_get_assuan_log_prefix (),
|
||||||
(unsigned int)getpid (), ctx);
|
(unsigned int)getpid (), ctx->inbound.fd);
|
||||||
if (ctx->confidential)
|
if (ctx->confidential)
|
||||||
fputs ("[Confidential data not shown]", ctx->log_fp);
|
fputs ("[Confidential data not shown]", ctx->log_fp);
|
||||||
else
|
else
|
||||||
_assuan_log_print_buffer (ctx->log_fp, line, len);
|
{
|
||||||
|
if (prefixlen)
|
||||||
|
_assuan_log_print_buffer (ctx->log_fp, prefix, prefixlen);
|
||||||
|
_assuan_log_print_buffer (ctx->log_fp, line, len);
|
||||||
|
}
|
||||||
putc ('\n', ctx->log_fp);
|
putc ('\n', ctx->log_fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,18 +281,18 @@ _assuan_write_line (assuan_context_t ctx, const char *prefix,
|
|||||||
{
|
{
|
||||||
rc = writen (ctx, prefix, prefixlen);
|
rc = writen (ctx, prefix, prefixlen);
|
||||||
if (rc)
|
if (rc)
|
||||||
rc = ASSUAN_Write_Error;
|
rc = _assuan_error (ASSUAN_Write_Error);
|
||||||
}
|
}
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
rc = writen (ctx, line, len);
|
rc = writen (ctx, line, len);
|
||||||
if (rc)
|
if (rc)
|
||||||
rc = ASSUAN_Write_Error;
|
rc = _assuan_error (ASSUAN_Write_Error);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
rc = writen (ctx, "\n", 1);
|
rc = writen (ctx, "\n", 1);
|
||||||
if (rc)
|
if (rc)
|
||||||
rc = ASSUAN_Write_Error;
|
rc = _assuan_error (ASSUAN_Write_Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
@ -287,13 +300,13 @@ _assuan_write_line (assuan_context_t ctx, const char *prefix,
|
|||||||
|
|
||||||
|
|
||||||
assuan_error_t
|
assuan_error_t
|
||||||
assuan_write_line (ASSUAN_CONTEXT ctx, const char *line)
|
assuan_write_line (assuan_context_t ctx, const char *line)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
const char *s;
|
const char *s;
|
||||||
|
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
|
|
||||||
/* Make sure that we never take a LF from the user - this might
|
/* Make sure that we never take a LF from the user - this might
|
||||||
violate the protocol. */
|
violate the protocol. */
|
||||||
@ -301,10 +314,10 @@ assuan_write_line (ASSUAN_CONTEXT ctx, const char *line)
|
|||||||
len = s? (s-line) : strlen (line);
|
len = s? (s-line) : strlen (line);
|
||||||
|
|
||||||
if (ctx->log_fp && s)
|
if (ctx->log_fp && s)
|
||||||
fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> "
|
fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> "
|
||||||
"[supplied line contained a LF -truncated]\n",
|
"[supplied line contained a LF - truncated]\n",
|
||||||
assuan_get_assuan_log_prefix (),
|
assuan_get_assuan_log_prefix (),
|
||||||
(unsigned int)getpid (), ctx);
|
(unsigned int)getpid (), ctx->inbound.fd);
|
||||||
|
|
||||||
return _assuan_write_line (ctx, NULL, line, len);
|
return _assuan_write_line (ctx, NULL, line, len);
|
||||||
}
|
}
|
||||||
@ -316,7 +329,7 @@ assuan_write_line (ASSUAN_CONTEXT ctx, const char *line)
|
|||||||
int
|
int
|
||||||
_assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size)
|
_assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size)
|
||||||
{
|
{
|
||||||
ASSUAN_CONTEXT ctx = cookie;
|
assuan_context_t ctx = cookie;
|
||||||
size_t size = orig_size;
|
size_t size = orig_size;
|
||||||
char *line;
|
char *line;
|
||||||
size_t linelen;
|
size_t linelen;
|
||||||
@ -359,9 +372,9 @@ _assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size)
|
|||||||
{
|
{
|
||||||
if (ctx->log_fp)
|
if (ctx->log_fp)
|
||||||
{
|
{
|
||||||
fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ",
|
fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ",
|
||||||
assuan_get_assuan_log_prefix (),
|
assuan_get_assuan_log_prefix (),
|
||||||
(unsigned int)getpid (), ctx);
|
(unsigned int)getpid (), ctx->inbound.fd);
|
||||||
|
|
||||||
if (ctx->confidential)
|
if (ctx->confidential)
|
||||||
fputs ("[Confidential data not shown]", ctx->log_fp);
|
fputs ("[Confidential data not shown]", ctx->log_fp);
|
||||||
@ -375,7 +388,7 @@ _assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size)
|
|||||||
linelen++;
|
linelen++;
|
||||||
if (writen (ctx, ctx->outbound.data.line, linelen))
|
if (writen (ctx, ctx->outbound.data.line, linelen))
|
||||||
{
|
{
|
||||||
ctx->outbound.data.error = ASSUAN_Write_Error;
|
ctx->outbound.data.error = _assuan_error (ASSUAN_Write_Error);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
line = ctx->outbound.data.line;
|
line = ctx->outbound.data.line;
|
||||||
@ -393,7 +406,7 @@ _assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size)
|
|||||||
int
|
int
|
||||||
_assuan_cookie_write_flush (void *cookie)
|
_assuan_cookie_write_flush (void *cookie)
|
||||||
{
|
{
|
||||||
ASSUAN_CONTEXT ctx = cookie;
|
assuan_context_t ctx = cookie;
|
||||||
char *line;
|
char *line;
|
||||||
size_t linelen;
|
size_t linelen;
|
||||||
|
|
||||||
@ -407,9 +420,9 @@ _assuan_cookie_write_flush (void *cookie)
|
|||||||
{
|
{
|
||||||
if (ctx->log_fp)
|
if (ctx->log_fp)
|
||||||
{
|
{
|
||||||
fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ",
|
fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ",
|
||||||
assuan_get_assuan_log_prefix (),
|
assuan_get_assuan_log_prefix (),
|
||||||
(unsigned int)getpid (), ctx);
|
(unsigned int)getpid (), ctx->inbound.fd);
|
||||||
if (ctx->confidential)
|
if (ctx->confidential)
|
||||||
fputs ("[Confidential data not shown]", ctx->log_fp);
|
fputs ("[Confidential data not shown]", ctx->log_fp);
|
||||||
else
|
else
|
||||||
@ -421,7 +434,7 @@ _assuan_cookie_write_flush (void *cookie)
|
|||||||
linelen++;
|
linelen++;
|
||||||
if (writen (ctx, ctx->outbound.data.line, linelen))
|
if (writen (ctx, ctx->outbound.data.line, linelen))
|
||||||
{
|
{
|
||||||
ctx->outbound.data.error = ASSUAN_Write_Error;
|
ctx->outbound.data.error = _assuan_error (ASSUAN_Write_Error);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ctx->outbound.data.linelen = 0;
|
ctx->outbound.data.linelen = 0;
|
||||||
@ -449,12 +462,12 @@ _assuan_cookie_write_flush (void *cookie)
|
|||||||
**/
|
**/
|
||||||
|
|
||||||
assuan_error_t
|
assuan_error_t
|
||||||
assuan_send_data (ASSUAN_CONTEXT ctx, const void *buffer, size_t length)
|
assuan_send_data (assuan_context_t ctx, const void *buffer, size_t length)
|
||||||
{
|
{
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
if (!buffer && length)
|
if (!buffer && length)
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
|
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
{ /* flush what we have */
|
{ /* flush what we have */
|
||||||
@ -475,7 +488,7 @@ assuan_send_data (ASSUAN_CONTEXT ctx, const void *buffer, size_t length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
assuan_error_t
|
assuan_error_t
|
||||||
assuan_sendfd (ASSUAN_CONTEXT ctx, int fd)
|
assuan_sendfd (assuan_context_t ctx, int fd)
|
||||||
{
|
{
|
||||||
if (! ctx->io->sendfd)
|
if (! ctx->io->sendfd)
|
||||||
return set_error (ctx, Not_Implemented,
|
return set_error (ctx, Not_Implemented,
|
||||||
@ -485,7 +498,7 @@ assuan_sendfd (ASSUAN_CONTEXT ctx, int fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
assuan_error_t
|
assuan_error_t
|
||||||
assuan_receivefd (ASSUAN_CONTEXT ctx, int *fd)
|
assuan_receivefd (assuan_context_t ctx, int *fd)
|
||||||
{
|
{
|
||||||
if (! ctx->io->receivefd)
|
if (! ctx->io->receivefd)
|
||||||
return set_error (ctx, Not_Implemented,
|
return set_error (ctx, Not_Implemented,
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this program; if not, write to the Free Software
|
* License along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
* USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@ -33,7 +34,7 @@
|
|||||||
|
|
||||||
|
|
||||||
assuan_error_t
|
assuan_error_t
|
||||||
_assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off)
|
_assuan_read_from_server (assuan_context_t ctx, int *okay, int *off)
|
||||||
{
|
{
|
||||||
char *line;
|
char *line;
|
||||||
int linelen;
|
int linelen;
|
||||||
@ -103,7 +104,7 @@ _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off)
|
|||||||
*off = 3;
|
*off = 3;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
rc = ASSUAN_Invalid_Response;
|
rc = _assuan_error (ASSUAN_Invalid_Response);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +113,7 @@ _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off)
|
|||||||
/**
|
/**
|
||||||
* assuan_transact:
|
* assuan_transact:
|
||||||
* @ctx: The Assuan context
|
* @ctx: The Assuan context
|
||||||
* @command: Coimmand line to be send to server
|
* @command: Command line to be send to the server
|
||||||
* @data_cb: Callback function for data lines
|
* @data_cb: Callback function for data lines
|
||||||
* @data_cb_arg: first argument passed to @data_cb
|
* @data_cb_arg: first argument passed to @data_cb
|
||||||
* @inquire_cb: Callback function for a inquire response
|
* @inquire_cb: Callback function for a inquire response
|
||||||
@ -124,19 +125,22 @@ _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off)
|
|||||||
*
|
*
|
||||||
* Return value: 0 on success or error code. The error code may be
|
* 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
|
* the one one returned by the server in error lines or from the
|
||||||
* callback functions.
|
* callback functions. Take care: When a callback returns an error
|
||||||
|
* this function returns immediately with an error and thus the caller
|
||||||
|
* will altter return an Assuan error (write erro in most cases).
|
||||||
**/
|
**/
|
||||||
assuan_error_t
|
assuan_error_t
|
||||||
assuan_transact (ASSUAN_CONTEXT ctx,
|
assuan_transact (assuan_context_t ctx,
|
||||||
const char *command,
|
const char *command,
|
||||||
assuan_error_t (*data_cb)(void *, const void *, size_t),
|
int (*data_cb)(void *, const void *, size_t),
|
||||||
void *data_cb_arg,
|
void *data_cb_arg,
|
||||||
assuan_error_t (*inquire_cb)(void*, const char *),
|
int (*inquire_cb)(void*, const char *),
|
||||||
void *inquire_cb_arg,
|
void *inquire_cb_arg,
|
||||||
assuan_error_t (*status_cb)(void*, const char *),
|
int (*status_cb)(void*, const char *),
|
||||||
void *status_cb_arg)
|
void *status_cb_arg)
|
||||||
{
|
{
|
||||||
int rc, okay, off;
|
assuan_error_t rc;
|
||||||
|
int okay, off;
|
||||||
char *line;
|
char *line;
|
||||||
int linelen;
|
int linelen;
|
||||||
|
|
||||||
@ -157,14 +161,14 @@ assuan_transact (ASSUAN_CONTEXT ctx,
|
|||||||
|
|
||||||
if (!okay)
|
if (!okay)
|
||||||
{
|
{
|
||||||
rc = atoi (line);
|
rc = _assuan_error (atoi (line));
|
||||||
if (rc < 100)
|
if (rc < 100)
|
||||||
rc = ASSUAN_Server_Fault;
|
rc = ASSUAN_Server_Fault;
|
||||||
}
|
}
|
||||||
else if (okay == 2)
|
else if (okay == 2)
|
||||||
{
|
{
|
||||||
if (!data_cb)
|
if (!data_cb)
|
||||||
rc = ASSUAN_No_Data_Callback;
|
rc = _assuan_error (ASSUAN_No_Data_Callback);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *s, *d;
|
char *s, *d;
|
||||||
@ -193,7 +197,7 @@ assuan_transact (ASSUAN_CONTEXT ctx,
|
|||||||
{
|
{
|
||||||
assuan_write_line (ctx, "END"); /* get out of inquire mode */
|
assuan_write_line (ctx, "END"); /* get out of inquire mode */
|
||||||
_assuan_read_from_server (ctx, &okay, &off); /* dummy read */
|
_assuan_read_from_server (ctx, &okay, &off); /* dummy read */
|
||||||
rc = ASSUAN_No_Inquire_Callback;
|
rc = _assuan_error (ASSUAN_No_Inquire_Callback);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -214,7 +218,7 @@ assuan_transact (ASSUAN_CONTEXT ctx,
|
|||||||
else if (okay == 5)
|
else if (okay == 5)
|
||||||
{
|
{
|
||||||
if (!data_cb)
|
if (!data_cb)
|
||||||
rc = ASSUAN_No_Data_Callback;
|
rc = _assuan_error (ASSUAN_No_Data_Callback);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rc = data_cb (data_cb_arg, NULL, 0);
|
rc = data_cb (data_cb_arg, NULL, 0);
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this program; if not, write to the Free Software
|
* License along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
* USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
@ -49,10 +50,30 @@ assuan_disconnect (assuan_context_t ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the PID of the peer or -1 if not known. */
|
/* Return the PID of the peer or -1 if not known. This function works
|
||||||
|
in some situations where assuan_get_ucred fails. */
|
||||||
pid_t
|
pid_t
|
||||||
assuan_get_pid (assuan_context_t ctx)
|
assuan_get_pid (assuan_context_t ctx)
|
||||||
{
|
{
|
||||||
return (ctx && ctx->pid)? ctx->pid : -1;
|
return (ctx && ctx->pid)? ctx->pid : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return user credentials. PID, UID and GID amy be gived as NULL if
|
||||||
|
you are not interested in this value. For getting the pid of the
|
||||||
|
peer the assuan_get_pid is usually better suited. */
|
||||||
|
assuan_error_t
|
||||||
|
assuan_get_peercred (assuan_context_t ctx, pid_t *pid, uid_t *uid, gid_t *gid)
|
||||||
|
{
|
||||||
|
if (!ctx)
|
||||||
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
|
if (!ctx->peercred.valid)
|
||||||
|
return _assuan_error (ASSUAN_General_Error);
|
||||||
|
if (pid)
|
||||||
|
*pid = ctx->peercred.pid;
|
||||||
|
if (uid)
|
||||||
|
*uid = ctx->peercred.uid;
|
||||||
|
if (gid)
|
||||||
|
*gid = ctx->peercred.gid;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* assuan-defs.c - Internal definitions to Assuan
|
/* assuan-defs.c - Internal definitions to Assuan
|
||||||
* Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
|
* Copyright (C) 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of Assuan.
|
* This file is part of Assuan.
|
||||||
*
|
*
|
||||||
@ -15,7 +15,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this program; if not, write to the Free Software
|
* License along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
* USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ASSUAN_DEFS_H
|
#ifndef ASSUAN_DEFS_H
|
||||||
@ -62,24 +63,30 @@ char * stpcpy (char *dest, const char *src);
|
|||||||
|
|
||||||
#define LINELENGTH ASSUAN_LINELENGTH
|
#define LINELENGTH ASSUAN_LINELENGTH
|
||||||
|
|
||||||
|
|
||||||
struct cmdtbl_s
|
struct cmdtbl_s
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
int (*handler)(ASSUAN_CONTEXT, char *line);
|
int (*handler)(assuan_context_t, char *line);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* A structure to dispatch I/O functions. All these functions need to
|
||||||
|
return 0 on success and set ERRNO on failure. */
|
||||||
struct assuan_io
|
struct assuan_io
|
||||||
{
|
{
|
||||||
/* Routine to read from input_fd. */
|
/* Routine to read from input_fd. */
|
||||||
ssize_t (*readfnc) (ASSUAN_CONTEXT, void *, size_t);
|
ssize_t (*readfnc) (assuan_context_t, void *, size_t);
|
||||||
/* Routine to write to output_fd. */
|
/* Routine to write to output_fd. */
|
||||||
ssize_t (*writefnc) (ASSUAN_CONTEXT, const void *, size_t);
|
ssize_t (*writefnc) (assuan_context_t, const void *, size_t);
|
||||||
/* Send a file descriptor. */
|
/* Send a file descriptor. */
|
||||||
assuan_error_t (*sendfd) (ASSUAN_CONTEXT, int);
|
assuan_error_t (*sendfd) (assuan_context_t, int);
|
||||||
/* Receive a file descriptor. */
|
/* Receive a file descriptor. */
|
||||||
assuan_error_t (*receivefd) (ASSUAN_CONTEXT, int *);
|
assuan_error_t (*receivefd) (assuan_context_t, int *);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* The context we use with most functions. */
|
||||||
struct assuan_context_s
|
struct assuan_context_s
|
||||||
{
|
{
|
||||||
assuan_error_t err_no;
|
assuan_error_t err_no;
|
||||||
@ -99,7 +106,7 @@ struct assuan_context_s
|
|||||||
char *hello_line;
|
char *hello_line;
|
||||||
char *okay_line; /* See assuan_set_okay_line() */
|
char *okay_line; /* See assuan_set_okay_line() */
|
||||||
|
|
||||||
void *user_pointer; /* For assuan_get_pointer and assuan-set_pointer (). */
|
void *user_pointer; /* For assuan_get_pointer and assuan_set_pointer (). */
|
||||||
|
|
||||||
FILE *log_fp;
|
FILE *log_fp;
|
||||||
|
|
||||||
@ -109,7 +116,7 @@ struct assuan_context_s
|
|||||||
char line[LINELENGTH];
|
char line[LINELENGTH];
|
||||||
int linelen; /* w/o CR, LF - might not be the same as
|
int linelen; /* w/o CR, LF - might not be the same as
|
||||||
strlen(line) due to embedded nuls. However a nul
|
strlen(line) due to embedded nuls. However a nul
|
||||||
is always written at this pos */
|
is always written at this pos. */
|
||||||
struct {
|
struct {
|
||||||
char line[LINELENGTH];
|
char line[LINELENGTH];
|
||||||
int linelen ;
|
int linelen ;
|
||||||
@ -128,43 +135,49 @@ struct assuan_context_s
|
|||||||
} outbound;
|
} outbound;
|
||||||
|
|
||||||
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; /* The the pid of the peer. */
|
pid_t pid; /* The pid of the peer. */
|
||||||
int listen_fd; /* The fd we are listening on (used by socket servers) */
|
int listen_fd; /* The fd we are listening on (used by socket servers) */
|
||||||
int connected_fd; /* helper */
|
int connected_fd; /* helper */
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int valid; /* Whether this structure has valid information. */
|
||||||
|
pid_t pid; /* The pid of the peer. */
|
||||||
|
uid_t uid; /* The uid of the peer. */
|
||||||
|
gid_t gid; /* The gid of the peer. */
|
||||||
|
} peercred;
|
||||||
|
|
||||||
/* Used for Unix domain sockets. */
|
/* Used for Unix domain sockets. */
|
||||||
struct sockaddr_un myaddr;
|
struct sockaddr_un myaddr;
|
||||||
struct sockaddr_un serveraddr;
|
struct sockaddr_un serveraddr;
|
||||||
/* When reading from datagram sockets, we must read an entire
|
|
||||||
message at a time. This means that we have to do our own
|
|
||||||
buffering to be able to get the semantics of read. */
|
|
||||||
void *domainbuffer;
|
|
||||||
/* Offset of start of buffer. */
|
|
||||||
int domainbufferoffset;
|
|
||||||
/* Bytes buffered. */
|
|
||||||
int domainbuffersize;
|
|
||||||
/* Memory allocated. */
|
|
||||||
int domainbufferallocated;
|
|
||||||
|
|
||||||
int *pendingfds;
|
/* Structure used for unix domain socket buffering. FIXME: We don't
|
||||||
int pendingfdscount;
|
use datagrams anymore thus we could get away with a simpler
|
||||||
|
buffering approach. */
|
||||||
|
struct {
|
||||||
|
void *buffer; /* Malloced buffer. */
|
||||||
|
int bufferallocated; /* Memory allocated. */
|
||||||
|
int bufferoffset; /* Offset of start of buffer. */
|
||||||
|
int buffersize; /* Bytes buffered. */
|
||||||
|
|
||||||
void (*deinit_handler)(ASSUAN_CONTEXT);
|
int pendingfds[5]; /* Array to save received descriptors. */
|
||||||
int (*accept_handler)(ASSUAN_CONTEXT);
|
int pendingfdscount; /* Number of received descriptors. */
|
||||||
int (*finish_handler)(ASSUAN_CONTEXT);
|
} uds;
|
||||||
|
|
||||||
|
void (*deinit_handler)(assuan_context_t);
|
||||||
|
int (*accept_handler)(assuan_context_t);
|
||||||
|
int (*finish_handler)(assuan_context_t);
|
||||||
|
|
||||||
struct cmdtbl_s *cmdtbl;
|
struct cmdtbl_s *cmdtbl;
|
||||||
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 (*bye_notify_fnc)(assuan_context_t);
|
||||||
void (*reset_notify_fnc)(ASSUAN_CONTEXT);
|
void (*reset_notify_fnc)(assuan_context_t);
|
||||||
void (*cancel_notify_fnc)(ASSUAN_CONTEXT);
|
void (*cancel_notify_fnc)(assuan_context_t);
|
||||||
int (*option_handler_fnc)(ASSUAN_CONTEXT,const char*, const char*);
|
int (*option_handler_fnc)(assuan_context_t,const char*, const char*);
|
||||||
void (*input_notify_fnc)(ASSUAN_CONTEXT, const char *);
|
void (*input_notify_fnc)(assuan_context_t, const char *);
|
||||||
void (*output_notify_fnc)(ASSUAN_CONTEXT, const char *);
|
void (*output_notify_fnc)(assuan_context_t, 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 */
|
||||||
@ -174,29 +187,45 @@ struct assuan_context_s
|
|||||||
};
|
};
|
||||||
|
|
||||||
/*-- assuan-pipe-server.c --*/
|
/*-- assuan-pipe-server.c --*/
|
||||||
int _assuan_new_context (ASSUAN_CONTEXT *r_ctx);
|
int _assuan_new_context (assuan_context_t *r_ctx);
|
||||||
void _assuan_release_context (ASSUAN_CONTEXT ctx);
|
void _assuan_release_context (assuan_context_t ctx);
|
||||||
|
|
||||||
|
/*-- assuan-uds.c --*/
|
||||||
|
void _assuan_uds_close_fds (assuan_context_t ctx);
|
||||||
|
void _assuan_uds_deinit (assuan_context_t ctx);
|
||||||
|
void _assuan_init_uds_io (assuan_context_t ctx);
|
||||||
|
|
||||||
/*-- assuan-domain-connect.c --*/
|
|
||||||
/* 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
|
|
||||||
become handy in the future. */
|
|
||||||
assuan_error_t _assuan_domain_init (ASSUAN_CONTEXT *r_ctx,
|
|
||||||
int rendezvousfd,
|
|
||||||
pid_t peer);
|
|
||||||
|
|
||||||
/*-- assuan-handler.c --*/
|
/*-- assuan-handler.c --*/
|
||||||
int _assuan_register_std_commands (ASSUAN_CONTEXT ctx);
|
int _assuan_register_std_commands (assuan_context_t ctx);
|
||||||
|
|
||||||
/*-- assuan-buffer.c --*/
|
/*-- assuan-buffer.c --*/
|
||||||
int _assuan_read_line (ASSUAN_CONTEXT ctx);
|
assuan_error_t _assuan_read_line (assuan_context_t 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_error_t _assuan_write_line (assuan_context_t ctx, const char *prefix,
|
assuan_error_t _assuan_write_line (assuan_context_t ctx, const char *prefix,
|
||||||
const char *line, size_t len);
|
const char *line, size_t len);
|
||||||
|
|
||||||
/*-- assuan-client.c --*/
|
/*-- assuan-client.c --*/
|
||||||
assuan_error_t _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off);
|
assuan_error_t _assuan_read_from_server (assuan_context_t ctx,
|
||||||
|
int *okay, int *off);
|
||||||
|
|
||||||
|
/*-- assuan-error.c --*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Map error codes as used in this implementaion to the libgpg-error
|
||||||
|
codes. */
|
||||||
|
assuan_error_t _assuan_error (int oldcode);
|
||||||
|
|
||||||
|
/* Extrac the erro code from A. This works for both the old and the
|
||||||
|
new style error codes. This needs to be whenever an error code is
|
||||||
|
compared. */
|
||||||
|
#define err_code(a) ((a) & 0x00ffffff)
|
||||||
|
|
||||||
|
/* Check whether A is the erro code for EOF. We allow forold and new
|
||||||
|
style EOF error codes here. */
|
||||||
|
#define err_is_eof(a) ((a) == (-1) || err_code (a) == 16383)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-- assuan-util.c --*/
|
/*-- assuan-util.c --*/
|
||||||
@ -210,10 +239,8 @@ void _assuan_free (void *p);
|
|||||||
#define xtryrealloc(a,b) _assuan_realloc((a),(b))
|
#define xtryrealloc(a,b) _assuan_realloc((a),(b))
|
||||||
#define xfree(a) _assuan_free ((a))
|
#define xfree(a) _assuan_free ((a))
|
||||||
|
|
||||||
#define set_error(c,e,t) assuan_set_error ((c), ASSUAN_ ## e, (t))
|
#define set_error(c,e,t) \
|
||||||
|
assuan_set_error ((c), _assuan_error (ASSUAN_ ## e), (t))
|
||||||
void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length);
|
|
||||||
void _assuan_log_sanitized_string (const char *string);
|
|
||||||
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
#ifdef HAVE_W32_SYSTEM
|
||||||
const char *_assuan_w32_strerror (int ec);
|
const char *_assuan_w32_strerror (int ec);
|
||||||
@ -229,11 +256,18 @@ void _assuan_log_printf (const char *format, ...)
|
|||||||
__attribute__ ((format (printf,1,2)))
|
__attribute__ ((format (printf,1,2)))
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
|
void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length);
|
||||||
|
void _assuan_log_sanitized_string (const char *string);
|
||||||
|
|
||||||
|
|
||||||
/*-- assuan-io.c --*/
|
/*-- assuan-io.c --*/
|
||||||
ssize_t _assuan_simple_read (ASSUAN_CONTEXT ctx, void *buffer, size_t size);
|
pid_t _assuan_waitpid (pid_t pid, int *status, int options);
|
||||||
ssize_t _assuan_simple_write (ASSUAN_CONTEXT ctx, const void *buffer,
|
|
||||||
|
ssize_t _assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size);
|
||||||
|
ssize_t _assuan_simple_write (assuan_context_t ctx, const void *buffer,
|
||||||
size_t size);
|
size_t size);
|
||||||
|
ssize_t _assuan_simple_sendmsg (assuan_context_t ctx, struct msghdr *msg);
|
||||||
|
ssize_t _assuan_simple_recvmsg (assuan_context_t ctx, struct msghdr *msg);
|
||||||
|
|
||||||
/*-- assuan-socket.c --*/
|
/*-- assuan-socket.c --*/
|
||||||
int _assuan_close (int fd);
|
int _assuan_close (int fd);
|
||||||
@ -251,5 +285,25 @@ FILE *_assuan_funopen(void *cookie,
|
|||||||
#define funopen(a,r,w,s,c) _assuan_funopen ((a), (r), (w), (s), (c))
|
#define funopen(a,r,w,s,c) _assuan_funopen ((a), (r), (w), (s), (c))
|
||||||
#endif /*HAVE_FOPENCOOKIE*/
|
#endif /*HAVE_FOPENCOOKIE*/
|
||||||
|
|
||||||
#endif /*ASSUAN_DEFS_H*/
|
/* Prototypes for replacement functions. */
|
||||||
|
#ifndef HAVE_MEMRCHR
|
||||||
|
void *memrchr (const void *block, int c, size_t size);
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_STPCPY
|
||||||
|
char *stpcpy (char *dest, const char *src);
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_SETENV
|
||||||
|
#define setenv _assuan_setenv
|
||||||
|
#define unsetenv _assuan_unsetenv
|
||||||
|
#define clearenv _assuan_clearenv
|
||||||
|
int setenv (const char *name, const char *value, int replace);
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_PUTC_UNLOCKED
|
||||||
|
int putc_unlocked (int c, FILE *stream)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DIM(v) (sizeof(v)/sizeof((v)[0]))
|
||||||
|
#define DIMof(type,member) DIM(((type *)0)->member)
|
||||||
|
|
||||||
|
|
||||||
|
#endif /*ASSUAN_DEFS_H*/
|
||||||
|
@ -1,504 +0,0 @@
|
|||||||
/* assuan-domain-connect.c - Assuan unix domain socket based client
|
|
||||||
* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
|
||||||
*
|
|
||||||
* This file is part of Assuan.
|
|
||||||
*
|
|
||||||
* Assuan is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU Lesser General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Assuan 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser 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 <stddef.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#ifndef HAVE_W32_SYSTEM
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#else
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_UIO_H
|
|
||||||
#include <sys/uio.h>
|
|
||||||
#endif
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "assuan-defs.h"
|
|
||||||
|
|
||||||
#ifndef PF_LOCAL
|
|
||||||
# ifdef PF_UNIX
|
|
||||||
# define PF_LOCAL PF_UNIX
|
|
||||||
# else
|
|
||||||
# define PF_LOCAL AF_UNIX
|
|
||||||
# endif
|
|
||||||
# ifndef AF_LOCAL
|
|
||||||
# define AF_LOCAL AF_UNIX
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
do_deinit (assuan_context_t ctx)
|
|
||||||
{
|
|
||||||
if (ctx->inbound.fd != -1)
|
|
||||||
_assuan_close (ctx->inbound.fd);
|
|
||||||
ctx->inbound.fd = -1;
|
|
||||||
ctx->outbound.fd = -1;
|
|
||||||
|
|
||||||
if (ctx->domainbuffer)
|
|
||||||
{
|
|
||||||
assert (ctx->domainbufferallocated);
|
|
||||||
free (ctx->domainbuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx->pendingfds)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
assert (ctx->pendingfdscount > 0);
|
|
||||||
for (i = 0; i < ctx->pendingfdscount; i ++)
|
|
||||||
_assuan_close (ctx->pendingfds[i]);
|
|
||||||
|
|
||||||
free (ctx->pendingfds);
|
|
||||||
}
|
|
||||||
|
|
||||||
unlink (ctx->myaddr.sun_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Read from the socket server. */
|
|
||||||
static ssize_t
|
|
||||||
domain_reader (assuan_context_t ctx, void *buf, size_t buflen)
|
|
||||||
{
|
|
||||||
int len = ctx->domainbuffersize;
|
|
||||||
|
|
||||||
#ifndef HAVE_W32_SYSTEM
|
|
||||||
start:
|
|
||||||
if (len == 0)
|
|
||||||
/* No data is buffered. */
|
|
||||||
{
|
|
||||||
struct msghdr msg;
|
|
||||||
struct iovec iovec;
|
|
||||||
struct sockaddr_un sender;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
struct cmsghdr hdr;
|
|
||||||
int fd;
|
|
||||||
}
|
|
||||||
cmsg;
|
|
||||||
|
|
||||||
memset (&msg, 0, sizeof (msg));
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
msg.msg_name = &sender;
|
|
||||||
msg.msg_namelen = sizeof (struct sockaddr_un);
|
|
||||||
msg.msg_iov = &iovec;
|
|
||||||
msg.msg_iovlen = 1;
|
|
||||||
iovec.iov_base = ctx->domainbuffer;
|
|
||||||
iovec.iov_len = ctx->domainbufferallocated;
|
|
||||||
msg.msg_control = &cmsg;
|
|
||||||
msg.msg_controllen = sizeof cmsg;
|
|
||||||
|
|
||||||
/* Peek first: if the buffer we have is too small then it
|
|
||||||
will be truncated. */
|
|
||||||
len = recvmsg (ctx->inbound.fd, &msg, MSG_PEEK);
|
|
||||||
if (len < 0)
|
|
||||||
{
|
|
||||||
printf ("domain_reader: %m\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp (ctx->serveraddr.sun_path,
|
|
||||||
((struct sockaddr_un *) msg.msg_name)->sun_path) != 0)
|
|
||||||
{
|
|
||||||
/* XXX: Arg. Not from whom we expected! What do we
|
|
||||||
want to do? Should we just ignore it? Either way,
|
|
||||||
we still need to consume the message. */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msg.msg_flags & MSG_TRUNC)
|
|
||||||
/* Enlarge the buffer and try again. */
|
|
||||||
{
|
|
||||||
int size = ctx->domainbufferallocated;
|
|
||||||
void *tmp;
|
|
||||||
|
|
||||||
if (size == 0)
|
|
||||||
size = 4 * 1024;
|
|
||||||
else
|
|
||||||
size *= 2;
|
|
||||||
|
|
||||||
tmp = malloc (size);
|
|
||||||
if (! tmp)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
free (ctx->domainbuffer);
|
|
||||||
ctx->domainbuffer = tmp;
|
|
||||||
ctx->domainbufferallocated = size;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* We have enough space! */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now we have to actually consume it (remember, we only
|
|
||||||
peeked). */
|
|
||||||
msg.msg_name = &sender;
|
|
||||||
msg.msg_namelen = sizeof (struct sockaddr_un);
|
|
||||||
msg.msg_iov = &iovec;
|
|
||||||
msg.msg_iovlen = 1;
|
|
||||||
iovec.iov_base = ctx->domainbuffer;
|
|
||||||
iovec.iov_len = ctx->domainbufferallocated;
|
|
||||||
msg.msg_control = &cmsg;
|
|
||||||
msg.msg_controllen = sizeof cmsg;
|
|
||||||
|
|
||||||
if (strcmp (ctx->serveraddr.sun_path,
|
|
||||||
((struct sockaddr_un *) msg.msg_name)->sun_path) != 0)
|
|
||||||
{
|
|
||||||
/* XXX: Arg. Not from whom we expected! What do we want to
|
|
||||||
do? Should we just ignore it? We shall do the latter
|
|
||||||
for the moment. */
|
|
||||||
_assuan_log_printf ("not setup to receive messages from `%s'\n",
|
|
||||||
((struct sockaddr_un *) msg.msg_name)->sun_path);
|
|
||||||
goto start;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = recvmsg (ctx->inbound.fd, &msg, 0);
|
|
||||||
if (len < 0)
|
|
||||||
{
|
|
||||||
_assuan_log_printf ("domain_reader: %s\n", strerror (errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->domainbuffersize = len;
|
|
||||||
ctx->domainbufferoffset = 0;
|
|
||||||
|
|
||||||
if (sizeof (cmsg) == msg.msg_controllen)
|
|
||||||
/* We received a file descriptor. */
|
|
||||||
{
|
|
||||||
void *tmp;
|
|
||||||
|
|
||||||
tmp = realloc (ctx->pendingfds,
|
|
||||||
sizeof (int) * (ctx->pendingfdscount + 1));
|
|
||||||
if (! tmp)
|
|
||||||
{
|
|
||||||
_assuan_log_printf ("domain_reader: %s\n", strerror (errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->pendingfds = tmp;
|
|
||||||
ctx->pendingfds[ctx->pendingfdscount++]
|
|
||||||
= *(int *) CMSG_DATA (&cmsg.hdr);
|
|
||||||
|
|
||||||
_assuan_log_printf ("received file descriptor %d from peer\n",
|
|
||||||
ctx->pendingfds[ctx->pendingfdscount - 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len == 0)
|
|
||||||
goto start;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
len = recvfrom (ctx->inbound.fd, buf, buflen, 0, NULL, NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Return some data to the user. */
|
|
||||||
|
|
||||||
if (len > buflen)
|
|
||||||
/* We have more than the user requested. */
|
|
||||||
len = buflen;
|
|
||||||
|
|
||||||
memcpy (buf, ctx->domainbuffer + ctx->domainbufferoffset, len);
|
|
||||||
ctx->domainbuffersize -= len;
|
|
||||||
assert (ctx->domainbuffersize >= 0);
|
|
||||||
ctx->domainbufferoffset += len;
|
|
||||||
assert (ctx->domainbufferoffset <= ctx->domainbufferallocated);
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write to the domain server. */
|
|
||||||
static ssize_t
|
|
||||||
domain_writer (assuan_context_t ctx, const void *buf, size_t buflen)
|
|
||||||
{
|
|
||||||
#ifndef HAVE_W32_SYSTEM
|
|
||||||
struct msghdr msg;
|
|
||||||
struct iovec iovec;
|
|
||||||
ssize_t len;
|
|
||||||
|
|
||||||
memset (&msg, 0, sizeof (msg));
|
|
||||||
|
|
||||||
msg.msg_name = &ctx->serveraddr;
|
|
||||||
msg.msg_namelen = offsetof (struct sockaddr_un, sun_path)
|
|
||||||
+ strlen (ctx->serveraddr.sun_path) + 1;
|
|
||||||
|
|
||||||
msg.msg_iovlen = 1;
|
|
||||||
msg.msg_iov = &iovec;
|
|
||||||
iovec.iov_base = (void *) buf;
|
|
||||||
iovec.iov_len = buflen;
|
|
||||||
msg.msg_control = 0;
|
|
||||||
msg.msg_controllen = 0;
|
|
||||||
|
|
||||||
len = sendmsg (ctx->outbound.fd, &msg, 0);
|
|
||||||
if (len < 0)
|
|
||||||
_assuan_log_printf ("domain_writer: %s\n", strerror (errno));
|
|
||||||
#else
|
|
||||||
int len;
|
|
||||||
|
|
||||||
len = sendto (ctx->outbound.fd, buf, buflen, 0,
|
|
||||||
(struct sockaddr *)&ctx->serveraddr,
|
|
||||||
sizeof (struct sockaddr_in));
|
|
||||||
#endif
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static assuan_error_t
|
|
||||||
domain_sendfd (assuan_context_t ctx, int fd)
|
|
||||||
{
|
|
||||||
#ifndef HAVE_W32_SYSTEM
|
|
||||||
struct msghdr msg;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
struct cmsghdr hdr;
|
|
||||||
int fd;
|
|
||||||
}
|
|
||||||
cmsg;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
memset (&msg, 0, sizeof (msg));
|
|
||||||
|
|
||||||
msg.msg_name = &ctx->serveraddr;
|
|
||||||
msg.msg_namelen = offsetof (struct sockaddr_un, sun_path)
|
|
||||||
+ strlen (ctx->serveraddr.sun_path) + 1;
|
|
||||||
|
|
||||||
msg.msg_iovlen = 0;
|
|
||||||
msg.msg_iov = 0;
|
|
||||||
|
|
||||||
cmsg.hdr.cmsg_level = SOL_SOCKET;
|
|
||||||
cmsg.hdr.cmsg_type = SCM_RIGHTS;
|
|
||||||
cmsg.hdr.cmsg_len = sizeof (cmsg);
|
|
||||||
|
|
||||||
msg.msg_control = &cmsg;
|
|
||||||
msg.msg_controllen = sizeof (cmsg);
|
|
||||||
|
|
||||||
*(int *) CMSG_DATA (&cmsg.hdr) = fd;
|
|
||||||
|
|
||||||
len = sendmsg (ctx->outbound.fd, &msg, 0);
|
|
||||||
if (len < 0)
|
|
||||||
{
|
|
||||||
_assuan_log_printf ("domain_sendfd: %s\n", strerror (errno));
|
|
||||||
return ASSUAN_General_Error;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static assuan_error_t
|
|
||||||
domain_receivefd (assuan_context_t ctx, int *fd)
|
|
||||||
{
|
|
||||||
#ifndef HAVE_W32_SYSTEM
|
|
||||||
if (ctx->pendingfds == 0)
|
|
||||||
{
|
|
||||||
_assuan_log_printf ("no pending file descriptors!\n");
|
|
||||||
return ASSUAN_General_Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
*fd = ctx->pendingfds[0];
|
|
||||||
if (-- ctx->pendingfdscount == 0)
|
|
||||||
{
|
|
||||||
free (ctx->pendingfds);
|
|
||||||
ctx->pendingfds = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* Fix the array. */
|
|
||||||
{
|
|
||||||
memmove (ctx->pendingfds, ctx->pendingfds + 1,
|
|
||||||
ctx->pendingfdscount * sizeof (int));
|
|
||||||
ctx->pendingfds = realloc (ctx->pendingfds,
|
|
||||||
ctx->pendingfdscount * sizeof (int));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* 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
|
|
||||||
become handy in the future. */
|
|
||||||
assuan_error_t
|
|
||||||
_assuan_domain_init (assuan_context_t *r_ctx, int rendezvousfd, pid_t peer)
|
|
||||||
{
|
|
||||||
static struct assuan_io io = { domain_reader, domain_writer,
|
|
||||||
domain_sendfd, domain_receivefd };
|
|
||||||
|
|
||||||
assuan_error_t err;
|
|
||||||
assuan_context_t ctx;
|
|
||||||
int fd;
|
|
||||||
size_t len;
|
|
||||||
int tries;
|
|
||||||
|
|
||||||
if (!r_ctx)
|
|
||||||
return ASSUAN_Invalid_Value;
|
|
||||||
*r_ctx = NULL;
|
|
||||||
|
|
||||||
err = _assuan_new_context (&ctx);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
/* Save it in case we need it later. */
|
|
||||||
ctx->pid = peer;
|
|
||||||
|
|
||||||
/* Override the default (NOP) handlers. */
|
|
||||||
ctx->deinit_handler = do_deinit;
|
|
||||||
|
|
||||||
/* Setup the socket. */
|
|
||||||
|
|
||||||
fd = _assuan_sock_new (PF_LOCAL, SOCK_DGRAM, 0);
|
|
||||||
if (fd == -1)
|
|
||||||
{
|
|
||||||
_assuan_log_printf ("can't create socket: %s\n", strerror (errno));
|
|
||||||
_assuan_release_context (ctx);
|
|
||||||
return ASSUAN_General_Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->inbound.fd = fd;
|
|
||||||
ctx->outbound.fd = fd;
|
|
||||||
|
|
||||||
/* And the io buffers. */
|
|
||||||
|
|
||||||
ctx->io = &io;
|
|
||||||
ctx->domainbuffer = 0;
|
|
||||||
ctx->domainbufferoffset = 0;
|
|
||||||
ctx->domainbuffersize = 0;
|
|
||||||
ctx->domainbufferallocated = 0;
|
|
||||||
ctx->pendingfds = 0;
|
|
||||||
ctx->pendingfdscount = 0;
|
|
||||||
|
|
||||||
/* Get usable name and bind to it. */
|
|
||||||
|
|
||||||
for (tries = 0; tries < TMP_MAX; tries ++)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
char buf[L_tmpnam];
|
|
||||||
|
|
||||||
/* XXX: L_tmpnam must be shorter than sizeof (sun_path)! */
|
|
||||||
assert (L_tmpnam < sizeof (ctx->myaddr.sun_path));
|
|
||||||
|
|
||||||
/* XXX: W32 tmpnam is broken */
|
|
||||||
p = tmpnam (buf);
|
|
||||||
if (! p)
|
|
||||||
{
|
|
||||||
_assuan_log_printf ("cannot determine an appropriate temporary file "
|
|
||||||
"name. DoS in progress?\n");
|
|
||||||
_assuan_release_context (ctx);
|
|
||||||
_assuan_close (fd);
|
|
||||||
return ASSUAN_General_Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset (&ctx->myaddr, 0, sizeof ctx->myaddr);
|
|
||||||
ctx->myaddr.sun_family = AF_LOCAL;
|
|
||||||
len = strlen (buf) + 1;
|
|
||||||
memcpy (ctx->myaddr.sun_path, buf, len);
|
|
||||||
len += offsetof (struct sockaddr_un, sun_path);
|
|
||||||
|
|
||||||
err = _assuan_sock_bind (fd, (struct sockaddr *) &ctx->myaddr, len);
|
|
||||||
if (! err)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
_assuan_log_printf ("can't bind to `%s': %s\n", ctx->myaddr.sun_path,
|
|
||||||
strerror (errno));
|
|
||||||
_assuan_release_context (ctx);
|
|
||||||
_assuan_close (fd);
|
|
||||||
return ASSUAN_Connect_Failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Rendezvous with our peer. */
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
fp = fdopen (rendezvousfd, "w+");
|
|
||||||
if (! fp)
|
|
||||||
{
|
|
||||||
_assuan_log_printf ("can't open rendezvous port: %s\n", strerror (errno));
|
|
||||||
return ASSUAN_Connect_Failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send our address. */
|
|
||||||
fprintf (fp, "%s\n", ctx->myaddr.sun_path);
|
|
||||||
fflush (fp);
|
|
||||||
|
|
||||||
/* And receive our peer's. */
|
|
||||||
memset (&ctx->serveraddr, 0, sizeof ctx->serveraddr);
|
|
||||||
for (p = ctx->serveraddr.sun_path;
|
|
||||||
p < (ctx->serveraddr.sun_path
|
|
||||||
+ sizeof ctx->serveraddr.sun_path - 1);
|
|
||||||
p ++)
|
|
||||||
{
|
|
||||||
*p = fgetc (fp);
|
|
||||||
if (*p == '\n')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*p = '\0';
|
|
||||||
fclose (fp);
|
|
||||||
|
|
||||||
ctx->serveraddr.sun_family = AF_LOCAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
*r_ctx = ctx;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
assuan_error_t
|
|
||||||
assuan_domain_connect (assuan_context_t * r_ctx, int rendezvousfd, pid_t peer)
|
|
||||||
{
|
|
||||||
assuan_error_t aerr;
|
|
||||||
int okay, off;
|
|
||||||
|
|
||||||
aerr = _assuan_domain_init (r_ctx, rendezvousfd, peer);
|
|
||||||
if (aerr)
|
|
||||||
return aerr;
|
|
||||||
|
|
||||||
/* Initial handshake. */
|
|
||||||
aerr = _assuan_read_from_server (*r_ctx, &okay, &off);
|
|
||||||
if (aerr)
|
|
||||||
_assuan_log_printf ("can't connect to server: %s\n",
|
|
||||||
assuan_strerror (aerr));
|
|
||||||
else if (okay != 1)
|
|
||||||
{
|
|
||||||
_assuan_log_printf ("can't connect to server: `");
|
|
||||||
_assuan_log_sanitized_string ((*r_ctx)->inbound.line);
|
|
||||||
fprintf (assuan_get_assuan_log_stream (), "'\n");
|
|
||||||
aerr = ASSUAN_Connect_Failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aerr)
|
|
||||||
assuan_disconnect (*r_ctx);
|
|
||||||
|
|
||||||
return aerr;
|
|
||||||
}
|
|
@ -1,46 +0,0 @@
|
|||||||
/* assuan-socket-server.c - Assuan socket based server
|
|
||||||
* Copyright (C) 2002 Free Software Foundation, Inc.
|
|
||||||
*
|
|
||||||
* This file is part of Assuan.
|
|
||||||
*
|
|
||||||
* Assuan is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU Lesser General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Assuan 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser 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 <unistd.h>
|
|
||||||
|
|
||||||
#include "assuan-defs.h"
|
|
||||||
|
|
||||||
/* Initialize a server. */
|
|
||||||
assuan_error_t
|
|
||||||
assuan_init_domain_server (ASSUAN_CONTEXT *r_ctx,
|
|
||||||
int rendezvousfd,
|
|
||||||
pid_t peer)
|
|
||||||
{
|
|
||||||
assuan_error_t err;
|
|
||||||
|
|
||||||
err = _assuan_domain_init (r_ctx, rendezvousfd, peer);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
(*r_ctx)->is_server = 1;
|
|
||||||
/* A domain server can only be used once. */
|
|
||||||
(*r_ctx)->pipe_mode = 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -15,7 +15,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this program; if not, write to the Free Software
|
* License along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
* USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@ -36,20 +37,20 @@ static int my_strcasecmp (const char *a, const char *b);
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
dummy_handler (ASSUAN_CONTEXT ctx, char *line)
|
dummy_handler (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
return set_error (ctx, Server_Fault, "no handler registered");
|
return set_error (ctx, Server_Fault, "no handler registered");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
std_handler_nop (ASSUAN_CONTEXT ctx, char *line)
|
std_handler_nop (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
return 0; /* okay */
|
return 0; /* okay */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
std_handler_cancel (ASSUAN_CONTEXT ctx, char *line)
|
std_handler_cancel (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
if (ctx->cancel_notify_fnc)
|
if (ctx->cancel_notify_fnc)
|
||||||
ctx->cancel_notify_fnc (ctx);
|
ctx->cancel_notify_fnc (ctx);
|
||||||
@ -57,7 +58,7 @@ std_handler_cancel (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
std_handler_option (ASSUAN_CONTEXT ctx, char *line)
|
std_handler_option (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
char *key, *value, *p;
|
char *key, *value, *p;
|
||||||
|
|
||||||
@ -104,7 +105,7 @@ std_handler_option (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
std_handler_bye (ASSUAN_CONTEXT ctx, char *line)
|
std_handler_bye (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
if (ctx->bye_notify_fnc)
|
if (ctx->bye_notify_fnc)
|
||||||
ctx->bye_notify_fnc (ctx);
|
ctx->bye_notify_fnc (ctx);
|
||||||
@ -114,33 +115,35 @@ std_handler_bye (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
std_handler_auth (ASSUAN_CONTEXT ctx, char *line)
|
std_handler_auth (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
return set_error (ctx, Not_Implemented, NULL);
|
return set_error (ctx, Not_Implemented, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
std_handler_reset (ASSUAN_CONTEXT ctx, char *line)
|
std_handler_reset (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
if (ctx->reset_notify_fnc)
|
if (ctx->reset_notify_fnc)
|
||||||
ctx->reset_notify_fnc (ctx);
|
ctx->reset_notify_fnc (ctx);
|
||||||
assuan_close_input_fd (ctx);
|
assuan_close_input_fd (ctx);
|
||||||
assuan_close_output_fd (ctx);
|
assuan_close_output_fd (ctx);
|
||||||
|
_assuan_uds_close_fds (ctx);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
std_handler_end (ASSUAN_CONTEXT ctx, char *line)
|
std_handler_end (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
return set_error (ctx, Not_Implemented, NULL);
|
return set_error (ctx, Not_Implemented, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
assuan_error_t
|
assuan_error_t
|
||||||
assuan_command_parse_fd (ASSUAN_CONTEXT ctx, char *line, int *rfd)
|
assuan_command_parse_fd (assuan_context_t ctx, char *line, int *rfd)
|
||||||
{
|
{
|
||||||
char *endp;
|
char *endp;
|
||||||
|
|
||||||
if (strncmp (line, "FD", 2) != 0 || (line[2] != '=' && line[2] != '\0'))
|
if ( (strncmp (line, "FD", 2) && strncmp (line, "fd", 2))
|
||||||
|
|| (line[2] != '=' && line[2] != '\0'))
|
||||||
return set_error (ctx, Syntax_Error, "FD[=<n>] expected");
|
return set_error (ctx, Syntax_Error, "FD[=<n>] expected");
|
||||||
line += 2;
|
line += 2;
|
||||||
if (*line == '=')
|
if (*line == '=')
|
||||||
@ -149,7 +152,7 @@ assuan_command_parse_fd (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);
|
||||||
/* remove that argument so that a notify handler won't see it */
|
/* Remove that argument so that a notify handler won't see it. */
|
||||||
memset (line, ' ', endp? (endp-line):strlen(line));
|
memset (line, ' ', endp? (endp-line):strlen(line));
|
||||||
|
|
||||||
if (*rfd == ctx->inbound.fd)
|
if (*rfd == ctx->inbound.fd)
|
||||||
@ -165,7 +168,7 @@ assuan_command_parse_fd (ASSUAN_CONTEXT ctx, char *line, int *rfd)
|
|||||||
|
|
||||||
/* Format is INPUT FD=<n> */
|
/* Format is INPUT FD=<n> */
|
||||||
static int
|
static int
|
||||||
std_handler_input (ASSUAN_CONTEXT ctx, char *line)
|
std_handler_input (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
int rc, fd;
|
int rc, fd;
|
||||||
|
|
||||||
@ -180,7 +183,7 @@ std_handler_input (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
|
|
||||||
/* Format is OUTPUT FD=<n> */
|
/* Format is OUTPUT FD=<n> */
|
||||||
static int
|
static int
|
||||||
std_handler_output (ASSUAN_CONTEXT ctx, char *line)
|
std_handler_output (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
int rc, fd;
|
int rc, fd;
|
||||||
|
|
||||||
@ -202,7 +205,7 @@ std_handler_output (ASSUAN_CONTEXT ctx, char *line)
|
|||||||
with default handlers */
|
with default handlers */
|
||||||
static struct {
|
static struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
int (*handler)(ASSUAN_CONTEXT, char *line);
|
int (*handler)(assuan_context_t, char *line);
|
||||||
int always; /* always initialize this command */
|
int always; /* always initialize this command */
|
||||||
} std_cmd_table[] = {
|
} std_cmd_table[] = {
|
||||||
{ "NOP", std_handler_nop, 1 },
|
{ "NOP", std_handler_nop, 1 },
|
||||||
@ -234,9 +237,9 @@ static struct {
|
|||||||
* Return value: 0 on success or an error code
|
* Return value: 0 on success or an error code
|
||||||
**/
|
**/
|
||||||
int
|
int
|
||||||
assuan_register_command (ASSUAN_CONTEXT ctx,
|
assuan_register_command (assuan_context_t ctx,
|
||||||
const char *cmd_name,
|
const char *cmd_name,
|
||||||
int (*handler)(ASSUAN_CONTEXT, char *))
|
int (*handler)(assuan_context_t, char *))
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
const char *s;
|
const char *s;
|
||||||
@ -245,7 +248,7 @@ assuan_register_command (ASSUAN_CONTEXT ctx,
|
|||||||
cmd_name = NULL;
|
cmd_name = NULL;
|
||||||
|
|
||||||
if (!cmd_name)
|
if (!cmd_name)
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
|
|
||||||
if (!handler)
|
if (!handler)
|
||||||
{ /* find a default handler. */
|
{ /* find a default handler. */
|
||||||
@ -268,7 +271,7 @@ assuan_register_command (ASSUAN_CONTEXT ctx,
|
|||||||
ctx->cmdtbl_size = 50;
|
ctx->cmdtbl_size = 50;
|
||||||
ctx->cmdtbl = xtrycalloc ( ctx->cmdtbl_size, sizeof *ctx->cmdtbl);
|
ctx->cmdtbl = xtrycalloc ( ctx->cmdtbl_size, sizeof *ctx->cmdtbl);
|
||||||
if (!ctx->cmdtbl)
|
if (!ctx->cmdtbl)
|
||||||
return ASSUAN_Out_Of_Core;
|
return _assuan_error (ASSUAN_Out_Of_Core);
|
||||||
ctx->cmdtbl_used = 0;
|
ctx->cmdtbl_used = 0;
|
||||||
}
|
}
|
||||||
else if (ctx->cmdtbl_used >= ctx->cmdtbl_size)
|
else if (ctx->cmdtbl_used >= ctx->cmdtbl_size)
|
||||||
@ -277,7 +280,7 @@ assuan_register_command (ASSUAN_CONTEXT ctx,
|
|||||||
|
|
||||||
x = xtryrealloc ( ctx->cmdtbl, (ctx->cmdtbl_size+10) * sizeof *x);
|
x = xtryrealloc ( ctx->cmdtbl, (ctx->cmdtbl_size+10) * sizeof *x);
|
||||||
if (!x)
|
if (!x)
|
||||||
return ASSUAN_Out_Of_Core;
|
return _assuan_error (ASSUAN_Out_Of_Core);
|
||||||
ctx->cmdtbl = x;
|
ctx->cmdtbl = x;
|
||||||
ctx->cmdtbl_size += 50;
|
ctx->cmdtbl_size += 50;
|
||||||
}
|
}
|
||||||
@ -289,59 +292,62 @@ assuan_register_command (ASSUAN_CONTEXT ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
assuan_register_bye_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
|
assuan_register_bye_notify (assuan_context_t ctx,
|
||||||
|
void (*fnc)(assuan_context_t))
|
||||||
{
|
{
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
ctx->bye_notify_fnc = fnc;
|
ctx->bye_notify_fnc = fnc;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
assuan_register_reset_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
|
assuan_register_reset_notify (assuan_context_t ctx,
|
||||||
|
void (*fnc)(assuan_context_t))
|
||||||
{
|
{
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
ctx->reset_notify_fnc = fnc;
|
ctx->reset_notify_fnc = fnc;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
assuan_register_cancel_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
|
assuan_register_cancel_notify (assuan_context_t ctx,
|
||||||
|
void (*fnc)(assuan_context_t))
|
||||||
{
|
{
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
ctx->cancel_notify_fnc = fnc;
|
ctx->cancel_notify_fnc = fnc;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
assuan_register_option_handler (ASSUAN_CONTEXT ctx,
|
assuan_register_option_handler (assuan_context_t ctx,
|
||||||
int (*fnc)(ASSUAN_CONTEXT,
|
int (*fnc)(assuan_context_t,
|
||||||
const char*, const char*))
|
const char*, const char*))
|
||||||
{
|
{
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
ctx->option_handler_fnc = fnc;
|
ctx->option_handler_fnc = fnc;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
assuan_register_input_notify (ASSUAN_CONTEXT ctx,
|
assuan_register_input_notify (assuan_context_t ctx,
|
||||||
void (*fnc)(ASSUAN_CONTEXT, const char *))
|
void (*fnc)(assuan_context_t, const char *))
|
||||||
{
|
{
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
ctx->input_notify_fnc = fnc;
|
ctx->input_notify_fnc = fnc;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
assuan_register_output_notify (ASSUAN_CONTEXT ctx,
|
assuan_register_output_notify (assuan_context_t ctx,
|
||||||
void (*fnc)(ASSUAN_CONTEXT, const char *))
|
void (*fnc)(assuan_context_t, const char *))
|
||||||
{
|
{
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
ctx->output_notify_fnc = fnc;
|
ctx->output_notify_fnc = fnc;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -349,7 +355,7 @@ assuan_register_output_notify (ASSUAN_CONTEXT ctx,
|
|||||||
|
|
||||||
/* 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_t ctx)
|
||||||
{
|
{
|
||||||
int i, rc;
|
int i, rc;
|
||||||
|
|
||||||
@ -370,7 +376,7 @@ _assuan_register_std_commands (ASSUAN_CONTEXT ctx)
|
|||||||
/* Process the special data lines. The "D " has already been removed
|
/* Process the special data lines. The "D " has already been removed
|
||||||
from the line. As all handlers this function may modify the line. */
|
from the line. As all handlers this function may modify the line. */
|
||||||
static int
|
static int
|
||||||
handle_data_line (ASSUAN_CONTEXT ctx, char *line, int linelen)
|
handle_data_line (assuan_context_t ctx, char *line, int linelen)
|
||||||
{
|
{
|
||||||
return set_error (ctx, Not_Implemented, NULL);
|
return set_error (ctx, Not_Implemented, NULL);
|
||||||
}
|
}
|
||||||
@ -394,7 +400,7 @@ my_strcasecmp (const char *a, const char *b)
|
|||||||
table, remove leading and white spaces from the arguments, call the
|
table, remove leading and white spaces from the arguments, call the
|
||||||
handler with the argument line and return the error */
|
handler with the argument line and return the error */
|
||||||
static int
|
static int
|
||||||
dispatch_command (ASSUAN_CONTEXT ctx, char *line, int linelen)
|
dispatch_command (assuan_context_t ctx, char *line, int linelen)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
const char *s;
|
const char *s;
|
||||||
@ -406,7 +412,7 @@ dispatch_command (ASSUAN_CONTEXT ctx, char *line, int linelen)
|
|||||||
for (p=line; *p && *p != ' ' && *p != '\t'; p++)
|
for (p=line; *p && *p != ' ' && *p != '\t'; p++)
|
||||||
;
|
;
|
||||||
if (p==line)
|
if (p==line)
|
||||||
return set_error (ctx, Invalid_Command, "leading white-space");
|
return set_error (ctx, Syntax_Error, "leading white-space");
|
||||||
if (*p)
|
if (*p)
|
||||||
{ /* Skip over leading WS after the keyword */
|
{ /* Skip over leading WS after the keyword */
|
||||||
*p++ = 0;
|
*p++ = 0;
|
||||||
@ -441,12 +447,12 @@ dispatch_command (ASSUAN_CONTEXT ctx, char *line, int linelen)
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
process_request (ASSUAN_CONTEXT ctx)
|
process_request (assuan_context_t ctx)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (ctx->in_inquire)
|
if (ctx->in_inquire)
|
||||||
return ASSUAN_Nested_Commands;
|
return _assuan_error (ASSUAN_Nested_Commands);
|
||||||
|
|
||||||
rc = _assuan_read_line (ctx);
|
rc = _assuan_read_line (ctx);
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -477,8 +483,8 @@ process_request (ASSUAN_CONTEXT ctx)
|
|||||||
{
|
{
|
||||||
rc = assuan_write_line (ctx, ctx->okay_line? ctx->okay_line : "OK");
|
rc = assuan_write_line (ctx, ctx->okay_line? ctx->okay_line : "OK");
|
||||||
}
|
}
|
||||||
else if (rc == -1)
|
else if (err_is_eof (rc))
|
||||||
{ /* 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);
|
ctx->finish_handler (ctx);
|
||||||
}
|
}
|
||||||
@ -488,7 +494,7 @@ process_request (ASSUAN_CONTEXT ctx)
|
|||||||
|
|
||||||
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_error (ASSUAN_Server_Fault), assuan_strerror (rc));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const char *text = ctx->err_no == rc? ctx->err_str:NULL;
|
const char *text = ctx->err_no == rc? ctx->err_str:NULL;
|
||||||
@ -498,7 +504,7 @@ process_request (ASSUAN_CONTEXT ctx)
|
|||||||
strings from libgpg-error without creating a dependency.
|
strings from libgpg-error without creating a dependency.
|
||||||
They are used for debugging purposes only, so there is no
|
They are used for debugging purposes only, so there is no
|
||||||
problem if they are not available. We need to make sure
|
problem if they are not available. We need to make sure
|
||||||
that we are using elf because only this guarantees that
|
that we are using ELF because only this guarantees that
|
||||||
weak symbol support is available in case GNU ld is not
|
weak symbol support is available in case GNU ld is not
|
||||||
used. */
|
used. */
|
||||||
unsigned int source, code;
|
unsigned int source, code;
|
||||||
@ -552,7 +558,7 @@ process_request (ASSUAN_CONTEXT ctx)
|
|||||||
* failed. Note, that no error is returned for operational errors.
|
* failed. Note, that no error is returned for operational errors.
|
||||||
**/
|
**/
|
||||||
int
|
int
|
||||||
assuan_process (ASSUAN_CONTEXT ctx)
|
assuan_process (assuan_context_t ctx)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@ -560,7 +566,7 @@ assuan_process (ASSUAN_CONTEXT ctx)
|
|||||||
rc = process_request (ctx);
|
rc = process_request (ctx);
|
||||||
} while (!rc);
|
} while (!rc);
|
||||||
|
|
||||||
if (rc == -1)
|
if (err_is_eof (rc))
|
||||||
rc = 0;
|
rc = 0;
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@ -579,7 +585,7 @@ assuan_process (ASSUAN_CONTEXT ctx)
|
|||||||
* Return value: -1 for end of server, 0 on success or an error code
|
* Return value: -1 for end of server, 0 on success or an error code
|
||||||
**/
|
**/
|
||||||
int
|
int
|
||||||
assuan_process_next (ASSUAN_CONTEXT ctx)
|
assuan_process_next (assuan_context_t ctx)
|
||||||
{
|
{
|
||||||
return process_request (ctx);
|
return process_request (ctx);
|
||||||
}
|
}
|
||||||
@ -603,7 +609,7 @@ assuan_process_next (ASSUAN_CONTEXT ctx)
|
|||||||
* error which is most likely a too small fdarray.
|
* error which is most likely a too small fdarray.
|
||||||
**/
|
**/
|
||||||
int
|
int
|
||||||
assuan_get_active_fds (ASSUAN_CONTEXT ctx, int what,
|
assuan_get_active_fds (assuan_context_t ctx, int what,
|
||||||
int *fdarray, int fdarraysize)
|
int *fdarray, int fdarraysize)
|
||||||
{
|
{
|
||||||
int n = 0;
|
int n = 0;
|
||||||
@ -636,7 +642,7 @@ assuan_get_active_fds (ASSUAN_CONTEXT ctx, int what,
|
|||||||
implementaion for systems w/o a glibc, a simple implementation
|
implementaion for systems w/o a glibc, a simple implementation
|
||||||
could use a child process */
|
could use a child process */
|
||||||
FILE *
|
FILE *
|
||||||
assuan_get_data_fp (ASSUAN_CONTEXT ctx)
|
assuan_get_data_fp (assuan_context_t ctx)
|
||||||
{
|
{
|
||||||
#if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN)
|
#if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN)
|
||||||
if (ctx->outbound.data.fp)
|
if (ctx->outbound.data.fp)
|
||||||
@ -658,10 +664,10 @@ assuan_get_data_fp (ASSUAN_CONTEXT ctx)
|
|||||||
/* Set the text used for the next OK reponse. This string is
|
/* Set the text used for the next OK reponse. This string is
|
||||||
automatically reset to NULL after the next command. */
|
automatically reset to NULL after the next command. */
|
||||||
assuan_error_t
|
assuan_error_t
|
||||||
assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line)
|
assuan_set_okay_line (assuan_context_t ctx, const char *line)
|
||||||
{
|
{
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
if (!line)
|
if (!line)
|
||||||
{
|
{
|
||||||
xfree (ctx->okay_line);
|
xfree (ctx->okay_line);
|
||||||
@ -673,7 +679,7 @@ assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line)
|
|||||||
we should allocate the entire line in secure memory */
|
we should allocate the entire line in secure memory */
|
||||||
char *buf = xtrymalloc (3+strlen(line)+1);
|
char *buf = xtrymalloc (3+strlen(line)+1);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return ASSUAN_Out_Of_Core;
|
return _assuan_error (ASSUAN_Out_Of_Core);
|
||||||
strcpy (buf, "OK ");
|
strcpy (buf, "OK ");
|
||||||
strcpy (buf+3, line);
|
strcpy (buf+3, line);
|
||||||
xfree (ctx->okay_line);
|
xfree (ctx->okay_line);
|
||||||
@ -685,7 +691,8 @@ assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line)
|
|||||||
|
|
||||||
|
|
||||||
assuan_error_t
|
assuan_error_t
|
||||||
assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text)
|
assuan_write_status (assuan_context_t ctx,
|
||||||
|
const char *keyword, const char *text)
|
||||||
{
|
{
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
char *helpbuf;
|
char *helpbuf;
|
||||||
@ -693,7 +700,7 @@ assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text)
|
|||||||
assuan_error_t ae;
|
assuan_error_t ae;
|
||||||
|
|
||||||
if ( !ctx || !keyword)
|
if ( !ctx || !keyword)
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
if (!text)
|
if (!text)
|
||||||
text = "";
|
text = "";
|
||||||
|
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this program; if not, write to the Free Software
|
* License along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
* USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@ -146,14 +147,14 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,
|
|||||||
int nodataexpected;
|
int nodataexpected;
|
||||||
|
|
||||||
if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf)))
|
if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf)))
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
nodataexpected = !r_buffer && !r_length && !maxlen;
|
nodataexpected = !r_buffer && !r_length && !maxlen;
|
||||||
if (!nodataexpected && (!r_buffer || !r_length))
|
if (!nodataexpected && (!r_buffer || !r_length))
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
if (!ctx->is_server)
|
if (!ctx->is_server)
|
||||||
return ASSUAN_Not_A_Server;
|
return _assuan_error (ASSUAN_Not_A_Server);
|
||||||
if (ctx->in_inquire)
|
if (ctx->in_inquire)
|
||||||
return ASSUAN_Nested_Commands;
|
return _assuan_error (ASSUAN_Nested_Commands);
|
||||||
|
|
||||||
ctx->in_inquire = 1;
|
ctx->in_inquire = 1;
|
||||||
if (nodataexpected)
|
if (nodataexpected)
|
||||||
@ -182,12 +183,12 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,
|
|||||||
break; /* END command received*/
|
break; /* END command received*/
|
||||||
if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N')
|
if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N')
|
||||||
{
|
{
|
||||||
rc = ASSUAN_Canceled;
|
rc = _assuan_error (ASSUAN_Canceled);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
if (line[0] != 'D' || line[1] != ' ' || nodataexpected)
|
if (line[0] != 'D' || line[1] != ' ' || nodataexpected)
|
||||||
{
|
{
|
||||||
rc = ASSUAN_Unexpected_Command;
|
rc = _assuan_error (ASSUAN_Unexpected_Command);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
if (linelen < 3)
|
if (linelen < 3)
|
||||||
@ -214,7 +215,7 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,
|
|||||||
}
|
}
|
||||||
if (mb.too_large)
|
if (mb.too_large)
|
||||||
{
|
{
|
||||||
rc = ASSUAN_Too_Much_Data;
|
rc = _assuan_error (ASSUAN_Too_Much_Data);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -223,7 +224,7 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,
|
|||||||
{
|
{
|
||||||
*r_buffer = get_membuf (&mb, r_length);
|
*r_buffer = get_membuf (&mb, r_length);
|
||||||
if (!*r_buffer)
|
if (!*r_buffer)
|
||||||
rc = ASSUAN_Out_Of_Core;
|
rc = _assuan_error (ASSUAN_Out_Of_Core);
|
||||||
}
|
}
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* assuan-io.c - Wraps the read and write functions.
|
/* assuan-io.c - Wraps the read and write functions.
|
||||||
* Copyright (C) 2002, 2004 Free Software Foundation, Inc.
|
* Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of Assuan.
|
* This file is part of Assuan.
|
||||||
*
|
*
|
||||||
@ -15,30 +15,93 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this program; if not, write to the Free Software
|
* License along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
* USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "assuan-defs.h"
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <sys/socket.h>
|
||||||
#ifdef HAVE_W32_SYSTEM
|
#include <sys/wait.h>
|
||||||
#include <windows.h>
|
#if HAVE_SYS_UIO_H
|
||||||
|
# include <sys/uio.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#ifdef HAVE_W32_SYSTEM
|
||||||
|
# include <windows.h>
|
||||||
|
#else
|
||||||
|
# include <sys/wait.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "assuan-defs.h"
|
||||||
|
|
||||||
|
/* We can't include pth.h and we are not sure whether other headers
|
||||||
|
already included it. This we define macros with the same
|
||||||
|
values. */
|
||||||
|
#define MY_PTH_FDMODE_ERROR (-1)
|
||||||
|
#define MY_PTH_FDMODE_POLL 0
|
||||||
|
#define MY_PTH_FDMODE_BLOCK 1
|
||||||
|
#define MY_PTH_FDMODE_NONBLOCK 2
|
||||||
|
|
||||||
|
|
||||||
#ifndef _ASSUAN_NO_PTH
|
#ifndef _ASSUAN_NO_PTH
|
||||||
|
extern pid_t pth_waitpid (pid_t pid, int *status, int options);
|
||||||
extern ssize_t pth_read (int fd, void *buffer, size_t size);
|
extern ssize_t pth_read (int fd, void *buffer, size_t size);
|
||||||
extern ssize_t pth_write (int fd, const void *buffer, size_t size);
|
extern ssize_t pth_write (int fd, const void *buffer, size_t size);
|
||||||
|
extern int pth_fdmode (int, int);
|
||||||
|
extern int pth_select(int, fd_set*, fd_set*, fd_set*, struct timeval*);
|
||||||
|
|
||||||
#ifndef HAVE_W32_SYSTEM
|
#ifndef HAVE_W32_SYSTEM
|
||||||
|
#pragma weak pth_waitpid
|
||||||
#pragma weak pth_read
|
#pragma weak pth_read
|
||||||
#pragma weak pth_write
|
#pragma weak pth_write
|
||||||
|
#pragma weak pth_fdmode
|
||||||
|
#pragma weak pth_select
|
||||||
#endif
|
#endif
|
||||||
#endif /*!_ASSUAN_NO_PTH*/
|
#endif /*!_ASSUAN_NO_PTH*/
|
||||||
|
|
||||||
|
#ifndef _ASSUAN_NO_PTH
|
||||||
|
/* Wrapper around pth_fdmode. */
|
||||||
|
static int
|
||||||
|
my_pth_fdmode (int fd, int mode)
|
||||||
|
{
|
||||||
|
if (pth_fdmode)
|
||||||
|
return pth_fdmode (fd, mode);
|
||||||
|
else
|
||||||
|
return MY_PTH_FDMODE_NONBLOCK; /* This is okay, given the way we use it. */
|
||||||
|
}
|
||||||
|
#endif /*_ASSUAN_NO_PTH*/
|
||||||
|
|
||||||
|
#ifndef _ASSUAN_NO_PTH
|
||||||
|
/* Wrapper around pth_select. */
|
||||||
|
static int
|
||||||
|
my_pth_select (int nfd, fd_set *rfds, fd_set *wfds, fd_set *efds,
|
||||||
|
struct timeval *timeout)
|
||||||
|
{
|
||||||
|
if (pth_select)
|
||||||
|
return pth_select (nfd, rfds, wfds, efds, timeout);
|
||||||
|
else
|
||||||
|
return 1; /* Fake one fd ready; this is okay, given the way we use it. */
|
||||||
|
}
|
||||||
|
#endif /*_ASSUAN_NO_PTH*/
|
||||||
|
|
||||||
|
#ifndef HAVE_W32_SYSTEM
|
||||||
|
pid_t
|
||||||
|
_assuan_waitpid (pid_t pid, int *status, int options)
|
||||||
|
{
|
||||||
|
#ifdef _ASSUAN_NO_PTH
|
||||||
|
return waitpid (pid, status, options);
|
||||||
|
#else
|
||||||
|
return (pth_waitpid ? pth_waitpid : waitpid) (pid, status, options);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
_assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size)
|
_assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size)
|
||||||
{
|
{
|
||||||
@ -51,7 +114,7 @@ _assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size)
|
|||||||
return pth_read ? pth_read (ctx->inbound.fd, buffer, size)
|
return pth_read ? pth_read (ctx->inbound.fd, buffer, size)
|
||||||
: recv (ctx->inbound.fd, buffer, size, 0);
|
: recv (ctx->inbound.fd, buffer, size, 0);
|
||||||
# endif
|
# endif
|
||||||
# endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
@ -68,3 +131,87 @@ _assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size)
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
_assuan_simple_sendmsg (assuan_context_t ctx, struct msghdr *msg)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_W32_SYSTEM)
|
||||||
|
return _assuan_error (ASSUAN_Not_Implemented);
|
||||||
|
#elif defined(_ASSUAN_NO_PTH)
|
||||||
|
int ret;
|
||||||
|
while ( (ret = sendmsg (ctx->outbound.fd, msg, 0)) == -1 && errno == EINTR)
|
||||||
|
;
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
|
/* Pth does not provide a sendmsg function. Thus we implement it here. */
|
||||||
|
int ret;
|
||||||
|
int fd = ctx->outbound.fd;
|
||||||
|
int fdmode;
|
||||||
|
|
||||||
|
fdmode = my_pth_fdmode (fd, MY_PTH_FDMODE_POLL);
|
||||||
|
if (fdmode == MY_PTH_FDMODE_ERROR)
|
||||||
|
{
|
||||||
|
errno = EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fdmode == MY_PTH_FDMODE_BLOCK)
|
||||||
|
{
|
||||||
|
fd_set fds;
|
||||||
|
|
||||||
|
FD_ZERO (&fds);
|
||||||
|
FD_SET (fd, &fds);
|
||||||
|
while ( (ret = my_pth_select (fd+1, NULL, &fds, NULL, NULL)) < 0
|
||||||
|
&& errno == EINTR)
|
||||||
|
;
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((ret = sendmsg (fd, msg, 0)) == -1 && errno == EINTR)
|
||||||
|
;
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
_assuan_simple_recvmsg (assuan_context_t ctx, struct msghdr *msg)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_W32_SYSTEM)
|
||||||
|
return _assuan_error (ASSUAN_Not_Implemented);
|
||||||
|
#elif defined(_ASSUAN_NO_PTH)
|
||||||
|
int ret;
|
||||||
|
while ( (ret = recvmsg (ctx->inbound.fd, msg, 0)) == -1 && errno == EINTR)
|
||||||
|
;
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
|
/* Pth does not provide a recvmsg function. Thus we implement it here. */
|
||||||
|
int ret;
|
||||||
|
int fd = ctx->inbound.fd;
|
||||||
|
int fdmode;
|
||||||
|
|
||||||
|
fdmode = my_pth_fdmode (fd, MY_PTH_FDMODE_POLL);
|
||||||
|
if (fdmode == MY_PTH_FDMODE_ERROR)
|
||||||
|
{
|
||||||
|
errno = EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fdmode == MY_PTH_FDMODE_BLOCK)
|
||||||
|
{
|
||||||
|
fd_set fds;
|
||||||
|
|
||||||
|
FD_ZERO (&fds);
|
||||||
|
FD_SET (fd, &fds);
|
||||||
|
while ( (ret = my_pth_select (fd+1, &fds, NULL, NULL, NULL)) < 0
|
||||||
|
&& errno == EINTR)
|
||||||
|
;
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((ret = recvmsg (fd, msg, 0)) == -1 && errno == EINTR)
|
||||||
|
;
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this program; if not, write to the Free Software
|
* License along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
* USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@ -23,6 +24,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include "assuan-defs.h"
|
#include "assuan-defs.h"
|
||||||
|
|
||||||
@ -30,7 +32,7 @@ assuan_error_t
|
|||||||
assuan_set_hello_line (assuan_context_t ctx, const char *line)
|
assuan_set_hello_line (assuan_context_t ctx, const char *line)
|
||||||
{
|
{
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
if (!line)
|
if (!line)
|
||||||
{
|
{
|
||||||
xfree (ctx->hello_line);
|
xfree (ctx->hello_line);
|
||||||
@ -40,7 +42,7 @@ assuan_set_hello_line (assuan_context_t ctx, const char *line)
|
|||||||
{
|
{
|
||||||
char *buf = xtrymalloc (3+strlen(line)+1);
|
char *buf = xtrymalloc (3+strlen(line)+1);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return ASSUAN_Out_Of_Core;
|
return _assuan_error (ASSUAN_Out_Of_Core);
|
||||||
if (strchr (line, '\n'))
|
if (strchr (line, '\n'))
|
||||||
strcpy (buf, line);
|
strcpy (buf, line);
|
||||||
else
|
else
|
||||||
@ -73,7 +75,7 @@ assuan_accept (assuan_context_t ctx)
|
|||||||
const char *p, *pend;
|
const char *p, *pend;
|
||||||
|
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
|
|
||||||
if (ctx->pipe_mode > 1)
|
if (ctx->pipe_mode > 1)
|
||||||
return -1; /* second invocation for pipemode -> terminate */
|
return -1; /* second invocation for pipemode -> terminate */
|
||||||
@ -134,7 +136,7 @@ assuan_error_t
|
|||||||
assuan_close_input_fd (assuan_context_t ctx)
|
assuan_close_input_fd (assuan_context_t ctx)
|
||||||
{
|
{
|
||||||
if (!ctx || ctx->input_fd == -1)
|
if (!ctx || ctx->input_fd == -1)
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
_assuan_close (ctx->input_fd);
|
_assuan_close (ctx->input_fd);
|
||||||
ctx->input_fd = -1;
|
ctx->input_fd = -1;
|
||||||
return 0;
|
return 0;
|
||||||
@ -146,7 +148,7 @@ assuan_error_t
|
|||||||
assuan_close_output_fd (assuan_context_t ctx)
|
assuan_close_output_fd (assuan_context_t ctx)
|
||||||
{
|
{
|
||||||
if (!ctx || ctx->output_fd == -1)
|
if (!ctx || ctx->output_fd == -1)
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
|
|
||||||
_assuan_close (ctx->output_fd);
|
_assuan_close (ctx->output_fd);
|
||||||
ctx->output_fd = -1;
|
ctx->output_fd = -1;
|
||||||
|
@ -15,29 +15,37 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this program; if not, write to the Free Software
|
* License along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
* USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#endif
|
#endif
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#ifdef HAVE_W32_SYSTEM
|
#ifdef HAVE_W32_SYSTEM
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif /*HAVE_W32_SYSTEM*/
|
#endif /*HAVE_W32_SYSTEM*/
|
||||||
|
#include <errno.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "assuan-defs.h"
|
#include "assuan-defs.h"
|
||||||
|
|
||||||
static char prefix_buffer[80];
|
static char prefix_buffer[80];
|
||||||
static FILE *_assuan_log;
|
static FILE *_assuan_log;
|
||||||
|
static int full_logging;
|
||||||
|
|
||||||
void
|
void
|
||||||
_assuan_set_default_log_stream (FILE *fp)
|
_assuan_set_default_log_stream (FILE *fp)
|
||||||
{
|
{
|
||||||
if (!_assuan_log)
|
if (!_assuan_log)
|
||||||
_assuan_log = fp;
|
{
|
||||||
|
_assuan_log = fp;
|
||||||
|
full_logging = !!getenv ("ASSUAN_FULL_LOGGING");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -46,6 +54,22 @@ assuan_set_assuan_log_stream (FILE *fp)
|
|||||||
_assuan_log = fp;
|
_assuan_log = fp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Set the per context log stream. Also enable the default log stream
|
||||||
|
if it has not been set. */
|
||||||
|
void
|
||||||
|
assuan_set_log_stream (assuan_context_t ctx, FILE *fp)
|
||||||
|
{
|
||||||
|
if (ctx)
|
||||||
|
{
|
||||||
|
if (ctx->log_fp)
|
||||||
|
fflush (ctx->log_fp);
|
||||||
|
ctx->log_fp = fp;
|
||||||
|
_assuan_set_default_log_stream (fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FILE *
|
FILE *
|
||||||
assuan_get_assuan_log_stream (void)
|
assuan_get_assuan_log_stream (void)
|
||||||
{
|
{
|
||||||
@ -80,18 +104,123 @@ _assuan_log_printf (const char *format, ...)
|
|||||||
va_list arg_ptr;
|
va_list arg_ptr;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
const char *prf;
|
const char *prf;
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
fp = assuan_get_assuan_log_stream ();
|
fp = assuan_get_assuan_log_stream ();
|
||||||
prf = assuan_get_assuan_log_prefix ();
|
prf = assuan_get_assuan_log_prefix ();
|
||||||
if (*prf)
|
if (*prf)
|
||||||
{
|
fprintf (fp, "%s[%u]: ", prf, (unsigned int)getpid ());
|
||||||
fputs (prf, fp);
|
|
||||||
fputs (": ", fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
va_start (arg_ptr, format);
|
va_start (arg_ptr, format);
|
||||||
vfprintf (fp, format, arg_ptr );
|
vfprintf (fp, format, arg_ptr );
|
||||||
va_end (arg_ptr);
|
va_end (arg_ptr);
|
||||||
|
errno = save_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Dump a possibly binary string (used for debugging). Distinguish
|
||||||
|
ascii text from binary and print it accordingly. This function
|
||||||
|
takes FILE pointer arg becuase logging may be enabled on a per
|
||||||
|
context basis. */
|
||||||
|
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 ((!isascii (*s) || iscntrl (*s) || !isprint (*s)) && !(*s >= 0x80))
|
||||||
|
break;
|
||||||
|
|
||||||
|
s = buffer;
|
||||||
|
if (!n && *s != '[')
|
||||||
|
fwrite (buffer, length, 1, fp);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef HAVE_FLOCKFILE
|
||||||
|
flockfile (fp);
|
||||||
|
#endif
|
||||||
|
putc_unlocked ('[', fp);
|
||||||
|
if ( length > 16 && !full_logging)
|
||||||
|
{
|
||||||
|
for (n=0; n < 12; n++, s++)
|
||||||
|
fprintf (fp, " %02x", *s);
|
||||||
|
fprintf (fp, " ...(%d bytes skipped)", (int)length - 12);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (n=0; n < length; n++, s++)
|
||||||
|
fprintf (fp, " %02x", *s);
|
||||||
|
}
|
||||||
|
putc_unlocked (' ', fp);
|
||||||
|
putc_unlocked (']', fp);
|
||||||
|
#ifdef HAVE_FUNLOCKFILE
|
||||||
|
funlockfile (fp);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Log a user supplied string. Escapes non-printable before
|
||||||
|
printing. */
|
||||||
|
void
|
||||||
|
_assuan_log_sanitized_string (const char *string)
|
||||||
|
{
|
||||||
|
const unsigned char *s = (const unsigned char *) string;
|
||||||
|
FILE *fp = assuan_get_assuan_log_stream ();
|
||||||
|
|
||||||
|
if (! *s)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#ifdef HAVE_FLOCKFILE
|
||||||
|
flockfile (fp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (; *s; s++)
|
||||||
|
{
|
||||||
|
int c = 0;
|
||||||
|
|
||||||
|
switch (*s)
|
||||||
|
{
|
||||||
|
case '\r':
|
||||||
|
c = 'r';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\n':
|
||||||
|
c = 'n';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\f':
|
||||||
|
c = 'f';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\v':
|
||||||
|
c = 'v';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\b':
|
||||||
|
c = 'b';
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if ((isascii (*s) && isprint (*s)) || (*s >= 0x80))
|
||||||
|
putc_unlocked (*s, fp);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
putc_unlocked ('\\', fp);
|
||||||
|
fprintf (fp, "x%02x", *s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c)
|
||||||
|
{
|
||||||
|
putc_unlocked ('\\', fp);
|
||||||
|
putc_unlocked (c, fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_FUNLOCKFILE
|
||||||
|
funlockfile (fp);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* assuan-pipe-connect.c - Establish a pipe connection (client)
|
/* assuan-pipe-connect.c - Establish a pipe connection (client)
|
||||||
* Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
|
* Copyright (C) 2001, 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of Assuan.
|
* This file is part of Assuan.
|
||||||
*
|
*
|
||||||
@ -15,7 +15,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this program; if not, write to the Free Software
|
* License along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
* USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
@ -38,6 +39,19 @@
|
|||||||
|
|
||||||
#include "assuan-defs.h"
|
#include "assuan-defs.h"
|
||||||
|
|
||||||
|
/* Hacks for Slowaris. */
|
||||||
|
#ifndef PF_LOCAL
|
||||||
|
# ifdef PF_UNIX
|
||||||
|
# define PF_LOCAL PF_UNIX
|
||||||
|
# else
|
||||||
|
# define PF_LOCAL AF_UNIX
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#ifndef AF_LOCAL
|
||||||
|
# define AF_LOCAL AF_UNIX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef _POSIX_OPEN_MAX
|
#ifdef _POSIX_OPEN_MAX
|
||||||
#define MAX_OPEN_FDS _POSIX_OPEN_MAX
|
#define MAX_OPEN_FDS _POSIX_OPEN_MAX
|
||||||
#else
|
#else
|
||||||
@ -111,6 +125,8 @@ do_finish (assuan_context_t ctx)
|
|||||||
if (ctx->inbound.fd != -1)
|
if (ctx->inbound.fd != -1)
|
||||||
{
|
{
|
||||||
_assuan_close (ctx->inbound.fd);
|
_assuan_close (ctx->inbound.fd);
|
||||||
|
if (ctx->inbound.fd == ctx->outbound.fd)
|
||||||
|
ctx->outbound.fd = -1;
|
||||||
ctx->inbound.fd = -1;
|
ctx->inbound.fd = -1;
|
||||||
}
|
}
|
||||||
if (ctx->outbound.fd != -1)
|
if (ctx->outbound.fd != -1)
|
||||||
@ -123,7 +139,7 @@ do_finish (assuan_context_t ctx)
|
|||||||
#ifndef HAVE_W32_SYSTEM
|
#ifndef HAVE_W32_SYSTEM
|
||||||
#ifndef _ASSUAN_USE_DOUBLE_FORK
|
#ifndef _ASSUAN_USE_DOUBLE_FORK
|
||||||
if (!ctx->flags.no_waitpid)
|
if (!ctx->flags.no_waitpid)
|
||||||
waitpid (ctx->pid, NULL, 0);
|
_assuan_waitpid (ctx->pid, NULL, 0);
|
||||||
ctx->pid = -1;
|
ctx->pid = -1;
|
||||||
#endif
|
#endif
|
||||||
#endif /*!HAVE_W32_SYSTEM*/
|
#endif /*!HAVE_W32_SYSTEM*/
|
||||||
@ -138,6 +154,402 @@ do_deinit (assuan_context_t ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Helper for pipe_connect. */
|
||||||
|
static assuan_error_t
|
||||||
|
initial_handshake (assuan_context_t *ctx)
|
||||||
|
{
|
||||||
|
int okay, off;
|
||||||
|
assuan_error_t err;
|
||||||
|
|
||||||
|
err = _assuan_read_from_server (*ctx, &okay, &off);
|
||||||
|
if (err)
|
||||||
|
_assuan_log_printf ("can't connect server: %s\n",
|
||||||
|
assuan_strerror (err));
|
||||||
|
else if (okay != 1)
|
||||||
|
{
|
||||||
|
_assuan_log_printf ("can't connect server: `%s'\n",
|
||||||
|
(*ctx)->inbound.line);
|
||||||
|
err = _assuan_error (ASSUAN_Connect_Failed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
assuan_disconnect (*ctx);
|
||||||
|
*ctx = NULL;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef HAVE_W32_SYSTEM
|
||||||
|
#define pipe_connect pipe_connect_unix
|
||||||
|
/* Unix version of the pipe connection code. We use an extra macro to
|
||||||
|
make ChangeLog entries easier. */
|
||||||
|
static assuan_error_t
|
||||||
|
pipe_connect_unix (assuan_context_t *ctx,
|
||||||
|
const char *name, const char *const argv[],
|
||||||
|
int *fd_child_list,
|
||||||
|
void (*atfork) (void *opaque, int reserved),
|
||||||
|
void *atforkvalue)
|
||||||
|
{
|
||||||
|
assuan_error_t err;
|
||||||
|
int rp[2];
|
||||||
|
int wp[2];
|
||||||
|
char mypidstr[50];
|
||||||
|
|
||||||
|
if (!ctx || !name || !argv || !argv[0])
|
||||||
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
|
|
||||||
|
fix_signals ();
|
||||||
|
|
||||||
|
sprintf (mypidstr, "%lu", (unsigned long)getpid ());
|
||||||
|
|
||||||
|
if (pipe (rp) < 0)
|
||||||
|
return _assuan_error (ASSUAN_General_Error);
|
||||||
|
|
||||||
|
if (pipe (wp) < 0)
|
||||||
|
{
|
||||||
|
close (rp[0]);
|
||||||
|
close (rp[1]);
|
||||||
|
return _assuan_error (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;
|
||||||
|
|
||||||
|
/* FIXME: For GPGME we should better use _gpgme_io_spawn. The PID
|
||||||
|
stored here is actually soon useless. */
|
||||||
|
(*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_error (ASSUAN_General_Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*ctx)->pid == 0)
|
||||||
|
{
|
||||||
|
#ifdef _ASSUAN_USE_DOUBLE_FORK
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
if ((pid = fork ()) == 0)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
int i, n;
|
||||||
|
char errbuf[512];
|
||||||
|
int *fdp;
|
||||||
|
|
||||||
|
if (atfork)
|
||||||
|
atfork (atforkvalue, 0);
|
||||||
|
|
||||||
|
/* Dup handles to stdin/stdout. */
|
||||||
|
if (rp[1] != STDOUT_FILENO)
|
||||||
|
{
|
||||||
|
if (dup2 (rp[1], STDOUT_FILENO) == -1)
|
||||||
|
{
|
||||||
|
_assuan_log_printf ("dup2 failed in child: %s\n",
|
||||||
|
strerror (errno));
|
||||||
|
_exit (4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (wp[0] != STDIN_FILENO)
|
||||||
|
{
|
||||||
|
if (dup2 (wp[0], STDIN_FILENO) == -1)
|
||||||
|
{
|
||||||
|
_assuan_log_printf ("dup2 failed in child: %s\n",
|
||||||
|
strerror (errno));
|
||||||
|
_exit (4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dup stderr to /dev/null unless it is in the list of FDs to be
|
||||||
|
passed to the child. */
|
||||||
|
fdp = fd_child_list;
|
||||||
|
if (fdp)
|
||||||
|
{
|
||||||
|
for (; *fdp != -1 && *fdp != STDERR_FILENO; fdp++)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
if (!fdp || *fdp == -1)
|
||||||
|
{
|
||||||
|
int fd = open ("/dev/null", O_WRONLY);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
_assuan_log_printf ("can't open `/dev/null': %s\n",
|
||||||
|
strerror (errno));
|
||||||
|
_exit (4);
|
||||||
|
}
|
||||||
|
if (dup2 (fd, STDERR_FILENO) == -1)
|
||||||
|
{
|
||||||
|
_assuan_log_printf ("dup2(dev/null, 2) failed: %s\n",
|
||||||
|
strerror (errno));
|
||||||
|
_exit (4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Close all files which will not be duped and are not in the
|
||||||
|
fd_child_list. */
|
||||||
|
n = sysconf (_SC_OPEN_MAX);
|
||||||
|
if (n < 0)
|
||||||
|
n = MAX_OPEN_FDS;
|
||||||
|
for (i=0; i < n; i++)
|
||||||
|
{
|
||||||
|
if ( i == STDIN_FILENO || i == STDOUT_FILENO
|
||||||
|
|| i == STDERR_FILENO)
|
||||||
|
continue;
|
||||||
|
fdp = fd_child_list;
|
||||||
|
if (fdp)
|
||||||
|
{
|
||||||
|
while (*fdp != -1 && *fdp != i)
|
||||||
|
fdp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(fdp && *fdp != -1))
|
||||||
|
close(i);
|
||||||
|
}
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
/* We store our parents pid in the environment so that the
|
||||||
|
execed assuan server is able to read the actual pid of the
|
||||||
|
client. The server can't use getppid because it might have
|
||||||
|
been double forked before the assuan server has been
|
||||||
|
initialized. */
|
||||||
|
setenv ("_assuan_pipe_connect_pid", mypidstr, 1);
|
||||||
|
|
||||||
|
/* Make sure that we never pass a connection fd variable
|
||||||
|
when using a simple pipe. */
|
||||||
|
unsetenv ("_assuan_connection_fd");
|
||||||
|
|
||||||
|
execv (name, (char *const *) 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_error (ASSUAN_Problem_Starting_Server),
|
||||||
|
name, strerror (errno));
|
||||||
|
errbuf[sizeof(errbuf)-1] = 0;
|
||||||
|
writen (1, errbuf, strlen (errbuf));
|
||||||
|
_exit (4);
|
||||||
|
}
|
||||||
|
#ifdef _ASSUAN_USE_DOUBLE_FORK
|
||||||
|
if (pid == -1)
|
||||||
|
_exit (1);
|
||||||
|
else
|
||||||
|
_exit (0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _ASSUAN_USE_DOUBLE_FORK
|
||||||
|
_assuan_waitpid ((*ctx)->pid, NULL, 0);
|
||||||
|
(*ctx)->pid = -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
close (rp[1]);
|
||||||
|
close (wp[0]);
|
||||||
|
|
||||||
|
return initial_handshake (ctx);
|
||||||
|
}
|
||||||
|
#endif /*!HAVE_W32_SYSTEM*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef HAVE_W32_SYSTEM
|
||||||
|
/* This function is similar to pipe_connect but uses a socketpair and
|
||||||
|
sets the I/O up to use sendmsg/recvmsg. */
|
||||||
|
static assuan_error_t
|
||||||
|
socketpair_connect (assuan_context_t *ctx,
|
||||||
|
const char *name, const char *const argv[],
|
||||||
|
int *fd_child_list,
|
||||||
|
void (*atfork) (void *opaque, int reserved),
|
||||||
|
void *atforkvalue)
|
||||||
|
{
|
||||||
|
assuan_error_t err;
|
||||||
|
int fds[2];
|
||||||
|
char mypidstr[50];
|
||||||
|
|
||||||
|
if (!ctx
|
||||||
|
|| (name && (!argv || !argv[0]))
|
||||||
|
|| (!name && argv))
|
||||||
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
|
|
||||||
|
fix_signals ();
|
||||||
|
|
||||||
|
sprintf (mypidstr, "%lu", (unsigned long)getpid ());
|
||||||
|
|
||||||
|
if ( socketpair (AF_LOCAL, SOCK_STREAM, 0, fds) )
|
||||||
|
{
|
||||||
|
_assuan_log_printf ("socketpair failed: %s\n", strerror (errno));
|
||||||
|
return _assuan_error (ASSUAN_General_Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = _assuan_new_context (ctx);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
close (fds[0]);
|
||||||
|
close (fds[1]);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
(*ctx)->pipe_mode = 1;
|
||||||
|
(*ctx)->inbound.fd = fds[0];
|
||||||
|
(*ctx)->outbound.fd = fds[0];
|
||||||
|
_assuan_init_uds_io (*ctx);
|
||||||
|
(*ctx)->deinit_handler = _assuan_uds_deinit;
|
||||||
|
(*ctx)->finish_handler = do_finish;
|
||||||
|
|
||||||
|
(*ctx)->pid = fork ();
|
||||||
|
if ((*ctx)->pid < 0)
|
||||||
|
{
|
||||||
|
close (fds[0]);
|
||||||
|
close (fds[1]);
|
||||||
|
_assuan_release_context (*ctx);
|
||||||
|
*ctx = NULL;
|
||||||
|
return _assuan_error (ASSUAN_General_Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*ctx)->pid == 0)
|
||||||
|
{
|
||||||
|
#ifdef _ASSUAN_USE_DOUBLE_FORK
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
if ((pid = fork ()) == 0)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
int fd, i, n;
|
||||||
|
char errbuf[512];
|
||||||
|
int *fdp;
|
||||||
|
|
||||||
|
if (atfork)
|
||||||
|
atfork (atforkvalue, 0);
|
||||||
|
|
||||||
|
/* Connect stdin and stdout to /dev/null. */
|
||||||
|
fd = open ("/dev/null", O_RDONLY);
|
||||||
|
if (fd == -1 || dup2 (fd, STDIN_FILENO) == -1)
|
||||||
|
{
|
||||||
|
_assuan_log_printf ("dup2(dev/null) failed: %s\n",
|
||||||
|
strerror (errno));
|
||||||
|
_exit (4);
|
||||||
|
}
|
||||||
|
fd = open ("/dev/null", O_WRONLY);
|
||||||
|
if (fd == -1 || dup2 (fd, STDOUT_FILENO) == -1)
|
||||||
|
{
|
||||||
|
_assuan_log_printf ("dup2(dev/null) failed: %s\n",
|
||||||
|
strerror (errno));
|
||||||
|
_exit (4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dup stderr to /dev/null unless it is in the list of FDs to be
|
||||||
|
passed to the child. */
|
||||||
|
fdp = fd_child_list;
|
||||||
|
if (fdp)
|
||||||
|
{
|
||||||
|
for (; *fdp != -1 && *fdp != STDERR_FILENO; fdp++)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
if (!fdp || *fdp == -1)
|
||||||
|
{
|
||||||
|
fd = open ("/dev/null", O_WRONLY);
|
||||||
|
if (fd == -1 || dup2 (fd, STDERR_FILENO) == -1)
|
||||||
|
{
|
||||||
|
_assuan_log_printf ("dup2(dev/null) failed: %s\n",
|
||||||
|
strerror (errno));
|
||||||
|
_exit (4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Close all files which will not be duped, are not in the
|
||||||
|
fd_child_list and are not the connection fd. */
|
||||||
|
n = sysconf (_SC_OPEN_MAX);
|
||||||
|
if (n < 0)
|
||||||
|
n = MAX_OPEN_FDS;
|
||||||
|
for (i=0; i < n; i++)
|
||||||
|
{
|
||||||
|
if ( i == STDIN_FILENO || i == STDOUT_FILENO
|
||||||
|
|| i == STDERR_FILENO || i == fds[1])
|
||||||
|
continue;
|
||||||
|
fdp = fd_child_list;
|
||||||
|
if (fdp)
|
||||||
|
{
|
||||||
|
while (*fdp != -1 && *fdp != i)
|
||||||
|
fdp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(fdp && *fdp != -1))
|
||||||
|
close(i);
|
||||||
|
}
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
/* We store our parents pid in the environment so that the
|
||||||
|
execed assuan server is able to read the actual pid of the
|
||||||
|
client. The server can't use getppid becuase it might have
|
||||||
|
been double forked before the assuan server has been
|
||||||
|
initialized. */
|
||||||
|
setenv ("_assuan_pipe_connect_pid", mypidstr, 1);
|
||||||
|
|
||||||
|
/* Now set the environment variable used to convey the
|
||||||
|
connection's file descriptor. */
|
||||||
|
sprintf (mypidstr, "%d", fds[1]);
|
||||||
|
if (setenv ("_assuan_connection_fd", mypidstr, 1))
|
||||||
|
{
|
||||||
|
_assuan_log_printf ("setenv failed: %s\n", strerror (errno));
|
||||||
|
_exit (4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!name && !argv)
|
||||||
|
{
|
||||||
|
/* No name and no args given, thus we don't do an exec
|
||||||
|
but continue the forked process. */
|
||||||
|
_assuan_release_context (*ctx);
|
||||||
|
*ctx = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
execv (name, (char *const *) 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_error (ASSUAN_Problem_Starting_Server),
|
||||||
|
name, strerror (errno));
|
||||||
|
errbuf[sizeof(errbuf)-1] = 0;
|
||||||
|
writen (fds[1], errbuf, strlen (errbuf));
|
||||||
|
_exit (4);
|
||||||
|
}
|
||||||
|
#ifdef _ASSUAN_USE_DOUBLE_FORK
|
||||||
|
if (pid == -1)
|
||||||
|
_exit (1);
|
||||||
|
else
|
||||||
|
_exit (0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _ASSUAN_USE_DOUBLE_FORK
|
||||||
|
_assuan_waitpid ((*ctx)->pid, NULL, 0);
|
||||||
|
(*ctx)->pid = -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
close (fds[1]);
|
||||||
|
|
||||||
|
return initial_handshake (ctx);
|
||||||
|
}
|
||||||
|
#endif /*!HAVE_W32_SYSTEM*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
#ifdef HAVE_W32_SYSTEM
|
||||||
/* Build a command line for use with W32's CreateProcess. On success
|
/* Build a command line for use with W32's CreateProcess. On success
|
||||||
CMDLINE gets the address of a newly allocated string. */
|
CMDLINE gets the address of a newly allocated string. */
|
||||||
@ -236,21 +648,16 @@ create_inheritable_pipe (int filedes[2], int for_write)
|
|||||||
#endif /*HAVE_W32_SYSTEM*/
|
#endif /*HAVE_W32_SYSTEM*/
|
||||||
|
|
||||||
|
|
||||||
/* 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. ATFORK is called in the
|
|
||||||
child right after the fork; ATFORKVALUE is passed as the first
|
|
||||||
argument and 0 is passed as the second argument. The ATFORK
|
|
||||||
function should only act if the second value is 0. */
|
|
||||||
assuan_error_t
|
|
||||||
assuan_pipe_connect2 (assuan_context_t *ctx,
|
|
||||||
const char *name, const char *const argv[],
|
|
||||||
int *fd_child_list,
|
|
||||||
void (*atfork) (void *opaque, int reserved),
|
|
||||||
void *atforkvalue)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
#ifdef HAVE_W32_SYSTEM
|
||||||
|
#define pipe_connect pipe_connect_w32
|
||||||
|
/* W32 version of the pipe connection code. */
|
||||||
|
static assuan_error_t
|
||||||
|
pipe_connect_w32 (assuan_context_t *ctx,
|
||||||
|
const char *name, const char *const argv[],
|
||||||
|
int *fd_child_list,
|
||||||
|
void (*atfork) (void *opaque, int reserved),
|
||||||
|
void *atforkvalue)
|
||||||
|
{
|
||||||
assuan_error_t err;
|
assuan_error_t err;
|
||||||
int rp[2];
|
int rp[2];
|
||||||
int wp[2];
|
int wp[2];
|
||||||
@ -269,7 +676,7 @@ assuan_pipe_connect2 (assuan_context_t *ctx,
|
|||||||
HANDLE nullfd = INVALID_HANDLE_VALUE;
|
HANDLE nullfd = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
if (!ctx || !name || !argv || !argv[0])
|
if (!ctx || !name || !argv || !argv[0])
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
|
|
||||||
fix_signals ();
|
fix_signals ();
|
||||||
|
|
||||||
@ -277,13 +684,13 @@ assuan_pipe_connect2 (assuan_context_t *ctx,
|
|||||||
|
|
||||||
/* Build the command line. */
|
/* Build the command line. */
|
||||||
if (build_w32_commandline (argv, &cmdline))
|
if (build_w32_commandline (argv, &cmdline))
|
||||||
return ASSUAN_Out_Of_Core;
|
return _assuan_error (ASSUAN_Out_Of_Core);
|
||||||
|
|
||||||
/* Create thew two pipes. */
|
/* Create thew two pipes. */
|
||||||
if (create_inheritable_pipe (rp, 0))
|
if (create_inheritable_pipe (rp, 0))
|
||||||
{
|
{
|
||||||
xfree (cmdline);
|
xfree (cmdline);
|
||||||
return ASSUAN_General_Error;
|
return _assuan_error (ASSUAN_General_Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (create_inheritable_pipe (wp, 1))
|
if (create_inheritable_pipe (wp, 1))
|
||||||
@ -291,7 +698,7 @@ assuan_pipe_connect2 (assuan_context_t *ctx,
|
|||||||
CloseHandle (fd_to_handle (rp[0]));
|
CloseHandle (fd_to_handle (rp[0]));
|
||||||
CloseHandle (fd_to_handle (rp[1]));
|
CloseHandle (fd_to_handle (rp[1]));
|
||||||
xfree (cmdline);
|
xfree (cmdline);
|
||||||
return ASSUAN_General_Error;
|
return _assuan_error (ASSUAN_General_Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -303,7 +710,7 @@ assuan_pipe_connect2 (assuan_context_t *ctx,
|
|||||||
CloseHandle (fd_to_handle (wp[0]));
|
CloseHandle (fd_to_handle (wp[0]));
|
||||||
CloseHandle (fd_to_handle (wp[1]));
|
CloseHandle (fd_to_handle (wp[1]));
|
||||||
xfree (cmdline);
|
xfree (cmdline);
|
||||||
return ASSUAN_General_Error;
|
return _assuan_error (ASSUAN_General_Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
(*ctx)->pipe_mode = 1;
|
(*ctx)->pipe_mode = 1;
|
||||||
@ -390,7 +797,7 @@ assuan_pipe_connect2 (assuan_context_t *ctx,
|
|||||||
CloseHandle (nullfd);
|
CloseHandle (nullfd);
|
||||||
xfree (cmdline);
|
xfree (cmdline);
|
||||||
_assuan_release_context (*ctx);
|
_assuan_release_context (*ctx);
|
||||||
return ASSUAN_General_Error;
|
return _assuan_error (ASSUAN_General_Error);
|
||||||
}
|
}
|
||||||
xfree (cmdline);
|
xfree (cmdline);
|
||||||
cmdline = NULL;
|
cmdline = NULL;
|
||||||
@ -413,200 +820,11 @@ assuan_pipe_connect2 (assuan_context_t *ctx,
|
|||||||
(*ctx)->pid = 0; /* We don't use the PID. */
|
(*ctx)->pid = 0; /* We don't use the PID. */
|
||||||
CloseHandle (pi.hProcess); /* We don't need to wait for the process. */
|
CloseHandle (pi.hProcess); /* We don't need to wait for the process. */
|
||||||
|
|
||||||
#else /*!HAVE_W32_SYSTEM*/
|
return initial_handshake (ctx);
|
||||||
assuan_error_t err;
|
|
||||||
int rp[2];
|
|
||||||
int wp[2];
|
|
||||||
char mypidstr[50];
|
|
||||||
|
|
||||||
if (!ctx || !name || !argv || !argv[0])
|
|
||||||
return ASSUAN_Invalid_Value;
|
|
||||||
|
|
||||||
fix_signals ();
|
|
||||||
|
|
||||||
sprintf (mypidstr, "%lu", (unsigned long)getpid ());
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
/* FIXME: For GPGME we should better use _gpgme_io_spawn. The PID
|
|
||||||
stored here is actually soon useless. */
|
|
||||||
(*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)
|
|
||||||
{
|
|
||||||
#ifdef _ASSUAN_USE_DOUBLE_FORK
|
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
if ((pid = fork ()) == 0)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
int i, n;
|
|
||||||
char errbuf[512];
|
|
||||||
int *fdp;
|
|
||||||
|
|
||||||
if (atfork)
|
|
||||||
atfork (atforkvalue, 0);
|
|
||||||
|
|
||||||
/* Dup handles to stdin/stdout. */
|
|
||||||
if (rp[1] != STDOUT_FILENO)
|
|
||||||
{
|
|
||||||
if (dup2 (rp[1], STDOUT_FILENO) == -1)
|
|
||||||
{
|
|
||||||
_assuan_log_printf ("dup2 failed in child: %s\n",
|
|
||||||
strerror (errno));
|
|
||||||
_exit (4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (wp[0] != STDIN_FILENO)
|
|
||||||
{
|
|
||||||
if (dup2 (wp[0], STDIN_FILENO) == -1)
|
|
||||||
{
|
|
||||||
_assuan_log_printf ("dup2 failed in child: %s\n",
|
|
||||||
strerror (errno));
|
|
||||||
_exit (4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dup stderr to /dev/null unless it is in the list of FDs to be
|
|
||||||
passed to the child. */
|
|
||||||
fdp = fd_child_list;
|
|
||||||
if (fdp)
|
|
||||||
{
|
|
||||||
for (; *fdp != -1 && *fdp != STDERR_FILENO; fdp++)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
if (!fdp || *fdp == -1)
|
|
||||||
{
|
|
||||||
int fd = open ("/dev/null", O_WRONLY);
|
|
||||||
if (fd == -1)
|
|
||||||
{
|
|
||||||
_assuan_log_printf ("can't open `/dev/null': %s\n",
|
|
||||||
strerror (errno));
|
|
||||||
_exit (4);
|
|
||||||
}
|
|
||||||
if (dup2 (fd, STDERR_FILENO) == -1)
|
|
||||||
{
|
|
||||||
_assuan_log_printf ("dup2(dev/null, 2) failed: %s\n",
|
|
||||||
strerror (errno));
|
|
||||||
_exit (4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Close all files which will not be duped and are not in the
|
|
||||||
fd_child_list. */
|
|
||||||
n = sysconf (_SC_OPEN_MAX);
|
|
||||||
if (n < 0)
|
|
||||||
n = MAX_OPEN_FDS;
|
|
||||||
for (i=0; i < n; i++)
|
|
||||||
{
|
|
||||||
if ( i == STDIN_FILENO || i == STDOUT_FILENO
|
|
||||||
|| i == STDERR_FILENO)
|
|
||||||
continue;
|
|
||||||
fdp = fd_child_list;
|
|
||||||
if (fdp)
|
|
||||||
{
|
|
||||||
while (*fdp != -1 && *fdp != i)
|
|
||||||
fdp++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(fdp && *fdp != -1))
|
|
||||||
close(i);
|
|
||||||
}
|
|
||||||
errno = 0;
|
|
||||||
|
|
||||||
/* We store our parents pid in the environment so that the
|
|
||||||
execed assuan server is able to read the actual pid of the
|
|
||||||
client. The server can't use getppid becuase it might have
|
|
||||||
been double forked before the assuan server has been
|
|
||||||
initialized. */
|
|
||||||
setenv ("_assuan_pipe_connect_pid", mypidstr, 1);
|
|
||||||
|
|
||||||
execv (name, (char *const *) 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);
|
|
||||||
}
|
|
||||||
#ifdef _ASSUAN_USE_DOUBLE_FORK
|
|
||||||
if (pid == -1)
|
|
||||||
_exit (1);
|
|
||||||
else
|
|
||||||
_exit (0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _ASSUAN_USE_DOUBLE_FORK
|
|
||||||
waitpid ((*ctx)->pid, NULL, 0);
|
|
||||||
(*ctx)->pid = -1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
close (rp[1]);
|
|
||||||
close (wp[0]);
|
|
||||||
|
|
||||||
#endif /*!HAVE_W32_SYSTEM*/
|
|
||||||
|
|
||||||
/* initial handshake */
|
|
||||||
{
|
|
||||||
int okay, off;
|
|
||||||
|
|
||||||
err = _assuan_read_from_server (*ctx, &okay, &off);
|
|
||||||
if (err)
|
|
||||||
_assuan_log_printf ("can't connect server: %s\n",
|
|
||||||
assuan_strerror (err));
|
|
||||||
else if (okay != 1)
|
|
||||||
{
|
|
||||||
_assuan_log_printf ("can't connect server: `%s'\n",
|
|
||||||
(*ctx)->inbound.line);
|
|
||||||
err = ASSUAN_Connect_Failed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
assuan_disconnect (*ctx);
|
|
||||||
*ctx = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
#endif /*HAVE_W32_SYSTEM*/
|
||||||
|
|
||||||
|
|
||||||
/* 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. FD_CHILD_LIST is a -1 terminated list of file
|
vector in ARGV. FD_CHILD_LIST is a -1 terminated list of file
|
||||||
@ -615,5 +833,57 @@ assuan_error_t
|
|||||||
assuan_pipe_connect (assuan_context_t *ctx, const char *name,
|
assuan_pipe_connect (assuan_context_t *ctx, const char *name,
|
||||||
const char *const argv[], int *fd_child_list)
|
const char *const argv[], int *fd_child_list)
|
||||||
{
|
{
|
||||||
return assuan_pipe_connect2 (ctx, name, argv, fd_child_list, NULL, NULL);
|
return pipe_connect (ctx, name, argv, fd_child_list, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
assuan_error_t
|
||||||
|
assuan_pipe_connect2 (assuan_context_t *ctx,
|
||||||
|
const char *name, const char *const argv[],
|
||||||
|
int *fd_child_list,
|
||||||
|
void (*atfork) (void *opaque, int reserved),
|
||||||
|
void *atforkvalue)
|
||||||
|
{
|
||||||
|
return pipe_connect (ctx, name, argv, fd_child_list, atfork, atforkvalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Connect to a server over a full-duplex socket (i.e. created by
|
||||||
|
socketpair), 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. ATFORK is called in the child right after the
|
||||||
|
fork; ATFORKVALUE is passed as the first argument and 0 is passed
|
||||||
|
as the second argument. The ATFORK function should only act if the
|
||||||
|
second value is 0.
|
||||||
|
|
||||||
|
For now FLAGS may either take the value 0 to behave like
|
||||||
|
assuan_pipe_connect2 or 1 to enable the described full-duplex
|
||||||
|
socket behaviour.
|
||||||
|
|
||||||
|
If NAME as well as ARGV are NULL, no exec is done but the same
|
||||||
|
process is continued. However all file descriptors are closed and
|
||||||
|
some special environment variables are set. To let the caller
|
||||||
|
detect whether the child or the parent continues, the child returns
|
||||||
|
a CTX of NULL. */
|
||||||
|
assuan_error_t
|
||||||
|
assuan_pipe_connect_ext (assuan_context_t *ctx,
|
||||||
|
const char *name, const char *const argv[],
|
||||||
|
int *fd_child_list,
|
||||||
|
void (*atfork) (void *opaque, int reserved),
|
||||||
|
void *atforkvalue, unsigned int flags)
|
||||||
|
{
|
||||||
|
if ((flags & 1))
|
||||||
|
{
|
||||||
|
#ifdef HAVE_W32_SYSTEM
|
||||||
|
return _assuan_error (ASSUAN_Not_Implemented);
|
||||||
|
#else
|
||||||
|
return socketpair_connect (ctx, name, argv, fd_child_list,
|
||||||
|
atfork, atforkvalue);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return pipe_connect (ctx, name, argv, fd_child_list, atfork, atforkvalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -15,12 +15,15 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this program; if not, write to the Free Software
|
* License along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
* USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#ifdef HAVE_W32_SYSTEM
|
#ifdef HAVE_W32_SYSTEM
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@ -31,20 +34,20 @@
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
deinit_pipe_server (ASSUAN_CONTEXT ctx)
|
deinit_pipe_server (assuan_context_t ctx)
|
||||||
{
|
{
|
||||||
/* nothing to do for this simple server */
|
/* nothing to do for this simple server */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
accept_connection (ASSUAN_CONTEXT ctx)
|
accept_connection (assuan_context_t ctx)
|
||||||
{
|
{
|
||||||
/* This is a NOP for a pipe server */
|
/* This is a NOP for a pipe server */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
finish_connection (ASSUAN_CONTEXT ctx)
|
finish_connection (assuan_context_t ctx)
|
||||||
{
|
{
|
||||||
/* This is a NOP for a pipe server */
|
/* This is a NOP for a pipe server */
|
||||||
return 0;
|
return 0;
|
||||||
@ -53,19 +56,19 @@ finish_connection (ASSUAN_CONTEXT ctx)
|
|||||||
/* Create a new context. Note that the handlers are set up for a pipe
|
/* Create a new context. Note that the handlers are set up for a pipe
|
||||||
server/client - this way we don't need extra dummy functions */
|
server/client - this way we don't need extra dummy functions */
|
||||||
int
|
int
|
||||||
_assuan_new_context (ASSUAN_CONTEXT *r_ctx)
|
_assuan_new_context (assuan_context_t *r_ctx)
|
||||||
{
|
{
|
||||||
static struct assuan_io io = { _assuan_simple_read,
|
static struct assuan_io io = { _assuan_simple_read,
|
||||||
_assuan_simple_write,
|
_assuan_simple_write,
|
||||||
0, 0 };
|
0, 0 };
|
||||||
|
|
||||||
ASSUAN_CONTEXT ctx;
|
assuan_context_t ctx;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
*r_ctx = NULL;
|
*r_ctx = NULL;
|
||||||
ctx = xtrycalloc (1, sizeof *ctx);
|
ctx = xtrycalloc (1, sizeof *ctx);
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return ASSUAN_Out_Of_Core;
|
return _assuan_error (ASSUAN_Out_Of_Core);
|
||||||
ctx->input_fd = -1;
|
ctx->input_fd = -1;
|
||||||
ctx->output_fd = -1;
|
ctx->output_fd = -1;
|
||||||
|
|
||||||
@ -88,15 +91,27 @@ _assuan_new_context (ASSUAN_CONTEXT *r_ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Returns true if atoi(S) denotes a valid socket. */
|
||||||
|
static int
|
||||||
|
is_valid_socket (const char *s)
|
||||||
|
{
|
||||||
|
struct stat buf;
|
||||||
|
|
||||||
|
if ( fstat (atoi (s), &buf ) )
|
||||||
|
return 0;
|
||||||
|
return S_ISSOCK (buf.st_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2])
|
assuan_init_pipe_server (assuan_context_t *r_ctx, int filedes[2])
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = _assuan_new_context (r_ctx);
|
rc = _assuan_new_context (r_ctx);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
ASSUAN_CONTEXT ctx = *r_ctx;
|
assuan_context_t ctx = *r_ctx;
|
||||||
const char *s;
|
const char *s;
|
||||||
unsigned long ul;
|
unsigned long ul;
|
||||||
|
|
||||||
@ -110,8 +125,28 @@ assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2])
|
|||||||
ctx->inbound.fd = _get_osfhandle (filedes[0]);
|
ctx->inbound.fd = _get_osfhandle (filedes[0]);
|
||||||
ctx->outbound.fd = _get_osfhandle (filedes[1]);
|
ctx->outbound.fd = _get_osfhandle (filedes[1]);
|
||||||
#else
|
#else
|
||||||
ctx->inbound.fd = filedes[0];
|
s = getenv ("_assuan_connection_fd");
|
||||||
ctx->outbound.fd = filedes[1];
|
if (s && *s && is_valid_socket (s) )
|
||||||
|
{
|
||||||
|
/* Well, we are called with an bi-directional file
|
||||||
|
descriptor. Prepare for using sendmsg/recvmsg. In this
|
||||||
|
case we ignore the passed file descriptors. */
|
||||||
|
ctx->inbound.fd = ctx->outbound.fd = atoi (s);
|
||||||
|
_assuan_init_uds_io (ctx);
|
||||||
|
ctx->deinit_handler = _assuan_uds_deinit;
|
||||||
|
}
|
||||||
|
else if (filedes && filedes[0] != -1 && filedes[1] != -1 )
|
||||||
|
{
|
||||||
|
/* Standard pipe server. */
|
||||||
|
ctx->inbound.fd = filedes[0];
|
||||||
|
ctx->outbound.fd = filedes[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_assuan_release_context (*r_ctx);
|
||||||
|
*r_ctx = NULL;
|
||||||
|
return ASSUAN_Problem_Starting_Server;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
ctx->pipe_mode = 1;
|
ctx->pipe_mode = 1;
|
||||||
|
|
||||||
@ -127,7 +162,7 @@ assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2])
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_assuan_release_context (ASSUAN_CONTEXT ctx)
|
_assuan_release_context (assuan_context_t ctx)
|
||||||
{
|
{
|
||||||
if (ctx)
|
if (ctx)
|
||||||
{
|
{
|
||||||
@ -138,7 +173,7 @@ _assuan_release_context (ASSUAN_CONTEXT ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
assuan_deinit_server (ASSUAN_CONTEXT ctx)
|
assuan_deinit_server (assuan_context_t ctx)
|
||||||
{
|
{
|
||||||
if (ctx)
|
if (ctx)
|
||||||
{
|
{
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this program; if not, write to the Free Software
|
* License along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
* USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@ -54,7 +55,7 @@
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
do_finish (ASSUAN_CONTEXT ctx)
|
do_finish (assuan_context_t ctx)
|
||||||
{
|
{
|
||||||
if (ctx->inbound.fd != -1)
|
if (ctx->inbound.fd != -1)
|
||||||
{
|
{
|
||||||
@ -66,56 +67,70 @@ do_finish (ASSUAN_CONTEXT ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
do_deinit (ASSUAN_CONTEXT ctx)
|
do_deinit (assuan_context_t ctx)
|
||||||
{
|
{
|
||||||
do_finish (ctx);
|
do_finish (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Make a connection to the Unix domain socket NAME and return a new
|
/* 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
|
Assuan context in CTX. SERVER_PID is currently not used but may
|
||||||
become handy in the future. */
|
become handy in the future. */
|
||||||
assuan_error_t
|
assuan_error_t
|
||||||
assuan_socket_connect (ASSUAN_CONTEXT *r_ctx,
|
assuan_socket_connect (assuan_context_t *r_ctx,
|
||||||
const char *name, pid_t server_pid)
|
const char *name, pid_t server_pid)
|
||||||
|
{
|
||||||
|
return assuan_socket_connect_ext (r_ctx, name, server_pid, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
become handy in the future. With flags set to 1 sendmsg and
|
||||||
|
recvmesg are used. */
|
||||||
|
assuan_error_t
|
||||||
|
assuan_socket_connect_ext (assuan_context_t *r_ctx,
|
||||||
|
const char *name, pid_t server_pid,
|
||||||
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
static struct assuan_io io = { _assuan_simple_read,
|
static struct assuan_io io = { _assuan_simple_read,
|
||||||
_assuan_simple_write };
|
_assuan_simple_write };
|
||||||
|
|
||||||
assuan_error_t err;
|
assuan_error_t err;
|
||||||
ASSUAN_CONTEXT ctx;
|
assuan_context_t ctx;
|
||||||
int fd;
|
int fd;
|
||||||
struct sockaddr_un srvr_addr;
|
struct sockaddr_un srvr_addr;
|
||||||
size_t len;
|
size_t len;
|
||||||
const char *s;
|
const char *s;
|
||||||
|
|
||||||
if (!r_ctx || !name)
|
if (!r_ctx || !name)
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
*r_ctx = NULL;
|
*r_ctx = NULL;
|
||||||
|
|
||||||
/* We require that the name starts with a slash, so that we can
|
/* We require that the name starts with a slash, so that we
|
||||||
alter reuse this function for other socket types. To make things
|
eventually can reuse this function for other socket types. To
|
||||||
easier we allow an optional dirver prefix. */
|
make things easier we allow an optional dirver prefix. */
|
||||||
s = name;
|
s = name;
|
||||||
if (*s && s[1] == ':')
|
if (*s && s[1] == ':')
|
||||||
s += 2;
|
s += 2;
|
||||||
if (*s != DIRSEP_C && *s != '/')
|
if (*s != DIRSEP_C && *s != '/')
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
|
|
||||||
if (strlen (name)+1 >= sizeof srvr_addr.sun_path)
|
if (strlen (name)+1 >= sizeof srvr_addr.sun_path)
|
||||||
return ASSUAN_Invalid_Value;
|
return _assuan_error (ASSUAN_Invalid_Value);
|
||||||
|
|
||||||
err = _assuan_new_context (&ctx);
|
err = _assuan_new_context (&ctx);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
ctx->deinit_handler = do_deinit;
|
ctx->deinit_handler = ((flags&1))? _assuan_uds_deinit : do_deinit;
|
||||||
ctx->finish_handler = do_finish;
|
ctx->finish_handler = do_finish;
|
||||||
|
|
||||||
|
|
||||||
fd = _assuan_sock_new (PF_LOCAL, SOCK_STREAM, 0);
|
fd = _assuan_sock_new (PF_LOCAL, SOCK_STREAM, 0);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
{
|
{
|
||||||
_assuan_log_printf ("can't create socket: %s\n", strerror (errno));
|
_assuan_log_printf ("can't create socket: %s\n", strerror (errno));
|
||||||
_assuan_release_context (ctx);
|
_assuan_release_context (ctx);
|
||||||
return ASSUAN_General_Error;
|
return _assuan_error (ASSUAN_General_Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset (&srvr_addr, 0, sizeof srvr_addr);
|
memset (&srvr_addr, 0, sizeof srvr_addr);
|
||||||
@ -131,12 +146,14 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx,
|
|||||||
name, strerror (errno));
|
name, strerror (errno));
|
||||||
_assuan_release_context (ctx);
|
_assuan_release_context (ctx);
|
||||||
_assuan_close (fd);
|
_assuan_close (fd);
|
||||||
return ASSUAN_Connect_Failed;
|
return _assuan_error (ASSUAN_Connect_Failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->inbound.fd = fd;
|
ctx->inbound.fd = fd;
|
||||||
ctx->outbound.fd = fd;
|
ctx->outbound.fd = fd;
|
||||||
ctx->io = &io;
|
ctx->io = &io;
|
||||||
|
if ((flags&1))
|
||||||
|
_assuan_init_uds_io (ctx);
|
||||||
|
|
||||||
/* initial handshake */
|
/* initial handshake */
|
||||||
{
|
{
|
||||||
@ -151,7 +168,7 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx,
|
|||||||
/*LOG ("can't connect to server: `");*/
|
/*LOG ("can't connect to server: `");*/
|
||||||
_assuan_log_sanitized_string (ctx->inbound.line);
|
_assuan_log_sanitized_string (ctx->inbound.line);
|
||||||
fprintf (assuan_get_assuan_log_stream (), "'\n");
|
fprintf (assuan_get_assuan_log_stream (), "'\n");
|
||||||
err = ASSUAN_Connect_Failed;
|
err = _assuan_error (ASSUAN_Connect_Failed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,3 +180,5 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx,
|
|||||||
*r_ctx = ctx;
|
*r_ctx = ctx;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this program; if not, write to the Free Software
|
* License along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
* USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@ -33,21 +34,33 @@
|
|||||||
|
|
||||||
#include "assuan-defs.h"
|
#include "assuan-defs.h"
|
||||||
|
|
||||||
|
static struct assuan_io io = { _assuan_simple_read,
|
||||||
|
_assuan_simple_write };
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
accept_connection_bottom (assuan_context_t ctx)
|
accept_connection_bottom (assuan_context_t ctx)
|
||||||
{
|
{
|
||||||
int fd = ctx->connected_fd;
|
int fd = ctx->connected_fd;
|
||||||
|
|
||||||
|
ctx->peercred.valid = 0;
|
||||||
#ifdef HAVE_SO_PEERCRED
|
#ifdef HAVE_SO_PEERCRED
|
||||||
{
|
{
|
||||||
/* This overrides any already set PID if the function returns a
|
|
||||||
valid one. */
|
|
||||||
struct ucred cr;
|
struct ucred cr;
|
||||||
int cl = sizeof cr;
|
socklen_t cl = sizeof cr;
|
||||||
|
|
||||||
if ( !getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl)
|
if ( !getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl))
|
||||||
&& cr.pid != (pid_t)-1 && cr.pid )
|
{
|
||||||
ctx->pid = cr.pid;
|
ctx->peercred.pid = cr.pid;
|
||||||
|
ctx->peercred.uid = cr.uid;
|
||||||
|
ctx->peercred.gid = cr.gid;
|
||||||
|
ctx->peercred.valid = 1;
|
||||||
|
|
||||||
|
/* This overrides any already set PID if the function returns
|
||||||
|
a valid one. */
|
||||||
|
if (cr.pid != (pid_t)-1 && cr.pid)
|
||||||
|
ctx->pid = cr.pid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -72,13 +85,13 @@ accept_connection (assuan_context_t ctx)
|
|||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
struct sockaddr_un clnt_addr;
|
struct sockaddr_un clnt_addr;
|
||||||
size_t len = sizeof clnt_addr;
|
socklen_t len = sizeof clnt_addr;
|
||||||
|
|
||||||
fd = accept (ctx->listen_fd, (struct sockaddr*)&clnt_addr, &len );
|
fd = accept (ctx->listen_fd, (struct sockaddr*)&clnt_addr, &len );
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
{
|
{
|
||||||
ctx->os_errno = errno;
|
ctx->os_errno = errno;
|
||||||
return ASSUAN_Accept_Failed;
|
return _assuan_error (ASSUAN_Accept_Failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->connected_fd = fd;
|
ctx->connected_fd = fd;
|
||||||
@ -104,47 +117,30 @@ deinit_socket_server (assuan_context_t ctx)
|
|||||||
finish_connection (ctx);
|
finish_connection (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct assuan_io io = { _assuan_simple_read,
|
|
||||||
_assuan_simple_write };
|
|
||||||
|
|
||||||
/* Initialize a server for the socket LISTEN_FD which has already be
|
/* Initialize a server for the socket LISTEN_FD which has already be
|
||||||
put into listen mode */
|
put into listen mode */
|
||||||
int
|
int
|
||||||
assuan_init_socket_server (assuan_context_t *r_ctx, int listen_fd)
|
assuan_init_socket_server (assuan_context_t *r_ctx, int listen_fd)
|
||||||
{
|
{
|
||||||
assuan_context_t ctx;
|
return assuan_init_socket_server_ext (r_ctx, listen_fd, 0);
|
||||||
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->connected_fd = -1;
|
|
||||||
ctx->deinit_handler = deinit_socket_server;
|
|
||||||
ctx->accept_handler = accept_connection;
|
|
||||||
ctx->finish_handler = finish_connection;
|
|
||||||
|
|
||||||
ctx->io = &io;
|
|
||||||
|
|
||||||
rc = _assuan_register_std_commands (ctx);
|
|
||||||
if (rc)
|
|
||||||
xfree (ctx);
|
|
||||||
else
|
|
||||||
*r_ctx = ctx;
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize a server using the already accepted socket FD. */
|
/* Initialize a server using the already accepted socket FD. This
|
||||||
|
fucntion is deprecated. */
|
||||||
int
|
int
|
||||||
assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd)
|
assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd)
|
||||||
|
{
|
||||||
|
return assuan_init_socket_server_ext (r_ctx, fd, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Flag bits: 0 - use sendmsg/recvmsg to allow descriptor passing
|
||||||
|
1 - FD has already been accepted.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
assuan_init_socket_server_ext (assuan_context_t *r_ctx, int fd,
|
||||||
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
assuan_context_t ctx;
|
assuan_context_t ctx;
|
||||||
int rc;
|
int rc;
|
||||||
@ -152,23 +148,36 @@ assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd)
|
|||||||
*r_ctx = NULL;
|
*r_ctx = NULL;
|
||||||
ctx = xtrycalloc (1, sizeof *ctx);
|
ctx = xtrycalloc (1, sizeof *ctx);
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return ASSUAN_Out_Of_Core;
|
return _assuan_error (ASSUAN_Out_Of_Core);
|
||||||
ctx->is_server = 1;
|
ctx->is_server = 1;
|
||||||
ctx->pipe_mode = 1; /* we want a second accept to indicate EOF */
|
if ((flags & 2))
|
||||||
|
ctx->pipe_mode = 1; /* We want a second accept to indicate EOF. */
|
||||||
ctx->input_fd = -1;
|
ctx->input_fd = -1;
|
||||||
ctx->output_fd = -1;
|
ctx->output_fd = -1;
|
||||||
|
|
||||||
ctx->inbound.fd = -1;
|
ctx->inbound.fd = -1;
|
||||||
ctx->outbound.fd = -1;
|
ctx->outbound.fd = -1;
|
||||||
|
|
||||||
ctx->io = &io;
|
if ((flags & 2))
|
||||||
|
{
|
||||||
ctx->listen_fd = -1;
|
ctx->listen_fd = -1;
|
||||||
ctx->connected_fd = fd;
|
ctx->connected_fd = fd;
|
||||||
ctx->deinit_handler = deinit_socket_server;
|
}
|
||||||
ctx->accept_handler = accept_connection_bottom;
|
else
|
||||||
|
{
|
||||||
|
ctx->listen_fd = fd;
|
||||||
|
ctx->connected_fd = -1;
|
||||||
|
}
|
||||||
|
ctx->deinit_handler = (flags & 1)? _assuan_uds_deinit:deinit_socket_server;
|
||||||
|
ctx->accept_handler = ((flags & 2)
|
||||||
|
? accept_connection_bottom
|
||||||
|
: accept_connection);
|
||||||
ctx->finish_handler = finish_connection;
|
ctx->finish_handler = finish_connection;
|
||||||
|
|
||||||
|
ctx->io = &io;
|
||||||
|
if ((flags & 1))
|
||||||
|
_assuan_init_uds_io (ctx);
|
||||||
|
|
||||||
rc = _assuan_register_std_commands (ctx);
|
rc = _assuan_register_std_commands (ctx);
|
||||||
if (rc)
|
if (rc)
|
||||||
xfree (ctx);
|
xfree (ctx);
|
||||||
@ -176,5 +185,3 @@ assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd)
|
|||||||
*r_ctx = ctx;
|
*r_ctx = ctx;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,22 +1,24 @@
|
|||||||
/* assuan-socket.c
|
/* assuan-socket.c
|
||||||
* Copyright (C) 2004 Free Software Foundation, Inc.
|
* Copyright (C) 2004, 2005 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of Assuan.
|
||||||
*
|
*
|
||||||
* GnuPG is free software; you can redistribute it and/or modify
|
* Assuan is free software; you can redistribute it and/or modify it
|
||||||
* it under the terms of the GNU General Public License as published by
|
* under the terms of the GNU Lesser General Public License as
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* published by the Free Software Foundation; either version 2.1 of
|
||||||
* (at your option) any later version.
|
* the License, or (at your option) any later version.
|
||||||
*
|
*
|
||||||
* GnuPG is distributed in the hope that it will be useful,
|
* Assuan is distributed in the hope that it will be useful, but
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* GNU General Public License for more details.
|
* Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* along with this program; if not, write to the Free Software
|
* License along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
* USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#ifdef HAVE_W32_SYSTEM
|
#ifdef HAVE_W32_SYSTEM
|
||||||
@ -28,6 +30,18 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "assuan-defs.h"
|
#include "assuan-defs.h"
|
||||||
|
|
||||||
|
/* Hacks for Slowaris. */
|
||||||
|
#ifndef PF_LOCAL
|
||||||
|
# ifdef PF_UNIX
|
||||||
|
# define PF_LOCAL PF_UNIX
|
||||||
|
# else
|
||||||
|
# define PF_LOCAL AF_UNIX
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#ifndef AF_LOCAL
|
||||||
|
# define AF_LOCAL AF_UNIX
|
||||||
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
_assuan_close (int fd)
|
_assuan_close (int fd)
|
||||||
{
|
{
|
||||||
|
285
assuan/assuan-uds.c
Normal file
285
assuan/assuan-uds.c
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
/* assuan-uds.c - Assuan unix domain socket utilities
|
||||||
|
* Copyright (C) 2006 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of Assuan.
|
||||||
|
*
|
||||||
|
* Assuan is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Assuan 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
* USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#ifndef HAVE_W32_SYSTEM
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#else
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
#if HAVE_SYS_UIO_H
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#endif
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "assuan-defs.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Read from a unix domain socket using sendmsg.
|
||||||
|
|
||||||
|
FIXME: We don't need the buffering. It is a leftover from the time
|
||||||
|
when we used datagrams. */
|
||||||
|
static ssize_t
|
||||||
|
uds_reader (assuan_context_t ctx, void *buf, size_t buflen)
|
||||||
|
{
|
||||||
|
int len = ctx->uds.buffersize;
|
||||||
|
|
||||||
|
#ifndef HAVE_W32_SYSTEM
|
||||||
|
|
||||||
|
if (!ctx->uds.bufferallocated)
|
||||||
|
{
|
||||||
|
ctx->uds.buffer = xtrymalloc (2048);
|
||||||
|
if (!ctx->uds.buffer)
|
||||||
|
return _assuan_error (ASSUAN_Out_Of_Core);
|
||||||
|
ctx->uds.bufferallocated = 2048;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!len) /* No data is buffered. */
|
||||||
|
{
|
||||||
|
struct msghdr msg;
|
||||||
|
struct iovec iovec;
|
||||||
|
union {
|
||||||
|
struct cmsghdr cm;
|
||||||
|
char control[CMSG_SPACE(sizeof (int))];
|
||||||
|
} control_u;
|
||||||
|
struct cmsghdr *cmptr;
|
||||||
|
|
||||||
|
memset (&msg, 0, sizeof (msg));
|
||||||
|
|
||||||
|
msg.msg_name = NULL;
|
||||||
|
msg.msg_namelen = 0;
|
||||||
|
msg.msg_iov = &iovec;
|
||||||
|
msg.msg_iovlen = 1;
|
||||||
|
iovec.iov_base = ctx->uds.buffer;
|
||||||
|
iovec.iov_len = ctx->uds.bufferallocated;
|
||||||
|
msg.msg_control = control_u.control;
|
||||||
|
msg.msg_controllen = sizeof (control_u.control);
|
||||||
|
|
||||||
|
len = _assuan_simple_recvmsg (ctx, &msg);
|
||||||
|
if (len < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ctx->uds.buffersize = len;
|
||||||
|
ctx->uds.bufferoffset = 0;
|
||||||
|
|
||||||
|
cmptr = CMSG_FIRSTHDR (&msg);
|
||||||
|
if (cmptr && cmptr->cmsg_len == CMSG_LEN (sizeof(int)))
|
||||||
|
{
|
||||||
|
if (cmptr->cmsg_level != SOL_SOCKET
|
||||||
|
|| cmptr->cmsg_type != SCM_RIGHTS)
|
||||||
|
_assuan_log_printf ("unexpected ancillary data received\n");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int fd = *((int*)CMSG_DATA (cmptr));
|
||||||
|
|
||||||
|
if (ctx->uds.pendingfdscount >= DIM (ctx->uds.pendingfds))
|
||||||
|
{
|
||||||
|
_assuan_log_printf ("too many descriptors pending - "
|
||||||
|
"closing received descriptor %d\n", fd);
|
||||||
|
_assuan_close (fd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ctx->uds.pendingfds[ctx->uds.pendingfdscount++] = fd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else /*HAVE_W32_SYSTEM*/
|
||||||
|
len = recvfrom (ctx->inbound.fd, buf, buflen, 0, NULL, NULL);
|
||||||
|
#endif /*HAVE_W32_SYSTEM*/
|
||||||
|
|
||||||
|
/* Return some data to the user. */
|
||||||
|
|
||||||
|
if (len > buflen) /* We have more than the user requested. */
|
||||||
|
len = buflen;
|
||||||
|
|
||||||
|
memcpy (buf, ctx->uds.buffer + ctx->uds.bufferoffset, len);
|
||||||
|
ctx->uds.buffersize -= len;
|
||||||
|
assert (ctx->uds.buffersize >= 0);
|
||||||
|
ctx->uds.bufferoffset += len;
|
||||||
|
assert (ctx->uds.bufferoffset <= ctx->uds.bufferallocated);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Write to the domain server. */
|
||||||
|
static ssize_t
|
||||||
|
uds_writer (assuan_context_t ctx, const void *buf, size_t buflen)
|
||||||
|
{
|
||||||
|
#ifndef HAVE_W32_SYSTEM
|
||||||
|
struct msghdr msg;
|
||||||
|
struct iovec iovec;
|
||||||
|
ssize_t len;
|
||||||
|
|
||||||
|
memset (&msg, 0, sizeof (msg));
|
||||||
|
|
||||||
|
msg.msg_name = NULL;
|
||||||
|
msg.msg_namelen = 0;
|
||||||
|
msg.msg_iovlen = 1;
|
||||||
|
msg.msg_iov = &iovec;
|
||||||
|
iovec.iov_base = (void*)buf;
|
||||||
|
iovec.iov_len = buflen;
|
||||||
|
msg.msg_control = 0;
|
||||||
|
msg.msg_controllen = 0;
|
||||||
|
|
||||||
|
len = _assuan_simple_sendmsg (ctx, &msg);
|
||||||
|
#else /*HAVE_W32_SYSTEM*/
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = sendto (ctx->outbound.fd, buf, buflen, 0,
|
||||||
|
(struct sockaddr *)&ctx->serveraddr,
|
||||||
|
sizeof (struct sockaddr_in));
|
||||||
|
#endif /*HAVE_W32_SYSTEM*/
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static assuan_error_t
|
||||||
|
uds_sendfd (assuan_context_t ctx, int fd)
|
||||||
|
{
|
||||||
|
#ifndef HAVE_W32_SYSTEM
|
||||||
|
struct msghdr msg;
|
||||||
|
struct iovec iovec;
|
||||||
|
union {
|
||||||
|
struct cmsghdr cm;
|
||||||
|
char control[CMSG_SPACE(sizeof (int))];
|
||||||
|
} control_u;
|
||||||
|
struct cmsghdr *cmptr;
|
||||||
|
int len;
|
||||||
|
char buffer[80];
|
||||||
|
|
||||||
|
/* We need to send some real data so that a read won't return 0
|
||||||
|
which will be taken as an EOF. It also helps with debugging. */
|
||||||
|
snprintf (buffer, sizeof(buffer)-1, "# descriptor %d is in flight\n", fd);
|
||||||
|
buffer[sizeof(buffer)-1] = 0;
|
||||||
|
|
||||||
|
memset (&msg, 0, sizeof (msg));
|
||||||
|
|
||||||
|
msg.msg_name = NULL;
|
||||||
|
msg.msg_namelen = 0;
|
||||||
|
msg.msg_iovlen = 1;
|
||||||
|
msg.msg_iov = &iovec;
|
||||||
|
iovec.iov_base = buffer;
|
||||||
|
iovec.iov_len = strlen (buffer);
|
||||||
|
|
||||||
|
msg.msg_control = control_u.control;
|
||||||
|
msg.msg_controllen = sizeof (control_u.control);
|
||||||
|
cmptr = CMSG_FIRSTHDR (&msg);
|
||||||
|
cmptr->cmsg_len = CMSG_LEN(sizeof(int));
|
||||||
|
cmptr->cmsg_level = SOL_SOCKET;
|
||||||
|
cmptr->cmsg_type = SCM_RIGHTS;
|
||||||
|
*((int*)CMSG_DATA (cmptr)) = fd;
|
||||||
|
|
||||||
|
len = _assuan_simple_sendmsg (ctx, &msg);
|
||||||
|
if (len < 0)
|
||||||
|
{
|
||||||
|
_assuan_log_printf ("uds_sendfd: %s\n", strerror (errno));
|
||||||
|
return _assuan_error (ASSUAN_Write_Error);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
return _assuan_error (ASSUAN_Not_Implemented);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static assuan_error_t
|
||||||
|
uds_receivefd (assuan_context_t ctx, int *fd)
|
||||||
|
{
|
||||||
|
#ifndef HAVE_W32_SYSTEM
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!ctx->uds.pendingfdscount)
|
||||||
|
{
|
||||||
|
_assuan_log_printf ("no pending file descriptors!\n");
|
||||||
|
return _assuan_error (ASSUAN_General_Error);
|
||||||
|
}
|
||||||
|
assert (ctx->uds.pendingfdscount <= DIM(ctx->uds.pendingfds));
|
||||||
|
|
||||||
|
*fd = ctx->uds.pendingfds[0];
|
||||||
|
for (i=1; i < ctx->uds.pendingfdscount; i++)
|
||||||
|
ctx->uds.pendingfds[i-1] = ctx->uds.pendingfds[i];
|
||||||
|
ctx->uds.pendingfdscount--;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
return _assuan_error (ASSUAN_Not_Implemented);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Close all pending fds. */
|
||||||
|
void
|
||||||
|
_assuan_uds_close_fds (assuan_context_t ctx)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ctx->uds.pendingfdscount; i++)
|
||||||
|
_assuan_close (ctx->uds.pendingfds[i]);
|
||||||
|
ctx->uds.pendingfdscount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Deinitialize the unix domain socket I/O functions. */
|
||||||
|
void
|
||||||
|
_assuan_uds_deinit (assuan_context_t ctx)
|
||||||
|
{
|
||||||
|
/* First call the finish_handler which should close descriptors etc. */
|
||||||
|
ctx->finish_handler (ctx);
|
||||||
|
|
||||||
|
if (ctx->uds.buffer)
|
||||||
|
{
|
||||||
|
assert (ctx->uds.bufferallocated);
|
||||||
|
ctx->uds.bufferallocated = 0;
|
||||||
|
xfree (ctx->uds.buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
_assuan_uds_close_fds (ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Helper function to initialize a context for domain I/O. */
|
||||||
|
void
|
||||||
|
_assuan_init_uds_io (assuan_context_t ctx)
|
||||||
|
{
|
||||||
|
static struct assuan_io io = { uds_reader, uds_writer,
|
||||||
|
uds_sendfd, uds_receivefd };
|
||||||
|
|
||||||
|
ctx->io = &io;
|
||||||
|
ctx->uds.buffer = 0;
|
||||||
|
ctx->uds.bufferoffset = 0;
|
||||||
|
ctx->uds.buffersize = 0;
|
||||||
|
ctx->uds.bufferallocated = 0;
|
||||||
|
ctx->uds.pendingfdscount = 0;
|
||||||
|
}
|
||||||
|
|
@ -15,7 +15,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this program; if not, write to the Free Software
|
* License along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
* USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@ -105,19 +106,6 @@ assuan_get_pointer (assuan_context_t ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
assuan_set_log_stream (assuan_context_t ctx, FILE *fp)
|
|
||||||
{
|
|
||||||
if (ctx)
|
|
||||||
{
|
|
||||||
if (ctx->log_fp)
|
|
||||||
fflush (ctx->log_fp);
|
|
||||||
ctx->log_fp = fp;
|
|
||||||
_assuan_set_default_log_stream (fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
assuan_begin_confidential (assuan_context_t ctx)
|
assuan_begin_confidential (assuan_context_t ctx)
|
||||||
{
|
{
|
||||||
@ -166,97 +154,3 @@ assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Dump a possibly binary string (used for debugging). Distinguish
|
|
||||||
ascii text from binary and print it accordingly. */
|
|
||||||
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 ((!isascii (*s) || iscntrl (*s) || !isprint (*s)) && !(*s >= 0x80))
|
|
||||||
break;
|
|
||||||
|
|
||||||
s = buffer;
|
|
||||||
if (!n && *s != '[')
|
|
||||||
fwrite (buffer, length, 1, fp);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef HAVE_FLOCKFILE
|
|
||||||
flockfile (fp);
|
|
||||||
#endif
|
|
||||||
putc_unlocked ('[', fp);
|
|
||||||
for (n=0; n < length; n++, s++)
|
|
||||||
fprintf (fp, " %02x", *s);
|
|
||||||
putc_unlocked (' ', fp);
|
|
||||||
putc_unlocked (']', fp);
|
|
||||||
#ifdef HAVE_FUNLOCKFILE
|
|
||||||
funlockfile (fp);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Log a user supplied string. Escapes non-printable before
|
|
||||||
printing. */
|
|
||||||
void
|
|
||||||
_assuan_log_sanitized_string (const char *string)
|
|
||||||
{
|
|
||||||
const unsigned char *s = (const unsigned char *) string;
|
|
||||||
FILE *fp = assuan_get_assuan_log_stream ();
|
|
||||||
|
|
||||||
if (! *s)
|
|
||||||
return;
|
|
||||||
|
|
||||||
#ifdef HAVE_FLOCKFILE
|
|
||||||
flockfile (fp);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (; *s; s++)
|
|
||||||
{
|
|
||||||
int c = 0;
|
|
||||||
|
|
||||||
switch (*s)
|
|
||||||
{
|
|
||||||
case '\r':
|
|
||||||
c = 'r';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\n':
|
|
||||||
c = 'n';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\f':
|
|
||||||
c = 'f';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\v':
|
|
||||||
c = 'v';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\b':
|
|
||||||
c = 'b';
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if ((isascii (*s) && isprint (*s)) || (*s >= 0x80))
|
|
||||||
putc_unlocked (*s, fp);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
putc_unlocked ('\\', fp);
|
|
||||||
fprintf (fp, "x%02x", *s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c)
|
|
||||||
{
|
|
||||||
putc_unlocked ('\\', fp);
|
|
||||||
putc_unlocked (c, fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_FUNLOCKFILE
|
|
||||||
funlockfile (fp);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
301
assuan/assuan.h
301
assuan/assuan.h
@ -15,7 +15,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this program; if not, write to the Free Software
|
* License along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
* USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ASSUAN_H
|
#ifndef ASSUAN_H
|
||||||
@ -26,24 +27,32 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
/* To use this file with libraries the following macros are often
|
/* To use this file with libraries the following macros are useful:
|
||||||
useful:
|
|
||||||
|
|
||||||
#define _ASSUAN_EXT_SYM_PREFIX _foo_
|
#define _ASSUAN_EXT_SYM_PREFIX _foo_
|
||||||
|
|
||||||
This prefixes all external symbols with "_foo_".
|
This prefixes all external symbols with "_foo_".
|
||||||
|
|
||||||
#define _ASSUAN_NO_PTH
|
#define _ASSUAN_ONLY_GPG_ERRORS
|
||||||
|
|
||||||
This avoids inclusion of special GNU Pth hacks.
|
If this is defined all old-style Assuan error codes are made
|
||||||
|
inactive as well as other dereacted stuff.
|
||||||
|
|
||||||
#define _ASSUAN_NO_FIXED_SIGNALS
|
The follwing macros are used internally in the implementation of
|
||||||
|
libassuan:
|
||||||
|
|
||||||
This disables changing of certain signal handler; i.e. SIGPIPE.
|
#define _ASSUAN_NO_PTH
|
||||||
|
|
||||||
#define _ASSUAN_USE_DOUBLE_FORK
|
This avoids inclusion of special GNU Pth hacks.
|
||||||
|
|
||||||
Use a double fork approach when connecting to a server through a pipe.
|
#define _ASSUAN_NO_FIXED_SIGNALS
|
||||||
|
|
||||||
|
This disables changing of certain signal handler; i.e. SIGPIPE.
|
||||||
|
|
||||||
|
#define _ASSUAN_USE_DOUBLE_FORK
|
||||||
|
|
||||||
|
Use a double fork approach when connecting to a server through
|
||||||
|
a pipe.
|
||||||
*/
|
*/
|
||||||
/**** Begin GPGME specific modifications. ******/
|
/**** Begin GPGME specific modifications. ******/
|
||||||
#define _ASSUAN_EXT_SYM_PREFIX _gpgme_
|
#define _ASSUAN_EXT_SYM_PREFIX _gpgme_
|
||||||
@ -115,12 +124,15 @@ int _gpgme_ath_recvmsg (int s, struct msghdr *msg, int flags);
|
|||||||
#define assuan_init_socket_server _ASSUAN_PREFIX(assuan_init_socket_server)
|
#define assuan_init_socket_server _ASSUAN_PREFIX(assuan_init_socket_server)
|
||||||
#define assuan_init_connected_socket_server \
|
#define assuan_init_connected_socket_server \
|
||||||
_ASSUAN_PREFIX(assuan_init_connected_socket_server)
|
_ASSUAN_PREFIX(assuan_init_connected_socket_server)
|
||||||
|
#define assuan_init_socket_server_ext \
|
||||||
|
_ASSUAN_PREFIX(assuan_init_socket_server_ext)
|
||||||
#define assuan_pipe_connect _ASSUAN_PREFIX(assuan_pipe_connect)
|
#define assuan_pipe_connect _ASSUAN_PREFIX(assuan_pipe_connect)
|
||||||
|
#define assuan_pipe_connect_ext _ASSUAN_PREFIX(assuan_pipe_connect_ext)
|
||||||
#define assuan_socket_connect _ASSUAN_PREFIX(assuan_socket_connect)
|
#define assuan_socket_connect _ASSUAN_PREFIX(assuan_socket_connect)
|
||||||
#define assuan_domain_connect _ASSUAN_PREFIX(assuan_domain_connect)
|
#define assuan_socket_connect_ext _ASSUAN_PREFIX(assuan_socket_connect_ext)
|
||||||
#define assuan_init_domain_server _ASSUAN_PREFIX(assuan_init_domain_server)
|
|
||||||
#define assuan_disconnect _ASSUAN_PREFIX(assuan_disconnect)
|
#define assuan_disconnect _ASSUAN_PREFIX(assuan_disconnect)
|
||||||
#define assuan_get_pid _ASSUAN_PREFIX(assuan_get_pid)
|
#define assuan_get_pid _ASSUAN_PREFIX(assuan_get_pid)
|
||||||
|
#define assuan_get_peercred _ASSUAN_PREFIX(assuan_get_peercred)
|
||||||
#define assuan_transact _ASSUAN_PREFIX(assuan_transact)
|
#define assuan_transact _ASSUAN_PREFIX(assuan_transact)
|
||||||
#define assuan_inquire _ASSUAN_PREFIX(assuan_inquire)
|
#define assuan_inquire _ASSUAN_PREFIX(assuan_inquire)
|
||||||
#define assuan_read_line _ASSUAN_PREFIX(assuan_read_line)
|
#define assuan_read_line _ASSUAN_PREFIX(assuan_read_line)
|
||||||
@ -137,6 +149,8 @@ int _gpgme_ath_recvmsg (int s, struct msghdr *msg, int flags);
|
|||||||
#define assuan_begin_confidential _ASSUAN_PREFIX(assuan_begin_confidential)
|
#define assuan_begin_confidential _ASSUAN_PREFIX(assuan_begin_confidential)
|
||||||
#define assuan_end_confidential _ASSUAN_PREFIX(assuan_end_confidential)
|
#define assuan_end_confidential _ASSUAN_PREFIX(assuan_end_confidential)
|
||||||
#define assuan_strerror _ASSUAN_PREFIX(assuan_strerror)
|
#define assuan_strerror _ASSUAN_PREFIX(assuan_strerror)
|
||||||
|
#define assuan_set_assuan_err_source \
|
||||||
|
_ASSUAN_PREFIX(assuan_set_assuan_err_source)
|
||||||
#define assuan_set_assuan_log_stream \
|
#define assuan_set_assuan_log_stream \
|
||||||
_ASSUAN_PREFIX(assuan_set_assuan_log_stream)
|
_ASSUAN_PREFIX(assuan_set_assuan_log_stream)
|
||||||
#define assuan_get_assuan_log_stream \
|
#define assuan_get_assuan_log_stream \
|
||||||
@ -189,89 +203,121 @@ extern "C"
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
typedef enum
|
/* Check for compiler features. */
|
||||||
{
|
#if __GNUC__
|
||||||
ASSUAN_No_Error = 0,
|
#define _ASSUAN_GCC_VERSION (__GNUC__ * 10000 \
|
||||||
ASSUAN_General_Error = 1,
|
+ __GNUC_MINOR__ * 100 \
|
||||||
ASSUAN_Out_Of_Core = 2,
|
+ __GNUC_PATCHLEVEL__)
|
||||||
ASSUAN_Invalid_Value = 3,
|
|
||||||
ASSUAN_Timeout = 4,
|
#if _ASSUAN_GCC_VERSION > 30100
|
||||||
ASSUAN_Read_Error = 5,
|
#define _ASSUAN_DEPRECATED __attribute__ ((__deprecated__))
|
||||||
ASSUAN_Write_Error = 6,
|
#endif
|
||||||
ASSUAN_Problem_Starting_Server = 7,
|
#endif
|
||||||
ASSUAN_Not_A_Server = 8,
|
#ifndef _ASSUAN_DEPRECATED
|
||||||
ASSUAN_Not_A_Client = 9,
|
#define _ASSUAN_DEPRECATED
|
||||||
ASSUAN_Nested_Commands = 10,
|
#endif
|
||||||
ASSUAN_Invalid_Response = 11,
|
|
||||||
ASSUAN_No_Data_Callback = 12,
|
|
||||||
ASSUAN_No_Inquire_Callback = 13,
|
/* Assuan error codes. These are only used by old applications or
|
||||||
ASSUAN_Connect_Failed = 14,
|
those applications which won't make use of libgpg-error. */
|
||||||
ASSUAN_Accept_Failed = 15,
|
#ifndef _ASSUAN_ONLY_GPG_ERRORS
|
||||||
|
#ifndef _ASSUAN_IN_LIBASSUAN
|
||||||
|
#define ASSUAN_No_Error 0
|
||||||
|
#endif
|
||||||
|
#define ASSUAN_General_Error 1
|
||||||
|
#define ASSUAN_Out_Of_Core 2
|
||||||
|
#define ASSUAN_Invalid_Value 3
|
||||||
|
#ifndef _ASSUAN_IN_LIBASSUAN
|
||||||
|
#define ASSUAN_Timeout 4
|
||||||
|
#endif
|
||||||
|
#define ASSUAN_Read_Error 5
|
||||||
|
#define ASSUAN_Write_Error 6
|
||||||
|
#define ASSUAN_Problem_Starting_Server 7
|
||||||
|
#define ASSUAN_Not_A_Server 8
|
||||||
|
#ifndef _ASSUAN_IN_LIBASSUAN
|
||||||
|
#define ASSUAN_Not_A_Client 9
|
||||||
|
#endif
|
||||||
|
#define ASSUAN_Nested_Commands 10
|
||||||
|
#define ASSUAN_Invalid_Response 11
|
||||||
|
#define ASSUAN_No_Data_Callback 12
|
||||||
|
#define ASSUAN_No_Inquire_Callback 13
|
||||||
|
#define ASSUAN_Connect_Failed 14
|
||||||
|
#define 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,
|
#define ASSUAN_Not_Implemented 100
|
||||||
ASSUAN_Server_Fault = 101,
|
#define ASSUAN_Server_Fault 101
|
||||||
ASSUAN_Invalid_Command = 102,
|
#ifndef _ASSUAN_IN_LIBASSUAN
|
||||||
ASSUAN_Unknown_Command = 103,
|
#define ASSUAN_Invalid_Command 102
|
||||||
ASSUAN_Syntax_Error = 104,
|
#endif
|
||||||
ASSUAN_Parameter_Error = 105,
|
#define ASSUAN_Unknown_Command 103
|
||||||
ASSUAN_Parameter_Conflict = 106,
|
#define ASSUAN_Syntax_Error 104
|
||||||
ASSUAN_Line_Too_Long = 107,
|
#ifndef _ASSUAN_IN_LIBASSUAN
|
||||||
ASSUAN_Line_Not_Terminated = 108,
|
#define ASSUAN_Parameter_Error 105
|
||||||
ASSUAN_No_Input = 109,
|
#endif
|
||||||
ASSUAN_No_Output = 110,
|
#define ASSUAN_Parameter_Conflict 106
|
||||||
ASSUAN_Canceled = 111,
|
#define ASSUAN_Line_Too_Long 107
|
||||||
ASSUAN_Unsupported_Algorithm = 112,
|
#define ASSUAN_Line_Not_Terminated 108
|
||||||
ASSUAN_Server_Resource_Problem = 113,
|
#ifndef _ASSUAN_IN_LIBASSUAN
|
||||||
ASSUAN_Server_IO_Error = 114,
|
#define ASSUAN_No_Input 109
|
||||||
ASSUAN_Server_Bug = 115,
|
#define ASSUAN_No_Output 110
|
||||||
ASSUAN_No_Data_Available = 116,
|
#endif
|
||||||
ASSUAN_Invalid_Data = 117,
|
#define ASSUAN_Canceled 111
|
||||||
ASSUAN_Unexpected_Command = 118,
|
#ifndef _ASSUAN_IN_LIBASSUAN
|
||||||
ASSUAN_Too_Much_Data = 119,
|
#define ASSUAN_Unsupported_Algorithm 112
|
||||||
ASSUAN_Inquire_Unknown = 120,
|
#define ASSUAN_Server_Resource_Problem 113
|
||||||
ASSUAN_Inquire_Error = 121,
|
#define ASSUAN_Server_IO_Error 114
|
||||||
ASSUAN_Invalid_Option = 122,
|
#define ASSUAN_Server_Bug 115
|
||||||
ASSUAN_Invalid_Index = 123,
|
#define ASSUAN_No_Data_Available 116
|
||||||
ASSUAN_Unexpected_Status = 124,
|
#define ASSUAN_Invalid_Data 117
|
||||||
ASSUAN_Unexpected_Data = 125,
|
#endif
|
||||||
ASSUAN_Invalid_Status = 126,
|
#define ASSUAN_Unexpected_Command 118
|
||||||
ASSUAN_Locale_Problem = 127,
|
#define ASSUAN_Too_Much_Data 119
|
||||||
ASSUAN_Not_Confirmed = 128,
|
#ifndef _ASSUAN_IN_LIBASSUAN
|
||||||
|
#define ASSUAN_Inquire_Unknown 120
|
||||||
|
#define ASSUAN_Inquire_Error 121
|
||||||
|
#define ASSUAN_Invalid_Option 122
|
||||||
|
#define ASSUAN_Invalid_Index 123
|
||||||
|
#define ASSUAN_Unexpected_Status 124
|
||||||
|
#define ASSUAN_Unexpected_Data 125
|
||||||
|
#define ASSUAN_Invalid_Status 126
|
||||||
|
#define ASSUAN_Locale_Problem 127
|
||||||
|
#define ASSUAN_Not_Confirmed 128
|
||||||
|
|
||||||
/* Warning: Don't use the rror codes, below they are deprecated. */
|
/* Warning: Don't use the Error codes, below they are deprecated. */
|
||||||
ASSUAN_Bad_Certificate = 201,
|
#define ASSUAN_Bad_Certificate 201
|
||||||
ASSUAN_Bad_Certificate_Chain = 202,
|
#define ASSUAN_Bad_Certificate_Chain 202
|
||||||
ASSUAN_Missing_Certificate = 203,
|
#define ASSUAN_Missing_Certificate 203
|
||||||
ASSUAN_Bad_Signature = 204,
|
#define ASSUAN_Bad_Signature 204
|
||||||
ASSUAN_No_Agent = 205,
|
#define ASSUAN_No_Agent 205
|
||||||
ASSUAN_Agent_Error = 206,
|
#define ASSUAN_Agent_Error 206
|
||||||
ASSUAN_No_Public_Key = 207,
|
#define ASSUAN_No_Public_Key 207
|
||||||
ASSUAN_No_Secret_Key = 208,
|
#define ASSUAN_No_Secret_Key 208
|
||||||
ASSUAN_Invalid_Name = 209,
|
#define ASSUAN_Invalid_Name 209
|
||||||
|
|
||||||
ASSUAN_Cert_Revoked = 301,
|
#define ASSUAN_Cert_Revoked 301
|
||||||
ASSUAN_No_CRL_For_Cert = 302,
|
#define ASSUAN_No_CRL_For_Cert 302
|
||||||
ASSUAN_CRL_Too_Old = 303,
|
#define ASSUAN_CRL_Too_Old 303
|
||||||
ASSUAN_Not_Trusted = 304,
|
#define ASSUAN_Not_Trusted 304
|
||||||
|
|
||||||
ASSUAN_Card_Error = 401,
|
#define ASSUAN_Card_Error 401
|
||||||
ASSUAN_Invalid_Card = 402,
|
#define ASSUAN_Invalid_Card 402
|
||||||
ASSUAN_No_PKCS15_App = 403,
|
#define ASSUAN_No_PKCS15_App 403
|
||||||
ASSUAN_Card_Not_Present = 404,
|
#define ASSUAN_Card_Not_Present 404
|
||||||
ASSUAN_Invalid_Id = 405,
|
#define ASSUAN_Invalid_Id 405
|
||||||
|
|
||||||
/* Error codes in the range 1000 to 9999 may be used by applications
|
/* Error codes in the range 1000 to 9999 may be used by applications
|
||||||
at their own discretion. */
|
at their own discretion. */
|
||||||
ASSUAN_USER_ERROR_FIRST = 1000,
|
#define ASSUAN_USER_ERROR_FIRST 1000
|
||||||
ASSUAN_USER_ERROR_LAST = 9999
|
#define ASSUAN_USER_ERROR_LAST 9999
|
||||||
|
#endif
|
||||||
|
|
||||||
} assuan_error_t;
|
typedef int assuan_error_t;
|
||||||
|
|
||||||
typedef assuan_error_t AssuanError; /* Deprecated. */
|
typedef assuan_error_t AssuanError _ASSUAN_DEPRECATED;
|
||||||
|
|
||||||
/* This is a list of pre-registered ASSUAN commands */
|
/* This is a list of pre-registered ASSUAN commands */
|
||||||
/* NOTE, these command IDs are now deprectated and solely exists for
|
/* Note, these command IDs are now deprectated and solely exists for
|
||||||
compatibility reasons. */
|
compatibility reasons. */
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
@ -290,6 +336,13 @@ typedef enum
|
|||||||
} AssuanCommand;
|
} AssuanCommand;
|
||||||
|
|
||||||
|
|
||||||
|
#else /*!_ASSUAN_ONLY_GPG_ERRORS*/
|
||||||
|
|
||||||
|
typedef int assuan_error_t;
|
||||||
|
|
||||||
|
#endif /*!_ASSUAN_ONLY_GPG_ERRORS*/
|
||||||
|
|
||||||
|
|
||||||
/* Definitions of flags for assuan_set_flag(). */
|
/* Definitions of flags for assuan_set_flag(). */
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
@ -306,7 +359,9 @@ assuan_flag_t;
|
|||||||
|
|
||||||
struct assuan_context_s;
|
struct assuan_context_s;
|
||||||
typedef struct assuan_context_s *assuan_context_t;
|
typedef struct assuan_context_s *assuan_context_t;
|
||||||
typedef struct assuan_context_s *ASSUAN_CONTEXT;
|
#ifndef _ASSUAN_ONLY_GPG_ERRORS
|
||||||
|
typedef struct assuan_context_s *ASSUAN_CONTEXT _ASSUAN_DEPRECATED;
|
||||||
|
#endif /*_ASSUAN_ONLY_GPG_ERRORS*/
|
||||||
|
|
||||||
/*-- assuan-handler.c --*/
|
/*-- assuan-handler.c --*/
|
||||||
int assuan_register_command (assuan_context_t ctx,
|
int assuan_register_command (assuan_context_t ctx,
|
||||||
@ -343,7 +398,7 @@ assuan_error_t assuan_write_status (assuan_context_t ctx,
|
|||||||
file descriptor via CTX and stores it in *RDF (the CTX must be
|
file descriptor via CTX and stores it in *RDF (the CTX must be
|
||||||
capable of passing file descriptors). */
|
capable of passing file descriptors). */
|
||||||
assuan_error_t assuan_command_parse_fd (assuan_context_t ctx, char *line,
|
assuan_error_t assuan_command_parse_fd (assuan_context_t ctx, char *line,
|
||||||
int *rfd);
|
int *rfd);
|
||||||
|
|
||||||
/*-- assuan-listen.c --*/
|
/*-- assuan-listen.c --*/
|
||||||
assuan_error_t assuan_set_hello_line (assuan_context_t ctx, const char *line);
|
assuan_error_t assuan_set_hello_line (assuan_context_t ctx, const char *line);
|
||||||
@ -360,55 +415,54 @@ void assuan_deinit_server (assuan_context_t ctx);
|
|||||||
|
|
||||||
/*-- assuan-socket-server.c --*/
|
/*-- assuan-socket-server.c --*/
|
||||||
int assuan_init_socket_server (assuan_context_t *r_ctx, int listen_fd);
|
int assuan_init_socket_server (assuan_context_t *r_ctx, int listen_fd);
|
||||||
int assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd);
|
int assuan_init_connected_socket_server (assuan_context_t *r_ctx,
|
||||||
|
int fd) _ASSUAN_DEPRECATED;
|
||||||
|
int assuan_init_socket_server_ext (assuan_context_t *r_ctx, int fd,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
/*-- assuan-pipe-connect.c --*/
|
/*-- assuan-pipe-connect.c --*/
|
||||||
assuan_error_t assuan_pipe_connect (assuan_context_t *ctx, const char *name,
|
assuan_error_t assuan_pipe_connect (assuan_context_t *ctx,
|
||||||
|
const char *name,
|
||||||
const char *const argv[],
|
const char *const argv[],
|
||||||
int *fd_child_list);
|
int *fd_child_list);
|
||||||
assuan_error_t assuan_pipe_connect2 (assuan_context_t *ctx, const char *name,
|
assuan_error_t assuan_pipe_connect2 (assuan_context_t *ctx,
|
||||||
|
const char *name,
|
||||||
const char *const argv[],
|
const char *const argv[],
|
||||||
int *fd_child_list,
|
int *fd_child_list,
|
||||||
void (*atfork) (void*, int),
|
void (*atfork) (void*, int),
|
||||||
void *atforkvalue);
|
void *atforkvalue) _ASSUAN_DEPRECATED;
|
||||||
|
assuan_error_t assuan_pipe_connect_ext (assuan_context_t *ctx,
|
||||||
|
const char *name,
|
||||||
|
const char *const argv[],
|
||||||
|
int *fd_child_list,
|
||||||
|
void (*atfork) (void *, int),
|
||||||
|
void *atforkvalue,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
/*-- assuan-socket-connect.c --*/
|
/*-- assuan-socket-connect.c --*/
|
||||||
assuan_error_t assuan_socket_connect (assuan_context_t *ctx, const char *name,
|
assuan_error_t assuan_socket_connect (assuan_context_t *ctx,
|
||||||
|
const char *name,
|
||||||
pid_t server_pid);
|
pid_t server_pid);
|
||||||
|
assuan_error_t assuan_socket_connect_ext (assuan_context_t *ctx,
|
||||||
/*-- assuan-domain-connect.c --*/
|
const char *name,
|
||||||
|
pid_t server_pid,
|
||||||
/* Connect to a Unix domain socket server. RENDEZVOUSFD is
|
unsigned int flags);
|
||||||
bidirectional file descriptor (normally returned via socketpair)
|
|
||||||
which the client can use to rendezvous with the server. SERVER s
|
|
||||||
the server's pid. */
|
|
||||||
assuan_error_t assuan_domain_connect (assuan_context_t *r_ctx,
|
|
||||||
int rendezvousfd,
|
|
||||||
pid_t server);
|
|
||||||
|
|
||||||
/*-- assuan-domain-server.c --*/
|
|
||||||
|
|
||||||
/* RENDEZVOUSFD is a bidirectional file descriptor (normally returned
|
|
||||||
via socketpair) that the domain server can use to rendezvous with
|
|
||||||
the client. CLIENT is the client's pid. */
|
|
||||||
assuan_error_t assuan_init_domain_server (assuan_context_t *r_ctx,
|
|
||||||
int rendezvousfd,
|
|
||||||
pid_t client);
|
|
||||||
|
|
||||||
|
|
||||||
/*-- assuan-connect.c --*/
|
/*-- assuan-connect.c --*/
|
||||||
void assuan_disconnect (assuan_context_t ctx);
|
void assuan_disconnect (assuan_context_t ctx);
|
||||||
pid_t assuan_get_pid (assuan_context_t ctx);
|
pid_t assuan_get_pid (assuan_context_t ctx);
|
||||||
|
assuan_error_t assuan_get_peercred (assuan_context_t ctx,
|
||||||
|
pid_t *pid, uid_t *uid, gid_t *gid);
|
||||||
|
|
||||||
/*-- assuan-client.c --*/
|
/*-- assuan-client.c --*/
|
||||||
assuan_error_t
|
assuan_error_t
|
||||||
assuan_transact (assuan_context_t ctx,
|
assuan_transact (assuan_context_t ctx,
|
||||||
const char *command,
|
const char *command,
|
||||||
assuan_error_t (*data_cb)(void *, const void *, size_t),
|
int (*data_cb)(void *, const void *, size_t),
|
||||||
void *data_cb_arg,
|
void *data_cb_arg,
|
||||||
assuan_error_t (*inquire_cb)(void*, const char *),
|
int (*inquire_cb)(void*, const char *),
|
||||||
void *inquire_cb_arg,
|
void *inquire_cb_arg,
|
||||||
assuan_error_t (*status_cb)(void*, const char *),
|
int (*status_cb)(void*, const char *),
|
||||||
void *status_cb_arg);
|
void *status_cb_arg);
|
||||||
|
|
||||||
|
|
||||||
@ -426,9 +480,8 @@ assuan_error_t assuan_send_data (assuan_context_t ctx,
|
|||||||
const void *buffer, size_t length);
|
const void *buffer, size_t length);
|
||||||
|
|
||||||
/* The file descriptor must be pending before assuan_receivefd is
|
/* The file descriptor must be pending before assuan_receivefd is
|
||||||
call. This means that assuan_sendfd should be called *before* the
|
called. This means that assuan_sendfd should be called *before* the
|
||||||
trigger is sent (normally via assuan_send_data ("I sent you a
|
trigger is sent (normally via assuan_write_line ("INPUT FD")). */
|
||||||
descriptor")). */
|
|
||||||
assuan_error_t assuan_sendfd (assuan_context_t ctx, int fd);
|
assuan_error_t assuan_sendfd (assuan_context_t ctx, int fd);
|
||||||
assuan_error_t assuan_receivefd (assuan_context_t ctx, int *fd);
|
assuan_error_t assuan_receivefd (assuan_context_t ctx, int *fd);
|
||||||
|
|
||||||
@ -453,8 +506,20 @@ void assuan_set_flag (assuan_context_t ctx, assuan_flag_t flag, int value);
|
|||||||
int assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag);
|
int assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag);
|
||||||
|
|
||||||
|
|
||||||
/*-- assuan-errors.c (built) --*/
|
/*-- assuan-errors.c --*/
|
||||||
|
|
||||||
|
#ifndef _ASSUAN_ONLY_GPG_ERRORS
|
||||||
|
/* Return a string describing the assuan error. The use of this
|
||||||
|
function is deprecated; it is better to call
|
||||||
|
assuan_set_assuan_err_source once and then make use libgpg-error. */
|
||||||
const char *assuan_strerror (assuan_error_t err);
|
const char *assuan_strerror (assuan_error_t err);
|
||||||
|
#endif /*_ASSUAN_ONLY_GPG_ERRORS*/
|
||||||
|
|
||||||
|
/* Enable gpg-error style error codes. ERRSOURCE is one of gpg-error
|
||||||
|
sources. Note, that this function is not thread-safe and should be
|
||||||
|
used right at startup. Switching back to the old style mode is not
|
||||||
|
supported. */
|
||||||
|
void assuan_set_assuan_err_source (int errsource);
|
||||||
|
|
||||||
/*-- assuan-logging.c --*/
|
/*-- assuan-logging.c --*/
|
||||||
|
|
||||||
|
@ -1,21 +1,22 @@
|
|||||||
/* funopen.c - Replacement for funopen.
|
/* funopen.c - Replacement for funopen.
|
||||||
* Copyright (C) 2003 Free Software Foundation, Inc.
|
* Copyright (C) 2003, 2005 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of Assuan.
|
||||||
*
|
*
|
||||||
* GnuPG is free software; you can redistribute it and/or modify
|
* Assuan is free software; you can redistribute it and/or modify it
|
||||||
* it under the terms of the GNU General Public License as published by
|
* under the terms of the GNU Lesser General Public License as
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* published by the Free Software Foundation; either version 2.1 of
|
||||||
* (at your option) any later version.
|
* the License, or (at your option) any later version.
|
||||||
*
|
*
|
||||||
* GnuPG is distributed in the hope that it will be useful,
|
* Assuan is distributed in the hope that it will be useful, but
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* GNU General Public License for more details.
|
* Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* along with this program; if not, write to the Free Software
|
* License along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
* USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
@ -54,7 +55,7 @@ _assuan_funopen(void *cookie,
|
|||||||
io.seek = seekfn;
|
io.seek = seekfn;
|
||||||
io.close = closefn;
|
io.close = closefn;
|
||||||
|
|
||||||
return fopencookie (cookie,
|
return fopencookie (cookie,
|
||||||
readfn ? ( writefn ? "rw" : "r" )
|
readfn ? ( writefn ? "rw" : "r" )
|
||||||
: ( writefn ? "w" : ""), io);
|
: ( writefn ? "w" : ""), io);
|
||||||
}
|
}
|
||||||
|
166
assuan/mkerrors
166
assuan/mkerrors
@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# mkerrors - Extract error strings from assuan.h
|
# mkerrors - Extract error strings from assuan.h
|
||||||
# and create C source for assuan_strerror
|
# and create C source for assuan_strerror
|
||||||
# Copyright (C) 2001, 2002 Free Software Foundation, Inc.
|
# Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
|
||||||
#
|
#
|
||||||
# This file is part of Assuan.
|
# This file is part of Assuan.
|
||||||
#
|
#
|
||||||
@ -17,19 +17,118 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Lesser General Public
|
# You should have received a copy of the GNU Lesser General Public
|
||||||
# License along with this program; if not, write to the Free Software
|
# License along with this program; if not, write to the Free Software
|
||||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
/* Generated automatically by mkerrors */
|
/* Generated automatically by mkerrors */
|
||||||
/* Do not edit! */
|
/* Do not edit! See mkerrors for copyright notice. */
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#undef _ASSUAN_IN_LIBASSUAN /* undef to get all error codes. */
|
||||||
#include "assuan.h"
|
#include "assuan.h"
|
||||||
|
|
||||||
|
/* If true the modern gpg-error style error codes are used in the
|
||||||
|
API. */
|
||||||
|
static unsigned int err_source;
|
||||||
|
|
||||||
|
/* Enable gpg-error style error codes. ERRSOURCE is one of gpg-error
|
||||||
|
sources. Note, that this function is not thread-safe and should be
|
||||||
|
used right at startup. Switching back to the old style mode is not
|
||||||
|
supported. */
|
||||||
|
void
|
||||||
|
assuan_set_assuan_err_source (int errsource)
|
||||||
|
{
|
||||||
|
errsource &= 0xff;
|
||||||
|
err_source = errsource? errsource : 31 /*GPG_ERR_SOURCE_ANY*/;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Helper to map old style Assuan error codes to gpg-error codes.
|
||||||
|
This is used internally to keep an compatible ABI. */
|
||||||
|
assuan_error_t
|
||||||
|
_assuan_error (int oldcode)
|
||||||
|
{
|
||||||
|
unsigned int n;
|
||||||
|
|
||||||
|
if (!err_source)
|
||||||
|
return (oldcode & 0x00ffffff); /* Make sure that the gpg-error
|
||||||
|
source part is cleared. */
|
||||||
|
|
||||||
|
switch (oldcode)
|
||||||
|
{
|
||||||
|
case ASSUAN_General_Error: n = 257; break;
|
||||||
|
case ASSUAN_Accept_Failed: n = 258; break;
|
||||||
|
case ASSUAN_Connect_Failed: n = 259; break;
|
||||||
|
case ASSUAN_Invalid_Response: n = 260; break;
|
||||||
|
case ASSUAN_Invalid_Value: n = 261; break;
|
||||||
|
case ASSUAN_Line_Not_Terminated: n = 262; break;
|
||||||
|
case ASSUAN_Line_Too_Long: n = 263; break;
|
||||||
|
case ASSUAN_Nested_Commands: n = 264; break;
|
||||||
|
case ASSUAN_No_Data_Callback: n = 265; break;
|
||||||
|
case ASSUAN_No_Inquire_Callback: n = 266; break;
|
||||||
|
case ASSUAN_Not_A_Server: n = 267; break;
|
||||||
|
case ASSUAN_Not_Implemented: n = 69; break;
|
||||||
|
case ASSUAN_Parameter_Conflict: n = 280; break;
|
||||||
|
case ASSUAN_Problem_Starting_Server: n = 269; break;
|
||||||
|
case ASSUAN_Server_Fault: n = 80; break;
|
||||||
|
case ASSUAN_Syntax_Error: n = 276; break;
|
||||||
|
case ASSUAN_Too_Much_Data: n = 273; break;
|
||||||
|
case ASSUAN_Unexpected_Command: n = 274; break;
|
||||||
|
case ASSUAN_Unknown_Command: n = 275; break;
|
||||||
|
case ASSUAN_Canceled: n = 277; break;
|
||||||
|
case ASSUAN_No_Secret_Key: n = 17; break;
|
||||||
|
|
||||||
|
case ASSUAN_Read_Error:
|
||||||
|
switch (errno)
|
||||||
|
{
|
||||||
|
case 0: n = 16381; /*GPG_ERR_MISSING_ERRNO*/ break;
|
||||||
|
default: n = 270; /*GPG_ERR_ASS_READ_ERROR*/ break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ASSUAN_Write_Error:
|
||||||
|
switch (errno)
|
||||||
|
{
|
||||||
|
case 0: n = 16381; /*GPG_ERR_MISSING_ERRNO*/ break;
|
||||||
|
default: n = 271; /*GPG_ERR_ASS_WRITE_ERROR*/ break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ASSUAN_Out_Of_Core:
|
||||||
|
switch (errno)
|
||||||
|
{
|
||||||
|
case 0: /* Should not happen but a user might have provided
|
||||||
|
an incomplete implemented malloc function. Give
|
||||||
|
him a chance to correct this fault but make sure
|
||||||
|
an error is indeed returned. */
|
||||||
|
n = 16381; /*GPG_ERR_MISSING_ERRNO*/
|
||||||
|
break;
|
||||||
|
case ENOMEM: n = (1 << 15) | 86; break;
|
||||||
|
default:
|
||||||
|
n = 16382; /*GPG_ERR_UNKNOWN_ERRNO*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case -1: n = 16383 /*GPG_ERR_EOF*/; break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
n = 257;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((err_source << 24) | (n & 0x00ffffff));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* assuan_strerror:
|
* assuan_strerror:
|
||||||
* @err: Error code
|
* @err: Error code
|
||||||
@ -41,7 +140,7 @@ cat <<EOF
|
|||||||
* Return value: String with the error description.
|
* Return value: String with the error description.
|
||||||
**/
|
**/
|
||||||
const char *
|
const char *
|
||||||
assuan_strerror (AssuanError err)
|
assuan_strerror (assuan_error_t err)
|
||||||
{
|
{
|
||||||
const char *s;
|
const char *s;
|
||||||
static char buf[50];
|
static char buf[50];
|
||||||
@ -51,10 +150,10 @@ assuan_strerror (AssuanError err)
|
|||||||
EOF
|
EOF
|
||||||
|
|
||||||
awk '
|
awk '
|
||||||
/ASSUAN_No_Error/ { okay=1 }
|
/ASSUAN_No_Error/ { okay=1 }
|
||||||
!okay {next}
|
!okay {next}
|
||||||
/}/ { exit 0 }
|
/^#define[ ]+ASSUAN_[A-Za-z_]*/ { print_code($2) }
|
||||||
/ASSUAN_[A-Za-z_]*/ { print_code($1) }
|
/ASSUAN_USER_ERROR_LAST/ { exit 0 }
|
||||||
|
|
||||||
|
|
||||||
function print_code( s )
|
function print_code( s )
|
||||||
@ -66,18 +165,59 @@ printf "%s\"; break;\n", tolower(substr(s,8));
|
|||||||
'
|
'
|
||||||
|
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
|
case -1: s = "EOF (-1)"; break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unsigned int source, code;
|
unsigned int source, code, n;
|
||||||
|
|
||||||
source = ((err >> 24) & 0xff);
|
source = ((err >> 24) & 0xff);
|
||||||
code = (err & 0x00ffffff);
|
code = (err & 0x00ffffff);
|
||||||
if (source) /* Assume this is an libgpg-error. */
|
if (source)
|
||||||
sprintf (buf, "ec=%u.%u", source, code );
|
{
|
||||||
|
/* Assume this is an libgpg-error and try to map the codes
|
||||||
|
back. */
|
||||||
|
switch (code)
|
||||||
|
{
|
||||||
|
case 257: n = ASSUAN_General_Error ; break;
|
||||||
|
case 258: n = ASSUAN_Accept_Failed ; break;
|
||||||
|
case 259: n = ASSUAN_Connect_Failed ; break;
|
||||||
|
case 260: n = ASSUAN_Invalid_Response ; break;
|
||||||
|
case 261: n = ASSUAN_Invalid_Value ; break;
|
||||||
|
case 262: n = ASSUAN_Line_Not_Terminated ; break;
|
||||||
|
case 263: n = ASSUAN_Line_Too_Long ; break;
|
||||||
|
case 264: n = ASSUAN_Nested_Commands ; break;
|
||||||
|
case 265: n = ASSUAN_No_Data_Callback ; break;
|
||||||
|
case 266: n = ASSUAN_No_Inquire_Callback ; break;
|
||||||
|
case 267: n = ASSUAN_Not_A_Server ; break;
|
||||||
|
case 69: n = ASSUAN_Not_Implemented ; break;
|
||||||
|
case 280: n = ASSUAN_Parameter_Conflict ; break;
|
||||||
|
case 269: n = ASSUAN_Problem_Starting_Server; break;
|
||||||
|
case 270: n = ASSUAN_Read_Error ; break;
|
||||||
|
case 271: n = ASSUAN_Write_Error ; break;
|
||||||
|
case 80: n = ASSUAN_Server_Fault ; break;
|
||||||
|
case 276: n = ASSUAN_Syntax_Error ; break;
|
||||||
|
case 273: n = ASSUAN_Too_Much_Data ; break;
|
||||||
|
case 274: n = ASSUAN_Unexpected_Command ; break;
|
||||||
|
case 275: n = ASSUAN_Unknown_Command ; break;
|
||||||
|
case 277: n = ASSUAN_Canceled ; break;
|
||||||
|
case ((1<<15)|86): n = ASSUAN_Out_Of_Core ; break;
|
||||||
|
default: n = 0; break;
|
||||||
|
}
|
||||||
|
if (n)
|
||||||
|
s = assuan_strerror (n);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf (buf, "ec=%u.%u", source, code );
|
||||||
|
s=buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
sprintf (buf, "ec=%d", err );
|
{
|
||||||
s=buf; break;
|
sprintf (buf, "ec=%d", err );
|
||||||
|
s=buf;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
|
@ -202,8 +202,6 @@ AC_SUBST(NETLIBS)
|
|||||||
# Checks for library functions.
|
# Checks for library functions.
|
||||||
AC_FUNC_FSEEKO
|
AC_FUNC_FSEEKO
|
||||||
|
|
||||||
AC_CHECK_FUNCS(stpcpy)
|
|
||||||
|
|
||||||
AC_REPLACE_FUNCS(vasprintf)
|
AC_REPLACE_FUNCS(vasprintf)
|
||||||
if test "$ac_cv_func_vasprintf" != yes; then
|
if test "$ac_cv_func_vasprintf" != yes; then
|
||||||
GNUPG_CHECK_VA_COPY
|
GNUPG_CHECK_VA_COPY
|
||||||
@ -462,6 +460,10 @@ fi
|
|||||||
AC_REPLACE_FUNCS(isascii)
|
AC_REPLACE_FUNCS(isascii)
|
||||||
AC_REPLACE_FUNCS(putc_unlocked)
|
AC_REPLACE_FUNCS(putc_unlocked)
|
||||||
AC_REPLACE_FUNCS(memrchr)
|
AC_REPLACE_FUNCS(memrchr)
|
||||||
|
AC_REPLACE_FUNCS(stpcpy)
|
||||||
|
# Check for unistd.h for setenv replacement function.
|
||||||
|
AC_CHECK_HEADERS(unistd.h)
|
||||||
|
AC_REPLACE_FUNCS(setenv)
|
||||||
|
|
||||||
# More assuan checks.
|
# More assuan checks.
|
||||||
AC_CHECK_HEADERS([sys/uio.h])
|
AC_CHECK_HEADERS([sys/uio.h])
|
||||||
|
@ -72,7 +72,7 @@ extern "C" {
|
|||||||
AM_PATH_GPGME macro) check that this header matches the installed
|
AM_PATH_GPGME macro) check that this header matches the installed
|
||||||
library. Warning: Do not edit the next line. configure will do
|
library. Warning: Do not edit the next line. configure will do
|
||||||
that for you! */
|
that for you! */
|
||||||
#define GPGME_VERSION "1.1.1-cvs1150"
|
#define GPGME_VERSION "1.1.3-cvs1179"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
352
gpgme/setenv.c
Normal file
352
gpgme/setenv.c
Normal file
@ -0,0 +1,352 @@
|
|||||||
|
/* Copyright (C) 1992,1995-2001,2004 Free Software Foundation, Inc.
|
||||||
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
The GNU C Library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with the GNU C Library; if not, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02110-1301 USA. */
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "assuan-defs.h"
|
||||||
|
|
||||||
|
#define __builtin_expect(cond,val) (cond)
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#if !_LIBC
|
||||||
|
# if !defined errno && !defined HAVE_ERRNO_DECL
|
||||||
|
extern int errno;
|
||||||
|
# endif
|
||||||
|
# define __set_errno(ev) ((errno) = (ev))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if _LIBC || HAVE_STDLIB_H
|
||||||
|
# include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#if _LIBC || HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#endif
|
||||||
|
#if _LIBC || HAVE_UNISTD_H
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !_LIBC
|
||||||
|
# define __environ environ
|
||||||
|
# ifndef HAVE_ENVIRON_DECL
|
||||||
|
extern char **environ;
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if _LIBC
|
||||||
|
/* This lock protects against simultaneous modifications of `environ'. */
|
||||||
|
# include <bits/libc-lock.h>
|
||||||
|
__libc_lock_define_initialized (static, envlock)
|
||||||
|
# define LOCK __libc_lock_lock (envlock)
|
||||||
|
# define UNLOCK __libc_lock_unlock (envlock)
|
||||||
|
#else
|
||||||
|
# define LOCK
|
||||||
|
# define UNLOCK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* In the GNU C library we must keep the namespace clean. */
|
||||||
|
#ifdef _LIBC
|
||||||
|
# define setenv __setenv
|
||||||
|
# define unsetenv __unsetenv
|
||||||
|
# define clearenv __clearenv
|
||||||
|
# define tfind __tfind
|
||||||
|
# define tsearch __tsearch
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* In the GNU C library implementation we try to be more clever and
|
||||||
|
allow arbitrarily many changes of the environment given that the used
|
||||||
|
values are from a small set. Outside glibc this will eat up all
|
||||||
|
memory after a while. */
|
||||||
|
#if defined _LIBC || (defined HAVE_SEARCH_H && defined HAVE_TSEARCH \
|
||||||
|
&& defined __GNUC__)
|
||||||
|
# define USE_TSEARCH 1
|
||||||
|
# include <search.h>
|
||||||
|
|
||||||
|
/* This is a pointer to the root of the search tree with the known
|
||||||
|
values. */
|
||||||
|
static void *known_values;
|
||||||
|
|
||||||
|
# define KNOWN_VALUE(Str) \
|
||||||
|
({ \
|
||||||
|
void *value = tfind (Str, &known_values, (__compar_fn_t) strcmp); \
|
||||||
|
value != NULL ? *(char **) value : NULL; \
|
||||||
|
})
|
||||||
|
# define STORE_VALUE(Str) \
|
||||||
|
tsearch (Str, &known_values, (__compar_fn_t) strcmp)
|
||||||
|
|
||||||
|
#else
|
||||||
|
# undef USE_TSEARCH
|
||||||
|
|
||||||
|
# define KNOWN_VALUE(Str) NULL
|
||||||
|
# define STORE_VALUE(Str) do { } while (0)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* If this variable is not a null pointer we allocated the current
|
||||||
|
environment. */
|
||||||
|
static char **last_environ;
|
||||||
|
|
||||||
|
|
||||||
|
/* This function is used by `setenv' and `putenv'. The difference between
|
||||||
|
the two functions is that for the former must create a new string which
|
||||||
|
is then placed in the environment, while the argument of `putenv'
|
||||||
|
must be used directly. This is all complicated by the fact that we try
|
||||||
|
to reuse values once generated for a `setenv' call since we can never
|
||||||
|
free the strings. */
|
||||||
|
static int
|
||||||
|
__add_to_environ (const char *name, const char *value, const char *combined,
|
||||||
|
int replace)
|
||||||
|
{
|
||||||
|
register char **ep;
|
||||||
|
register size_t size;
|
||||||
|
const size_t namelen = strlen (name);
|
||||||
|
const size_t vallen = value != NULL ? strlen (value) + 1 : 0;
|
||||||
|
|
||||||
|
LOCK;
|
||||||
|
|
||||||
|
/* We have to get the pointer now that we have the lock and not earlier
|
||||||
|
since another thread might have created a new environment. */
|
||||||
|
ep = __environ;
|
||||||
|
|
||||||
|
size = 0;
|
||||||
|
if (ep != NULL)
|
||||||
|
{
|
||||||
|
for (; *ep != NULL; ++ep)
|
||||||
|
if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
++size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ep == NULL || __builtin_expect (*ep == NULL, 1))
|
||||||
|
{
|
||||||
|
char **new_environ;
|
||||||
|
|
||||||
|
/* We allocated this space; we can extend it. */
|
||||||
|
new_environ = (char **) realloc (last_environ,
|
||||||
|
(size + 2) * sizeof (char *));
|
||||||
|
if (new_environ == NULL)
|
||||||
|
{
|
||||||
|
UNLOCK;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the whole entry is given add it. */
|
||||||
|
if (combined != NULL)
|
||||||
|
/* We must not add the string to the search tree since it belongs
|
||||||
|
to the user. */
|
||||||
|
new_environ[size] = (char *) combined;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* See whether the value is already known. */
|
||||||
|
#ifdef USE_TSEARCH
|
||||||
|
# ifdef __GNUC__
|
||||||
|
char new_value[namelen + 1 + vallen];
|
||||||
|
# else
|
||||||
|
char *new_value = (char *) alloca (namelen + 1 + vallen);
|
||||||
|
# endif
|
||||||
|
# ifdef _LIBC
|
||||||
|
__mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
|
||||||
|
value, vallen);
|
||||||
|
# else
|
||||||
|
memcpy (new_value, name, namelen);
|
||||||
|
new_value[namelen] = '=';
|
||||||
|
memcpy (&new_value[namelen + 1], value, vallen);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
new_environ[size] = KNOWN_VALUE (new_value);
|
||||||
|
if (__builtin_expect (new_environ[size] == NULL, 1))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
new_environ[size] = (char *) malloc (namelen + 1 + vallen);
|
||||||
|
if (__builtin_expect (new_environ[size] == NULL, 0))
|
||||||
|
{
|
||||||
|
__set_errno (ENOMEM);
|
||||||
|
UNLOCK;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_TSEARCH
|
||||||
|
memcpy (new_environ[size], new_value, namelen + 1 + vallen);
|
||||||
|
#else
|
||||||
|
memcpy (new_environ[size], name, namelen);
|
||||||
|
new_environ[size][namelen] = '=';
|
||||||
|
memcpy (&new_environ[size][namelen + 1], value, vallen);
|
||||||
|
#endif
|
||||||
|
/* And save the value now. We cannot do this when we remove
|
||||||
|
the string since then we cannot decide whether it is a
|
||||||
|
user string or not. */
|
||||||
|
STORE_VALUE (new_environ[size]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (__environ != last_environ)
|
||||||
|
memcpy ((char *) new_environ, (char *) __environ,
|
||||||
|
size * sizeof (char *));
|
||||||
|
|
||||||
|
new_environ[size + 1] = NULL;
|
||||||
|
|
||||||
|
last_environ = __environ = new_environ;
|
||||||
|
}
|
||||||
|
else if (replace)
|
||||||
|
{
|
||||||
|
char *np;
|
||||||
|
|
||||||
|
/* Use the user string if given. */
|
||||||
|
if (combined != NULL)
|
||||||
|
np = (char *) combined;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef USE_TSEARCH
|
||||||
|
# ifdef __GNUC__
|
||||||
|
char new_value[namelen + 1 + vallen];
|
||||||
|
# else
|
||||||
|
char *new_value = (char *) alloca (namelen + 1 + vallen);
|
||||||
|
# endif
|
||||||
|
# ifdef _LIBC
|
||||||
|
__mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
|
||||||
|
value, vallen);
|
||||||
|
# else
|
||||||
|
memcpy (new_value, name, namelen);
|
||||||
|
new_value[namelen] = '=';
|
||||||
|
memcpy (&new_value[namelen + 1], value, vallen);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
np = KNOWN_VALUE (new_value);
|
||||||
|
if (__builtin_expect (np == NULL, 1))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
np = malloc (namelen + 1 + vallen);
|
||||||
|
if (__builtin_expect (np == NULL, 0))
|
||||||
|
{
|
||||||
|
UNLOCK;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_TSEARCH
|
||||||
|
memcpy (np, new_value, namelen + 1 + vallen);
|
||||||
|
#else
|
||||||
|
memcpy (np, name, namelen);
|
||||||
|
np[namelen] = '=';
|
||||||
|
memcpy (&np[namelen + 1], value, vallen);
|
||||||
|
#endif
|
||||||
|
/* And remember the value. */
|
||||||
|
STORE_VALUE (np);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*ep = np;
|
||||||
|
}
|
||||||
|
|
||||||
|
UNLOCK;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
setenv (const char *name, const char *value, int replace)
|
||||||
|
{
|
||||||
|
if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return __add_to_environ (name, value, NULL, replace);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
unsetenv (const char *name)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
char **ep;
|
||||||
|
|
||||||
|
if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = strlen (name);
|
||||||
|
|
||||||
|
LOCK;
|
||||||
|
|
||||||
|
ep = __environ;
|
||||||
|
while (*ep != NULL)
|
||||||
|
if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
|
||||||
|
{
|
||||||
|
/* Found it. Remove this pointer by moving later ones back. */
|
||||||
|
char **dp = ep;
|
||||||
|
|
||||||
|
do
|
||||||
|
dp[0] = dp[1];
|
||||||
|
while (*dp++);
|
||||||
|
/* Continue the loop in case NAME appears again. */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++ep;
|
||||||
|
|
||||||
|
UNLOCK;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The `clearenv' was planned to be added to POSIX.1 but probably
|
||||||
|
never made it. Nevertheless the POSIX.9 standard (POSIX bindings
|
||||||
|
for Fortran 77) requires this function. */
|
||||||
|
int
|
||||||
|
clearenv (void)
|
||||||
|
{
|
||||||
|
LOCK;
|
||||||
|
|
||||||
|
if (__environ == last_environ && __environ != NULL)
|
||||||
|
{
|
||||||
|
/* We allocated this environment so we can free it. */
|
||||||
|
free (__environ);
|
||||||
|
last_environ = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear the environment pointer removes the whole environment. */
|
||||||
|
__environ = NULL;
|
||||||
|
|
||||||
|
UNLOCK;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#ifdef _LIBC
|
||||||
|
libc_freeres_fn (free_mem)
|
||||||
|
{
|
||||||
|
/* Remove all traces. */
|
||||||
|
clearenv ();
|
||||||
|
|
||||||
|
/* Now remove the search tree. */
|
||||||
|
__tdestroy (known_values, free);
|
||||||
|
known_values = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
# undef setenv
|
||||||
|
# undef unsetenv
|
||||||
|
# undef clearenv
|
||||||
|
weak_alias (__setenv, setenv)
|
||||||
|
weak_alias (__unsetenv, unsetenv)
|
||||||
|
weak_alias (__clearenv, clearenv)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user