diff options
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | NEWS | 9 | ||||
-rw-r--r-- | TODO | 12 | ||||
-rw-r--r-- | configure.ac | 8 | ||||
-rw-r--r-- | doc/assuan.texi | 6 | ||||
-rw-r--r-- | src/ChangeLog | 34 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/assuan-buffer.c | 74 | ||||
-rw-r--r-- | src/assuan-client.c | 10 | ||||
-rw-r--r-- | src/assuan-defs.h | 49 | ||||
-rw-r--r-- | src/assuan-domain-connect.c | 70 | ||||
-rw-r--r-- | src/assuan-domain-server.c | 9 | ||||
-rw-r--r-- | src/assuan-handler.c | 36 | ||||
-rw-r--r-- | src/assuan-inquire.c | 16 | ||||
-rw-r--r-- | src/assuan-listen.c | 10 | ||||
-rw-r--r-- | src/assuan-logging.c | 10 | ||||
-rw-r--r-- | src/assuan-pipe-connect.c | 25 | ||||
-rw-r--r-- | src/assuan-pipe-server.c | 2 | ||||
-rw-r--r-- | src/assuan-socket-connect.c | 12 | ||||
-rw-r--r-- | src/assuan-socket-server.c | 6 | ||||
-rw-r--r-- | src/assuan.h | 82 | ||||
-rwxr-xr-x | src/mkerrors | 157 | ||||
-rw-r--r-- | tests/Makefile.am | 37 | ||||
-rw-r--r-- | tests/common.h | 149 | ||||
-rw-r--r-- | tests/fdpassing.c | 213 |
26 files changed, 866 insertions, 180 deletions
@@ -1,3 +1,7 @@ +2006-09-05 Werner Koch <[email protected]> + + * configure.ac (AH_BOTTOM): Define _ASSUAN_IN_LIBASSUAN. + 2005-10-24 Werner Koch <[email protected]> * COPYING.LESSER: Added. diff --git a/Makefile.am b/Makefile.am index 0ef8170..44ae9a7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,8 @@ -SUBDIRS = src doc + ACLOCAL_AMFLAGS = -I m4 AUTOMAKE_OPTIONS = dist-bzip2 EXTRA_DIST = config.rpath config.rpath autogen.sh README.SVN +SUBDIRS = src doc tests + @@ -1,4 +1,4 @@ -Noteworthy changes in version 0.6.11 +Noteworthy changes in version 0.9.0 ------------------------------------------------- * Internal cleanups to make inclusion of the code into libraries @@ -6,6 +6,13 @@ Noteworthy changes in version 0.6.11 * Made clear that the software is under the LGPL. + * New function assuan_set_assuan_err_source. All gpg-error enabled + software should call this right at startup to switch libassuan into + the gpg-error style mode. All error codes are then returned as + gpg-error style codes (GPG_ERR_ASS_* as well as others). + If the new macro _ASSUAN_ONLY_GPG_ERRORS is defned all old + definitions are excluded from assuan.h. + Noteworthy changes in version 0.6.10 (2005-06-20) ------------------------------------------------- @@ -1,11 +1,15 @@ + -*- outline -*- * waitpid is used instead of pth_waitpid as well as some other functions. * When turning libassuan into a shared library, provide a general version as well as a Pth-enabled one. * Need API documentation. -* assuan_transact returns immetitely on an error in the callback - function. It might be Better to return the error to the caller. As - an example see dirmngr-client, where we need to send empty reponses +* assuan_transact returns immediately on an error in the callback + function. It might be better to return the error to the caller. As + an example see dirmngr-client, where we need to send empty responses for unknown inquiries, albeit dirmngr itself would handle the - returns for assuan_inquire gracefully. We need to chekc all + returns for assuan_inquire gracefully. We need to check all applications whether it is safe to change this. +* Check the system error to assuan error translation +* Do a configure test for SO_PEERCRED. + We already use HAVE_SO_PEERCRED buty it never gets defined. diff --git a/configure.ac b/configure.ac index a38471e..7600b93 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ min_automake_version="1.9.3" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(libassuan, 0.6.11-cvs, [email protected]) +AC_INIT(libassuan, 0.9.0-cvs, [email protected]) # Note, that this is not yet available as a shared library. PACKAGE=$PACKAGE_NAME @@ -68,6 +68,11 @@ if test "$GCC" = yes; then fi +AH_BOTTOM([ +#define _ASSUAN_IN_LIBASSUAN 1 +]) + + # # Options depending on the host OS. # @@ -160,6 +165,7 @@ AC_REPLACE_FUNCS(setenv) AC_CONFIG_FILES([Makefile]) AC_CONFIG_FILES([src/Makefile]) AC_CONFIG_FILES([doc/Makefile]) +AC_CONFIG_FILES([tests/Makefile]) AC_CONFIG_FILES([src/libassuan-config], [chmod +x src/libassuan-config]) AC_OUTPUT diff --git a/doc/assuan.texi b/doc/assuan.texi index 20c1f1f..7404709 100644 --- a/doc/assuan.texi +++ b/doc/assuan.texi @@ -175,7 +175,7 @@ Goals: @item Easy module testing @item Extendible @item Optional authentication and encryption facility -@item Usable by access external hardware +@item Usable to access external hardware @end itemize @@ -261,7 +261,7 @@ A client should only check the first letter of each line and then skip over to the next token (except for data lines where the raw data starts exactly after 2 bytes). Lines larger than 1000 bytes should be treated as a communication error. (The rationale for having a line -length limit is to allow for easier multiplexing of multiple channels). +length limit is to allow for easier multiplexing of several channels). @node Client requests @@ -405,7 +405,7 @@ Error codes used as status codes in the Assuan protocol: @end table For historical reasons a few more error codes are defined in -@file{assuan.h}; they should not be used be new applications. +@file{assuan.h}; they should not be used by new applications. Errror codes in the range @var{ASSUAN_USER_ERROR_FIRST} to @var{ASSUAN_USER_ERROR_LAST} may be used at the applications own diff --git a/src/ChangeLog b/src/ChangeLog index 12578d0..7740e0e 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,37 @@ +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 diff --git a/src/Makefile.am b/src/Makefile.am index 27d0511..1774875 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -54,5 +54,5 @@ libassuan_a_SOURCES = \ libassuan_a_LIBADD = @LIBOBJS@ -assuan-errors.c : assuan.h +assuan-errors.c : assuan.h mkerrors $(srcdir)/mkerrors < $(srcdir)/assuan.h > assuan-errors.c diff --git a/src/assuan-buffer.c b/src/assuan-buffer.c index 507944d..57eba95 100644 --- a/src/assuan-buffer.c +++ b/src/assuan-buffer.c @@ -31,6 +31,9 @@ #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) { @@ -50,7 +53,9 @@ 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, int *r_nread, int *r_eof) @@ -89,6 +94,7 @@ readline (ASSUAN_CONTEXT ctx, char *buf, size_t buflen, } +/* Function returns an Assuan error. */ int _assuan_read_line (ASSUAN_CONTEXT ctx) { @@ -129,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; @@ -171,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 @@ -187,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); } } @@ -213,7 +221,7 @@ assuan_read_line (ASSUAN_CONTEXT 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; @@ -242,10 +250,10 @@ _assuan_write_line (assuan_context_t ctx, const char *prefix, 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) @@ -255,9 +263,9 @@ _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 @@ -269,18 +277,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; @@ -294,7 +302,7 @@ assuan_write_line (ASSUAN_CONTEXT ctx, const char *line) 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. */ @@ -302,10 +310,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); } @@ -360,9 +368,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); @@ -376,7 +384,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; @@ -408,9 +416,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 @@ -422,7 +430,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; @@ -453,9 +461,9 @@ assuan_error_t assuan_send_data (ASSUAN_CONTEXT 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 */ diff --git a/src/assuan-client.c b/src/assuan-client.c index 56ce299..d8f1cee 100644 --- a/src/assuan-client.c +++ b/src/assuan-client.c @@ -104,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; } @@ -113,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 @@ -167,7 +167,7 @@ assuan_transact (ASSUAN_CONTEXT ctx, else if (okay == 2) { if (!data_cb) - rc = ASSUAN_No_Data_Callback; + rc = _assuan_error (ASSUAN_No_Data_Callback); else { char *s, *d; @@ -196,7 +196,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 { @@ -217,7 +217,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/src/assuan-defs.h b/src/assuan-defs.h index 98758e2..11f4cfd 100644 --- a/src/assuan-defs.h +++ b/src/assuan-defs.h @@ -16,7 +16,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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. + * USA. */ #ifndef ASSUAN_DEFS_H @@ -63,12 +63,16 @@ char * stpcpy (char *dest, const char *src); #define LINELENGTH ASSUAN_LINELENGTH + struct cmdtbl_s { const char *name; int (*handler)(ASSUAN_CONTEXT, 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. */ @@ -79,8 +83,10 @@ struct assuan_io assuan_error_t (*sendfd) (ASSUAN_CONTEXT, int); /* Receive a file descriptor. */ assuan_error_t (*receivefd) (ASSUAN_CONTEXT, int *); -}; +}; + +/* The context we use with most functions. */ struct assuan_context_s { assuan_error_t err_no; @@ -89,17 +95,17 @@ 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 (). */ FILE *log_fp; @@ -123,14 +129,14 @@ 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. */ + 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 */ @@ -152,7 +158,7 @@ struct assuan_context_s int *pendingfds; int pendingfdscount; - void (*deinit_handler)(ASSUAN_CONTEXT); + void (*deinit_handler)(ASSUAN_CONTEXT); int (*accept_handler)(ASSUAN_CONTEXT); int (*finish_handler)(ASSUAN_CONTEXT); @@ -183,8 +189,8 @@ void _assuan_release_context (ASSUAN_CONTEXT ctx); 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); + int rendezvousfd, + pid_t peer); /*-- assuan-handler.c --*/ int _assuan_register_std_commands (ASSUAN_CONTEXT ctx); @@ -199,6 +205,23 @@ assuan_error_t _assuan_write_line (assuan_context_t ctx, const char *prefix, /*-- assuan-client.c --*/ assuan_error_t _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off); +/*-- assuan-error.c --*/ + + +/* Map error codes as used in this implementaion to the libgpg-error + codes. */ +int _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 --*/ void *_assuan_malloc (size_t n); @@ -211,7 +234,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)) +#define set_error(c,e,t) \ + assuan_set_error ((c), _assuan_error (ASSUAN_ ## e), (t)) void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length); void _assuan_log_sanitized_string (const char *string); @@ -267,4 +291,3 @@ int setenv (const char *name, const char *value, int replace); #endif #endif /*ASSUAN_DEFS_H*/ - diff --git a/src/assuan-domain-connect.c b/src/assuan-domain-connect.c index 63947f9..bc98e39 100644 --- a/src/assuan-domain-connect.c +++ b/src/assuan-domain-connect.c @@ -60,7 +60,7 @@ /* Read an integer from byte address ADDR. Works even if ADDR is misaligned. */ static int -read_int (const char *addr) +read_int (const void *addr) { int val; @@ -73,7 +73,7 @@ read_int (const char *addr) /* Write the integer VAL to byte address ADDR. Works even if ADDR is misaligned. */ static void -write_int (char *addr, int val) +write_int (void *addr, int val) { memcpy (addr, &val, sizeof (int)); } @@ -90,7 +90,7 @@ do_deinit (assuan_context_t ctx) if (ctx->domainbuffer) { assert (ctx->domainbufferallocated); - free (ctx->domainbuffer); + xfree (ctx->domainbuffer); } if (ctx->pendingfds) @@ -101,7 +101,7 @@ do_deinit (assuan_context_t ctx) for (i = 0; i < ctx->pendingfdscount; i ++) _assuan_close (ctx->pendingfds[i]); - free (ctx->pendingfds); + xfree (ctx->pendingfds); } unlink (ctx->myaddr.sun_path); @@ -126,8 +126,7 @@ domain_reader (assuan_context_t ctx, void *buf, size_t buflen) { struct cmsghdr hdr; int fd; - } - cmsg; + } cmsg; memset (&msg, 0, sizeof (msg)); @@ -147,7 +146,7 @@ domain_reader (assuan_context_t ctx, void *buf, size_t buflen) len = recvmsg (ctx->inbound.fd, &msg, MSG_PEEK); if (len < 0) { - printf ("domain_reader: %m\n"); + _assuan_log_printf ("domain_reader: %s\n", strerror (errno)); return -1; } @@ -171,11 +170,11 @@ domain_reader (assuan_context_t ctx, void *buf, size_t buflen) else size *= 2; - tmp = malloc (size); + tmp = xtrymalloc (size); if (! tmp) return -1; - free (ctx->domainbuffer); + xfree (ctx->domainbuffer); ctx->domainbuffer = tmp; ctx->domainbufferallocated = size; } @@ -221,8 +220,8 @@ domain_reader (assuan_context_t ctx, void *buf, size_t buflen) { void *tmp; - tmp = realloc (ctx->pendingfds, - sizeof (int) * (ctx->pendingfdscount + 1)); + tmp = xtryrealloc (ctx->pendingfds, + sizeof (int) * (ctx->pendingfdscount + 1)); if (! tmp) { _assuan_log_printf ("domain_reader: %s\n", strerror (errno)); @@ -303,8 +302,7 @@ domain_sendfd (assuan_context_t ctx, int fd) { struct cmsghdr hdr; int fd; - } - cmsg; + } cmsg; int len; memset (&msg, 0, sizeof (msg)); @@ -329,7 +327,7 @@ domain_sendfd (assuan_context_t ctx, int fd) if (len < 0) { _assuan_log_printf ("domain_sendfd: %s\n", strerror (errno)); - return ASSUAN_General_Error; + return _assuan_error (ASSUAN_General_Error); } else return 0; @@ -345,22 +343,28 @@ domain_receivefd (assuan_context_t ctx, int *fd) if (ctx->pendingfds == 0) { _assuan_log_printf ("no pending file descriptors!\n"); - return ASSUAN_General_Error; + return _assuan_error (ASSUAN_General_Error); } *fd = ctx->pendingfds[0]; if (-- ctx->pendingfdscount == 0) { - free (ctx->pendingfds); + xfree (ctx->pendingfds); ctx->pendingfds = 0; } - else - /* Fix the array. */ + else /* Fix the array. */ { + void *tmp; + memmove (ctx->pendingfds, ctx->pendingfds + 1, ctx->pendingfdscount * sizeof (int)); - ctx->pendingfds = realloc (ctx->pendingfds, - ctx->pendingfdscount * sizeof (int)); + tmp = xtryrealloc (ctx->pendingfds, + ctx->pendingfdscount * sizeof (int)); + if (tmp) + ctx->pendingfds = tmp; + /* Note: we ignore an shrinking error here thus the next realloc + to increase the size will succeed as the block is already of + the then requested size. */ } #endif return 0; @@ -368,9 +372,6 @@ domain_receivefd (assuan_context_t ctx, int *fd) -/* Make a connection to the Unix domain socket NAME and return a new - Assuan context in CTX. SERVER_PID is currently not used but may - become handy in the future. */ assuan_error_t _assuan_domain_init (assuan_context_t *r_ctx, int rendezvousfd, pid_t peer) { @@ -384,7 +385,7 @@ _assuan_domain_init (assuan_context_t *r_ctx, int rendezvousfd, pid_t peer) int tries; if (!r_ctx) - return ASSUAN_Invalid_Value; + return _assuan_error (ASSUAN_Invalid_Value); *r_ctx = NULL; err = _assuan_new_context (&ctx); @@ -404,7 +405,7 @@ _assuan_domain_init (assuan_context_t *r_ctx, int rendezvousfd, pid_t peer) { _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); } ctx->inbound.fd = fd; @@ -438,7 +439,7 @@ _assuan_domain_init (assuan_context_t *r_ctx, int rendezvousfd, pid_t peer) "name. DoS in progress?\n"); _assuan_release_context (ctx); _assuan_close (fd); - return ASSUAN_General_Error; + return _assuan_error (ASSUAN_General_Error); } memset (&ctx->myaddr, 0, sizeof ctx->myaddr); @@ -458,7 +459,7 @@ _assuan_domain_init (assuan_context_t *r_ctx, int rendezvousfd, pid_t peer) strerror (errno)); _assuan_release_context (ctx); _assuan_close (fd); - return ASSUAN_Connect_Failed; + return _assuan_error (ASSUAN_Connect_Failed); } /* Rendezvous with our peer. */ @@ -469,8 +470,9 @@ _assuan_domain_init (assuan_context_t *r_ctx, int rendezvousfd, pid_t peer) fp = fdopen (rendezvousfd, "w+"); if (! fp) { - _assuan_log_printf ("can't open rendezvous port: %s\n", strerror (errno)); - return ASSUAN_Connect_Failed; + _assuan_log_printf ("can't open rendezvous port: %s\n", + strerror (errno)); + return _assuan_error (ASSUAN_Connect_Failed); } /* Send our address. */ @@ -498,13 +500,17 @@ _assuan_domain_init (assuan_context_t *r_ctx, int rendezvousfd, pid_t peer) return 0; } +/* 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 is + the server's pid. */ assuan_error_t -assuan_domain_connect (assuan_context_t * r_ctx, int rendezvousfd, pid_t peer) +assuan_domain_connect (assuan_context_t *r_ctx, int rendezvousfd, pid_t server) { assuan_error_t aerr; int okay, off; - aerr = _assuan_domain_init (r_ctx, rendezvousfd, peer); + aerr = _assuan_domain_init (r_ctx, rendezvousfd, server); if (aerr) return aerr; @@ -518,7 +524,7 @@ assuan_domain_connect (assuan_context_t * r_ctx, int rendezvousfd, pid_t peer) _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; + aerr = _assuan_error (ASSUAN_Connect_Failed); } if (aerr) diff --git a/src/assuan-domain-server.c b/src/assuan-domain-server.c index 2732c07..2194c39 100644 --- a/src/assuan-domain-server.c +++ b/src/assuan-domain-server.c @@ -27,15 +27,18 @@ #include "assuan-defs.h" -/* Initialize a server. */ +/* Initialize a server. 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 *r_ctx, int rendezvousfd, - pid_t peer) + pid_t client) { assuan_error_t err; - err = _assuan_domain_init (r_ctx, rendezvousfd, peer); + err = _assuan_domain_init (r_ctx, rendezvousfd, client); if (err) return err; diff --git a/src/assuan-handler.c b/src/assuan-handler.c index d80415d..d2e90a2 100644 --- a/src/assuan-handler.c +++ b/src/assuan-handler.c @@ -246,7 +246,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. */ @@ -269,7 +269,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) @@ -278,7 +278,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; } @@ -293,7 +293,7 @@ int assuan_register_bye_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT)) { if (!ctx) - return ASSUAN_Invalid_Value; + return _assuan_error (ASSUAN_Invalid_Value); ctx->bye_notify_fnc = fnc; return 0; } @@ -302,7 +302,7 @@ int assuan_register_reset_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT)) { if (!ctx) - return ASSUAN_Invalid_Value; + return _assuan_error (ASSUAN_Invalid_Value); ctx->reset_notify_fnc = fnc; return 0; } @@ -311,7 +311,7 @@ int assuan_register_cancel_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT)) { if (!ctx) - return ASSUAN_Invalid_Value; + return _assuan_error (ASSUAN_Invalid_Value); ctx->cancel_notify_fnc = fnc; return 0; } @@ -322,7 +322,7 @@ assuan_register_option_handler (ASSUAN_CONTEXT ctx, const char*, const char*)) { if (!ctx) - return ASSUAN_Invalid_Value; + return _assuan_error (ASSUAN_Invalid_Value); ctx->option_handler_fnc = fnc; return 0; } @@ -332,7 +332,7 @@ assuan_register_input_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT, const char *)) { if (!ctx) - return ASSUAN_Invalid_Value; + return _assuan_error (ASSUAN_Invalid_Value); ctx->input_notify_fnc = fnc; return 0; } @@ -342,7 +342,7 @@ assuan_register_output_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT, const char *)) { if (!ctx) - return ASSUAN_Invalid_Value; + return _assuan_error (ASSUAN_Invalid_Value); ctx->output_notify_fnc = fnc; return 0; } @@ -407,7 +407,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; @@ -447,7 +447,7 @@ process_request (ASSUAN_CONTEXT ctx) int rc; if (ctx->in_inquire) - return ASSUAN_Nested_Commands; + return _assuan_error (ASSUAN_Nested_Commands); rc = _assuan_read_line (ctx); if (rc) @@ -478,7 +478,7 @@ process_request (ASSUAN_CONTEXT ctx) { rc = assuan_write_line (ctx, ctx->okay_line? ctx->okay_line : "OK"); } - else if (rc == -1) + else if (err_is_eof (rc)) { /* No error checking because the peer may have already disconnect */ assuan_write_line (ctx, "OK closing connection"); ctx->finish_handler (ctx); @@ -489,7 +489,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; @@ -499,7 +499,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; @@ -561,7 +561,7 @@ assuan_process (ASSUAN_CONTEXT ctx) rc = process_request (ctx); } while (!rc); - if (rc == -1) + if (err_is_eof (rc)) rc = 0; return rc; @@ -662,7 +662,7 @@ assuan_error_t assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line) { if (!ctx) - return ASSUAN_Invalid_Value; + return _assuan_error (ASSUAN_Invalid_Value); if (!line) { xfree (ctx->okay_line); @@ -674,7 +674,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); @@ -694,7 +694,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/src/assuan-inquire.c b/src/assuan-inquire.c index e58469d..d8c52d0 100644 --- a/src/assuan-inquire.c +++ b/src/assuan-inquire.c @@ -147,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) @@ -183,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) @@ -215,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; } } @@ -224,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/src/assuan-listen.c b/src/assuan-listen.c index fe4589b..b81db84 100644 --- a/src/assuan-listen.c +++ b/src/assuan-listen.c @@ -31,7 +31,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); @@ -41,7 +41,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 @@ -74,7 +74,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 */ @@ -135,7 +135,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; @@ -147,7 +147,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/src/assuan-logging.c b/src/assuan-logging.c index 9106e61..665efa9 100644 --- a/src/assuan-logging.c +++ b/src/assuan-logging.c @@ -28,6 +28,7 @@ #ifdef HAVE_W32_SYSTEM #include <windows.h> #endif /*HAVE_W32_SYSTEM*/ +#include <errno.h> #include "assuan-defs.h" @@ -81,18 +82,17 @@ _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; } diff --git a/src/assuan-pipe-connect.c b/src/assuan-pipe-connect.c index 94f86ae..4a6b436 100644 --- a/src/assuan-pipe-connect.c +++ b/src/assuan-pipe-connect.c @@ -270,7 +270,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 (); @@ -278,13 +278,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)) @@ -292,7 +292,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); } @@ -304,7 +304,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; @@ -391,7 +391,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; @@ -421,20 +421,20 @@ assuan_pipe_connect2 (assuan_context_t *ctx, char mypidstr[50]; if (!ctx || !name || !argv || !argv[0]) - return ASSUAN_Invalid_Value; + return _assuan_error (ASSUAN_Invalid_Value); fix_signals (); sprintf (mypidstr, "%lu", (unsigned long)getpid ()); if (pipe (rp) < 0) - return ASSUAN_General_Error; + return _assuan_error (ASSUAN_General_Error); if (pipe (wp) < 0) { close (rp[0]); close (rp[1]); - return ASSUAN_General_Error; + return _assuan_error (ASSUAN_General_Error); } err = _assuan_new_context (ctx); @@ -462,7 +462,7 @@ assuan_pipe_connect2 (assuan_context_t *ctx, close (wp[0]); close (wp[1]); _assuan_release_context (*ctx); - return ASSUAN_General_Error; + return _assuan_error (ASSUAN_General_Error); } if ((*ctx)->pid == 0) @@ -559,7 +559,8 @@ assuan_pipe_connect2 (assuan_context_t *ctx, /* 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)); + _assuan_error (ASSUAN_Problem_Starting_Server), + name, strerror (errno)); errbuf[sizeof(errbuf)-1] = 0; writen (1, errbuf, strlen (errbuf)); _exit (4); @@ -594,7 +595,7 @@ assuan_pipe_connect2 (assuan_context_t *ctx, { _assuan_log_printf ("can't connect server: `%s'\n", (*ctx)->inbound.line); - err = ASSUAN_Connect_Failed; + err = _assuan_error (ASSUAN_Connect_Failed); } } diff --git a/src/assuan-pipe-server.c b/src/assuan-pipe-server.c index b0e7c7b..1ad85dc 100644 --- a/src/assuan-pipe-server.c +++ b/src/assuan-pipe-server.c @@ -66,7 +66,7 @@ _assuan_new_context (ASSUAN_CONTEXT *r_ctx) *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; diff --git a/src/assuan-socket-connect.c b/src/assuan-socket-connect.c index f1c0695..8df7812 100644 --- a/src/assuan-socket-connect.c +++ b/src/assuan-socket-connect.c @@ -89,7 +89,7 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx, 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 @@ -99,10 +99,10 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx, 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) @@ -116,7 +116,7 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx, { _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); @@ -132,7 +132,7 @@ 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; @@ -152,7 +152,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); } } diff --git a/src/assuan-socket-server.c b/src/assuan-socket-server.c index 302c59b..aab1b5a 100644 --- a/src/assuan-socket-server.c +++ b/src/assuan-socket-server.c @@ -79,7 +79,7 @@ accept_connection (assuan_context_t ctx) if (fd == -1) { ctx->os_errno = errno; - return ASSUAN_Accept_Failed; + return _assuan_error (ASSUAN_Accept_Failed); } ctx->connected_fd = fd; @@ -119,7 +119,7 @@ assuan_init_socket_server (assuan_context_t *r_ctx, int listen_fd) *r_ctx = NULL; ctx = xtrycalloc (1, sizeof *ctx); if (!ctx) - return ASSUAN_Out_Of_Core; + return _assuan_error (ASSUAN_Out_Of_Core); ctx->is_server = 1; ctx->input_fd = -1; ctx->output_fd = -1; @@ -153,7 +153,7 @@ assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd) *r_ctx = NULL; ctx = xtrycalloc (1, sizeof *ctx); if (!ctx) - return ASSUAN_Out_Of_Core; + return _assuan_error (ASSUAN_Out_Of_Core); ctx->is_server = 1; ctx->pipe_mode = 1; /* we want a second accept to indicate EOF */ ctx->input_fd = -1; diff --git a/src/assuan.h b/src/assuan.h index cc2d49b..44c458a 100644 --- a/src/assuan.h +++ b/src/assuan.h @@ -27,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. */ @@ -105,6 +113,8 @@ #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 \ @@ -156,19 +166,27 @@ extern "C" #endif #endif - +#ifndef _ASSUAN_ONLY_GPG_ERRORS +/* Assuan error codes. These are only used by old applications or + those applications which won't make use of libgpg-error. */ typedef enum { +#ifndef _ASSUAN_IN_LIBASSUAN ASSUAN_No_Error = 0, +#endif ASSUAN_General_Error = 1, ASSUAN_Out_Of_Core = 2, ASSUAN_Invalid_Value = 3, +#ifndef _ASSUAN_IN_LIBASSUAN ASSUAN_Timeout = 4, +#endif ASSUAN_Read_Error = 5, ASSUAN_Write_Error = 6, ASSUAN_Problem_Starting_Server = 7, ASSUAN_Not_A_Server = 8, +#ifndef _ASSUAN_IN_LIBASSUAN ASSUAN_Not_A_Client = 9, +#endif ASSUAN_Nested_Commands = 10, ASSUAN_Invalid_Response = 11, ASSUAN_No_Data_Callback = 12, @@ -179,24 +197,33 @@ typedef enum /* Error codes above 99 are meant as status codes */ ASSUAN_Not_Implemented = 100, ASSUAN_Server_Fault = 101, +#ifndef _ASSUAN_IN_LIBASSUAN ASSUAN_Invalid_Command = 102, +#endif ASSUAN_Unknown_Command = 103, ASSUAN_Syntax_Error = 104, +#ifndef _ASSUAN_IN_LIBASSUAN ASSUAN_Parameter_Error = 105, +#endif ASSUAN_Parameter_Conflict = 106, ASSUAN_Line_Too_Long = 107, ASSUAN_Line_Not_Terminated = 108, +#ifndef _ASSUAN_IN_LIBASSUAN ASSUAN_No_Input = 109, ASSUAN_No_Output = 110, +#endif ASSUAN_Canceled = 111, +#ifndef _ASSUAN_IN_LIBASSUAN 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, +#endif ASSUAN_Unexpected_Command = 118, ASSUAN_Too_Much_Data = 119, +#ifndef _ASSUAN_IN_LIBASSUAN ASSUAN_Inquire_Unknown = 120, ASSUAN_Inquire_Error = 121, ASSUAN_Invalid_Option = 122, @@ -207,7 +234,7 @@ typedef enum ASSUAN_Locale_Problem = 127, ASSUAN_Not_Confirmed = 128, - /* Warning: Don't use the rror codes, below they are deprecated. */ + /* Warning: Don't use the Error codes, below they are deprecated. */ ASSUAN_Bad_Certificate = 201, ASSUAN_Bad_Certificate_Chain = 202, ASSUAN_Missing_Certificate = 203, @@ -233,7 +260,7 @@ typedef enum at their own discretion. */ ASSUAN_USER_ERROR_FIRST = 1000, ASSUAN_USER_ERROR_LAST = 9999 - +#endif } assuan_error_t; typedef assuan_error_t AssuanError; /* Deprecated. */ @@ -258,6 +285,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 { @@ -274,7 +308,9 @@ assuan_flag_t; struct assuan_context_s; typedef struct assuan_context_s *assuan_context_t; +#ifndef _ASSUAN_ONLY_GPG_ERRORS typedef struct assuan_context_s *ASSUAN_CONTEXT; +#endif /*_ASSUAN_ONLY_GPG_ERRORS*/ /*-- assuan-handler.c --*/ int assuan_register_command (assuan_context_t ctx, @@ -351,8 +387,8 @@ assuan_error_t assuan_socket_connect (assuan_context_t *ctx, const char *name, 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); + int rendezvousfd, + pid_t server); /*-- assuan-domain-server.c --*/ @@ -360,8 +396,8 @@ assuan_error_t assuan_domain_connect (assuan_context_t *r_ctx, 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); + int rendezvousfd, + pid_t client); /*-- assuan-connect.c --*/ @@ -421,8 +457,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/src/mkerrors b/src/mkerrors index 534fa92..552cb17 100755 --- a/src/mkerrors +++ b/src/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. # @@ -21,15 +21,114 @@ 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. */ +int +_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_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: + assert (!"unmapped error code used in libassuan!!"); + n = 257; /* Just in case someone compiled with NDEBUG. */ + break; + } + + return ((err_source << 24) | (n & 0x00ffffff)); + +} + + /** * assuan_strerror: * @err: Error code @@ -54,6 +153,7 @@ awk ' /ASSUAN_No_Error/ { okay=1 } !okay {next} /}/ { exit 0 } +/^#/ {next} /ASSUAN_[A-Za-z_]*/ { print_code($1) } @@ -66,21 +166,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/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..ef2510e --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,37 @@ +# Makefile for Assuan regression tests +# 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 + +## Process this file with automake to produce Makefile.in + +TESTS_ENVIRONMENT = + +EXTRA_DIST = + +BUILT_SOURCES = +CLEANFILES = + +TESTS = fdpassing + +AM_CFLAGS = # $(GPG_ERROR_CFLAGS) + +noinst_HEADERS = common.h +noinst_PROGRAMS = $(TESTS) +LDADD = ../src/libassuan.a # $(GPG_ERROR_LIBS) + diff --git a/tests/common.h b/tests/common.h new file mode 100644 index 0000000..180dc47 --- /dev/null +++ b/tests/common.h @@ -0,0 +1,149 @@ +/* common.h - Common functions for the tests. + * 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. + */ + +#include <stdarg.h> + + +static const char *log_prefix; +static int errorcount; +static int verbose; +static int debug; + + +void * +xmalloc (size_t n) +{ + char *p = malloc (n); + if (!p) + { + fprintf (stderr, "out of core\n"); + exit (1); + } + return p; +} + +void * +xcalloc (size_t n, size_t m) +{ + char *p = calloc (n, m); + if (!p) + { + fprintf (stderr, "out of core\n"); + exit (1); + } + return p; +} + +void +xfree (void *a) +{ + if (a) + free (a); +} + + +void +log_set_prefix (const char *s) +{ + log_prefix = strrchr (s, '/'); + if (log_prefix) + log_prefix++; + else + log_prefix = s; +} + + +void +log_info (const char *format, ...) +{ + va_list arg_ptr ; + + if (!verbose) + return; + + va_start (arg_ptr, format) ; + if (log_prefix) + fprintf (stderr, "%s[%u]: ", log_prefix, (unsigned int)getpid ()); + vfprintf (stderr, format, arg_ptr ); + va_end (arg_ptr); +} + + +void +log_error (const char *format, ...) +{ + va_list arg_ptr ; + + va_start (arg_ptr, format) ; + if (log_prefix) + fprintf (stderr, "%s[%u]: ", log_prefix, (unsigned int)getpid ()); + vfprintf (stderr, format, arg_ptr ); + va_end (arg_ptr); + errorcount++; +} + + +void +log_fatal (const char *format, ...) +{ + va_list arg_ptr ; + + va_start (arg_ptr, format) ; + if (log_prefix) + fprintf (stderr, "%s[%u]: ", log_prefix, (unsigned int)getpid ()); + vfprintf (stderr, format, arg_ptr ); + va_end (arg_ptr); + exit (2); +} + + +void +log_printhex (const char *text, const void *buffer, size_t length) +{ + const unsigned char *s; + + if (log_prefix) + fprintf (stderr, "%s[%u]: ", log_prefix, (unsigned int)getpid ()); + fputs (text, stderr); + for (s=buffer; length; s++, length--) + fprintf (stderr, "%02X", *s); + putc ('\n', stderr); +} + + +/* Prepend FNAME with the srcdir environment variable's value and + return an allocated filename. */ +char * +prepend_srcdir (const char *fname) +{ + static const char *srcdir; + char *result; + + if (!srcdir && !(srcdir = getenv ("srcdir"))) + srcdir = "."; + + result = xmalloc (strlen (srcdir) + 1 + strlen (fname) + 1); + strcpy (result, srcdir); + strcat (result, "/"); + strcat (result, fname); + return result; +} + diff --git a/tests/fdpassing.c b/tests/fdpassing.c new file mode 100644 index 0000000..9317ed2 --- /dev/null +++ b/tests/fdpassing.c @@ -0,0 +1,213 @@ +/* fdpassing - Check the fiel descriptor passing. + * 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. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <unistd.h> +#include <errno.h> +#include <sys/wait.h> /* Used by main driver. */ + +#include "../src/assuan.h" +#include "common.h" + + +/* + + S E R V E R + +*/ + +static int +cmd_echo (assuan_context_t ctx, char *line) +{ + log_info ("got ECHO command (%s)\n", line); + return 0; +} + +static assuan_error_t +register_commands (assuan_context_t ctx) +{ + static struct { + const char *name; + int (*handler)(assuan_context_t, char *line); + } table[] = { + { "ECHO", cmd_echo }, + { "INPUT", NULL }, + { "OUTPUT", NULL }, + { NULL } + }; + int i; + assuan_error_t rc; + + for (i=0; table[i].name; i++) + { + rc = assuan_register_command (ctx, table[i].name, table[i].handler); + if (rc) + return rc; + } + return 0; +} + + +static void +server (int fd) +{ + int rc; + assuan_context_t ctx; + + log_info ("server started on fd %d\n", fd); + + rc = assuan_init_domain_server (&ctx, fd, (pid_t)(-1)); + if (rc) + log_fatal ("assuan_init_domain_server failed: %s\n", assuan_strerror (rc)); + + rc = register_commands (ctx); + if (rc) + log_fatal ("register_commands failed: %s\n", assuan_strerror(rc)); + + assuan_set_assuan_log_prefix (log_prefix); + assuan_set_log_stream (ctx, stderr); + + for (;;) + { + rc = assuan_accept (ctx); + if (rc) + { + log_error ("assuan_accept failed: %s\n", assuan_strerror (rc)); + break; + } + + rc = assuan_process (ctx); + if (rc) + log_error ("assuan_process failed: %s\n", assuan_strerror (rc)); + } + + assuan_deinit_server (ctx); +} + + + + +/* + + C L I E N T + +*/ + + +/* Client main. If true is returned, a disconnect has not been done. */ +static int +client (int fd) +{ + int rc; + assuan_context_t ctx; + + log_info ("client started on fd %d\n", fd); + + rc = assuan_domain_connect (&ctx, fd, (pid_t)(-1)); + if (rc) + { + log_error ("assuan_domain_connect failed: %s\n", assuan_strerror (rc)); + return -1; + } + + + assuan_disconnect (ctx); + return 0; +} + + + + +/* + + M A I N + +*/ +int +main (int argc, char **argv) +{ + int last_argc = -1; + const char *srcdir = getenv ("srcdir"); + int fds[2]; + pid_t pid; + + if (!srcdir) + srcdir = "."; + + if (argc) + { + log_set_prefix (*argv); + argc--; argv++; + } + while (argc && last_argc != argc ) + { + last_argc = argc; + if (!strcmp (*argv, "--help")) + { + puts ( +"usage: ./fdpassing [options]\n" +"\n" +" Options are --verbose and --debug"); + exit (0); + } + if (!strcmp (*argv, "--verbose")) + { + verbose = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--debug")) + { + verbose = debug = 1; + argc--; argv++; + } + } + + /* Create a socketpair. */ + if ( socketpair (AF_LOCAL, SOCK_STREAM, 0, fds) ) + log_fatal ("socketpair failed: %s\n", strerror (errno)); + + /* Fork and run server and client. */ + pid = fork (); + if (pid == (pid_t)(-1)) + log_fatal ("fork failed: %s\n", strerror (errno)); + if (!pid) + { + server (fds[0]); /* The child is our server. */ + log_info ("server finished\n"); + } + else + { + if (client (fds[1])) /* The parent is the client. */ + { + log_info ("waiting for server to terminate...\n"); + waitpid (pid, NULL, 0); + } + log_info ("client finished\n"); + } + + return errorcount? 1:0; +} + |