diff --git a/ChangeLog b/ChangeLog index a55f2ae6..83209c46 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2005-08-08 Werner Koch + + * configure.ac (stpcpy): Changed from replace to test. + 2005-03-24 Marcus Brinkmann * configure.ac (AH_BOTTOM): Removed. diff --git a/assuan/ChangeLog b/assuan/ChangeLog index b73a5dae..22c5189b 100644 --- a/assuan/ChangeLog +++ b/assuan/ChangeLog @@ -1,3 +1,50 @@ +2005-08-09 Werner Koch + + * README.1st: Adjusted to cope with changes done in upstream Assuan. + + Merged changes for W32 support from libassuan. + + * assuan.h [_ASSUAN_EXT_SYM_PREFIX]: New. + * assuan-io.c [_ASSUAN_NO_PTH]: New. + * assuan-pipe-connect.c (fix_signals) [_ASSUAN_NO_FIXED_SIGNALS]: New. + (assuan_pipe_connect2) [_ASSUAN_USE_DOUBLE_FORK]: Use double fork. + (fix_signals) [_ASSUAN_USE_DOUBLE_FORK]: Do not wait.. + * assuan-logging.c, assuan-io.c: Include config.h + Replaced all usages of _WIN32 by the new HAVE_W32_SYSTEM because + there is nothing winning in this API. + * assuan-pipe-connect.c (assuan_pipe_connect2) [_WIN32]: Return + error Not Imlemented. + * assuan-logging.c (_assuan_w32_strerror): New. + * assuan-defs.h (w32_strerror): new. + * assuan-pipe-connect.c (assuan_pipe_connect2, fix_signals): + Factored signal code out to new function. + (build_w32_commandline, create_inheritable_pipe): New. Taken + from gnupg 1.9. + (assuan_pipe_connect2) [W32]: Implemented for W32. + * assuan-pipe-server.c (assuan_init_pipe_server) [W32]: Map file + descriptors using _get_osfhandle. + * assuan-socket-connect.c (assuan_socket_connect) [W32]: Allow for + a drive letter in the path. + * assuan-client.c (assuan_transact): Handle empty and comment + commands correctly. + * assuan-util.c (_assuan_calloc): Avoid integer overflow. + * assuan-util.c (assuan_set_flag, assuan_get_flag): New. + * assuan-defs.h (struct assuan_context_s): New field flags. + * assuan.h (assuan_flag_t): New with one flag value + ASSUAN_NO_WAITPID for now. + * assuan-pipe-connect.c (do_finish): Take care of the no_waitpid + flag. + * mkerrors: Include config.h into assuan-errors.c. This is + required so that assuan.h knows about the W32 macro. + +2005-08-09 Timo Schulz (ported from libassuan by wk) + + * assuan-io.c (_assuan_simple_read, _assuan_simple_write): W32 + support. + * assuan-socket.c (_assuan_close): New. + (_assuan_sock_new): New. + (_assuan_sock_bind): New. + 2005-03-22 Werner Koch * assuan-defs.h (struct assuan_io): Renamed elements READ and diff --git a/assuan/README.1st b/assuan/README.1st index 47bdefa2..670efb57 100644 --- a/assuan/README.1st +++ b/assuan/README.1st @@ -13,16 +13,15 @@ updating this directory, are: with ATH replacements. * assuan.h -** Define _ASSUAN_IN_GPGME to enable GPGME specific code. -** Put all exported Assuan functions in the _gpgme namespace. -** Also wrap all system functions that are wrapped by GNU Pth to - _gpgme wrappers. - -* assuan-io.c -** Don't try to support GNU Pth here. - -* assuan-pipe-connect.c -** Do not install SIGPIPE signal handler here. +** Preserve the block between "Begin/End GPGME specific modifications". + In particular make sure that + #define _ASSUAN_EXT_SYM_PREFIX _gpgme_ + #define _ASSUAN_NO_PTH + #define _ASSUAN_NO_FIXED_SIGNALS + #define _ASSUAN_USE_DOUBLE_FORK + are defined. This puts all exported Assuan functions in the _gpgme + namespace. It also wraps all system functions that are wrapped by + GNU Pth to _gpgme wrappers. Copyright 2004 g10 Code GmbH diff --git a/assuan/assuan-buffer.c b/assuan/assuan-buffer.c index d9163b79..99ea72e3 100644 --- a/assuan/assuan-buffer.c +++ b/assuan/assuan-buffer.c @@ -1,5 +1,5 @@ /* assuan-buffer.c - read and send data - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. * * This file is part of Assuan. * @@ -25,6 +25,9 @@ #include #include #include +#ifdef HAVE_W32_SYSTEM +#include +#endif #include "assuan-defs.h" static int @@ -49,12 +52,12 @@ writen (ASSUAN_CONTEXT ctx, const char *buffer, size_t length) /* Read an entire line. */ static int readline (ASSUAN_CONTEXT ctx, char *buf, size_t buflen, - int *r_nread, int *eof) + int *r_nread, int *r_eof) { size_t nleft = buflen; char *p; - *eof = 0; + *r_eof = 0; *r_nread = 0; while (nleft > 0) { @@ -68,7 +71,7 @@ readline (ASSUAN_CONTEXT ctx, char *buf, size_t buflen, } else if (!n) { - *eof = 1; + *r_eof = 1; break; /* allow incomplete lines */ } p = buf; @@ -125,16 +128,18 @@ _assuan_read_line (ASSUAN_CONTEXT ctx) if (rc) { if (ctx->log_fp) - fprintf (ctx->log_fp, "%s[%p] <- [Error: %s]\n", - assuan_get_assuan_log_prefix (), ctx, strerror (errno)); + fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [Error: %s]\n", + assuan_get_assuan_log_prefix (), + (unsigned int)getpid (), ctx, strerror (errno)); return ASSUAN_Read_Error; } if (!nread) { assert (ctx->inbound.eof); if (ctx->log_fp) - fprintf (ctx->log_fp, "%s[%p] <- [EOF]\n", - assuan_get_assuan_log_prefix (), ctx); + fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [EOF]\n", + assuan_get_assuan_log_prefix (), + (unsigned int)getpid (), ctx); return -1; } @@ -165,8 +170,9 @@ _assuan_read_line (ASSUAN_CONTEXT ctx) ctx->inbound.linelen = endp - line; if (ctx->log_fp) { - fprintf (ctx->log_fp, "%s[%p] <- ", - assuan_get_assuan_log_prefix (), ctx); + fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- ", + assuan_get_assuan_log_prefix (), + (unsigned int)getpid (), ctx); if (ctx->confidential) fputs ("[Confidential data not shown]", ctx->log_fp); else @@ -180,8 +186,9 @@ _assuan_read_line (ASSUAN_CONTEXT ctx) else { if (ctx->log_fp) - fprintf (ctx->log_fp, "%s[%p] <- [Invalid line]\n", - assuan_get_assuan_log_prefix (), ctx); + fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [Invalid line]\n", + assuan_get_assuan_log_prefix (), + (unsigned int)getpid (), ctx); *line = 0; ctx->inbound.linelen = 0; return ctx->inbound.eof ? ASSUAN_Line_Not_Terminated @@ -199,10 +206,10 @@ _assuan_read_line (ASSUAN_CONTEXT ctx) Returns 0 on success or an assuan error code. See also: assuan_pending_line(). */ -AssuanError +assuan_error_t assuan_read_line (ASSUAN_CONTEXT ctx, char **line, size_t *linelen) { - AssuanError err; + assuan_error_t err; if (!ctx) return ASSUAN_Invalid_Value; @@ -223,10 +230,65 @@ assuan_pending_line (ASSUAN_CONTEXT ctx) } -AssuanError +assuan_error_t +_assuan_write_line (assuan_context_t ctx, const char *prefix, + const char *line, size_t len) +{ + int 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: -> " + "[supplied line too long -truncated]\n", + assuan_get_assuan_log_prefix (), + (unsigned int)getpid (), ctx); + if (prefixlen > 5) + prefixlen = 5; + if (len > ASSUAN_LINELENGTH - prefixlen - 2) + len = ASSUAN_LINELENGTH - prefixlen - 2 - 1; + } + + /* Fixme: we should do some kind of line buffering. */ + if (ctx->log_fp) + { + fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ", + assuan_get_assuan_log_prefix (), + (unsigned int)getpid (), ctx); + if (ctx->confidential) + fputs ("[Confidential data not shown]", ctx->log_fp); + else + _assuan_log_print_buffer (ctx->log_fp, line, len); + putc ('\n', ctx->log_fp); + } + + if (prefixlen) + { + rc = writen (ctx, prefix, prefixlen); + if (rc) + rc = ASSUAN_Write_Error; + } + if (!rc) + { + rc = writen (ctx, line, len); + if (rc) + rc = ASSUAN_Write_Error; + if (!rc) + { + rc = writen (ctx, "\n", 1); + if (rc) + rc = ASSUAN_Write_Error; + } + } + return rc; +} + + +assuan_error_t assuan_write_line (ASSUAN_CONTEXT ctx, const char *line) { - int rc; size_t len; const char *s; @@ -238,44 +300,24 @@ assuan_write_line (ASSUAN_CONTEXT ctx, const char *line) s = strchr (line, '\n'); len = s? (s-line) : strlen (line); - if (len > LINELENGTH - 2) - return ASSUAN_Line_Too_Long; + if (ctx->log_fp && s) + fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> " + "[supplied line contained a LF -truncated]\n", + assuan_get_assuan_log_prefix (), + (unsigned int)getpid (), ctx); - /* fixme: we should do some kind of line buffering. */ - if (ctx->log_fp) - { - fprintf (ctx->log_fp, "%s[%p] -> ", - assuan_get_assuan_log_prefix (), ctx); - if (s) - fputs ("[supplied line contained a LF]", ctx->log_fp); - if (ctx->confidential) - fputs ("[Confidential data not shown]", ctx->log_fp); - else - _assuan_log_print_buffer (ctx->log_fp, line, len); - putc ('\n', ctx->log_fp); - } - - rc = writen (ctx, line, len); - if (rc) - rc = ASSUAN_Write_Error; - if (!rc) - { - rc = writen (ctx, "\n", 1); - if (rc) - rc = ASSUAN_Write_Error; - } - - return rc; + return _assuan_write_line (ctx, NULL, line, len); } /* Write out the data in buffer as datalines with line wrapping and - percent escaping. This fucntion is used for GNU's custom streams */ + percent escaping. This function is used for GNU's custom streams */ int -_assuan_cookie_write_data (void *cookie, const char *buffer, size_t size) +_assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size) { ASSUAN_CONTEXT ctx = cookie; + size_t size = orig_size; char *line; size_t linelen; @@ -317,8 +359,9 @@ _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size) { if (ctx->log_fp) { - fprintf (ctx->log_fp, "%s[%p] -> ", - assuan_get_assuan_log_prefix (), ctx); + fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ", + assuan_get_assuan_log_prefix (), + (unsigned int)getpid (), ctx); if (ctx->confidential) fputs ("[Confidential data not shown]", ctx->log_fp); @@ -341,12 +384,12 @@ _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size) } ctx->outbound.data.linelen = linelen; - return 0; + return (int)orig_size; } /* Write out any buffered data - This fucntion is used for GNU's custom streams */ + This function is used for GNU's custom streams */ int _assuan_cookie_write_flush (void *cookie) { @@ -364,8 +407,9 @@ _assuan_cookie_write_flush (void *cookie) { if (ctx->log_fp) { - fprintf (ctx->log_fp, "%s[%p] -> ", - assuan_get_assuan_log_prefix (), ctx); + fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ", + assuan_get_assuan_log_prefix (), + (unsigned int)getpid (), ctx); if (ctx->confidential) fputs ("[Confidential data not shown]", ctx->log_fp); else @@ -404,7 +448,7 @@ _assuan_cookie_write_flush (void *cookie) * Return value: 0 on success or an error code **/ -AssuanError +assuan_error_t assuan_send_data (ASSUAN_CONTEXT ctx, const void *buffer, size_t length) { if (!ctx) @@ -430,7 +474,7 @@ assuan_send_data (ASSUAN_CONTEXT ctx, const void *buffer, size_t length) return 0; } -AssuanError +assuan_error_t assuan_sendfd (ASSUAN_CONTEXT ctx, int fd) { if (! ctx->io->sendfd) @@ -440,7 +484,7 @@ assuan_sendfd (ASSUAN_CONTEXT ctx, int fd) return ctx->io->sendfd (ctx, fd); } -AssuanError +assuan_error_t assuan_receivefd (ASSUAN_CONTEXT ctx, int *fd) { if (! ctx->io->receivefd) diff --git a/assuan/assuan-client.c b/assuan/assuan-client.c index d5c0ec81..a2189946 100644 --- a/assuan/assuan-client.c +++ b/assuan/assuan-client.c @@ -32,12 +32,12 @@ #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) -AssuanError +assuan_error_t _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off) { char *line; int linelen; - AssuanError rc; + assuan_error_t rc; *okay = 0; *off = 0; @@ -126,14 +126,14 @@ _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off) * the one one returned by the server in error lines or from the * callback functions. **/ -AssuanError +assuan_error_t assuan_transact (ASSUAN_CONTEXT ctx, const char *command, - AssuanError (*data_cb)(void *, const void *, size_t), + assuan_error_t (*data_cb)(void *, const void *, size_t), void *data_cb_arg, - AssuanError (*inquire_cb)(void*, const char *), + assuan_error_t (*inquire_cb)(void*, const char *), void *inquire_cb_arg, - AssuanError (*status_cb)(void*, const char *), + assuan_error_t (*status_cb)(void*, const char *), void *status_cb_arg) { int rc, okay, off; @@ -144,6 +144,9 @@ assuan_transact (ASSUAN_CONTEXT ctx, if (rc) return rc; + if (*command == '#' || !*command) + return 0; /* Don't expect a response for a comment line. */ + again: rc = _assuan_read_from_server (ctx, &okay, &off); if (rc) diff --git a/assuan/assuan-connect.c b/assuan/assuan-connect.c index d260e927..ff1f6ffd 100644 --- a/assuan/assuan-connect.c +++ b/assuan/assuan-connect.c @@ -29,21 +29,19 @@ #include #include #include +#ifndef HAVE_W32_SYSTEM #include +#endif #include "assuan-defs.h" /* Disconnect and release the context CTX. */ void -assuan_disconnect (ASSUAN_CONTEXT ctx) +assuan_disconnect (assuan_context_t ctx) { if (ctx) { -#if 0 - /* This may not work if the pipe is full and the other end is - blocked. */ assuan_write_line (ctx, "BYE"); -#endif ctx->finish_handler (ctx); ctx->deinit_handler (ctx); ctx->deinit_handler = NULL; @@ -51,8 +49,10 @@ assuan_disconnect (ASSUAN_CONTEXT ctx) } } +/* Return the PID of the peer or -1 if not known. */ pid_t -assuan_get_pid (ASSUAN_CONTEXT ctx) +assuan_get_pid (assuan_context_t ctx) { - return ctx ? ctx->pid : -1; + return (ctx && ctx->pid)? ctx->pid : -1; } + diff --git a/assuan/assuan-defs.h b/assuan/assuan-defs.h index 248dbf4e..2917fe85 100644 --- a/assuan/assuan-defs.h +++ b/assuan/assuan-defs.h @@ -1,5 +1,5 @@ /* assuan-defs.c - Internal definitions to Assuan - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. * * This file is part of Assuan. * @@ -22,12 +22,44 @@ #define ASSUAN_DEFS_H #include +#ifndef HAVE_W32_SYSTEM #include #include +#else +#include +#endif #include #include "assuan.h" +#ifndef HAVE_W32_SYSTEM +#define DIRSEP_C '/' +#else +#define DIRSEP_C '\\' +#endif + +#ifdef HAVE_W32_SYSTEM +#define AF_LOCAL AF_UNIX +/* We need to prefix the structure with a sockaddr_in header so we can + use it later for sendto and recvfrom. */ +struct sockaddr_un +{ + short sun_family; + unsigned short sun_port; + struct in_addr sun_addr; + char sun_path[108-2-4]; /* Path name. */ +}; + +/* Not needed anymore because the current mingw32 defines this in + sys/types.h */ +/* typedef int ssize_t; */ + +/* Missing W32 functions */ +int putc_unlocked (int c, FILE *stream); +void * memrchr (const void *block, int c, size_t size); +char * stpcpy (char *dest, const char *src); +#endif + #define LINELENGTH ASSUAN_LINELENGTH struct cmdtbl_s @@ -43,24 +75,31 @@ struct assuan_io /* Routine to write to output_fd. */ ssize_t (*writefnc) (ASSUAN_CONTEXT, const void *, size_t); /* Send a file descriptor. */ - AssuanError (*sendfd) (ASSUAN_CONTEXT, int); + assuan_error_t (*sendfd) (ASSUAN_CONTEXT, int); /* Receive a file descriptor. */ - AssuanError (*receivefd) (ASSUAN_CONTEXT, int *); + assuan_error_t (*receivefd) (ASSUAN_CONTEXT, int *); }; struct assuan_context_s { - AssuanError err_no; + assuan_error_t err_no; const char *err_str; - int os_errno; /* last system error number used with certain error codes*/ + int os_errno; /* Last system error number used with certain + error codes. */ + + /* Context specific flags (cf. assuan_flag_t). */ + struct + { + unsigned int no_waitpid:1; /* See ASSUAN_NO_WAITPID. */ + } flags; int confidential; - int is_server; /* set if this is context belongs to a server */ + int is_server; /* Set if this is context belongs to a server */ int in_inquire; char *hello_line; - char *okay_line; /* see assan_set_okay_line() */ + char *okay_line; /* See assuan_set_okay_line() */ - void *user_pointer; /* for assuan_[gs]et_pointer () */ + void *user_pointer; /* For assuan_get_pointer and assuan-set_pointer (). */ FILE *log_fp; @@ -90,13 +129,10 @@ struct assuan_context_s int pipe_mode; /* We are in pipe mode, i.e. we can handle just one connection and must terminate then */ - pid_t pid; /* In pipe mode, the pid of the child server process. - In socket mode, the pid of the server */ + pid_t pid; /* The the pid of the peer. */ int listen_fd; /* The fd we are listening on (used by socket servers) */ int connected_fd; /* helper */ - pid_t client_pid; /* for a socket server the PID of the client or -1 - if not available */ /* Used for Unix domain sockets. */ struct sockaddr_un myaddr; @@ -145,7 +181,7 @@ void _assuan_release_context (ASSUAN_CONTEXT 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. */ -AssuanError _assuan_domain_init (ASSUAN_CONTEXT *r_ctx, +assuan_error_t _assuan_domain_init (ASSUAN_CONTEXT *r_ctx, int rendezvousfd, pid_t peer); @@ -156,9 +192,11 @@ int _assuan_register_std_commands (ASSUAN_CONTEXT ctx); int _assuan_read_line (ASSUAN_CONTEXT ctx); int _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size); int _assuan_cookie_write_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 --*/ -AssuanError _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off); +assuan_error_t _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off); /*-- assuan-util.c --*/ @@ -177,17 +215,40 @@ void _assuan_free (void *p); void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length); void _assuan_log_sanitized_string (const char *string); +#ifdef HAVE_W32_SYSTEM +const char *_assuan_w32_strerror (int ec); +#define w32_strerror(e) _assuan_w32_strerror ((e)) +#endif /*HAVE_W32_SYSTEM*/ + + +/*-- assuan-logging.c --*/ +void _assuan_set_default_log_stream (FILE *fp); + +void _assuan_log_printf (const char *format, ...) +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) + __attribute__ ((format (printf,1,2))) +#endif + ; + /*-- 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, size_t size); +/*-- assuan-socket.c --*/ +int _assuan_close (int fd); +int _assuan_sock_new (int domain, int type, int proto); +int _assuan_sock_bind (int sockfd, struct sockaddr *addr, int addrlen); +int _assuan_sock_connect (int sockfd, struct sockaddr *addr, int addrlen); + #ifdef HAVE_FOPENCOOKIE /* We have to implement funopen in terms of glibc's fopencookie. */ -FILE *funopen(const void *cookie, cookie_read_function_t *readfn, - cookie_write_function_t *writefn, - cookie_seek_function_t *seekfn, - cookie_close_function_t *closefn); +FILE *_assuan_funopen(void *cookie, + cookie_read_function_t *readfn, + cookie_write_function_t *writefn, + cookie_seek_function_t *seekfn, + cookie_close_function_t *closefn); +#define funopen(a,r,w,s,c) _assuan_funopen ((a), (r), (w), (s), (c)) #endif /*HAVE_FOPENCOOKIE*/ #endif /*ASSUAN_DEFS_H*/ diff --git a/assuan/assuan-domain-connect.c b/assuan/assuan-domain-connect.c index b92be3b8..b55e9c31 100644 --- a/assuan/assuan-domain-connect.c +++ b/assuan/assuan-domain-connect.c @@ -27,8 +27,12 @@ #include #include #include +#ifndef HAVE_W32_SYSTEM #include #include +#else +#include +#endif #if HAVE_SYS_UIO_H #include #endif @@ -39,17 +43,23 @@ #include "assuan-defs.h" -#define LOG(format, args...) \ - fprintf (assuan_get_assuan_log_stream (), \ - assuan_get_assuan_log_prefix (), \ - "%s" format , ## args) +#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 ctx) +do_deinit (assuan_context_t ctx) { if (ctx->inbound.fd != -1) - close (ctx->inbound.fd); + _assuan_close (ctx->inbound.fd); ctx->inbound.fd = -1; ctx->outbound.fd = -1; @@ -65,7 +75,7 @@ do_deinit (ASSUAN_CONTEXT ctx) assert (ctx->pendingfdscount > 0); for (i = 0; i < ctx->pendingfdscount; i ++) - close (ctx->pendingfds[i]); + _assuan_close (ctx->pendingfds[i]); free (ctx->pendingfds); } @@ -76,10 +86,11 @@ do_deinit (ASSUAN_CONTEXT ctx) /* Read from the socket server. */ static ssize_t -domain_reader (ASSUAN_CONTEXT ctx, void *buf, size_t buflen) +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. */ @@ -166,15 +177,15 @@ domain_reader (ASSUAN_CONTEXT ctx, void *buf, size_t buflen) /* 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. */ - LOG ("Not setup to receive messages from: `%s'.", - ((struct sockaddr_un *) msg.msg_name)->sun_path); + _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) { - LOG ("domain_reader: %s\n", strerror (errno)); + _assuan_log_printf ("domain_reader: %s\n", strerror (errno)); return -1; } @@ -190,7 +201,7 @@ domain_reader (ASSUAN_CONTEXT ctx, void *buf, size_t buflen) sizeof (int) * (ctx->pendingfdscount + 1)); if (! tmp) { - LOG ("domain_reader: %s\n", strerror (errno)); + _assuan_log_printf ("domain_reader: %s\n", strerror (errno)); return -1; } @@ -198,13 +209,16 @@ domain_reader (ASSUAN_CONTEXT ctx, void *buf, size_t buflen) ctx->pendingfds[ctx->pendingfdscount++] = *(int *) CMSG_DATA (&cmsg.hdr); - LOG ("Received file descriptor %d from peer.\n", + _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. */ @@ -223,8 +237,9 @@ domain_reader (ASSUAN_CONTEXT ctx, void *buf, size_t buflen) /* Write to the domain server. */ static ssize_t -domain_writer (ASSUAN_CONTEXT ctx, const void *buf, size_t buflen) +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; @@ -244,14 +259,21 @@ domain_writer (ASSUAN_CONTEXT ctx, const void *buf, size_t buflen) len = sendmsg (ctx->outbound.fd, &msg, 0); if (len < 0) - LOG ("domain_writer: %s\n", strerror (errno)); - + _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 AssuanError -domain_sendfd (ASSUAN_CONTEXT ctx, int fd) +static assuan_error_t +domain_sendfd (assuan_context_t ctx, int fd) { +#ifndef HAVE_W32_SYSTEM struct msghdr msg; struct { @@ -282,19 +304,23 @@ domain_sendfd (ASSUAN_CONTEXT ctx, int fd) len = sendmsg (ctx->outbound.fd, &msg, 0); if (len < 0) { - LOG ("domain_sendfd: %s\n", strerror (errno)); + _assuan_log_printf ("domain_sendfd: %s\n", strerror (errno)); return ASSUAN_General_Error; } else return 0; +#else + return 0; +#endif } -static AssuanError -domain_receivefd (ASSUAN_CONTEXT ctx, int *fd) +static assuan_error_t +domain_receivefd (assuan_context_t ctx, int *fd) { +#ifndef HAVE_W32_SYSTEM if (ctx->pendingfds == 0) { - LOG ("No pending file descriptors!\n"); + _assuan_log_printf ("no pending file descriptors!\n"); return ASSUAN_General_Error; } @@ -312,7 +338,7 @@ domain_receivefd (ASSUAN_CONTEXT ctx, int *fd) ctx->pendingfds = realloc (ctx->pendingfds, ctx->pendingfdscount * sizeof (int)); } - +#endif return 0; } @@ -321,14 +347,14 @@ domain_receivefd (ASSUAN_CONTEXT ctx, int *fd) /* 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. */ -AssuanError -_assuan_domain_init (ASSUAN_CONTEXT *r_ctx, int rendezvousfd, pid_t peer) +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 }; - AssuanError err; - ASSUAN_CONTEXT ctx; + assuan_error_t err; + assuan_context_t ctx; int fd; size_t len; int tries; @@ -349,17 +375,17 @@ _assuan_domain_init (ASSUAN_CONTEXT *r_ctx, int rendezvousfd, pid_t peer) /* Setup the socket. */ - fd = socket (PF_LOCAL, SOCK_DGRAM, 0); + fd = _assuan_sock_new (PF_LOCAL, SOCK_DGRAM, 0); if (fd == -1) { - LOG ("can't create socket: %s\n", strerror (errno)); + _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; @@ -380,13 +406,14 @@ _assuan_domain_init (ASSUAN_CONTEXT *r_ctx, int rendezvousfd, pid_t peer) /* 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) { - LOG ("cannot determine an appropriate temporary file " - "name. DOS in progress?\n"); + _assuan_log_printf ("cannot determine an appropriate temporary file " + "name. DoS in progress?\n"); _assuan_release_context (ctx); - close (fd); + _assuan_close (fd); return ASSUAN_General_Error; } @@ -396,17 +423,17 @@ _assuan_domain_init (ASSUAN_CONTEXT *r_ctx, int rendezvousfd, pid_t peer) memcpy (ctx->myaddr.sun_path, buf, len); len += offsetof (struct sockaddr_un, sun_path); - err = bind (fd, (struct sockaddr *) &ctx->myaddr, len); + err = _assuan_sock_bind (fd, (struct sockaddr *) &ctx->myaddr, len); if (! err) break; } if (err) { - LOG ("can't bind to `%s': %s\n", ctx->myaddr.sun_path, - strerror (errno)); + _assuan_log_printf ("can't bind to `%s': %s\n", ctx->myaddr.sun_path, + strerror (errno)); _assuan_release_context (ctx); - close (fd); + _assuan_close (fd); return ASSUAN_Connect_Failed; } @@ -418,7 +445,7 @@ _assuan_domain_init (ASSUAN_CONTEXT *r_ctx, int rendezvousfd, pid_t peer) fp = fdopen (rendezvousfd, "w+"); if (! fp) { - LOG ("can't open rendezvous port: %s\n", strerror (errno)); + _assuan_log_printf ("can't open rendezvous port: %s\n", strerror (errno)); return ASSUAN_Connect_Failed; } @@ -447,10 +474,10 @@ _assuan_domain_init (ASSUAN_CONTEXT *r_ctx, int rendezvousfd, pid_t peer) return 0; } -AssuanError -assuan_domain_connect (ASSUAN_CONTEXT * r_ctx, int rendezvousfd, pid_t peer) +assuan_error_t +assuan_domain_connect (assuan_context_t * r_ctx, int rendezvousfd, pid_t peer) { - AssuanError aerr; + assuan_error_t aerr; int okay, off; aerr = _assuan_domain_init (r_ctx, rendezvousfd, peer); @@ -460,10 +487,11 @@ assuan_domain_connect (ASSUAN_CONTEXT * r_ctx, int rendezvousfd, pid_t peer) /* Initial handshake. */ aerr = _assuan_read_from_server (*r_ctx, &okay, &off); if (aerr) - LOG ("can't connect to server: %s\n", assuan_strerror (aerr)); + _assuan_log_printf ("can't connect to server: %s\n", + assuan_strerror (aerr)); else if (okay != 1) { - LOG ("can't connect to server: `"); + _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; diff --git a/assuan/assuan-domain-server.c b/assuan/assuan-domain-server.c index b62b140d..45d53c26 100644 --- a/assuan/assuan-domain-server.c +++ b/assuan/assuan-domain-server.c @@ -27,12 +27,12 @@ #include "assuan-defs.h" /* Initialize a server. */ -AssuanError +assuan_error_t assuan_init_domain_server (ASSUAN_CONTEXT *r_ctx, int rendezvousfd, pid_t peer) { - AssuanError err; + assuan_error_t err; err = _assuan_domain_init (r_ctx, rendezvousfd, peer); if (err) diff --git a/assuan/assuan-handler.c b/assuan/assuan-handler.c index 7a774cb6..21501a35 100644 --- a/assuan/assuan-handler.c +++ b/assuan/assuan-handler.c @@ -135,7 +135,7 @@ std_handler_end (ASSUAN_CONTEXT ctx, char *line) return set_error (ctx, Not_Implemented, NULL); } -AssuanError +assuan_error_t assuan_command_parse_fd (ASSUAN_CONTEXT ctx, char *line, int *rfd) { char *endp; @@ -391,7 +391,7 @@ my_strcasecmp (const char *a, const char *b) } /* Parse the line, break out the command, find it in the command - table, remove leading and white spaces from the arguments, all the + table, remove leading and white spaces from the arguments, call the handler with the argument line and return the error */ static int dispatch_command (ASSUAN_CONTEXT ctx, char *line, int linelen) @@ -484,7 +484,7 @@ process_request (ASSUAN_CONTEXT ctx) } else { - char errline[256]; + char errline[300]; if (rc < 100) sprintf (errline, "ERR %d server fault (%.50s)", @@ -493,8 +493,40 @@ process_request (ASSUAN_CONTEXT ctx) { const char *text = ctx->err_no == rc? ctx->err_str:NULL; - sprintf (errline, "ERR %d %.50s%s%.100s", - rc, assuan_strerror (rc), text? " - ":"", text?text:""); +#if defined(__GNUC__) && defined(__ELF__) + /* If we have weak symbol support we try to use the error + 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 + weak symbol support is available in case GNU ld is not + used. */ + unsigned int source, code; + + int gpg_strerror_r (unsigned int err, char *buf, size_t buflen) + __attribute__ ((weak)); + + const char *gpg_strsource (unsigned int err) + __attribute__ ((weak)); + + source = ((rc >> 24) & 0xff); + code = (rc & 0x00ffffff); + if (source && gpg_strsource && gpg_strerror_r) + { + /* Assume this is an libgpg-error. */ + char ebuf[50]; + + gpg_strerror_r (rc, ebuf, sizeof ebuf ); + sprintf (errline, "ERR %d %.50s <%.30s>%s%.100s", + rc, + ebuf, + gpg_strsource (rc), + text? " - ":"", text?text:""); + } + else +#endif /* __GNUC__ && __ELF__ */ + sprintf (errline, "ERR %d %.50s%s%.100s", + rc, assuan_strerror (rc), text? " - ":"", text?text:""); } rc = assuan_write_line (ctx, errline); } @@ -512,7 +544,7 @@ process_request (ASSUAN_CONTEXT ctx) * assuan_process: * @ctx: assuan context * - * This fucntion is used to handle the assuan protocol after a + * This function is used to handle the assuan protocol after a * connection has been established using assuan_accept(). This is the * main protocol handler. * @@ -625,7 +657,7 @@ assuan_get_data_fp (ASSUAN_CONTEXT ctx) /* Set the text used for the next OK reponse. This string is automatically reset to NULL after the next command. */ -AssuanError +assuan_error_t assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line) { if (!ctx) @@ -652,15 +684,16 @@ assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line) -void +assuan_error_t assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text) { char buffer[256]; char *helpbuf; size_t n; + assuan_error_t ae; if ( !ctx || !keyword) - return; + return ASSUAN_Invalid_Value; if (!text) text = ""; @@ -674,7 +707,7 @@ assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text) strcat (buffer, " "); strcat (buffer, text); } - assuan_write_line (ctx, buffer); + ae = assuan_write_line (ctx, buffer); } else if ( (helpbuf = xtrymalloc (n)) ) { @@ -685,7 +718,10 @@ assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text) strcat (helpbuf, " "); strcat (helpbuf, text); } - assuan_write_line (ctx, helpbuf); + ae = assuan_write_line (ctx, helpbuf); xfree (helpbuf); } + else + ae = 0; + return ae; } diff --git a/assuan/assuan-inquire.c b/assuan/assuan-inquire.c index ec9d8e65..8d034ca5 100644 --- a/assuan/assuan-inquire.c +++ b/assuan/assuan-inquire.c @@ -134,11 +134,11 @@ free_membuf (struct membuf *mb) * * Return value: 0 on success or an ASSUAN error code **/ -AssuanError -assuan_inquire (ASSUAN_CONTEXT ctx, const char *keyword, - char **r_buffer, size_t *r_length, size_t maxlen) +assuan_error_t +assuan_inquire (assuan_context_t ctx, const char *keyword, + unsigned char **r_buffer, size_t *r_length, size_t maxlen) { - AssuanError rc; + assuan_error_t rc; struct membuf mb; char cmdbuf[LINELENGTH-10]; /* (10 = strlen ("INQUIRE ")+CR,LF) */ unsigned char *line, *p; diff --git a/assuan/assuan-io.c b/assuan/assuan-io.c index 5dca009d..321f2bae 100644 --- a/assuan/assuan-io.c +++ b/assuan/assuan-io.c @@ -1,5 +1,5 @@ /* assuan-io.c - Wraps the read and write functions. - * Copyright (C) 2002 Free Software Foundation, Inc. + * Copyright (C) 2002, 2004 Free Software Foundation, Inc. * * This file is part of Assuan. * @@ -18,41 +18,53 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include "assuan-defs.h" #include #include +#ifdef HAVE_W32_SYSTEM +#include +#endif -#ifdef _ASSUAN_IN_GPGME -ssize_t -_assuan_simple_read (ASSUAN_CONTEXT ctx, void *buffer, size_t size) -{ - return read (ctx->inbound.fd, buffer, size); -} - -ssize_t -_assuan_simple_write (ASSUAN_CONTEXT ctx, const void *buffer, size_t size) -{ - return write (ctx->outbound.fd, buffer, size); -} - -#else - +#ifndef _ASSUAN_NO_PTH 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); +#ifndef HAVE_W32_SYSTEM #pragma weak pth_read #pragma weak pth_write - -ssize_t -_assuan_simple_read (ASSUAN_CONTEXT ctx, void *buffer, size_t size) -{ - return (pth_read ? pth_read : read) (ctx->inbound.fd, buffer, size); -} - -ssize_t -_assuan_simple_write (ASSUAN_CONTEXT ctx, const void *buffer, size_t size) -{ - return (pth_write ? pth_write : write) (ctx->outbound.fd, buffer, size); -} - #endif +#endif /*!_ASSUAN_NO_PTH*/ + +ssize_t +_assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size) +{ +#ifdef _ASSUAN_NO_PTH + return read (ctx->inbound.fd, buffer, size); +#else +# ifndef HAVE_W32_SYSTEM + return (pth_read ? pth_read : read) (ctx->inbound.fd, buffer, size); +# else + return pth_read ? pth_read (ctx->inbound.fd, buffer, size) + : recv (ctx->inbound.fd, buffer, size, 0); +# endif +# endif +} + +ssize_t +_assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size) +{ +#ifdef _ASSUAN_NO_PTH + return write (ctx->outbound.fd, buffer, size); +#else +# ifndef HAVE_W32_SYSTEM + return (pth_write ? pth_write : write) (ctx->outbound.fd, buffer, size); +# else + return pth_write ? pth_write (ctx->outbound.fd, buffer, size) + : send (ctx->outbound.fd, buffer, size, 0); +# endif +#endif +} diff --git a/assuan/assuan-listen.c b/assuan/assuan-listen.c index aae3f7b7..04f138ef 100644 --- a/assuan/assuan-listen.c +++ b/assuan/assuan-listen.c @@ -1,5 +1,5 @@ /* assuan-listen.c - Wait for a connection (server) - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. * * This file is part of Assuan. * @@ -26,8 +26,8 @@ #include "assuan-defs.h" -AssuanError -assuan_set_hello_line (ASSUAN_CONTEXT ctx, const char *line) +assuan_error_t +assuan_set_hello_line (assuan_context_t ctx, const char *line) { if (!ctx) return ASSUAN_Invalid_Value; @@ -41,8 +41,13 @@ assuan_set_hello_line (ASSUAN_CONTEXT ctx, const char *line) char *buf = xtrymalloc (3+strlen(line)+1); if (!buf) return ASSUAN_Out_Of_Core; - strcpy (buf, "OK "); - strcpy (buf+3, line); + if (strchr (line, '\n')) + strcpy (buf, line); + else + { + strcpy (buf, "OK "); + strcpy (buf+3, line); + } xfree (ctx->hello_line); ctx->hello_line = buf; } @@ -61,10 +66,11 @@ assuan_set_hello_line (ASSUAN_CONTEXT ctx, const char *line) * Return value: 0 on success or an error if the connection could for * some reason not be established. **/ -AssuanError -assuan_accept (ASSUAN_CONTEXT ctx) +assuan_error_t +assuan_accept (assuan_context_t ctx) { int rc; + const char *p, *pend; if (!ctx) return ASSUAN_Invalid_Value; @@ -77,9 +83,26 @@ assuan_accept (ASSUAN_CONTEXT ctx) if (rc) return rc; - /* send the hello */ - rc = assuan_write_line (ctx, ctx->hello_line? ctx->hello_line - : "OK Your orders please"); + /* Send the hello. */ + p = ctx->hello_line; + if (p && (pend = strchr (p, '\n'))) + { /* This is a multi line hello. Send all but the last line as + comments. */ + do + { + rc = _assuan_write_line (ctx, "# ", p, pend - p); + if (rc) + return rc; + p = pend + 1; + pend = strchr (p, '\n'); + } + while (pend); + rc = _assuan_write_line (ctx, "OK ", p, strlen (p)); + } + else if (p) + rc = assuan_write_line (ctx, p); + else + rc = assuan_write_line (ctx, "OK Pleased to meet you"); if (rc) return rc; @@ -92,14 +115,14 @@ assuan_accept (ASSUAN_CONTEXT ctx) int -assuan_get_input_fd (ASSUAN_CONTEXT ctx) +assuan_get_input_fd (assuan_context_t ctx) { return ctx? ctx->input_fd : -1; } int -assuan_get_output_fd (ASSUAN_CONTEXT ctx) +assuan_get_output_fd (assuan_context_t ctx) { return ctx? ctx->output_fd : -1; } @@ -107,25 +130,25 @@ assuan_get_output_fd (ASSUAN_CONTEXT ctx) /* Close the fd descriptor set by the command INPUT FD=n. We handle this fd inside assuan so that we can do some initial checks */ -AssuanError -assuan_close_input_fd (ASSUAN_CONTEXT ctx) +assuan_error_t +assuan_close_input_fd (assuan_context_t ctx) { if (!ctx || ctx->input_fd == -1) return ASSUAN_Invalid_Value; - close (ctx->input_fd); + _assuan_close (ctx->input_fd); ctx->input_fd = -1; return 0; } /* Close the fd descriptor set by the command OUTPUT FD=n. We handle this fd inside assuan so that we can do some initial checks */ -AssuanError -assuan_close_output_fd (ASSUAN_CONTEXT ctx) +assuan_error_t +assuan_close_output_fd (assuan_context_t ctx) { if (!ctx || ctx->output_fd == -1) return ASSUAN_Invalid_Value; - close (ctx->output_fd); + _assuan_close (ctx->output_fd); ctx->output_fd = -1; return 0; } diff --git a/assuan/assuan-logging.c b/assuan/assuan-logging.c index 340ce724..7c65d579 100644 --- a/assuan/assuan-logging.c +++ b/assuan/assuan-logging.c @@ -1,5 +1,5 @@ /* assuan-logging.c - Default logging function. - * Copyright (C) 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. * * This file is part of Assuan. * @@ -18,11 +18,28 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#include "assuan-defs.h" +#ifdef HAVE_CONFIG_H +#include +#endif #include +#include +#include +#ifdef HAVE_W32_SYSTEM +#include +#endif /*HAVE_W32_SYSTEM*/ +#include "assuan-defs.h" + +static char prefix_buffer[80]; static FILE *_assuan_log; +void +_assuan_set_default_log_stream (FILE *fp) +{ + if (!_assuan_log) + _assuan_log = fp; +} + void assuan_set_assuan_log_stream (FILE *fp) { @@ -35,8 +52,61 @@ assuan_get_assuan_log_stream (void) return _assuan_log ? _assuan_log : stderr; } + +/* Set the prefix to be used for logging to TEXT or + resets it to the default if TEXT is NULL. */ +void +assuan_set_assuan_log_prefix (const char *text) +{ + if (text) + { + strncpy (prefix_buffer, text, sizeof (prefix_buffer)-1); + prefix_buffer[sizeof (prefix_buffer)-1] = 0; + } + else + *prefix_buffer = 0; +} + const char * assuan_get_assuan_log_prefix (void) { - return ""; + return prefix_buffer; } + + +void +_assuan_log_printf (const char *format, ...) +{ + va_list arg_ptr; + FILE *fp; + const char *prf; + + fp = assuan_get_assuan_log_stream (); + prf = assuan_get_assuan_log_prefix (); + if (*prf) + { + fputs (prf, fp); + fputs (": ", fp); + } + + va_start (arg_ptr, format); + vfprintf (fp, format, arg_ptr ); + va_end (arg_ptr); +} + + + +#ifdef HAVE_W32_SYSTEM +const char * +_assuan_w32_strerror (int ec) +{ + static char strerr[256]; + + if (ec == -1) + ec = (int)GetLastError (); + FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec, + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), + strerr, sizeof (strerr)-1, NULL); + return strerr; +} +#endif /*HAVE_W32_SYSTEM*/ diff --git a/assuan/assuan-pipe-connect.c b/assuan/assuan-pipe-connect.c index f79884cf..4ce3862a 100644 --- a/assuan/assuan-pipe-connect.c +++ b/assuan/assuan-pipe-connect.c @@ -30,7 +30,11 @@ #include #include #include +#ifndef HAVE_W32_SYSTEM #include +#else +#include +#endif #include "assuan-defs.h" @@ -40,11 +44,47 @@ #define MAX_OPEN_FDS 20 #endif -#define LOG(format, args...) \ - fprintf (assuan_get_assuan_log_stream (), \ - assuan_get_assuan_log_prefix (), \ - "%s" format , ## args) +#ifdef HAVE_W32_SYSTEM +/* We assume that a HANDLE can be represented by an int which should + be true for all i386 systems (HANDLE is defined as void *) and + these are the only systems for which Windows is available. Further + we assume that -1 denotes an invalid handle. */ +#define fd_to_handle(a) ((HANDLE)(a)) +#define handle_to_fd(a) ((int)(a)) +#define pid_to_handle(a) ((HANDLE)(a)) +#define handle_to_pid(a) ((int)(a)) +#endif /*HAVE_W32_SYSTEM*/ + +/* This should be called to make sure that SIGPIPE gets ignored. */ +static void +fix_signals (void) +{ +#ifndef _ASSUAN_NO_FIXED_SIGNALS +#ifndef HAVE_DOSISH_SYSTEM /* No SIGPIPE for these systems. */ + static int fixed_signals; + + if (!fixed_signals) + { + struct sigaction act; + + sigaction (SIGPIPE, NULL, &act); + if (act.sa_handler == SIG_DFL) + { + act.sa_handler = SIG_IGN; + sigemptyset (&act.sa_mask); + act.sa_flags = 0; + sigaction (SIGPIPE, &act, NULL); + } + fixed_signals = 1; + /* FIXME: This is not MT safe */ + } +#endif /*HAVE_DOSISH_SYSTEM*/ +#endif /*!_ASSUAN_NO_FIXED_SIGNALS*/ +} + + +#ifndef HAVE_W32_SYSTEM static int writen (int fd, const char *buffer, size_t length) { @@ -63,75 +103,328 @@ writen (int fd, const char *buffer, size_t length) } return 0; /* okay */ } - +#endif static int -do_finish (ASSUAN_CONTEXT ctx) +do_finish (assuan_context_t ctx) { if (ctx->inbound.fd != -1) { - close (ctx->inbound.fd); + _assuan_close (ctx->inbound.fd); ctx->inbound.fd = -1; } if (ctx->outbound.fd != -1) { - close (ctx->outbound.fd); + _assuan_close (ctx->outbound.fd); ctx->outbound.fd = -1; } - if (ctx->pid != -1) + if (ctx->pid != -1 && ctx->pid) { -#if 0 - /* This is already done by the double fork. */ - waitpid (ctx->pid, NULL, 0); /* FIXME Check return value. */ +#ifndef HAVE_W32_SYSTEM +#ifndef _ASSUAN_USE_DOUBLE_FORK + if (!ctx->flags.no_waitpid) + waitpid (ctx->pid, NULL, 0); ctx->pid = -1; #endif +#endif /*!HAVE_W32_SYSTEM*/ } return 0; } static void -do_deinit (ASSUAN_CONTEXT ctx) +do_deinit (assuan_context_t ctx) { do_finish (ctx); } +#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. */ +static int +build_w32_commandline (char * const *argv, char **cmdline) +{ + int i, n; + const char *s; + char *buf, *p; + + *cmdline = NULL; + n = 0; + for (i=0; (s=argv[i]); i++) + { + n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */ + for (; *s; s++) + if (*s == '\"') + n++; /* Need to double inner quotes. */ + } + n++; + + buf = p = xtrymalloc (n); + if (!buf) + return -1; + + for (i=0; argv[i]; i++) + { + if (i) + p = stpcpy (p, " "); + if (!*argv[i]) /* Empty string. */ + p = stpcpy (p, "\"\""); + else if (strpbrk (argv[i], " \t\n\v\f\"")) + { + p = stpcpy (p, "\""); + for (s=argv[i]; *s; s++) + { + *p++ = *s; + if (*s == '\"') + *p++ = *s; + } + *p++ = '\"'; + *p = 0; + } + else + p = stpcpy (p, argv[i]); + } + + *cmdline= buf; + return 0; +} +#endif /*HAVE_W32_SYSTEM*/ + + +#ifdef HAVE_W32_SYSTEM +/* Create pipe where one end end is inheritable. */ +static int +create_inheritable_pipe (int filedes[2], int for_write) +{ + HANDLE r, w, h; + SECURITY_ATTRIBUTES sec_attr; + + memset (&sec_attr, 0, sizeof sec_attr ); + sec_attr.nLength = sizeof sec_attr; + sec_attr.bInheritHandle = FALSE; + + if (!CreatePipe (&r, &w, &sec_attr, 0)) + { + _assuan_log_printf ("CreatePipe failed: %s\n", w32_strerror (-1)); + return -1; + } + + if (!DuplicateHandle (GetCurrentProcess(), for_write? r : w, + GetCurrentProcess(), &h, 0, + TRUE, DUPLICATE_SAME_ACCESS )) + { + _assuan_log_printf ("DuplicateHandle failed: %s\n", w32_strerror (-1)); + CloseHandle (r); + CloseHandle (w); + return -1; + } + if (for_write) + { + CloseHandle (r); + r = h; + } + else + { + CloseHandle (w); + w = h; + } + + filedes[0] = handle_to_fd (r); + filedes[1] = handle_to_fd (w); + return 0; +} +#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. */ -AssuanError -assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[], - int *fd_child_list) + 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, char *const argv[], + int *fd_child_list, + void (*atfork) (void *opaque, int reserved), + void *atforkvalue) { -#ifndef _ASSUAN_IN_GPGME - static int fixed_signals = 0; -#endif - AssuanError err; +#ifdef HAVE_W32_SYSTEM + assuan_error_t err; int rp[2]; int wp[2]; + char mypidstr[50]; + char *cmdline; + SECURITY_ATTRIBUTES sec_attr; + PROCESS_INFORMATION pi = + { + NULL, /* Returns process handle. */ + 0, /* Returns primary thread handle. */ + 0, /* Returns pid. */ + 0 /* Returns tid. */ + }; + STARTUPINFO si; + int fd, *fdp; + HANDLE nullfd = INVALID_HANDLE_VALUE; if (!ctx || !name || !argv || !argv[0]) return ASSUAN_Invalid_Value; -#ifndef _ASSUAN_IN_GPGME - if (!fixed_signals) - { - struct sigaction act; - - sigaction (SIGPIPE, NULL, &act); - if (act.sa_handler == SIG_DFL) - { - act.sa_handler = SIG_IGN; - sigemptyset (&act.sa_mask); - act.sa_flags = 0; - sigaction (SIGPIPE, &act, NULL); - } - fixed_signals = 1; - /* FIXME: This is not MT safe */ + fix_signals (); + + sprintf (mypidstr, "%lu", (unsigned long)getpid ()); + + /* Build the command line. */ + if (build_w32_commandline (argv, &cmdline)) + return ASSUAN_Out_Of_Core; + + /* Create thew two pipes. */ + if (create_inheritable_pipe (rp, 0)) + { + xfree (cmdline); + return ASSUAN_General_Error; } -#endif + + if (create_inheritable_pipe (wp, 1)) + { + CloseHandle (fd_to_handle (rp[0])); + CloseHandle (fd_to_handle (rp[1])); + xfree (cmdline); + return ASSUAN_General_Error; + } + + + err = _assuan_new_context (ctx); + if (err) + { + CloseHandle (fd_to_handle (rp[0])); + CloseHandle (fd_to_handle (rp[1])); + CloseHandle (fd_to_handle (wp[0])); + CloseHandle (fd_to_handle (wp[1])); + xfree (cmdline); + return ASSUAN_General_Error; + } + + (*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: Actually we should set the "_assuan_pipe_connect_pid" env + variable. However this requires us to write a full environment + handler, because the strings are expected in sorted order. The + suggestion given in the MS Reference Library, to save the old + value, changeit, create proces and restore it, is not thread + safe. */ + + /* Start the process. */ + memset (&sec_attr, 0, sizeof sec_attr ); + sec_attr.nLength = sizeof sec_attr; + sec_attr.bInheritHandle = FALSE; + + memset (&si, 0, sizeof si); + si.cb = sizeof (si); + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdInput = fd_to_handle (wp[0]); + si.hStdOutput = fd_to_handle (rp[1]); + + /* Dup stderr to /dev/null unless it is in the list of FDs to be + passed to the child. */ + fd = fileno (stderr); + fdp = fd_child_list; + if (fdp) + { + for (; *fdp != -1 && *fdp != fd; fdp++) + ; + } + if (!fdp || *fdp == -1) + { + nullfd = CreateFile ("nul", GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL); + if (nullfd == INVALID_HANDLE_VALUE) + { + _assuan_log_printf ("can't open `nul': %s\n", w32_strerror (-1)); + CloseHandle (fd_to_handle (rp[0])); + CloseHandle (fd_to_handle (rp[1])); + CloseHandle (fd_to_handle (wp[0])); + CloseHandle (fd_to_handle (wp[1])); + xfree (cmdline); + _assuan_release_context (*ctx); + return -1; + } + si.hStdError = nullfd; + } + else + si.hStdError = fd_to_handle (_get_osfhandle (fd)); + + + /* Note: We inherit all handles flagged as inheritable. This seems + to be a security flaw but there seems to be no way of selecting + handles to inherit. */ + /* _assuan_log_printf ("CreateProcess, path=`%s' cmdline=`%s'\n", */ + /* name, cmdline); */ + if (!CreateProcess (name, /* Program to start. */ + cmdline, /* Command line arguments. */ + &sec_attr, /* Process security attributes. */ + &sec_attr, /* Thread security attributes. */ + TRUE, /* Inherit handles. */ + (CREATE_DEFAULT_ERROR_MODE + | GetPriorityClass (GetCurrentProcess ()) + | CREATE_SUSPENDED), /* Creation flags. */ + NULL, /* Environment. */ + NULL, /* Use current drive/directory. */ + &si, /* Startup information. */ + &pi /* Returns process information. */ + )) + { + _assuan_log_printf ("CreateProcess failed: %s\n", w32_strerror (-1)); + CloseHandle (fd_to_handle (rp[0])); + CloseHandle (fd_to_handle (rp[1])); + CloseHandle (fd_to_handle (wp[0])); + CloseHandle (fd_to_handle (wp[1])); + if (nullfd != INVALID_HANDLE_VALUE) + CloseHandle (nullfd); + xfree (cmdline); + _assuan_release_context (*ctx); + return ASSUAN_General_Error; + } + xfree (cmdline); + cmdline = NULL; + if (nullfd != INVALID_HANDLE_VALUE) + { + CloseHandle (nullfd); + nullfd = INVALID_HANDLE_VALUE; + } + + CloseHandle (fd_to_handle (rp[1])); + CloseHandle (fd_to_handle (wp[0])); + + /* _assuan_log_printf ("CreateProcess ready: hProcess=%p hThread=%p" */ + /* " dwProcessID=%d dwThreadId=%d\n", */ + /* pi.hProcess, pi.hThread, */ + /* (int) pi.dwProcessId, (int) pi.dwThreadId); */ + + ResumeThread (pi.hThread); + CloseHandle (pi.hThread); + (*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; @@ -158,8 +451,8 @@ assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[], (*ctx)->deinit_handler = do_deinit; (*ctx)->finish_handler = do_finish; - /* FIXME: Use _gpgme_io_spawn. The PID stored here is actually - soon useless. */ + /* 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) { @@ -173,111 +466,131 @@ assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[], if ((*ctx)->pid == 0) { - /* Intermediate child to prevent zombie processes. */ - pid_t pid; - +#ifdef _ASSUAN_USE_DOUBLE_FORK if ((pid = fork ()) == 0) +#endif { - /* Child. */ + int i, n; + char errbuf[512]; + int *fdp; + + if (atfork) + atfork (atforkvalue, 0); - int i, n; - char errbuf[512]; - int *fdp; + /* 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 handles to stdin/stdout. */ - if (rp[1] != STDOUT_FILENO) - { - if (dup2 (rp[1], STDOUT_FILENO) == -1) - { - LOG ("dup2 failed in child: %s\n", strerror (errno)); - _exit (4); - } - } - if (wp[0] != STDIN_FILENO) - { - if (dup2 (wp[0], STDIN_FILENO) == -1) - { - LOG ("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) - { - LOG ("can't open `/dev/null': %s\n", strerror (errno)); - _exit (4); - } - if (dup2 (fd, STDERR_FILENO) == -1) - { - LOG ("dup2(dev/null, 2) 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) + { + 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); - } + /* 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++; + } - errno = 0; + if (!(fdp && *fdp != -1)) + close(i); + } + errno = 0; - execv (name, argv); - /* oops - use the pipe to tell the parent about it */ - snprintf (errbuf, sizeof(errbuf)-1, "ERR %d can't exec `%s': %.50s\n", - ASSUAN_Problem_Starting_Server, name, strerror (errno)); - errbuf[sizeof(errbuf)-1] = 0; - writen (1, errbuf, strlen (errbuf)); - _exit (4); - } /* End child. */ + /* 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, 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) - LOG ("can't connect server: %s\n", assuan_strerror (err)); + _assuan_log_printf ("can't connect server: %s\n", + assuan_strerror (err)); else if (okay != 1) { - LOG ("can't connect server: `%s'\n", (*ctx)->inbound.line); + _assuan_log_printf ("can't connect server: `%s'\n", + (*ctx)->inbound.line); err = ASSUAN_Connect_Failed; } } @@ -292,15 +605,13 @@ assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[], } - - - - - - - - - - - - +/* 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. */ +assuan_error_t +assuan_pipe_connect (assuan_context_t *ctx, const char *name, char *const argv[], + int *fd_child_list) +{ + return assuan_pipe_connect2 (ctx, name, argv, fd_child_list, NULL, NULL); +} diff --git a/assuan/assuan-pipe-server.c b/assuan/assuan-pipe-server.c index ba269b04..beff9a3e 100644 --- a/assuan/assuan-pipe-server.c +++ b/assuan/assuan-pipe-server.c @@ -22,9 +22,14 @@ #include #include #include +#ifdef HAVE_W32_SYSTEM +#include +#include +#endif #include "assuan-defs.h" + static void deinit_pipe_server (ASSUAN_CONTEXT ctx) { @@ -69,7 +74,6 @@ _assuan_new_context (ASSUAN_CONTEXT *r_ctx) ctx->io = &io; ctx->listen_fd = -1; - ctx->client_pid = (pid_t)-1; /* Use the pipe server handler as a default. */ ctx->deinit_handler = deinit_pipe_server; ctx->accept_handler = accept_connection; @@ -84,7 +88,6 @@ _assuan_new_context (ASSUAN_CONTEXT *r_ctx) } - int assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2]) { @@ -94,11 +97,30 @@ assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2]) if (!rc) { ASSUAN_CONTEXT ctx = *r_ctx; + const char *s; + unsigned long ul; ctx->is_server = 1; - ctx->inbound.fd = filedes[0]; +#ifdef HAVE_W32_SYSTEM + /* MS Windows has so many different types of handle that one + needs to tranlsate them at many place forth and back. Also + make sure that the fiel descriptos are in binary mode. */ + setmode (filedes[0], O_BINARY); + setmode (filedes[1], O_BINARY); + 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]; +#endif ctx->pipe_mode = 1; + + s = getenv ("_assuan_pipe_connect_pid"); + if (s && (ul=strtoul (s, NULL, 10)) && ul) + ctx->pid = (pid_t)ul; + else + ctx->pid = (pid_t)-1; + } return rc; } diff --git a/assuan/assuan-socket-connect.c b/assuan/assuan-socket-connect.c index cd963ed2..9937c7a6 100644 --- a/assuan/assuan-socket-connect.c +++ b/assuan/assuan-socket-connect.c @@ -1,5 +1,5 @@ /* assuan-socket-connect.c - Assuan socket based client - * Copyright (C) 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. * * This file is part of Assuan. * @@ -22,25 +22,43 @@ #include #include #include +#include #include +#include #include +#ifndef HAVE_W32_SYSTEM #include #include -#include +#else +#include +#endif #include "assuan-defs.h" -#define LOG(format, args...) \ - fprintf (assuan_get_assuan_log_stream (), \ - assuan_get_assuan_log_prefix (), \ - "%s" format , ## args) +/* 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 +#ifndef SUN_LEN +# define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \ + + strlen ((ptr)->sun_path)) +#endif + + static int do_finish (ASSUAN_CONTEXT ctx) { if (ctx->inbound.fd != -1) { - close (ctx->inbound.fd); + _assuan_close (ctx->inbound.fd); } ctx->inbound.fd = -1; ctx->outbound.fd = -1; @@ -55,56 +73,64 @@ do_deinit (ASSUAN_CONTEXT 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. */ -AssuanError +assuan_error_t assuan_socket_connect (ASSUAN_CONTEXT *r_ctx, const char *name, pid_t server_pid) { static struct assuan_io io = { _assuan_simple_read, _assuan_simple_write }; - AssuanError err; + assuan_error_t err; ASSUAN_CONTEXT ctx; int fd; struct sockaddr_un srvr_addr; size_t len; + const char *s; if (!r_ctx || !name) return ASSUAN_Invalid_Value; *r_ctx = NULL; - /* we require that the name starts with a slash, so that we can - alter reuse this function for other socket types */ - if (*name != '/') + /* 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. */ + s = name; + if (*s && s[1] == ':') + s += 2; + if (*s != DIRSEP_C && *s != '/') return ASSUAN_Invalid_Value; + if (strlen (name)+1 >= sizeof srvr_addr.sun_path) return ASSUAN_Invalid_Value; err = _assuan_new_context (&ctx); if (err) return err; - ctx->pid = server_pid; /* save it in case we need it later */ ctx->deinit_handler = do_deinit; ctx->finish_handler = do_finish; - fd = socket (PF_LOCAL, SOCK_STREAM, 0); + + fd = _assuan_sock_new (PF_LOCAL, SOCK_STREAM, 0); if (fd == -1) { - LOG ("can't create socket: %s\n", strerror (errno)); + _assuan_log_printf ("can't create socket: %s\n", strerror (errno)); _assuan_release_context (ctx); return ASSUAN_General_Error; } memset (&srvr_addr, 0, sizeof srvr_addr); srvr_addr.sun_family = AF_LOCAL; - len = strlen (srvr_addr.sun_path) + 1; - memcpy (srvr_addr.sun_path, name, len); - len += (offsetof (struct sockaddr_un, sun_path)); + strncpy (srvr_addr.sun_path, name, sizeof (srvr_addr.sun_path) - 1); + srvr_addr.sun_path[sizeof (srvr_addr.sun_path) - 1] = 0; + len = SUN_LEN (&srvr_addr); - if (connect (fd, (struct sockaddr *) &srvr_addr, len) == -1) + + if (_assuan_sock_connect (fd, (struct sockaddr *) &srvr_addr, len) == -1) { - LOG ("can't connect to `%s': %s\n", name, strerror (errno)); + _assuan_log_printf ("can't connect to `%s': %s\n", + name, strerror (errno)); _assuan_release_context (ctx); - close (fd); + _assuan_close (fd); return ASSUAN_Connect_Failed; } @@ -118,10 +144,11 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx, err = _assuan_read_from_server (ctx, &okay, &off); if (err) - LOG ("can't connect to server: %s\n", assuan_strerror (err)); + _assuan_log_printf ("can't connect to server: %s\n", + assuan_strerror (err)); else if (okay != 1) { - LOG ("can't connect to server: `"); + /*LOG ("can't connect to server: `");*/ _assuan_log_sanitized_string (ctx->inbound.line); fprintf (assuan_get_assuan_log_stream (), "'\n"); err = ASSUAN_Connect_Failed; diff --git a/assuan/assuan-socket-server.c b/assuan/assuan-socket-server.c index d92e6e42..275af42c 100644 --- a/assuan/assuan-socket-server.c +++ b/assuan/assuan-socket-server.c @@ -22,26 +22,32 @@ #include #include #include +#include #include +#ifndef HAVE_W32_SYSTEM #include #include -#include +#else +#include +#endif #include "assuan-defs.h" static int -accept_connection_bottom (ASSUAN_CONTEXT ctx) +accept_connection_bottom (assuan_context_t ctx) { int fd = ctx->connected_fd; - ctx->client_pid = (pid_t)-1; #ifdef HAVE_SO_PEERCRED { + /* This overrides any already set PID if the function returns a + valid one. */ struct ucred cr; int cl = sizeof cr; - if ( !getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl) ) - ctx->client_pid = cr.pid; + if ( !getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl) + && cr.pid != (pid_t)-1 && cr.pid ) + ctx->pid = cr.pid; } #endif @@ -62,13 +68,12 @@ accept_connection_bottom (ASSUAN_CONTEXT ctx) static int -accept_connection (ASSUAN_CONTEXT ctx) +accept_connection (assuan_context_t ctx) { int fd; struct sockaddr_un clnt_addr; size_t len = sizeof clnt_addr; - ctx->client_pid = (pid_t)-1; fd = accept (ctx->listen_fd, (struct sockaddr*)&clnt_addr, &len ); if (fd == -1) { @@ -81,11 +86,11 @@ accept_connection (ASSUAN_CONTEXT ctx) } static int -finish_connection (ASSUAN_CONTEXT ctx) +finish_connection (assuan_context_t ctx) { if (ctx->inbound.fd != -1) { - close (ctx->inbound.fd); + _assuan_close (ctx->inbound.fd); } ctx->inbound.fd = -1; ctx->outbound.fd = -1; @@ -94,7 +99,7 @@ finish_connection (ASSUAN_CONTEXT ctx) static void -deinit_socket_server (ASSUAN_CONTEXT ctx) +deinit_socket_server (assuan_context_t ctx) { finish_connection (ctx); } @@ -105,9 +110,9 @@ static struct assuan_io io = { _assuan_simple_read, /* Initialize a server for the socket LISTEN_FD which has already be put into listen mode */ int -assuan_init_socket_server (ASSUAN_CONTEXT *r_ctx, int listen_fd) +assuan_init_socket_server (assuan_context_t *r_ctx, int listen_fd) { - ASSUAN_CONTEXT ctx; + assuan_context_t ctx; int rc; *r_ctx = NULL; @@ -139,9 +144,9 @@ assuan_init_socket_server (ASSUAN_CONTEXT *r_ctx, int listen_fd) /* Initialize a server using the already accepted socket FD. */ int -assuan_init_connected_socket_server (ASSUAN_CONTEXT *r_ctx, int fd) +assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd) { - ASSUAN_CONTEXT ctx; + assuan_context_t ctx; int rc; *r_ctx = NULL; diff --git a/assuan/assuan-util.c b/assuan/assuan-util.c index fc0beedb..7f442e93 100644 --- a/assuan/assuan-util.c +++ b/assuan/assuan-util.c @@ -1,5 +1,5 @@ /* assuan-util.c - Utility functions for Assuan - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. * * This file is part of Assuan. * @@ -23,6 +23,7 @@ #include #include #include +#include #include "assuan-defs.h" @@ -55,9 +56,19 @@ _assuan_realloc (void *a, size_t n) void * _assuan_calloc (size_t n, size_t m) { - void *p = _assuan_malloc (n*m); + void *p; + size_t nbytes; + + nbytes = n * m; + if (m && nbytes / m != n) + { + errno = ENOMEM; + return NULL; + } + + p = _assuan_malloc (nbytes); if (p) - memset (p, 0, n* m); + memset (p, 0, nbytes); return p; } @@ -73,7 +84,7 @@ _assuan_free (void *p) can take out a descriptive text. Inside the assuan code, use the macro set_error instead of this function. */ int -assuan_set_error (ASSUAN_CONTEXT ctx, int err, const char *text) +assuan_set_error (assuan_context_t ctx, int err, const char *text) { ctx->err_no = err; ctx->err_str = text; @@ -81,33 +92,34 @@ assuan_set_error (ASSUAN_CONTEXT ctx, int err, const char *text) } void -assuan_set_pointer (ASSUAN_CONTEXT ctx, void *pointer) +assuan_set_pointer (assuan_context_t ctx, void *pointer) { if (ctx) ctx->user_pointer = pointer; } void * -assuan_get_pointer (ASSUAN_CONTEXT ctx) +assuan_get_pointer (assuan_context_t ctx) { return ctx? ctx->user_pointer : NULL; } void -assuan_set_log_stream (ASSUAN_CONTEXT ctx, FILE *fp) +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 ctx) +assuan_begin_confidential (assuan_context_t ctx) { if (ctx) { @@ -116,7 +128,7 @@ assuan_begin_confidential (ASSUAN_CONTEXT ctx) } void -assuan_end_confidential (ASSUAN_CONTEXT ctx) +assuan_end_confidential (assuan_context_t ctx) { if (ctx) { @@ -124,6 +136,36 @@ assuan_end_confidential (ASSUAN_CONTEXT ctx) } } + + +/* For context CTX, set the flag FLAG to VALUE. Values for flags + are usually 1 or 0 but certain flags might allow for other values; + see the description of the type assuan_flag_t for details. */ +void +assuan_set_flag (assuan_context_t ctx, assuan_flag_t flag, int value) +{ + if (!ctx) + return; + switch (flag) + { + case ASSUAN_NO_WAITPID: ctx->flags.no_waitpid = value; break; + } +} + +/* Return the VALUE of FLAG in context CTX. */ +int +assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag) +{ + if (!ctx) + return 0; + switch (flag) + { + case ASSUAN_NO_WAITPID: return ctx->flags.no_waitpid; + } + return 0; +} + + /* Dump a possibly binary string (used for debugging). Distinguish ascii text from binary and print it accordingly. */ void @@ -133,7 +175,7 @@ _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length) int n; for (n=length,s=buffer; n; n--, s++) - if (!isascii (*s) || iscntrl (*s) || !isprint (*s)) + if ((!isascii (*s) || iscntrl (*s) || !isprint (*s)) && !(*s >= 0x80)) break; s = buffer; @@ -197,7 +239,7 @@ _assuan_log_sanitized_string (const char *string) break; default: - if (isascii (*s) && isprint (*s)) + if ((isascii (*s) && isprint (*s)) || (*s >= 0x80)) putc_unlocked (*s, fp); else { @@ -217,3 +259,4 @@ _assuan_log_sanitized_string (const char *string) funlockfile (fp); #endif } + diff --git a/assuan/assuan.h b/assuan/assuan.h index 05f02126..47404705 100644 --- a/assuan/assuan.h +++ b/assuan/assuan.h @@ -1,5 +1,5 @@ -/* assuan.c - Definitions for the Assuan protocol - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. +/* assuan.c - Definitions for the Assuan IPC library + * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. * * This file is part of Assuan. * @@ -25,22 +25,46 @@ #include #include -#include -#define _ASSUAN_IN_GPGME -#ifdef _ASSUAN_IN_GPGME +/* To use this file with libraries the following macros are often + useful: + + #define _ASSUAN_EXT_SYM_PREFIX _foo_ + + This prefixes all external symbols with "_foo_". + + #define _ASSUAN_NO_PTH + + This avoids inclusion of special GNU Pth hacks. + + #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_ +#define _ASSUAN_NO_PTH +#define _ASSUAN_NO_FIXED_SIGNALS +#define _ASSUAN_USE_DOUBLE_FORK #ifdef _ASSUAN_IN_GPGME_BUILD_ASSUAN int _gpgme_io_read (int fd, void *buffer, size_t count); int _gpgme_io_write (int fd, const void *buffer, size_t count); -ssize_t _gpgme_ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset, - struct timeval *timeout); ssize_t _gpgme_ath_waitpid (pid_t pid, int *status, int options); +#ifdef HAVE_W32_SYSTEM +int _gpgme_ath_accept (int s, void *addr, int *length_ptr); +#else /*!HAVE_W32_SYSTEM*/ +ssize_t _gpgme_ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset, + struct timeval *timeout); int _gpgme_ath_accept (int s, struct sockaddr *addr, socklen_t *length_ptr); int _gpgme_ath_connect (int s, struct sockaddr *addr, socklen_t length); int _gpgme_ath_sendmsg (int s, const struct msghdr *msg, int flags); int _gpgme_ath_recvmsg (int s, struct msghdr *msg, int flags); +#endif /*!HAVE_W32_SYSTEM*/ #define read _gpgme_io_read #define write _gpgme_io_write @@ -50,8 +74,9 @@ int _gpgme_ath_recvmsg (int s, struct msghdr *msg, int flags); #define connect _gpgme_ath_connect #define sendmsg _gpgme_ath_sendmsg #define recvmsg _gpgme_ath_recvmsg -#endif -#endif +#endif /*_ASSUAN_IN_GPGME_BUILD_ASSUAN*/ +/**** End GPGME specific modifications. ******/ + #ifdef _ASSUAN_EXT_SYM_PREFIX #define _ASSUAN_PREFIX1(x,y) x ## y @@ -116,6 +141,8 @@ int _gpgme_ath_recvmsg (int s, struct msghdr *msg, int flags); _ASSUAN_PREFIX(assuan_get_assuan_log_stream) #define assuan_get_assuan_log_prefix \ _ASSUAN_PREFIX(assuan_get_assuan_log_prefix) +#define assuan_set_flag _ASSUAN_PREFIX(assuan_set_flag) +#define assuan_get_flag _ASSUAN_PREFIX(assuan_get_flag) /* And now the internal functions, argh... */ #define _assuan_read_line _ASSUAN_PREFIX(_assuan_read_line) @@ -138,14 +165,27 @@ int _gpgme_ath_recvmsg (int s, struct msghdr *msg, int flags); #define _assuan_log_print_buffer _ASSUAN_PREFIX(_assuan_log_print_buffer) #define _assuan_log_sanitized_string \ _ASSUAN_PREFIX(_assuan_log_sanitized_string) +#define _assuan_log_printf _ASSUAN_PREFIX(_assuan_log_printf) +#define _assuan_set_default_log_stream \ + _ASSUAN_PREFIX(_assuan_set_default_log_stream) +#define _assuan_w32_strerror _ASSUAN_PREFIX(_assuan_w32_strerror) +#define _assuan_write_line _ASSUAN_PREFIX(_assuan_write_line) +#define _assuan_close _ASSUAN_PREFIX(_assuan_close) +#define _assuan_sock_new _ASSUAN_PREFIX(_assuan_sock_new) +#define _assuan_sock_bind _ASSUAN_PREFIX(_assuan_sock_bind) +#define _assuan_sock_connect _ASSUAN_PREFIX(_assuan_sock_connect) + +#endif /*_ASSUAN_EXT_SYM_PREFIX*/ -#endif #ifdef __cplusplus extern "C" { +#if 0 +} #endif - +#endif + typedef enum { @@ -166,7 +206,7 @@ typedef enum ASSUAN_Connect_Failed = 14, ASSUAN_Accept_Failed = 15, - /* error codes above 99 are meant as status codes */ + /* Error codes above 99 are meant as status codes */ ASSUAN_Not_Implemented = 100, ASSUAN_Server_Fault = 101, ASSUAN_Invalid_Command = 102, @@ -194,9 +234,10 @@ typedef enum ASSUAN_Unexpected_Status = 124, ASSUAN_Unexpected_Data = 125, ASSUAN_Invalid_Status = 126, - + ASSUAN_Locale_Problem = 127, 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, @@ -216,11 +257,20 @@ typedef enum ASSUAN_Invalid_Card = 402, ASSUAN_No_PKCS15_App = 403, ASSUAN_Card_Not_Present = 404, - ASSUAN_Invalid_Id = 405 + ASSUAN_Invalid_Id = 405, -} AssuanError; + /* 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 + +} assuan_error_t; + +typedef assuan_error_t AssuanError; /* Deprecated. */ /* This is a list of pre-registered ASSUAN commands */ +/* NOTE, these command IDs are now deprectated and solely exists for + compatibility reasons. */ typedef enum { ASSUAN_CMD_NOP = 0, @@ -237,72 +287,90 @@ typedef enum ASSUAN_CMD_USER = 256 /* Other commands should be used with this offset*/ } AssuanCommand; + +/* Definitions of flags for assuan_set_flag(). */ +typedef enum + { + /* When using a pipe server, by default Assuan will wait for the + forked process to die in assuan_disconnect. In certain cases + this is not desirable. By setting this flag, the waitpid will + be skipped and the caller is responsible to cleanup a forked + process. */ + ASSUAN_NO_WAITPID = 1 + } +assuan_flag_t; + #define ASSUAN_LINELENGTH 1002 /* 1000 + [CR,]LF */ struct assuan_context_s; +typedef struct assuan_context_s *assuan_context_t; typedef struct assuan_context_s *ASSUAN_CONTEXT; /*-- assuan-handler.c --*/ -int assuan_register_command (ASSUAN_CONTEXT ctx, +int assuan_register_command (assuan_context_t ctx, const char *cmd_string, - int (*handler)(ASSUAN_CONTEXT, char *)); -int assuan_register_bye_notify (ASSUAN_CONTEXT ctx, - void (*fnc)(ASSUAN_CONTEXT)); -int assuan_register_reset_notify (ASSUAN_CONTEXT ctx, - void (*fnc)(ASSUAN_CONTEXT)); -int assuan_register_cancel_notify (ASSUAN_CONTEXT ctx, - void (*fnc)(ASSUAN_CONTEXT)); -int assuan_register_input_notify (ASSUAN_CONTEXT ctx, - void (*fnc)(ASSUAN_CONTEXT, const char *)); -int assuan_register_output_notify (ASSUAN_CONTEXT ctx, - void (*fnc)(ASSUAN_CONTEXT, const char *)); + int (*handler)(assuan_context_t, char *)); +int assuan_register_bye_notify (assuan_context_t ctx, + void (*fnc)(assuan_context_t)); +int assuan_register_reset_notify (assuan_context_t ctx, + void (*fnc)(assuan_context_t)); +int assuan_register_cancel_notify (assuan_context_t ctx, + void (*fnc)(assuan_context_t)); +int assuan_register_input_notify (assuan_context_t ctx, + void (*fnc)(assuan_context_t, const char *)); +int assuan_register_output_notify (assuan_context_t ctx, + void (*fnc)(assuan_context_t, const char *)); -int assuan_register_option_handler (ASSUAN_CONTEXT ctx, - int (*fnc)(ASSUAN_CONTEXT, +int assuan_register_option_handler (assuan_context_t ctx, + int (*fnc)(assuan_context_t, const char*, const char*)); -int assuan_process (ASSUAN_CONTEXT ctx); -int assuan_process_next (ASSUAN_CONTEXT ctx); -int assuan_get_active_fds (ASSUAN_CONTEXT ctx, int what, +int assuan_process (assuan_context_t ctx); +int assuan_process_next (assuan_context_t ctx); +int assuan_get_active_fds (assuan_context_t ctx, int what, int *fdarray, int fdarraysize); -FILE *assuan_get_data_fp (ASSUAN_CONTEXT ctx); -AssuanError assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line); -void assuan_write_status (ASSUAN_CONTEXT ctx, - const char *keyword, const char *text); +FILE *assuan_get_data_fp (assuan_context_t ctx); +assuan_error_t assuan_set_okay_line (assuan_context_t ctx, const char *line); +assuan_error_t assuan_write_status (assuan_context_t ctx, + const char *keyword, const char *text); /* Negotiate a file descriptor. If LINE contains "FD=N", returns N assuming a local file descriptor. If LINE contains "FD" reads a file descriptor via CTX and stores it in *RDF (the CTX must be capable of passing file descriptors). */ -AssuanError assuan_command_parse_fd (ASSUAN_CONTEXT ctx, char *line, +assuan_error_t assuan_command_parse_fd (assuan_context_t ctx, char *line, int *rfd); /*-- assuan-listen.c --*/ -AssuanError assuan_set_hello_line (ASSUAN_CONTEXT ctx, const char *line); -AssuanError assuan_accept (ASSUAN_CONTEXT ctx); -int assuan_get_input_fd (ASSUAN_CONTEXT ctx); -int assuan_get_output_fd (ASSUAN_CONTEXT ctx); -AssuanError assuan_close_input_fd (ASSUAN_CONTEXT ctx); -AssuanError assuan_close_output_fd (ASSUAN_CONTEXT ctx); +assuan_error_t assuan_set_hello_line (assuan_context_t ctx, const char *line); +assuan_error_t assuan_accept (assuan_context_t ctx); +int assuan_get_input_fd (assuan_context_t ctx); +int assuan_get_output_fd (assuan_context_t ctx); +assuan_error_t assuan_close_input_fd (assuan_context_t ctx); +assuan_error_t assuan_close_output_fd (assuan_context_t ctx); /*-- assuan-pipe-server.c --*/ -int assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2]); -void assuan_deinit_server (ASSUAN_CONTEXT ctx); +int assuan_init_pipe_server (assuan_context_t *r_ctx, int filedes[2]); +void assuan_deinit_server (assuan_context_t ctx); /*-- assuan-socket-server.c --*/ -int assuan_init_socket_server (ASSUAN_CONTEXT *r_ctx, int listen_fd); -int assuan_init_connected_socket_server (ASSUAN_CONTEXT *r_ctx, int fd); +int assuan_init_socket_server (assuan_context_t *r_ctx, int listen_fd); +int assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd); /*-- assuan-pipe-connect.c --*/ -AssuanError assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, +assuan_error_t assuan_pipe_connect (assuan_context_t *ctx, const char *name, char *const argv[], int *fd_child_list); +assuan_error_t assuan_pipe_connect2 (assuan_context_t *ctx, const char *name, + char *const argv[], int *fd_child_list, + void (*atfork) (void*, int), + void *atforkvalue); /*-- assuan-socket-connect.c --*/ -AssuanError assuan_socket_connect (ASSUAN_CONTEXT *ctx, const char *name, - pid_t server_pid); +assuan_error_t assuan_socket_connect (assuan_context_t *ctx, const char *name, + pid_t server_pid); /*-- assuan-domain-connect.c --*/ @@ -310,7 +378,7 @@ AssuanError assuan_socket_connect (ASSUAN_CONTEXT *ctx, const char *name, bidirectional file descriptor (normally returned via socketpair) which the client can use to rendezvous with the server. SERVER s the server's pid. */ -AssuanError assuan_domain_connect (ASSUAN_CONTEXT *r_ctx, +assuan_error_t assuan_domain_connect (assuan_context_t *r_ctx, int rendezvousfd, pid_t server); @@ -319,74 +387,93 @@ AssuanError assuan_domain_connect (ASSUAN_CONTEXT *r_ctx, /* 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. */ -AssuanError assuan_init_domain_server (ASSUAN_CONTEXT *r_ctx, +assuan_error_t assuan_init_domain_server (assuan_context_t *r_ctx, int rendezvousfd, pid_t client); /*-- assuan-connect.c --*/ -void assuan_disconnect (ASSUAN_CONTEXT ctx); -pid_t assuan_get_pid (ASSUAN_CONTEXT ctx); +void assuan_disconnect (assuan_context_t ctx); +pid_t assuan_get_pid (assuan_context_t ctx); /*-- assuan-client.c --*/ -AssuanError -assuan_transact (ASSUAN_CONTEXT ctx, +assuan_error_t +assuan_transact (assuan_context_t ctx, const char *command, - AssuanError (*data_cb)(void *, const void *, size_t), + assuan_error_t (*data_cb)(void *, const void *, size_t), void *data_cb_arg, - AssuanError (*inquire_cb)(void*, const char *), + assuan_error_t (*inquire_cb)(void*, const char *), void *inquire_cb_arg, - AssuanError (*status_cb)(void*, const char *), + assuan_error_t (*status_cb)(void*, const char *), void *status_cb_arg); /*-- assuan-inquire.c --*/ -AssuanError assuan_inquire (ASSUAN_CONTEXT ctx, const char *keyword, - char **r_buffer, size_t *r_length, size_t maxlen); +assuan_error_t assuan_inquire (assuan_context_t ctx, const char *keyword, + unsigned char **r_buffer, size_t *r_length, + size_t maxlen); /*-- assuan-buffer.c --*/ -AssuanError assuan_read_line (ASSUAN_CONTEXT ctx, +assuan_error_t assuan_read_line (assuan_context_t ctx, char **line, size_t *linelen); -int assuan_pending_line (ASSUAN_CONTEXT ctx); -AssuanError assuan_write_line (ASSUAN_CONTEXT ctx, const char *line ); -AssuanError assuan_send_data (ASSUAN_CONTEXT ctx, +int assuan_pending_line (assuan_context_t ctx); +assuan_error_t assuan_write_line (assuan_context_t ctx, const char *line ); +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")). */ -AssuanError assuan_sendfd (ASSUAN_CONTEXT ctx, int fd); -AssuanError assuan_receivefd (ASSUAN_CONTEXT ctx, int *fd); +assuan_error_t assuan_sendfd (assuan_context_t ctx, int fd); +assuan_error_t assuan_receivefd (assuan_context_t ctx, int *fd); /*-- assuan-util.c --*/ void assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n), void *(*new_realloc_func)(void *p, size_t n), void (*new_free_func)(void*) ); -void assuan_set_log_stream (ASSUAN_CONTEXT ctx, FILE *fp); -int assuan_set_error (ASSUAN_CONTEXT ctx, int err, const char *text); -void assuan_set_pointer (ASSUAN_CONTEXT ctx, void *pointer); -void *assuan_get_pointer (ASSUAN_CONTEXT ctx); +void assuan_set_log_stream (assuan_context_t ctx, FILE *fp); +int assuan_set_error (assuan_context_t ctx, int err, const char *text); +void assuan_set_pointer (assuan_context_t ctx, void *pointer); +void *assuan_get_pointer (assuan_context_t ctx); + +void assuan_begin_confidential (assuan_context_t ctx); +void assuan_end_confidential (assuan_context_t ctx); + +/* For context CTX, set the flag FLAG to VALUE. Values for flags + are usually 1 or 0 but certain flags might allow for other values; + see the description of the type assuan_flag_t for details. */ +void assuan_set_flag (assuan_context_t ctx, assuan_flag_t flag, int value); + +/* Return the VALUE of FLAG in context CTX. */ +int assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag); -void assuan_begin_confidential (ASSUAN_CONTEXT ctx); -void assuan_end_confidential (ASSUAN_CONTEXT ctx); /*-- assuan-errors.c (built) --*/ -const char *assuan_strerror (AssuanError err); +const char *assuan_strerror (assuan_error_t err); /*-- assuan-logging.c --*/ -/* Set the stream to which assuan should log. By default, this is - stderr. */ +/* Set the stream to which assuan should log message not associated + with a context. By default, this is stderr. The default value + will be changed when the first log stream is associated with a + context. Note, that this function is not thread-safe and should + in general be used right at startup. */ extern void assuan_set_assuan_log_stream (FILE *fp); -/* Return the stream which is currently being using for logging. */ +/* Return the stream which is currently being using for global logging. */ extern FILE *assuan_get_assuan_log_stream (void); -/* User defined call back. Return a prefix to be used at the start of - a line emitted by assuan on the log stream. The default - implementation returns the empty string, i.e. "" */ -extern const char *assuan_get_assuan_log_prefix (void); +/* Set the prefix to be used at the start of a line emitted by assuan + on the log stream. The default is the empty string. Note, that + this function is not thread-safe and should in general be used + right at startup. */ +void assuan_set_assuan_log_prefix (const char *text); + +/* Return a prefix to be used at the start of a line emitted by assuan + on the log stream. The default implementation returns the empty + string, i.e. "" */ +const char *assuan_get_assuan_log_prefix (void); #ifdef __cplusplus } diff --git a/assuan/mkerrors b/assuan/mkerrors index 11129419..e00011ba 100755 --- a/assuan/mkerrors +++ b/assuan/mkerrors @@ -23,6 +23,10 @@ cat < +#endif + #include #include "assuan.h" diff --git a/configure.ac b/configure.ac index 6a31bd5b..2271357c 100644 --- a/configure.ac +++ b/configure.ac @@ -169,7 +169,7 @@ fi # Checks for library functions. AC_FUNC_FSEEKO -AC_REPLACE_FUNCS(stpcpy) +AC_CHECK_FUNCS(stpcpy) AC_REPLACE_FUNCS(vasprintf) if test "$ac_cv_func_vasprintf" != yes; then diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index bd25f51b..caa73ad4 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,3 +1,10 @@ +2005-08-08 Werner Koch + + * util.h (stpcpy): Renamed to .. + (_gpgme_stpcpy): .. this and made inline. This avoids duplicate + definitions when linking statically. + * stpcpy.c: Removed. + 2005-07-27 Marcus Brinkmann * gpgme.h (gpgme_status_code_t): Add GPGME_STATUS_PLAINTEXT. diff --git a/gpgme/util.h b/gpgme/util.h index 0434208d..6d542373 100644 --- a/gpgme/util.h +++ b/gpgme/util.h @@ -1,6 +1,6 @@ /* util.h Copyright (C) 2000 Werner Koch (dd9jn) - Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH This file is part of GPGME. @@ -35,9 +35,18 @@ const char *_gpgme_get_gpgsm_path (void); /*-- replacement functions in .c --*/ #ifdef HAVE_CONFIG_H + #ifndef HAVE_STPCPY -char *stpcpy (char *a, const char *b); -#endif +static _GPGME_INLINE char * +_gpgme_stpcpy (char *a, const char *b) +{ + while (*b) + *a++ = *b++; + *a = 0; + return a; +} +#define stpcpy(a,b) _gpgme_stpcpy ((a), (b)) +#endif /*!HAVE_STPCPY*/ #if !HAVE_VASPRINTF #include