diff options
| -rw-r--r-- | ChangeLog | 5 | ||||
| -rw-r--r-- | assuan/ChangeLog | 168 | ||||
| -rw-r--r-- | assuan/Makefile.am | 11 | ||||
| -rw-r--r-- | assuan/assuan-buffer.c | 111 | ||||
| -rw-r--r-- | assuan/assuan-client.c | 32 | ||||
| -rw-r--r-- | assuan/assuan-connect.c | 25 | ||||
| -rw-r--r-- | assuan/assuan-defs.h | 172 | ||||
| -rw-r--r-- | assuan/assuan-domain-connect.c | 504 | ||||
| -rw-r--r-- | assuan/assuan-domain-server.c | 46 | ||||
| -rw-r--r-- | assuan/assuan-handler.c | 117 | ||||
| -rw-r--r-- | assuan/assuan-inquire.c | 19 | ||||
| -rw-r--r-- | assuan/assuan-io.c | 157 | ||||
| -rw-r--r-- | assuan/assuan-listen.c | 14 | ||||
| -rw-r--r-- | assuan/assuan-logging.c | 143 | ||||
| -rw-r--r-- | assuan/assuan-pipe-connect.c | 702 | ||||
| -rw-r--r-- | assuan/assuan-pipe-server.c | 61 | ||||
| -rw-r--r-- | assuan/assuan-socket-connect.c | 53 | ||||
| -rw-r--r-- | assuan/assuan-socket-server.c | 111 | ||||
| -rw-r--r-- | assuan/assuan-socket.c | 40 | ||||
| -rw-r--r-- | assuan/assuan-uds.c | 285 | ||||
| -rw-r--r-- | assuan/assuan-util.c | 110 | ||||
| -rw-r--r-- | assuan/assuan.h | 307 | ||||
| -rw-r--r-- | assuan/funopen.c | 29 | ||||
| -rwxr-xr-x | assuan/mkerrors | 168 | ||||
| -rw-r--r-- | configure.ac | 6 | ||||
| -rw-r--r-- | gpgme/gpgme.h | 2 | ||||
| -rw-r--r-- | gpgme/setenv.c | 352 | 
27 files changed, 2417 insertions, 1333 deletions
| @@ -1,3 +1,8 @@ +2006-09-19  Marcus Brinkmann  <[email protected]> + +	* configure.ac: Turn stpcpy into a replacement function. +	Check for unistd.h and add setenv as replacement function. +  2006-07-29  Marcus Brinkmann  <[email protected]>  	* configure.ac: Check for network libraries and set NETLIBS. diff --git a/assuan/ChangeLog b/assuan/ChangeLog index 3aef8395..d9519c12 100644 --- a/assuan/ChangeLog +++ b/assuan/ChangeLog @@ -1,3 +1,171 @@ +2006-09-19  Marcus Brinkmann  <[email protected]> + +	* assuan.h (assuan_init_socket_server_ext) +	[_ASSUAN_EXT_SYM_PREFIX]: Fix typo in macro. + +2006-09-19  Werner Koch  <[email protected]> + +	* 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  <[email protected]> + +	* 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  <[email protected]> + +	* 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  <[email protected]> + +	* 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  <[email protected]> + +	* 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  <[email protected]> + +	* 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  <[email protected]> + +	* 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  <[email protected]> + +	* 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  <[email protected]> + +	* 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  <[email protected]> + +	* 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  <[email protected]> + +	* 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  <[email protected]> + +	* 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  <[email protected]>  	* assuan.h (assuan_pipe_connect, assuan_pipe_connect2): Make type diff --git a/assuan/Makefile.am b/assuan/Makefile.am index b88b7dc5..e19a356e 100644 --- a/assuan/Makefile.am +++ b/assuan/Makefile.am @@ -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 diff --git a/assuan/assuan-buffer.c b/assuan/assuan-buffer.c index 99ea72e3..5580392a 100644 --- a/assuan/assuan-buffer.c +++ b/assuan/assuan-buffer.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, diff --git a/assuan/assuan-client.c b/assuan/assuan-client.c index 2f78d0c8..06e3966f 100644 --- a/assuan/assuan-client.c +++ b/assuan/assuan-client.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> @@ -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); diff --git a/assuan/assuan-connect.c b/assuan/assuan-connect.c index ff1f6ffd..92995d8c 100644 --- a/assuan/assuan-connect.c +++ b/assuan/assuan-connect.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.    */  #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; +} diff --git a/assuan/assuan-defs.h b/assuan/assuan-defs.h index 2917fe85..7a96c0f8 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, 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; - -  void (*deinit_handler)(ASSUAN_CONTEXT);   -  int (*accept_handler)(ASSUAN_CONTEXT); -  int (*finish_handler)(ASSUAN_CONTEXT); + +  /* 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_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*/ diff --git a/assuan/assuan-domain-connect.c b/assuan/assuan-domain-connect.c index b55e9c31..e69de29b 100644 --- a/assuan/assuan-domain-connect.c +++ b/assuan/assuan-domain-connect.c @@ -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; -} diff --git a/assuan/assuan-domain-server.c b/assuan/assuan-domain-server.c index 45d53c26..e69de29b 100644 --- a/assuan/assuan-domain-server.c +++ b/assuan/assuan-domain-server.c @@ -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; -} diff --git a/assuan/assuan-handler.c b/assuan/assuan-handler.c index 21501a35..bf00d1a1 100644 --- a/assuan/assuan-handler.c +++ b/assuan/assuan-handler.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> @@ -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 = ""; diff --git a/assuan/assuan-inquire.c b/assuan/assuan-inquire.c index 0547aae3..d8c52d09 100644 --- a/assuan/assuan-inquire.c +++ b/assuan/assuan-inquire.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> @@ -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: diff --git a/assuan/assuan-io.c b/assuan/assuan-io.c index 321f2bae..0fe48b70 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, 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 <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> +# 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 +} diff --git a/assuan/assuan-listen.c b/assuan/assuan-listen.c index 04f138ef..04db68ce 100644 --- a/assuan/assuan-listen.c +++ b/assuan/assuan-listen.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> @@ -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; diff --git a/assuan/assuan-logging.c b/assuan/assuan-logging.c index 7c65d579..cfc3d846 100644 --- a/assuan/assuan-logging.c +++ b/assuan/assuan-logging.c @@ -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  } diff --git a/assuan/assuan-pipe-connect.c b/assuan/assuan-pipe-connect.c index ecedb166..8ee9c748 100644 --- a/assuan/assuan-pipe-connect.c +++ b/assuan/assuan-pipe-connect.c @@ -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);  } + diff --git a/assuan/assuan-pipe-server.c b/assuan/assuan-pipe-server.c index beff9a3e..a19c88ec 100644 --- a/assuan/assuan-pipe-server.c +++ b/assuan/assuan-pipe-server.c @@ -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)      { diff --git a/assuan/assuan-socket-connect.c b/assuan/assuan-socket-connect.c index 9937c7a6..5953f1c3 100644 --- a/assuan/assuan-socket-connect.c +++ b/assuan/assuan-socket-connect.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> @@ -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;  } + + diff --git a/assuan/assuan-socket-server.c b/assuan/assuan-socket-server.c index 275af42c..45c227d6 100644 --- a/assuan/assuan-socket-server.c +++ b/assuan/assuan-socket-server.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> @@ -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; - -    if ( !getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl) -         && cr.pid != (pid_t)-1 && cr.pid )  -      ctx->pid = cr.pid; +    socklen_t cl = sizeof cr; + +    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,71 +117,67 @@ 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;    *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;  } - - diff --git a/assuan/assuan-socket.c b/assuan/assuan-socket.c index 005f7307..6aa57089 100644 --- a/assuan/assuan-socket.c +++ b/assuan/assuan-socket.c @@ -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)  { diff --git a/assuan/assuan-uds.c b/assuan/assuan-uds.c new file mode 100644 index 00000000..c7253928 --- /dev/null +++ b/assuan/assuan-uds.c @@ -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; +} + diff --git a/assuan/assuan-util.c b/assuan/assuan-util.c index 2c2f744d..3e627fc5 100644 --- a/assuan/assuan-util.c +++ b/assuan/assuan-util.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> @@ -106,19 +107,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)  {    if (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 -} - diff --git a/assuan/assuan.h b/assuan/assuan.h index b2641b24..0f36cddb 100644 --- a/assuan/assuan.h +++ b/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, - -  /* 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, - -  ASSUAN_Cert_Revoked = 301, -  ASSUAN_No_CRL_For_Cert = 302, -  ASSUAN_CRL_Too_Old = 303, -  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_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 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 + +#define  ASSUAN_Cert_Revoked 301 +#define  ASSUAN_No_CRL_For_Cert 302 +#define  ASSUAN_CRL_Too_Old 303 +#define  ASSUAN_Not_Trusted 304 + +#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 --*/ diff --git a/assuan/funopen.c b/assuan/funopen.c index 47f33701..ac31007a 100644 --- a/assuan/funopen.c +++ b/assuan/funopen.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);  } diff --git a/assuan/mkerrors b/assuan/mkerrors index e00011ba..ded7ba31 100755 --- a/assuan/mkerrors +++ b/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
\ No newline at end of file +EOF diff --git a/configure.ac b/configure.ac index d40fc320..45f295ac 100644 --- a/configure.ac +++ b/configure.ac @@ -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]) diff --git a/gpgme/gpgme.h b/gpgme/gpgme.h index f0fee7c0..ac662429 100644 --- a/gpgme/gpgme.h +++ b/gpgme/gpgme.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" diff --git a/gpgme/setenv.c b/gpgme/setenv.c new file mode 100644 index 00000000..3c803b0b --- /dev/null +++ b/gpgme/setenv.c @@ -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 + + | 
