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>
|
||||
|
||||
* 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>
|
||||
|
||||
* 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
|
||||
# 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
|
||||
|
||||
@ -44,12 +44,11 @@ libassuan_la_SOURCES = \
|
||||
assuan-socket-server.c \
|
||||
assuan-pipe-connect.c \
|
||||
assuan-socket-connect.c \
|
||||
assuan-socket.c \
|
||||
assuan-uds.c \
|
||||
funopen.c \
|
||||
assuan-io.c \
|
||||
assuan-domain-connect.c \
|
||||
assuan-domain-server.c \
|
||||
assuan-logging.c
|
||||
assuan-logging.c \
|
||||
assuan-socket.c
|
||||
|
||||
assuan-errors.c : assuan.h
|
||||
assuan-errors.c : assuan.h mkerrors
|
||||
$(srcdir)/mkerrors < $(srcdir)/assuan.h > assuan-errors.c
|
||||
|
@ -15,7 +15,8 @@
|
||||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@ -30,8 +31,11 @@
|
||||
#endif
|
||||
#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
|
||||
writen (ASSUAN_CONTEXT ctx, const char *buffer, size_t length)
|
||||
writen (assuan_context_t ctx, const char *buffer, size_t length)
|
||||
{
|
||||
while (length)
|
||||
{
|
||||
@ -49,9 +53,11 @@ writen (ASSUAN_CONTEXT ctx, const char *buffer, size_t length)
|
||||
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
|
||||
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)
|
||||
{
|
||||
size_t nleft = buflen;
|
||||
@ -88,8 +94,9 @@ readline (ASSUAN_CONTEXT ctx, char *buf, size_t buflen,
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_assuan_read_line (ASSUAN_CONTEXT ctx)
|
||||
/* Function returns an Assuan error. */
|
||||
assuan_error_t
|
||||
_assuan_read_line (assuan_context_t ctx)
|
||||
{
|
||||
char *line = ctx->inbound.line;
|
||||
int nread, atticlen;
|
||||
@ -97,7 +104,7 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
|
||||
char *endp = 0;
|
||||
|
||||
if (ctx->inbound.eof)
|
||||
return -1;
|
||||
return _assuan_error (-1);
|
||||
|
||||
atticlen = ctx->inbound.attic.linelen;
|
||||
if (atticlen)
|
||||
@ -128,19 +135,20 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
|
||||
if (rc)
|
||||
{
|
||||
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 (),
|
||||
(unsigned int)getpid (), ctx, strerror (errno));
|
||||
return ASSUAN_Read_Error;
|
||||
(unsigned int)getpid (), ctx->inbound.fd,
|
||||
strerror (errno));
|
||||
return _assuan_error (ASSUAN_Read_Error);
|
||||
}
|
||||
if (!nread)
|
||||
{
|
||||
assert (ctx->inbound.eof);
|
||||
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 (),
|
||||
(unsigned int)getpid (), ctx);
|
||||
return -1;
|
||||
(unsigned int)getpid (), ctx->inbound.fd);
|
||||
return _assuan_error (-1);
|
||||
}
|
||||
|
||||
ctx->inbound.attic.pending = 0;
|
||||
@ -170,9 +178,9 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
|
||||
ctx->inbound.linelen = endp - line;
|
||||
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 (),
|
||||
(unsigned int)getpid (), ctx);
|
||||
(unsigned int)getpid (), ctx->inbound.fd);
|
||||
if (ctx->confidential)
|
||||
fputs ("[Confidential data not shown]", ctx->log_fp);
|
||||
else
|
||||
@ -186,13 +194,14 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
|
||||
else
|
||||
{
|
||||
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 (),
|
||||
(unsigned int)getpid (), ctx);
|
||||
(unsigned int)getpid (), ctx->inbound.fd);
|
||||
*line = 0;
|
||||
ctx->inbound.linelen = 0;
|
||||
return ctx->inbound.eof ? ASSUAN_Line_Not_Terminated
|
||||
: ASSUAN_Line_Too_Long;
|
||||
return _assuan_error (ctx->inbound.eof
|
||||
? ASSUAN_Line_Not_Terminated
|
||||
: ASSUAN_Line_Too_Long);
|
||||
}
|
||||
}
|
||||
|
||||
@ -207,12 +216,12 @@ _assuan_read_line (ASSUAN_CONTEXT ctx)
|
||||
See also: assuan_pending_line().
|
||||
*/
|
||||
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;
|
||||
|
||||
if (!ctx)
|
||||
return ASSUAN_Invalid_Value;
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
|
||||
err = _assuan_read_line (ctx);
|
||||
*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
|
||||
read without any I/O). */
|
||||
int
|
||||
assuan_pending_line (ASSUAN_CONTEXT ctx)
|
||||
assuan_pending_line (assuan_context_t ctx)
|
||||
{
|
||||
return ctx && ctx->inbound.attic.pending;
|
||||
}
|
||||
@ -234,17 +243,17 @@ assuan_error_t
|
||||
_assuan_write_line (assuan_context_t ctx, const char *prefix,
|
||||
const char *line, size_t len)
|
||||
{
|
||||
int rc = 0;
|
||||
assuan_error_t rc = 0;
|
||||
size_t prefixlen = prefix? strlen (prefix):0;
|
||||
|
||||
/* Make sure that the line is short enough. */
|
||||
if (len + prefixlen + 2 > ASSUAN_LINELENGTH)
|
||||
{
|
||||
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",
|
||||
assuan_get_assuan_log_prefix (),
|
||||
(unsigned int)getpid (), ctx);
|
||||
(unsigned int)getpid (), ctx->inbound.fd);
|
||||
if (prefixlen > 5)
|
||||
prefixlen = 5;
|
||||
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. */
|
||||
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 (),
|
||||
(unsigned int)getpid (), ctx);
|
||||
(unsigned int)getpid (), ctx->inbound.fd);
|
||||
if (ctx->confidential)
|
||||
fputs ("[Confidential data not shown]", ctx->log_fp);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -268,18 +281,18 @@ _assuan_write_line (assuan_context_t ctx, const char *prefix,
|
||||
{
|
||||
rc = writen (ctx, prefix, prefixlen);
|
||||
if (rc)
|
||||
rc = ASSUAN_Write_Error;
|
||||
rc = _assuan_error (ASSUAN_Write_Error);
|
||||
}
|
||||
if (!rc)
|
||||
{
|
||||
rc = writen (ctx, line, len);
|
||||
if (rc)
|
||||
rc = ASSUAN_Write_Error;
|
||||
rc = _assuan_error (ASSUAN_Write_Error);
|
||||
if (!rc)
|
||||
{
|
||||
rc = writen (ctx, "\n", 1);
|
||||
if (rc)
|
||||
rc = ASSUAN_Write_Error;
|
||||
rc = _assuan_error (ASSUAN_Write_Error);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
@ -287,13 +300,13 @@ _assuan_write_line (assuan_context_t ctx, const char *prefix,
|
||||
|
||||
|
||||
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;
|
||||
const char *s;
|
||||
|
||||
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
|
||||
violate the protocol. */
|
||||
@ -301,10 +314,10 @@ assuan_write_line (ASSUAN_CONTEXT ctx, const char *line)
|
||||
len = s? (s-line) : strlen (line);
|
||||
|
||||
if (ctx->log_fp && s)
|
||||
fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> "
|
||||
"[supplied line contained a LF -truncated]\n",
|
||||
fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> "
|
||||
"[supplied line contained a LF - truncated]\n",
|
||||
assuan_get_assuan_log_prefix (),
|
||||
(unsigned int)getpid (), ctx);
|
||||
(unsigned int)getpid (), ctx->inbound.fd);
|
||||
|
||||
return _assuan_write_line (ctx, NULL, line, len);
|
||||
}
|
||||
@ -316,7 +329,7 @@ assuan_write_line (ASSUAN_CONTEXT ctx, const char *line)
|
||||
int
|
||||
_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;
|
||||
char *line;
|
||||
size_t linelen;
|
||||
@ -359,9 +372,9 @@ _assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size)
|
||||
{
|
||||
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 (),
|
||||
(unsigned int)getpid (), ctx);
|
||||
(unsigned int)getpid (), ctx->inbound.fd);
|
||||
|
||||
if (ctx->confidential)
|
||||
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++;
|
||||
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;
|
||||
}
|
||||
line = ctx->outbound.data.line;
|
||||
@ -393,7 +406,7 @@ _assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size)
|
||||
int
|
||||
_assuan_cookie_write_flush (void *cookie)
|
||||
{
|
||||
ASSUAN_CONTEXT ctx = cookie;
|
||||
assuan_context_t ctx = cookie;
|
||||
char *line;
|
||||
size_t linelen;
|
||||
|
||||
@ -407,9 +420,9 @@ _assuan_cookie_write_flush (void *cookie)
|
||||
{
|
||||
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 (),
|
||||
(unsigned int)getpid (), ctx);
|
||||
(unsigned int)getpid (), ctx->inbound.fd);
|
||||
if (ctx->confidential)
|
||||
fputs ("[Confidential data not shown]", ctx->log_fp);
|
||||
else
|
||||
@ -421,7 +434,7 @@ _assuan_cookie_write_flush (void *cookie)
|
||||
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;
|
||||
}
|
||||
ctx->outbound.data.linelen = 0;
|
||||
@ -449,12 +462,12 @@ _assuan_cookie_write_flush (void *cookie)
|
||||
**/
|
||||
|
||||
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)
|
||||
return ASSUAN_Invalid_Value;
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
if (!buffer && length)
|
||||
return ASSUAN_Invalid_Value;
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
|
||||
if (!buffer)
|
||||
{ /* flush what we have */
|
||||
@ -475,7 +488,7 @@ assuan_send_data (ASSUAN_CONTEXT ctx, const void *buffer, size_t length)
|
||||
}
|
||||
|
||||
assuan_error_t
|
||||
assuan_sendfd (ASSUAN_CONTEXT ctx, int fd)
|
||||
assuan_sendfd (assuan_context_t ctx, int fd)
|
||||
{
|
||||
if (! ctx->io->sendfd)
|
||||
return set_error (ctx, Not_Implemented,
|
||||
@ -485,7 +498,7 @@ assuan_sendfd (ASSUAN_CONTEXT ctx, int fd)
|
||||
}
|
||||
|
||||
assuan_error_t
|
||||
assuan_receivefd (ASSUAN_CONTEXT ctx, int *fd)
|
||||
assuan_receivefd (assuan_context_t ctx, int *fd)
|
||||
{
|
||||
if (! ctx->io->receivefd)
|
||||
return set_error (ctx, Not_Implemented,
|
||||
|
@ -15,7 +15,8 @@
|
||||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@ -33,7 +34,7 @@
|
||||
|
||||
|
||||
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;
|
||||
int linelen;
|
||||
@ -103,7 +104,7 @@ _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off)
|
||||
*off = 3;
|
||||
}
|
||||
else
|
||||
rc = ASSUAN_Invalid_Response;
|
||||
rc = _assuan_error (ASSUAN_Invalid_Response);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -112,7 +113,7 @@ _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off)
|
||||
/**
|
||||
* assuan_transact:
|
||||
* @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_arg: first argument passed to @data_cb
|
||||
* @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
|
||||
* 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_transact (ASSUAN_CONTEXT ctx,
|
||||
assuan_transact (assuan_context_t ctx,
|
||||
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,
|
||||
assuan_error_t (*inquire_cb)(void*, const char *),
|
||||
int (*inquire_cb)(void*, const char *),
|
||||
void *inquire_cb_arg,
|
||||
assuan_error_t (*status_cb)(void*, const char *),
|
||||
int (*status_cb)(void*, const char *),
|
||||
void *status_cb_arg)
|
||||
{
|
||||
int rc, okay, off;
|
||||
assuan_error_t rc;
|
||||
int okay, off;
|
||||
char *line;
|
||||
int linelen;
|
||||
|
||||
@ -157,14 +161,14 @@ assuan_transact (ASSUAN_CONTEXT ctx,
|
||||
|
||||
if (!okay)
|
||||
{
|
||||
rc = atoi (line);
|
||||
rc = _assuan_error (atoi (line));
|
||||
if (rc < 100)
|
||||
rc = ASSUAN_Server_Fault;
|
||||
}
|
||||
else if (okay == 2)
|
||||
{
|
||||
if (!data_cb)
|
||||
rc = ASSUAN_No_Data_Callback;
|
||||
rc = _assuan_error (ASSUAN_No_Data_Callback);
|
||||
else
|
||||
{
|
||||
char *s, *d;
|
||||
@ -193,7 +197,7 @@ assuan_transact (ASSUAN_CONTEXT ctx,
|
||||
{
|
||||
assuan_write_line (ctx, "END"); /* get out of inquire mode */
|
||||
_assuan_read_from_server (ctx, &okay, &off); /* dummy read */
|
||||
rc = ASSUAN_No_Inquire_Callback;
|
||||
rc = _assuan_error (ASSUAN_No_Inquire_Callback);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -214,7 +218,7 @@ assuan_transact (ASSUAN_CONTEXT ctx,
|
||||
else if (okay == 5)
|
||||
{
|
||||
if (!data_cb)
|
||||
rc = ASSUAN_No_Data_Callback;
|
||||
rc = _assuan_error (ASSUAN_No_Data_Callback);
|
||||
else
|
||||
{
|
||||
rc = data_cb (data_cb_arg, NULL, 0);
|
||||
|
@ -15,7 +15,8 @@
|
||||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#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
|
||||
assuan_get_pid (assuan_context_t ctx)
|
||||
{
|
||||
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
|
||||
* 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.
|
||||
*
|
||||
@ -15,7 +15,8 @@
|
||||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifndef ASSUAN_DEFS_H
|
||||
@ -62,24 +63,30 @@ char * stpcpy (char *dest, const char *src);
|
||||
|
||||
#define LINELENGTH ASSUAN_LINELENGTH
|
||||
|
||||
|
||||
struct cmdtbl_s
|
||||
{
|
||||
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
|
||||
{
|
||||
/* 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. */
|
||||
ssize_t (*writefnc) (ASSUAN_CONTEXT, const void *, size_t);
|
||||
ssize_t (*writefnc) (assuan_context_t, const void *, size_t);
|
||||
/* Send a file descriptor. */
|
||||
assuan_error_t (*sendfd) (ASSUAN_CONTEXT, int);
|
||||
assuan_error_t (*sendfd) (assuan_context_t, int);
|
||||
/* 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
|
||||
{
|
||||
assuan_error_t err_no;
|
||||
@ -88,18 +95,18 @@ struct assuan_context_s
|
||||
error codes. */
|
||||
|
||||
/* Context specific flags (cf. assuan_flag_t). */
|
||||
struct
|
||||
struct
|
||||
{
|
||||
unsigned int no_waitpid:1; /* See ASSUAN_NO_WAITPID. */
|
||||
} flags;
|
||||
} flags;
|
||||
|
||||
int confidential;
|
||||
int is_server; /* Set if this is context belongs to a server */
|
||||
int in_inquire;
|
||||
char *hello_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;
|
||||
|
||||
@ -109,7 +116,7 @@ struct assuan_context_s
|
||||
char line[LINELENGTH];
|
||||
int linelen; /* w/o CR, LF - might not be the same as
|
||||
strlen(line) due to embedded nuls. However a nul
|
||||
is always written at this pos */
|
||||
is always written at this pos. */
|
||||
struct {
|
||||
char line[LINELENGTH];
|
||||
int linelen ;
|
||||
@ -122,49 +129,55 @@ struct assuan_context_s
|
||||
struct {
|
||||
FILE *fp;
|
||||
char line[LINELENGTH];
|
||||
int linelen;
|
||||
int linelen;
|
||||
int error;
|
||||
} data;
|
||||
} data;
|
||||
} outbound;
|
||||
|
||||
int pipe_mode; /* We are in pipe mode, i.e. we can handle just one
|
||||
connection and must terminate then */
|
||||
pid_t pid; /* The the pid of the peer. */
|
||||
connection and must terminate then. */
|
||||
pid_t pid; /* The pid of the peer. */
|
||||
int listen_fd; /* The fd we are listening on (used by socket servers) */
|
||||
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. */
|
||||
struct sockaddr_un myaddr;
|
||||
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;
|
||||
int pendingfdscount;
|
||||
/* Structure used for unix domain socket buffering. FIXME: We don't
|
||||
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. */
|
||||
|
||||
int pendingfds[5]; /* Array to save received descriptors. */
|
||||
int pendingfdscount; /* Number of received descriptors. */
|
||||
} uds;
|
||||
|
||||
void (*deinit_handler)(ASSUAN_CONTEXT);
|
||||
int (*accept_handler)(ASSUAN_CONTEXT);
|
||||
int (*finish_handler)(ASSUAN_CONTEXT);
|
||||
void (*deinit_handler)(assuan_context_t);
|
||||
int (*accept_handler)(assuan_context_t);
|
||||
int (*finish_handler)(assuan_context_t);
|
||||
|
||||
struct cmdtbl_s *cmdtbl;
|
||||
size_t cmdtbl_used; /* used entries */
|
||||
size_t cmdtbl_size; /* allocated size of table */
|
||||
|
||||
void (*bye_notify_fnc)(ASSUAN_CONTEXT);
|
||||
void (*reset_notify_fnc)(ASSUAN_CONTEXT);
|
||||
void (*cancel_notify_fnc)(ASSUAN_CONTEXT);
|
||||
int (*option_handler_fnc)(ASSUAN_CONTEXT,const char*, const char*);
|
||||
void (*input_notify_fnc)(ASSUAN_CONTEXT, const char *);
|
||||
void (*output_notify_fnc)(ASSUAN_CONTEXT, const char *);
|
||||
void (*bye_notify_fnc)(assuan_context_t);
|
||||
void (*reset_notify_fnc)(assuan_context_t);
|
||||
void (*cancel_notify_fnc)(assuan_context_t);
|
||||
int (*option_handler_fnc)(assuan_context_t,const char*, const char*);
|
||||
void (*input_notify_fnc)(assuan_context_t, const char *);
|
||||
void (*output_notify_fnc)(assuan_context_t, const char *);
|
||||
|
||||
int input_fd; /* set by INPUT command */
|
||||
int output_fd; /* set by OUTPUT command */
|
||||
@ -174,29 +187,45 @@ struct assuan_context_s
|
||||
};
|
||||
|
||||
/*-- assuan-pipe-server.c --*/
|
||||
int _assuan_new_context (ASSUAN_CONTEXT *r_ctx);
|
||||
void _assuan_release_context (ASSUAN_CONTEXT ctx);
|
||||
int _assuan_new_context (assuan_context_t *r_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 --*/
|
||||
int _assuan_register_std_commands (ASSUAN_CONTEXT ctx);
|
||||
int _assuan_register_std_commands (assuan_context_t ctx);
|
||||
|
||||
/*-- 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_flush (void *cookie);
|
||||
assuan_error_t _assuan_write_line (assuan_context_t ctx, const char *prefix,
|
||||
const char *line, size_t len);
|
||||
|
||||
/*-- 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 --*/
|
||||
@ -210,10 +239,8 @@ void _assuan_free (void *p);
|
||||
#define xtryrealloc(a,b) _assuan_realloc((a),(b))
|
||||
#define xfree(a) _assuan_free ((a))
|
||||
|
||||
#define set_error(c,e,t) assuan_set_error ((c), ASSUAN_ ## e, (t))
|
||||
|
||||
void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length);
|
||||
void _assuan_log_sanitized_string (const char *string);
|
||||
#define set_error(c,e,t) \
|
||||
assuan_set_error ((c), _assuan_error (ASSUAN_ ## e), (t))
|
||||
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
const char *_assuan_w32_strerror (int ec);
|
||||
@ -229,11 +256,18 @@ void _assuan_log_printf (const char *format, ...)
|
||||
__attribute__ ((format (printf,1,2)))
|
||||
#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 --*/
|
||||
ssize_t _assuan_simple_read (ASSUAN_CONTEXT ctx, void *buffer, size_t size);
|
||||
ssize_t _assuan_simple_write (ASSUAN_CONTEXT ctx, const void *buffer,
|
||||
pid_t _assuan_waitpid (pid_t pid, int *status, int options);
|
||||
|
||||
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);
|
||||
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 --*/
|
||||
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))
|
||||
#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
|
||||
* 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>
|
||||
@ -36,20 +37,20 @@ static int my_strcasecmp (const char *a, const char *b);
|
||||
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
std_handler_nop (ASSUAN_CONTEXT ctx, char *line)
|
||||
std_handler_nop (assuan_context_t ctx, char *line)
|
||||
{
|
||||
return 0; /* okay */
|
||||
}
|
||||
|
||||
static int
|
||||
std_handler_cancel (ASSUAN_CONTEXT ctx, char *line)
|
||||
std_handler_cancel (assuan_context_t ctx, char *line)
|
||||
{
|
||||
if (ctx->cancel_notify_fnc)
|
||||
ctx->cancel_notify_fnc (ctx);
|
||||
@ -57,7 +58,7 @@ std_handler_cancel (ASSUAN_CONTEXT ctx, char *line)
|
||||
}
|
||||
|
||||
static int
|
||||
std_handler_option (ASSUAN_CONTEXT ctx, char *line)
|
||||
std_handler_option (assuan_context_t ctx, char *line)
|
||||
{
|
||||
char *key, *value, *p;
|
||||
|
||||
@ -104,7 +105,7 @@ std_handler_option (ASSUAN_CONTEXT ctx, char *line)
|
||||
}
|
||||
|
||||
static int
|
||||
std_handler_bye (ASSUAN_CONTEXT ctx, char *line)
|
||||
std_handler_bye (assuan_context_t ctx, char *line)
|
||||
{
|
||||
if (ctx->bye_notify_fnc)
|
||||
ctx->bye_notify_fnc (ctx);
|
||||
@ -114,33 +115,35 @@ std_handler_bye (ASSUAN_CONTEXT ctx, char *line)
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static int
|
||||
std_handler_reset (ASSUAN_CONTEXT ctx, char *line)
|
||||
std_handler_reset (assuan_context_t ctx, char *line)
|
||||
{
|
||||
if (ctx->reset_notify_fnc)
|
||||
ctx->reset_notify_fnc (ctx);
|
||||
assuan_close_input_fd (ctx);
|
||||
assuan_close_output_fd (ctx);
|
||||
_assuan_uds_close_fds (ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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");
|
||||
line += 2;
|
||||
if (*line == '=')
|
||||
@ -149,7 +152,7 @@ assuan_command_parse_fd (ASSUAN_CONTEXT ctx, char *line, int *rfd)
|
||||
if (!digitp (*line))
|
||||
return set_error (ctx, Syntax_Error, "number required");
|
||||
*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));
|
||||
|
||||
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> */
|
||||
static int
|
||||
std_handler_input (ASSUAN_CONTEXT ctx, char *line)
|
||||
std_handler_input (assuan_context_t ctx, char *line)
|
||||
{
|
||||
int rc, fd;
|
||||
|
||||
@ -180,7 +183,7 @@ std_handler_input (ASSUAN_CONTEXT ctx, char *line)
|
||||
|
||||
/* Format is OUTPUT FD=<n> */
|
||||
static int
|
||||
std_handler_output (ASSUAN_CONTEXT ctx, char *line)
|
||||
std_handler_output (assuan_context_t ctx, char *line)
|
||||
{
|
||||
int rc, fd;
|
||||
|
||||
@ -202,7 +205,7 @@ std_handler_output (ASSUAN_CONTEXT ctx, char *line)
|
||||
with default handlers */
|
||||
static struct {
|
||||
const char *name;
|
||||
int (*handler)(ASSUAN_CONTEXT, char *line);
|
||||
int (*handler)(assuan_context_t, char *line);
|
||||
int always; /* always initialize this command */
|
||||
} std_cmd_table[] = {
|
||||
{ "NOP", std_handler_nop, 1 },
|
||||
@ -234,9 +237,9 @@ static struct {
|
||||
* Return value: 0 on success or an error code
|
||||
**/
|
||||
int
|
||||
assuan_register_command (ASSUAN_CONTEXT ctx,
|
||||
assuan_register_command (assuan_context_t ctx,
|
||||
const char *cmd_name,
|
||||
int (*handler)(ASSUAN_CONTEXT, char *))
|
||||
int (*handler)(assuan_context_t, char *))
|
||||
{
|
||||
int i;
|
||||
const char *s;
|
||||
@ -245,7 +248,7 @@ assuan_register_command (ASSUAN_CONTEXT ctx,
|
||||
cmd_name = NULL;
|
||||
|
||||
if (!cmd_name)
|
||||
return ASSUAN_Invalid_Value;
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
|
||||
if (!handler)
|
||||
{ /* find a default handler. */
|
||||
@ -268,7 +271,7 @@ assuan_register_command (ASSUAN_CONTEXT ctx,
|
||||
ctx->cmdtbl_size = 50;
|
||||
ctx->cmdtbl = xtrycalloc ( ctx->cmdtbl_size, sizeof *ctx->cmdtbl);
|
||||
if (!ctx->cmdtbl)
|
||||
return ASSUAN_Out_Of_Core;
|
||||
return _assuan_error (ASSUAN_Out_Of_Core);
|
||||
ctx->cmdtbl_used = 0;
|
||||
}
|
||||
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);
|
||||
if (!x)
|
||||
return ASSUAN_Out_Of_Core;
|
||||
return _assuan_error (ASSUAN_Out_Of_Core);
|
||||
ctx->cmdtbl = x;
|
||||
ctx->cmdtbl_size += 50;
|
||||
}
|
||||
@ -289,59 +292,62 @@ assuan_register_command (ASSUAN_CONTEXT ctx,
|
||||
}
|
||||
|
||||
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)
|
||||
return ASSUAN_Invalid_Value;
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
ctx->bye_notify_fnc = fnc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
return ASSUAN_Invalid_Value;
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
ctx->reset_notify_fnc = fnc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
return ASSUAN_Invalid_Value;
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
ctx->cancel_notify_fnc = fnc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
assuan_register_option_handler (ASSUAN_CONTEXT ctx,
|
||||
int (*fnc)(ASSUAN_CONTEXT,
|
||||
assuan_register_option_handler (assuan_context_t ctx,
|
||||
int (*fnc)(assuan_context_t,
|
||||
const char*, const char*))
|
||||
{
|
||||
if (!ctx)
|
||||
return ASSUAN_Invalid_Value;
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
ctx->option_handler_fnc = fnc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
assuan_register_input_notify (ASSUAN_CONTEXT ctx,
|
||||
void (*fnc)(ASSUAN_CONTEXT, const char *))
|
||||
assuan_register_input_notify (assuan_context_t ctx,
|
||||
void (*fnc)(assuan_context_t, const char *))
|
||||
{
|
||||
if (!ctx)
|
||||
return ASSUAN_Invalid_Value;
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
ctx->input_notify_fnc = fnc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
assuan_register_output_notify (ASSUAN_CONTEXT ctx,
|
||||
void (*fnc)(ASSUAN_CONTEXT, const char *))
|
||||
assuan_register_output_notify (assuan_context_t ctx,
|
||||
void (*fnc)(assuan_context_t, const char *))
|
||||
{
|
||||
if (!ctx)
|
||||
return ASSUAN_Invalid_Value;
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
ctx->output_notify_fnc = fnc;
|
||||
return 0;
|
||||
}
|
||||
@ -349,7 +355,7 @@ assuan_register_output_notify (ASSUAN_CONTEXT ctx,
|
||||
|
||||
/* Helper to register the standards commands */
|
||||
int
|
||||
_assuan_register_std_commands (ASSUAN_CONTEXT ctx)
|
||||
_assuan_register_std_commands (assuan_context_t ctx)
|
||||
{
|
||||
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
|
||||
from the line. As all handlers this function may modify the line. */
|
||||
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);
|
||||
}
|
||||
@ -394,7 +400,7 @@ my_strcasecmp (const char *a, const char *b)
|
||||
table, remove leading and white spaces from the arguments, call the
|
||||
handler with the argument line and return the error */
|
||||
static int
|
||||
dispatch_command (ASSUAN_CONTEXT ctx, char *line, int linelen)
|
||||
dispatch_command (assuan_context_t ctx, char *line, int linelen)
|
||||
{
|
||||
char *p;
|
||||
const char *s;
|
||||
@ -406,7 +412,7 @@ dispatch_command (ASSUAN_CONTEXT ctx, char *line, int linelen)
|
||||
for (p=line; *p && *p != ' ' && *p != '\t'; p++)
|
||||
;
|
||||
if (p==line)
|
||||
return set_error (ctx, Invalid_Command, "leading white-space");
|
||||
return set_error (ctx, Syntax_Error, "leading white-space");
|
||||
if (*p)
|
||||
{ /* Skip over leading WS after the keyword */
|
||||
*p++ = 0;
|
||||
@ -441,12 +447,12 @@ dispatch_command (ASSUAN_CONTEXT ctx, char *line, int linelen)
|
||||
|
||||
|
||||
static int
|
||||
process_request (ASSUAN_CONTEXT ctx)
|
||||
process_request (assuan_context_t ctx)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (ctx->in_inquire)
|
||||
return ASSUAN_Nested_Commands;
|
||||
return _assuan_error (ASSUAN_Nested_Commands);
|
||||
|
||||
rc = _assuan_read_line (ctx);
|
||||
if (rc)
|
||||
@ -477,8 +483,8 @@ process_request (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
rc = assuan_write_line (ctx, ctx->okay_line? ctx->okay_line : "OK");
|
||||
}
|
||||
else if (rc == -1)
|
||||
{ /* No error checking because the peer may have already disconnect */
|
||||
else if (err_is_eof (rc))
|
||||
{ /* No error checking because the peer may have already disconnect. */
|
||||
assuan_write_line (ctx, "OK closing connection");
|
||||
ctx->finish_handler (ctx);
|
||||
}
|
||||
@ -488,7 +494,7 @@ process_request (ASSUAN_CONTEXT ctx)
|
||||
|
||||
if (rc < 100)
|
||||
sprintf (errline, "ERR %d server fault (%.50s)",
|
||||
ASSUAN_Server_Fault, assuan_strerror (rc));
|
||||
_assuan_error (ASSUAN_Server_Fault), assuan_strerror (rc));
|
||||
else
|
||||
{
|
||||
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.
|
||||
They are used for debugging purposes only, so there is no
|
||||
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
|
||||
used. */
|
||||
unsigned int source, code;
|
||||
@ -552,7 +558,7 @@ process_request (ASSUAN_CONTEXT ctx)
|
||||
* failed. Note, that no error is returned for operational errors.
|
||||
**/
|
||||
int
|
||||
assuan_process (ASSUAN_CONTEXT ctx)
|
||||
assuan_process (assuan_context_t ctx)
|
||||
{
|
||||
int rc;
|
||||
|
||||
@ -560,7 +566,7 @@ assuan_process (ASSUAN_CONTEXT ctx)
|
||||
rc = process_request (ctx);
|
||||
} while (!rc);
|
||||
|
||||
if (rc == -1)
|
||||
if (err_is_eof (rc))
|
||||
rc = 0;
|
||||
|
||||
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
|
||||
**/
|
||||
int
|
||||
assuan_process_next (ASSUAN_CONTEXT ctx)
|
||||
assuan_process_next (assuan_context_t ctx)
|
||||
{
|
||||
return process_request (ctx);
|
||||
}
|
||||
@ -603,7 +609,7 @@ assuan_process_next (ASSUAN_CONTEXT ctx)
|
||||
* error which is most likely a too small fdarray.
|
||||
**/
|
||||
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 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
|
||||
could use a child process */
|
||||
FILE *
|
||||
assuan_get_data_fp (ASSUAN_CONTEXT ctx)
|
||||
assuan_get_data_fp (assuan_context_t ctx)
|
||||
{
|
||||
#if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN)
|
||||
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
|
||||
automatically reset to NULL after the next command. */
|
||||
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)
|
||||
return ASSUAN_Invalid_Value;
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
if (!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 */
|
||||
char *buf = xtrymalloc (3+strlen(line)+1);
|
||||
if (!buf)
|
||||
return ASSUAN_Out_Of_Core;
|
||||
return _assuan_error (ASSUAN_Out_Of_Core);
|
||||
strcpy (buf, "OK ");
|
||||
strcpy (buf+3, line);
|
||||
xfree (ctx->okay_line);
|
||||
@ -685,7 +691,8 @@ assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line)
|
||||
|
||||
|
||||
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 *helpbuf;
|
||||
@ -693,7 +700,7 @@ assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text)
|
||||
assuan_error_t ae;
|
||||
|
||||
if ( !ctx || !keyword)
|
||||
return ASSUAN_Invalid_Value;
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
if (!text)
|
||||
text = "";
|
||||
|
||||
|
@ -15,7 +15,8 @@
|
||||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@ -146,14 +147,14 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,
|
||||
int nodataexpected;
|
||||
|
||||
if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf)))
|
||||
return ASSUAN_Invalid_Value;
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
nodataexpected = !r_buffer && !r_length && !maxlen;
|
||||
if (!nodataexpected && (!r_buffer || !r_length))
|
||||
return ASSUAN_Invalid_Value;
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
if (!ctx->is_server)
|
||||
return ASSUAN_Not_A_Server;
|
||||
return _assuan_error (ASSUAN_Not_A_Server);
|
||||
if (ctx->in_inquire)
|
||||
return ASSUAN_Nested_Commands;
|
||||
return _assuan_error (ASSUAN_Nested_Commands);
|
||||
|
||||
ctx->in_inquire = 1;
|
||||
if (nodataexpected)
|
||||
@ -182,12 +183,12 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,
|
||||
break; /* END command received*/
|
||||
if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N')
|
||||
{
|
||||
rc = ASSUAN_Canceled;
|
||||
rc = _assuan_error (ASSUAN_Canceled);
|
||||
goto leave;
|
||||
}
|
||||
if (line[0] != 'D' || line[1] != ' ' || nodataexpected)
|
||||
{
|
||||
rc = ASSUAN_Unexpected_Command;
|
||||
rc = _assuan_error (ASSUAN_Unexpected_Command);
|
||||
goto leave;
|
||||
}
|
||||
if (linelen < 3)
|
||||
@ -214,7 +215,7 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,
|
||||
}
|
||||
if (mb.too_large)
|
||||
{
|
||||
rc = ASSUAN_Too_Much_Data;
|
||||
rc = _assuan_error (ASSUAN_Too_Much_Data);
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
@ -223,7 +224,7 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,
|
||||
{
|
||||
*r_buffer = get_membuf (&mb, r_length);
|
||||
if (!*r_buffer)
|
||||
rc = ASSUAN_Out_Of_Core;
|
||||
rc = _assuan_error (ASSUAN_Out_Of_Core);
|
||||
}
|
||||
|
||||
leave:
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* 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.
|
||||
*
|
||||
@ -15,30 +15,93 @@
|
||||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "assuan-defs.h"
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
#include <windows.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#if HAVE_SYS_UIO_H
|
||||
# include <sys/uio.h>
|
||||
#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
|
||||
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_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
|
||||
#pragma weak pth_waitpid
|
||||
#pragma weak pth_read
|
||||
#pragma weak pth_write
|
||||
#pragma weak pth_fdmode
|
||||
#pragma weak pth_select
|
||||
#endif
|
||||
#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
|
||||
_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)
|
||||
: recv (ctx->inbound.fd, buffer, size, 0);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
ssize_t
|
||||
@ -68,3 +131,87 @@ _assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size)
|
||||
# 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
|
||||
* 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>
|
||||
@ -23,6 +24,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "assuan-defs.h"
|
||||
|
||||
@ -30,7 +32,7 @@ assuan_error_t
|
||||
assuan_set_hello_line (assuan_context_t ctx, const char *line)
|
||||
{
|
||||
if (!ctx)
|
||||
return ASSUAN_Invalid_Value;
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
if (!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);
|
||||
if (!buf)
|
||||
return ASSUAN_Out_Of_Core;
|
||||
return _assuan_error (ASSUAN_Out_Of_Core);
|
||||
if (strchr (line, '\n'))
|
||||
strcpy (buf, line);
|
||||
else
|
||||
@ -73,7 +75,7 @@ assuan_accept (assuan_context_t ctx)
|
||||
const char *p, *pend;
|
||||
|
||||
if (!ctx)
|
||||
return ASSUAN_Invalid_Value;
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
|
||||
if (ctx->pipe_mode > 1)
|
||||
return -1; /* second invocation for pipemode -> terminate */
|
||||
@ -134,7 +136,7 @@ assuan_error_t
|
||||
assuan_close_input_fd (assuan_context_t ctx)
|
||||
{
|
||||
if (!ctx || ctx->input_fd == -1)
|
||||
return ASSUAN_Invalid_Value;
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
_assuan_close (ctx->input_fd);
|
||||
ctx->input_fd = -1;
|
||||
return 0;
|
||||
@ -146,7 +148,7 @@ assuan_error_t
|
||||
assuan_close_output_fd (assuan_context_t ctx)
|
||||
{
|
||||
if (!ctx || ctx->output_fd == -1)
|
||||
return ASSUAN_Invalid_Value;
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
|
||||
_assuan_close (ctx->output_fd);
|
||||
ctx->output_fd = -1;
|
||||
|
@ -15,29 +15,37 @@
|
||||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
#include <windows.h>
|
||||
#endif /*HAVE_W32_SYSTEM*/
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "assuan-defs.h"
|
||||
|
||||
static char prefix_buffer[80];
|
||||
static FILE *_assuan_log;
|
||||
static int full_logging;
|
||||
|
||||
void
|
||||
_assuan_set_default_log_stream (FILE *fp)
|
||||
{
|
||||
if (!_assuan_log)
|
||||
_assuan_log = fp;
|
||||
{
|
||||
_assuan_log = fp;
|
||||
full_logging = !!getenv ("ASSUAN_FULL_LOGGING");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -46,6 +54,22 @@ assuan_set_assuan_log_stream (FILE *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 *
|
||||
assuan_get_assuan_log_stream (void)
|
||||
{
|
||||
@ -80,18 +104,123 @@ _assuan_log_printf (const char *format, ...)
|
||||
va_list arg_ptr;
|
||||
FILE *fp;
|
||||
const char *prf;
|
||||
|
||||
int save_errno = errno;
|
||||
|
||||
fp = assuan_get_assuan_log_stream ();
|
||||
prf = assuan_get_assuan_log_prefix ();
|
||||
if (*prf)
|
||||
{
|
||||
fputs (prf, fp);
|
||||
fputs (": ", fp);
|
||||
}
|
||||
fprintf (fp, "%s[%u]: ", prf, (unsigned int)getpid ());
|
||||
|
||||
va_start (arg_ptr, format);
|
||||
vfprintf (fp, format, 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)
|
||||
* 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.
|
||||
*
|
||||
@ -15,7 +15,8 @@
|
||||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
@ -38,6 +39,19 @@
|
||||
|
||||
#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
|
||||
#define MAX_OPEN_FDS _POSIX_OPEN_MAX
|
||||
#else
|
||||
@ -111,6 +125,8 @@ do_finish (assuan_context_t ctx)
|
||||
if (ctx->inbound.fd != -1)
|
||||
{
|
||||
_assuan_close (ctx->inbound.fd);
|
||||
if (ctx->inbound.fd == ctx->outbound.fd)
|
||||
ctx->outbound.fd = -1;
|
||||
ctx->inbound.fd = -1;
|
||||
}
|
||||
if (ctx->outbound.fd != -1)
|
||||
@ -123,7 +139,7 @@ do_finish (assuan_context_t ctx)
|
||||
#ifndef HAVE_W32_SYSTEM
|
||||
#ifndef _ASSUAN_USE_DOUBLE_FORK
|
||||
if (!ctx->flags.no_waitpid)
|
||||
waitpid (ctx->pid, NULL, 0);
|
||||
_assuan_waitpid (ctx->pid, NULL, 0);
|
||||
ctx->pid = -1;
|
||||
#endif
|
||||
#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
|
||||
/* Build a command line for use with W32's CreateProcess. On success
|
||||
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*/
|
||||
|
||||
|
||||
/* 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
|
||||
#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;
|
||||
int rp[2];
|
||||
int wp[2];
|
||||
@ -269,7 +676,7 @@ assuan_pipe_connect2 (assuan_context_t *ctx,
|
||||
HANDLE nullfd = INVALID_HANDLE_VALUE;
|
||||
|
||||
if (!ctx || !name || !argv || !argv[0])
|
||||
return ASSUAN_Invalid_Value;
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
|
||||
fix_signals ();
|
||||
|
||||
@ -277,13 +684,13 @@ assuan_pipe_connect2 (assuan_context_t *ctx,
|
||||
|
||||
/* Build the command line. */
|
||||
if (build_w32_commandline (argv, &cmdline))
|
||||
return ASSUAN_Out_Of_Core;
|
||||
return _assuan_error (ASSUAN_Out_Of_Core);
|
||||
|
||||
/* Create thew two pipes. */
|
||||
if (create_inheritable_pipe (rp, 0))
|
||||
{
|
||||
xfree (cmdline);
|
||||
return ASSUAN_General_Error;
|
||||
return _assuan_error (ASSUAN_General_Error);
|
||||
}
|
||||
|
||||
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[1]));
|
||||
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[1]));
|
||||
xfree (cmdline);
|
||||
return ASSUAN_General_Error;
|
||||
return _assuan_error (ASSUAN_General_Error);
|
||||
}
|
||||
|
||||
(*ctx)->pipe_mode = 1;
|
||||
@ -390,7 +797,7 @@ assuan_pipe_connect2 (assuan_context_t *ctx,
|
||||
CloseHandle (nullfd);
|
||||
xfree (cmdline);
|
||||
_assuan_release_context (*ctx);
|
||||
return ASSUAN_General_Error;
|
||||
return _assuan_error (ASSUAN_General_Error);
|
||||
}
|
||||
xfree (cmdline);
|
||||
cmdline = NULL;
|
||||
@ -413,200 +820,11 @@ assuan_pipe_connect2 (assuan_context_t *ctx,
|
||||
(*ctx)->pid = 0; /* We don't use the PID. */
|
||||
CloseHandle (pi.hProcess); /* We don't need to wait for the process. */
|
||||
|
||||
#else /*!HAVE_W32_SYSTEM*/
|
||||
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;
|
||||
return initial_handshake (ctx);
|
||||
}
|
||||
#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
|
||||
@ -615,5 +833,57 @@ assuan_error_t
|
||||
assuan_pipe_connect (assuan_context_t *ctx, const char *name,
|
||||
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
|
||||
* 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
#include <windows.h>
|
||||
@ -31,20 +34,20 @@
|
||||
|
||||
|
||||
static void
|
||||
deinit_pipe_server (ASSUAN_CONTEXT ctx)
|
||||
deinit_pipe_server (assuan_context_t ctx)
|
||||
{
|
||||
/* nothing to do for this simple server */
|
||||
}
|
||||
|
||||
static int
|
||||
accept_connection (ASSUAN_CONTEXT ctx)
|
||||
accept_connection (assuan_context_t ctx)
|
||||
{
|
||||
/* This is a NOP for a pipe server */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
finish_connection (ASSUAN_CONTEXT ctx)
|
||||
finish_connection (assuan_context_t ctx)
|
||||
{
|
||||
/* This is a NOP for a pipe server */
|
||||
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
|
||||
server/client - this way we don't need extra dummy functions */
|
||||
int
|
||||
_assuan_new_context (ASSUAN_CONTEXT *r_ctx)
|
||||
_assuan_new_context (assuan_context_t *r_ctx)
|
||||
{
|
||||
static struct assuan_io io = { _assuan_simple_read,
|
||||
_assuan_simple_write,
|
||||
0, 0 };
|
||||
|
||||
ASSUAN_CONTEXT ctx;
|
||||
assuan_context_t ctx;
|
||||
int rc;
|
||||
|
||||
*r_ctx = NULL;
|
||||
ctx = xtrycalloc (1, sizeof *ctx);
|
||||
if (!ctx)
|
||||
return ASSUAN_Out_Of_Core;
|
||||
return _assuan_error (ASSUAN_Out_Of_Core);
|
||||
ctx->input_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
|
||||
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;
|
||||
|
||||
rc = _assuan_new_context (r_ctx);
|
||||
if (!rc)
|
||||
{
|
||||
ASSUAN_CONTEXT ctx = *r_ctx;
|
||||
assuan_context_t ctx = *r_ctx;
|
||||
const char *s;
|
||||
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->outbound.fd = _get_osfhandle (filedes[1]);
|
||||
#else
|
||||
ctx->inbound.fd = filedes[0];
|
||||
ctx->outbound.fd = filedes[1];
|
||||
s = getenv ("_assuan_connection_fd");
|
||||
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
|
||||
ctx->pipe_mode = 1;
|
||||
|
||||
@ -127,7 +162,7 @@ assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2])
|
||||
|
||||
|
||||
void
|
||||
_assuan_release_context (ASSUAN_CONTEXT ctx)
|
||||
_assuan_release_context (assuan_context_t ctx)
|
||||
{
|
||||
if (ctx)
|
||||
{
|
||||
@ -138,7 +173,7 @@ _assuan_release_context (ASSUAN_CONTEXT ctx)
|
||||
}
|
||||
|
||||
void
|
||||
assuan_deinit_server (ASSUAN_CONTEXT ctx)
|
||||
assuan_deinit_server (assuan_context_t ctx)
|
||||
{
|
||||
if (ctx)
|
||||
{
|
||||
|
@ -15,7 +15,8 @@
|
||||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@ -54,7 +55,7 @@
|
||||
|
||||
|
||||
static int
|
||||
do_finish (ASSUAN_CONTEXT ctx)
|
||||
do_finish (assuan_context_t ctx)
|
||||
{
|
||||
if (ctx->inbound.fd != -1)
|
||||
{
|
||||
@ -66,56 +67,70 @@ do_finish (ASSUAN_CONTEXT ctx)
|
||||
}
|
||||
|
||||
static void
|
||||
do_deinit (ASSUAN_CONTEXT ctx)
|
||||
do_deinit (assuan_context_t ctx)
|
||||
{
|
||||
do_finish (ctx);
|
||||
}
|
||||
|
||||
|
||||
/* Make a connection to the Unix domain socket NAME and return a new
|
||||
Assuan context in CTX. SERVER_PID is currently not used but may
|
||||
become handy in the future. */
|
||||
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)
|
||||
{
|
||||
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,
|
||||
_assuan_simple_write };
|
||||
|
||||
assuan_error_t err;
|
||||
ASSUAN_CONTEXT ctx;
|
||||
assuan_context_t ctx;
|
||||
int fd;
|
||||
struct sockaddr_un srvr_addr;
|
||||
size_t len;
|
||||
const char *s;
|
||||
|
||||
if (!r_ctx || !name)
|
||||
return ASSUAN_Invalid_Value;
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
*r_ctx = NULL;
|
||||
|
||||
/* We require that the name starts with a slash, so that we can
|
||||
alter reuse this function for other socket types. To make things
|
||||
easier we allow an optional dirver prefix. */
|
||||
/* We require that the name starts with a slash, so that we
|
||||
eventually can reuse this function for other socket types. To
|
||||
make things easier we allow an optional dirver prefix. */
|
||||
s = name;
|
||||
if (*s && s[1] == ':')
|
||||
s += 2;
|
||||
if (*s != DIRSEP_C && *s != '/')
|
||||
return ASSUAN_Invalid_Value;
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
|
||||
if (strlen (name)+1 >= sizeof srvr_addr.sun_path)
|
||||
return ASSUAN_Invalid_Value;
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
|
||||
err = _assuan_new_context (&ctx);
|
||||
if (err)
|
||||
return err;
|
||||
ctx->deinit_handler = do_deinit;
|
||||
ctx->deinit_handler = ((flags&1))? _assuan_uds_deinit : do_deinit;
|
||||
ctx->finish_handler = do_finish;
|
||||
|
||||
|
||||
fd = _assuan_sock_new (PF_LOCAL, SOCK_STREAM, 0);
|
||||
if (fd == -1)
|
||||
{
|
||||
_assuan_log_printf ("can't create socket: %s\n", strerror (errno));
|
||||
_assuan_release_context (ctx);
|
||||
return ASSUAN_General_Error;
|
||||
return _assuan_error (ASSUAN_General_Error);
|
||||
}
|
||||
|
||||
memset (&srvr_addr, 0, sizeof srvr_addr);
|
||||
@ -131,13 +146,15 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx,
|
||||
name, strerror (errno));
|
||||
_assuan_release_context (ctx);
|
||||
_assuan_close (fd);
|
||||
return ASSUAN_Connect_Failed;
|
||||
return _assuan_error (ASSUAN_Connect_Failed);
|
||||
}
|
||||
|
||||
ctx->inbound.fd = fd;
|
||||
ctx->outbound.fd = fd;
|
||||
ctx->io = &io;
|
||||
|
||||
if ((flags&1))
|
||||
_assuan_init_uds_io (ctx);
|
||||
|
||||
/* initial handshake */
|
||||
{
|
||||
int okay, off;
|
||||
@ -151,7 +168,7 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx,
|
||||
/*LOG ("can't connect to server: `");*/
|
||||
_assuan_log_sanitized_string (ctx->inbound.line);
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -15,7 +15,8 @@
|
||||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@ -33,21 +34,33 @@
|
||||
|
||||
#include "assuan-defs.h"
|
||||
|
||||
static struct assuan_io io = { _assuan_simple_read,
|
||||
_assuan_simple_write };
|
||||
|
||||
|
||||
static int
|
||||
accept_connection_bottom (assuan_context_t ctx)
|
||||
{
|
||||
int fd = ctx->connected_fd;
|
||||
|
||||
ctx->peercred.valid = 0;
|
||||
#ifdef HAVE_SO_PEERCRED
|
||||
{
|
||||
/* This overrides any already set PID if the function returns a
|
||||
valid one. */
|
||||
struct ucred cr;
|
||||
int cl = sizeof cr;
|
||||
socklen_t cl = sizeof cr;
|
||||
|
||||
if ( !getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl)
|
||||
&& cr.pid != (pid_t)-1 && cr.pid )
|
||||
ctx->pid = cr.pid;
|
||||
if ( !getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl))
|
||||
{
|
||||
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
|
||||
|
||||
@ -72,13 +85,13 @@ accept_connection (assuan_context_t ctx)
|
||||
{
|
||||
int fd;
|
||||
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 );
|
||||
if (fd == -1)
|
||||
{
|
||||
ctx->os_errno = errno;
|
||||
return ASSUAN_Accept_Failed;
|
||||
return _assuan_error (ASSUAN_Accept_Failed);
|
||||
}
|
||||
|
||||
ctx->connected_fd = fd;
|
||||
@ -104,47 +117,30 @@ deinit_socket_server (assuan_context_t 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
|
||||
put into listen mode */
|
||||
int
|
||||
assuan_init_socket_server (assuan_context_t *r_ctx, int listen_fd)
|
||||
{
|
||||
assuan_context_t ctx;
|
||||
int rc;
|
||||
|
||||
*r_ctx = NULL;
|
||||
ctx = xtrycalloc (1, sizeof *ctx);
|
||||
if (!ctx)
|
||||
return ASSUAN_Out_Of_Core;
|
||||
ctx->is_server = 1;
|
||||
ctx->input_fd = -1;
|
||||
ctx->output_fd = -1;
|
||||
|
||||
ctx->inbound.fd = -1;
|
||||
ctx->outbound.fd = -1;
|
||||
|
||||
ctx->listen_fd = listen_fd;
|
||||
ctx->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;
|
||||
return assuan_init_socket_server_ext (r_ctx, listen_fd, 0);
|
||||
}
|
||||
|
||||
/* Initialize a server using the already accepted socket FD. */
|
||||
/* Initialize a server using the already accepted socket FD. This
|
||||
fucntion is deprecated. */
|
||||
int
|
||||
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;
|
||||
int rc;
|
||||
@ -152,23 +148,36 @@ assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd)
|
||||
*r_ctx = NULL;
|
||||
ctx = xtrycalloc (1, sizeof *ctx);
|
||||
if (!ctx)
|
||||
return ASSUAN_Out_Of_Core;
|
||||
return _assuan_error (ASSUAN_Out_Of_Core);
|
||||
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->output_fd = -1;
|
||||
|
||||
ctx->inbound.fd = -1;
|
||||
ctx->outbound.fd = -1;
|
||||
|
||||
ctx->io = &io;
|
||||
|
||||
ctx->listen_fd = -1;
|
||||
ctx->connected_fd = fd;
|
||||
ctx->deinit_handler = deinit_socket_server;
|
||||
ctx->accept_handler = accept_connection_bottom;
|
||||
if ((flags & 2))
|
||||
{
|
||||
ctx->listen_fd = -1;
|
||||
ctx->connected_fd = fd;
|
||||
}
|
||||
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->io = &io;
|
||||
if ((flags & 1))
|
||||
_assuan_init_uds_io (ctx);
|
||||
|
||||
rc = _assuan_register_std_commands (ctx);
|
||||
if (rc)
|
||||
xfree (ctx);
|
||||
@ -176,5 +185,3 @@ assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd)
|
||||
*r_ctx = ctx;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,22 +1,24 @@
|
||||
/* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* 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.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* 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 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
@ -28,6 +30,18 @@
|
||||
#endif
|
||||
#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
|
||||
_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
|
||||
* 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>
|
||||
@ -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
|
||||
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
|
||||
* 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
|
||||
@ -26,24 +27,32 @@
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
/* To use this file with libraries the following macros are often
|
||||
useful:
|
||||
/* To use this file with libraries the following macros are useful:
|
||||
|
||||
#define _ASSUAN_EXT_SYM_PREFIX _foo_
|
||||
#define _ASSUAN_EXT_SYM_PREFIX _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. ******/
|
||||
#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_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_ext _ASSUAN_PREFIX(assuan_pipe_connect_ext)
|
||||
#define assuan_socket_connect _ASSUAN_PREFIX(assuan_socket_connect)
|
||||
#define assuan_domain_connect _ASSUAN_PREFIX(assuan_domain_connect)
|
||||
#define assuan_init_domain_server _ASSUAN_PREFIX(assuan_init_domain_server)
|
||||
#define assuan_socket_connect_ext _ASSUAN_PREFIX(assuan_socket_connect_ext)
|
||||
#define assuan_disconnect _ASSUAN_PREFIX(assuan_disconnect)
|
||||
#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_inquire _ASSUAN_PREFIX(assuan_inquire)
|
||||
#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_end_confidential _ASSUAN_PREFIX(assuan_end_confidential)
|
||||
#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 \
|
||||
_ASSUAN_PREFIX(assuan_set_assuan_log_stream)
|
||||
#define assuan_get_assuan_log_stream \
|
||||
@ -189,89 +203,121 @@ extern "C"
|
||||
#endif
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ASSUAN_No_Error = 0,
|
||||
ASSUAN_General_Error = 1,
|
||||
ASSUAN_Out_Of_Core = 2,
|
||||
ASSUAN_Invalid_Value = 3,
|
||||
ASSUAN_Timeout = 4,
|
||||
ASSUAN_Read_Error = 5,
|
||||
ASSUAN_Write_Error = 6,
|
||||
ASSUAN_Problem_Starting_Server = 7,
|
||||
ASSUAN_Not_A_Server = 8,
|
||||
ASSUAN_Not_A_Client = 9,
|
||||
ASSUAN_Nested_Commands = 10,
|
||||
ASSUAN_Invalid_Response = 11,
|
||||
ASSUAN_No_Data_Callback = 12,
|
||||
ASSUAN_No_Inquire_Callback = 13,
|
||||
ASSUAN_Connect_Failed = 14,
|
||||
ASSUAN_Accept_Failed = 15,
|
||||
/* Check for compiler features. */
|
||||
#if __GNUC__
|
||||
#define _ASSUAN_GCC_VERSION (__GNUC__ * 10000 \
|
||||
+ __GNUC_MINOR__ * 100 \
|
||||
+ __GNUC_PATCHLEVEL__)
|
||||
|
||||
#if _ASSUAN_GCC_VERSION > 30100
|
||||
#define _ASSUAN_DEPRECATED __attribute__ ((__deprecated__))
|
||||
#endif
|
||||
#endif
|
||||
#ifndef _ASSUAN_DEPRECATED
|
||||
#define _ASSUAN_DEPRECATED
|
||||
#endif
|
||||
|
||||
|
||||
/* Assuan error codes. These are only used by old applications or
|
||||
those applications which won't make use of libgpg-error. */
|
||||
#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 */
|
||||
ASSUAN_Not_Implemented = 100,
|
||||
ASSUAN_Server_Fault = 101,
|
||||
ASSUAN_Invalid_Command = 102,
|
||||
ASSUAN_Unknown_Command = 103,
|
||||
ASSUAN_Syntax_Error = 104,
|
||||
ASSUAN_Parameter_Error = 105,
|
||||
ASSUAN_Parameter_Conflict = 106,
|
||||
ASSUAN_Line_Too_Long = 107,
|
||||
ASSUAN_Line_Not_Terminated = 108,
|
||||
ASSUAN_No_Input = 109,
|
||||
ASSUAN_No_Output = 110,
|
||||
ASSUAN_Canceled = 111,
|
||||
ASSUAN_Unsupported_Algorithm = 112,
|
||||
ASSUAN_Server_Resource_Problem = 113,
|
||||
ASSUAN_Server_IO_Error = 114,
|
||||
ASSUAN_Server_Bug = 115,
|
||||
ASSUAN_No_Data_Available = 116,
|
||||
ASSUAN_Invalid_Data = 117,
|
||||
ASSUAN_Unexpected_Command = 118,
|
||||
ASSUAN_Too_Much_Data = 119,
|
||||
ASSUAN_Inquire_Unknown = 120,
|
||||
ASSUAN_Inquire_Error = 121,
|
||||
ASSUAN_Invalid_Option = 122,
|
||||
ASSUAN_Invalid_Index = 123,
|
||||
ASSUAN_Unexpected_Status = 124,
|
||||
ASSUAN_Unexpected_Data = 125,
|
||||
ASSUAN_Invalid_Status = 126,
|
||||
ASSUAN_Locale_Problem = 127,
|
||||
ASSUAN_Not_Confirmed = 128,
|
||||
#define ASSUAN_Not_Implemented 100
|
||||
#define ASSUAN_Server_Fault 101
|
||||
#ifndef _ASSUAN_IN_LIBASSUAN
|
||||
#define ASSUAN_Invalid_Command 102
|
||||
#endif
|
||||
#define ASSUAN_Unknown_Command 103
|
||||
#define ASSUAN_Syntax_Error 104
|
||||
#ifndef _ASSUAN_IN_LIBASSUAN
|
||||
#define ASSUAN_Parameter_Error 105
|
||||
#endif
|
||||
#define ASSUAN_Parameter_Conflict 106
|
||||
#define ASSUAN_Line_Too_Long 107
|
||||
#define ASSUAN_Line_Not_Terminated 108
|
||||
#ifndef _ASSUAN_IN_LIBASSUAN
|
||||
#define ASSUAN_No_Input 109
|
||||
#define ASSUAN_No_Output 110
|
||||
#endif
|
||||
#define ASSUAN_Canceled 111
|
||||
#ifndef _ASSUAN_IN_LIBASSUAN
|
||||
#define ASSUAN_Unsupported_Algorithm 112
|
||||
#define ASSUAN_Server_Resource_Problem 113
|
||||
#define ASSUAN_Server_IO_Error 114
|
||||
#define ASSUAN_Server_Bug 115
|
||||
#define ASSUAN_No_Data_Available 116
|
||||
#define ASSUAN_Invalid_Data 117
|
||||
#endif
|
||||
#define ASSUAN_Unexpected_Command 118
|
||||
#define ASSUAN_Too_Much_Data 119
|
||||
#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. */
|
||||
ASSUAN_Bad_Certificate = 201,
|
||||
ASSUAN_Bad_Certificate_Chain = 202,
|
||||
ASSUAN_Missing_Certificate = 203,
|
||||
ASSUAN_Bad_Signature = 204,
|
||||
ASSUAN_No_Agent = 205,
|
||||
ASSUAN_Agent_Error = 206,
|
||||
ASSUAN_No_Public_Key = 207,
|
||||
ASSUAN_No_Secret_Key = 208,
|
||||
ASSUAN_Invalid_Name = 209,
|
||||
/* Warning: Don't use the Error codes, below they are deprecated. */
|
||||
#define ASSUAN_Bad_Certificate 201
|
||||
#define ASSUAN_Bad_Certificate_Chain 202
|
||||
#define ASSUAN_Missing_Certificate 203
|
||||
#define ASSUAN_Bad_Signature 204
|
||||
#define ASSUAN_No_Agent 205
|
||||
#define ASSUAN_Agent_Error 206
|
||||
#define ASSUAN_No_Public_Key 207
|
||||
#define ASSUAN_No_Secret_Key 208
|
||||
#define ASSUAN_Invalid_Name 209
|
||||
|
||||
ASSUAN_Cert_Revoked = 301,
|
||||
ASSUAN_No_CRL_For_Cert = 302,
|
||||
ASSUAN_CRL_Too_Old = 303,
|
||||
ASSUAN_Not_Trusted = 304,
|
||||
#define ASSUAN_Cert_Revoked 301
|
||||
#define ASSUAN_No_CRL_For_Cert 302
|
||||
#define ASSUAN_CRL_Too_Old 303
|
||||
#define ASSUAN_Not_Trusted 304
|
||||
|
||||
ASSUAN_Card_Error = 401,
|
||||
ASSUAN_Invalid_Card = 402,
|
||||
ASSUAN_No_PKCS15_App = 403,
|
||||
ASSUAN_Card_Not_Present = 404,
|
||||
ASSUAN_Invalid_Id = 405,
|
||||
#define ASSUAN_Card_Error 401
|
||||
#define ASSUAN_Invalid_Card 402
|
||||
#define ASSUAN_No_PKCS15_App 403
|
||||
#define ASSUAN_Card_Not_Present 404
|
||||
#define ASSUAN_Invalid_Id 405
|
||||
|
||||
/* Error codes in the range 1000 to 9999 may be used by applications
|
||||
at their own discretion. */
|
||||
ASSUAN_USER_ERROR_FIRST = 1000,
|
||||
ASSUAN_USER_ERROR_LAST = 9999
|
||||
#define ASSUAN_USER_ERROR_FIRST 1000
|
||||
#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 */
|
||||
/* NOTE, these command IDs are now deprectated and solely exists for
|
||||
/* Note, these command IDs are now deprectated and solely exists for
|
||||
compatibility reasons. */
|
||||
typedef enum
|
||||
{
|
||||
@ -290,6 +336,13 @@ typedef enum
|
||||
} AssuanCommand;
|
||||
|
||||
|
||||
#else /*!_ASSUAN_ONLY_GPG_ERRORS*/
|
||||
|
||||
typedef int assuan_error_t;
|
||||
|
||||
#endif /*!_ASSUAN_ONLY_GPG_ERRORS*/
|
||||
|
||||
|
||||
/* Definitions of flags for assuan_set_flag(). */
|
||||
typedef enum
|
||||
{
|
||||
@ -306,7 +359,9 @@ assuan_flag_t;
|
||||
|
||||
struct assuan_context_s;
|
||||
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 --*/
|
||||
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
|
||||
capable of passing file descriptors). */
|
||||
assuan_error_t assuan_command_parse_fd (assuan_context_t ctx, char *line,
|
||||
int *rfd);
|
||||
int *rfd);
|
||||
|
||||
/*-- assuan-listen.c --*/
|
||||
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 --*/
|
||||
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_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[],
|
||||
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[],
|
||||
int *fd_child_list,
|
||||
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_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);
|
||||
|
||||
/*-- assuan-domain-connect.c --*/
|
||||
|
||||
/* Connect to a Unix domain socket server. RENDEZVOUSFD is
|
||||
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_error_t assuan_socket_connect_ext (assuan_context_t *ctx,
|
||||
const char *name,
|
||||
pid_t server_pid,
|
||||
unsigned int flags);
|
||||
|
||||
/*-- assuan-connect.c --*/
|
||||
void assuan_disconnect (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_error_t
|
||||
assuan_transact (assuan_context_t ctx,
|
||||
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,
|
||||
assuan_error_t (*inquire_cb)(void*, const char *),
|
||||
int (*inquire_cb)(void*, const char *),
|
||||
void *inquire_cb_arg,
|
||||
assuan_error_t (*status_cb)(void*, const char *),
|
||||
int (*status_cb)(void*, const char *),
|
||||
void *status_cb_arg);
|
||||
|
||||
|
||||
@ -426,9 +480,8 @@ assuan_error_t assuan_send_data (assuan_context_t ctx,
|
||||
const void *buffer, size_t length);
|
||||
|
||||
/* The file descriptor must be pending before assuan_receivefd is
|
||||
call. This means that assuan_sendfd should be called *before* the
|
||||
trigger is sent (normally via assuan_send_data ("I sent you a
|
||||
descriptor")). */
|
||||
called. This means that assuan_sendfd should be called *before* the
|
||||
trigger is sent (normally via assuan_write_line ("INPUT FD")). */
|
||||
assuan_error_t assuan_sendfd (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);
|
||||
|
||||
|
||||
/*-- 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);
|
||||
#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 --*/
|
||||
|
||||
|
@ -1,21 +1,22 @@
|
||||
/* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* 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.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* 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 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
|
||||
* 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
|
||||
@ -54,7 +55,7 @@ _assuan_funopen(void *cookie,
|
||||
io.seek = seekfn;
|
||||
io.close = closefn;
|
||||
|
||||
return fopencookie (cookie,
|
||||
return fopencookie (cookie,
|
||||
readfn ? ( writefn ? "rw" : "r" )
|
||||
: ( writefn ? "w" : ""), io);
|
||||
}
|
||||
|
168
assuan/mkerrors
168
assuan/mkerrors
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
# mkerrors - Extract error strings from assuan.h
|
||||
# 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.
|
||||
#
|
||||
@ -17,19 +17,118 @@
|
||||
#
|
||||
# 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
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
cat <<EOF
|
||||
/* Generated automatically by mkerrors */
|
||||
/* Do not edit! */
|
||||
/* Do not edit! See mkerrors for copyright notice. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#undef _ASSUAN_IN_LIBASSUAN /* undef to get all error codes. */
|
||||
#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:
|
||||
* @err: Error code
|
||||
@ -41,7 +140,7 @@ cat <<EOF
|
||||
* Return value: String with the error description.
|
||||
**/
|
||||
const char *
|
||||
assuan_strerror (AssuanError err)
|
||||
assuan_strerror (assuan_error_t err)
|
||||
{
|
||||
const char *s;
|
||||
static char buf[50];
|
||||
@ -51,10 +150,10 @@ assuan_strerror (AssuanError err)
|
||||
EOF
|
||||
|
||||
awk '
|
||||
/ASSUAN_No_Error/ { okay=1 }
|
||||
!okay {next}
|
||||
/}/ { exit 0 }
|
||||
/ASSUAN_[A-Za-z_]*/ { print_code($1) }
|
||||
/ASSUAN_No_Error/ { okay=1 }
|
||||
!okay {next}
|
||||
/^#define[ ]+ASSUAN_[A-Za-z_]*/ { print_code($2) }
|
||||
/ASSUAN_USER_ERROR_LAST/ { exit 0 }
|
||||
|
||||
|
||||
function print_code( s )
|
||||
@ -66,21 +165,62 @@ printf "%s\"; break;\n", tolower(substr(s,8));
|
||||
'
|
||||
|
||||
cat <<EOF
|
||||
case -1: s = "EOF (-1)"; break;
|
||||
default:
|
||||
{
|
||||
unsigned int source, code;
|
||||
unsigned int source, code, n;
|
||||
|
||||
source = ((err >> 24) & 0xff);
|
||||
code = (err & 0x00ffffff);
|
||||
if (source) /* Assume this is an libgpg-error. */
|
||||
sprintf (buf, "ec=%u.%u", source, code );
|
||||
if (source)
|
||||
{
|
||||
/* 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
|
||||
sprintf (buf, "ec=%d", err );
|
||||
s=buf; break;
|
||||
{
|
||||
sprintf (buf, "ec=%d", err );
|
||||
s=buf;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
EOF
|
||||
EOF
|
||||
|
@ -202,8 +202,6 @@ AC_SUBST(NETLIBS)
|
||||
# Checks for library functions.
|
||||
AC_FUNC_FSEEKO
|
||||
|
||||
AC_CHECK_FUNCS(stpcpy)
|
||||
|
||||
AC_REPLACE_FUNCS(vasprintf)
|
||||
if test "$ac_cv_func_vasprintf" != yes; then
|
||||
GNUPG_CHECK_VA_COPY
|
||||
@ -462,6 +460,10 @@ fi
|
||||
AC_REPLACE_FUNCS(isascii)
|
||||
AC_REPLACE_FUNCS(putc_unlocked)
|
||||
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.
|
||||
AC_CHECK_HEADERS([sys/uio.h])
|
||||
|
@ -72,7 +72,7 @@ extern "C" {
|
||||
AM_PATH_GPGME macro) check that this header matches the installed
|
||||
library. Warning: Do not edit the next line. configure will do
|
||||
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