aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2003-12-16 11:30:16 +0000
committerWerner Koch <[email protected]>2003-12-16 11:30:16 +0000
commitdba63c0a0ceb473909528ec51b5851ec28731218 (patch)
treea68c2499ab81167e61875513e395b7138ea664f7
parentKeep those files in CVS too. (diff)
downloadgnupg-dba63c0a0ceb473909528ec51b5851ec28731218.tar.gz
gnupg-dba63c0a0ceb473909528ec51b5851ec28731218.zip
* configure.ac: Check for funopen and fopencookie as part of the
jnlib checks. * logging.c (writen, fun_writer, fun_closer): New. (log_set_file): Add feature to log to a socket.
-rw-r--r--ChangeLog5
-rw-r--r--NEWS8
-rw-r--r--configure.ac3
-rw-r--r--jnlib/ChangeLog5
-rw-r--r--jnlib/logging.c181
5 files changed, 187 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index f270cad13..2a08051f0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2003-12-16 Werner Koch <[email protected]>
+
+ * configure.ac: Check for funopen and fopencookie as part of the
+ jnlib checks.
+
2003-12-09 Werner Koch <[email protected]>
* configure.ac: Add a min_automake_version.
diff --git a/NEWS b/NEWS
index 8aff1add1..ebc65a27d 100644
--- a/NEWS
+++ b/NEWS
@@ -2,7 +2,13 @@ Noteworthy changes in version 1.9.3 (unreleased)
------------------------------------------------
* New options --{enable,disable}-ocsp to validate keys using OCSP
- This requires at least DirMngr 0.5.1 to work. Default is disabled.
+ This requires a not yet released DirMngr 0.5.1. Default is
+ disabled.
+
+ * The --log-file may now be used to print logs to a socket. Prefix
+ the socket name with "socket://" to enable this. This does not
+ work on all systems and falls back to stderr if there is a problem
+ with the socket.
Noteworthy changes in version 1.9.2 (2003-11-17)
diff --git a/configure.ac b/configure.ac
index 7bca11986..a0cf391a4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -698,7 +698,7 @@ AC_CHECK_TYPES([struct sigaction, sigset_t],,,[#include <signal.h>])
# These are needed by libjnlib - fixme: we should have macros for them
AC_CHECK_FUNCS(memicmp stpcpy strlwr strtoul memmove stricmp strtol)
AC_CHECK_FUNCS(getrusage setrlimit stat setlocale)
-AC_CHECK_FUNCS(flockfile funlockfile)
+AC_CHECK_FUNCS(flockfile funlockfile fopencookie funopen)
AC_REPLACE_FUNCS(vasprintf)
AC_REPLACE_FUNCS(fopencookie)
@@ -709,6 +709,7 @@ AC_REPLACE_FUNCS(putc_unlocked)
+
#
# check for gethrtime and run a testprogram to see whether
# it is broken. It has been reported that some Solaris and HP UX systems
diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog
index e12dd8e00..e6b7dc3fb 100644
--- a/jnlib/ChangeLog
+++ b/jnlib/ChangeLog
@@ -1,3 +1,8 @@
+2003-12-16 Werner Koch <[email protected]>
+
+ * logging.c (writen, fun_writer, fun_closer): New.
+ (log_set_file): Add feature to log to a socket.
+
2003-11-13 Werner Koch <[email protected]>
* strlist.c (strlist_copy): New.
diff --git a/jnlib/logging.c b/jnlib/logging.c
index 913d01b6f..b019fb76c 100644
--- a/jnlib/logging.c
+++ b/jnlib/logging.c
@@ -29,12 +29,15 @@
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
+#include <stddef.h>
#include <errno.h>
#include <time.h>
#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
#include <unistd.h>
#ifdef __MINGW32__
- #include <io.h>
+# include <io.h>
#endif
#define JNLIB_NEED_LOG_LOGV 1
@@ -84,22 +87,173 @@ log_inc_errorcount (void)
errorcount++;
}
-void
-log_set_file( const char *name )
+
+/* The follwing 3 functions are used by funopen to write logs to a
+ socket. */
+#if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN)
+struct fun_cookie_s {
+ int fd;
+ int quiet;
+ char name[1];
+};
+
+/* Write NBYTES of BUF to file descriptor FD. */
+static int
+writen (int fd, const unsigned char *buf, size_t nbytes)
{
- FILE *fp = (name && strcmp(name,"-"))? fopen(name, "a") : stderr;
- if( !fp ) {
- fprintf(stderr, "failed to open log file `%s': %s\n",
- name, strerror(errno));
- return;
+ size_t nleft = nbytes;
+ int nwritten;
+
+ while (nleft > 0)
+ {
+ nwritten = write (fd, buf, nleft);
+ if (nwritten < 0 && errno == EINTR)
+ continue;
+ if (nwritten < 0)
+ return -1;
+ nleft -= nwritten;
+ buf = buf + nwritten;
}
- setvbuf( fp, NULL, _IOLBF, 0 );
+
+ return 0;
+}
+
+
+static int
+fun_writer (void *cookie_arg, const char *buffer, size_t size)
+{
+ struct fun_cookie_s *cookie = cookie_arg;
+
+ /* Note that we always try to reconnect to the socket but print error
+ messages only the first time an error occured. */
+ if (cookie->fd == -1 )
+ {
+ /* Note yet open or meanwhile closed due to an error. */
+ struct sockaddr_un addr;
+ size_t addrlen;
+
+ cookie->fd = socket (PF_LOCAL, SOCK_STREAM, 0);
+ if (cookie->fd == -1)
+ {
+ if (!cookie->quiet)
+ fprintf (stderr, "failed to create socket for logging: %s\n",
+ strerror(errno));
+ goto failure;
+ }
+
+ memset (&addr, 0, sizeof addr);
+ addr.sun_family = PF_LOCAL;
+ strncpy (addr.sun_path, cookie->name, sizeof (addr.sun_path)-1);
+ addr.sun_path[sizeof (addr.sun_path)-1] = 0;
+ addrlen = (offsetof (struct sockaddr_un, sun_path)
+ + strlen (addr.sun_path) + 1);
+
+ if (connect (cookie->fd, (struct sockaddr *) &addr, addrlen) == -1)
+ {
+ if (!cookie->quiet)
+ fprintf (stderr, "can't connect to `%s': %s\n",
+ cookie->name, strerror(errno));
+ close (cookie->fd);
+ cookie->fd = -1;
+ goto failure;
+ }
+ /* Connection established. */
+ cookie->quiet = 0;
+ }
+
+ if (!writen (cookie->fd, buffer, size))
+ return size; /* Okay. */
+
+ fprintf (stderr, "error writing to `%s': %s\n",
+ cookie->name, strerror(errno));
+ close (cookie->fd);
+ cookie->fd = -1;
+
+ failure:
+ if (!cookie->quiet)
+ {
+ fputs ("switching logging to stderr\n", stderr);
+ cookie->quiet = 1;
+ }
+
+ fwrite (buffer, size, 1, stderr);
+ return size;
+}
- if (logstream && logstream != stderr && logstream != stdout)
- fclose( logstream );
- logstream = fp;
- missing_lf = 0;
+static int
+fun_closer (void *cookie_arg)
+{
+ struct fun_cookie_s *cookie = cookie_arg;
+
+ if (cookie->fd != -1)
+ close (cookie->fd);
+ jnlib_free (cookie);
+ return 0;
}
+#endif /* HAVE_FOPENCOOKIE || HAVE_FUNOPEN */
+
+
+
+
+/* Set the file to write log to. The sepcial names NULL and "_" may
+ be used to select stderr and names formatted like
+ "socket:///home/foo/mylogs" may be used to write the logging to the
+ socket "/home/foo/mylogs". If the connection to the socket fails
+ or a write error is detected, the function writes to stderr and
+ tries the next time again to connect the socket.
+ */
+void
+log_set_file (const char *name)
+{
+ FILE *fp;
+
+ if (name && !strncmp (name, "socket://", 9) && name[9])
+ {
+#if defined (HAVE_FOPENCOOKIE)|| defined (HAVE_FUNOPEN)
+ struct fun_cookie_s *cookie;
+
+ cookie = jnlib_xmalloc (sizeof *cookie + strlen (name+9));
+ cookie->fd = -1;
+ cookie->quiet = 0;
+ strcpy (cookie->name, name+9);
+
+#ifdef HAVE_FOPENCOOKIE
+ {
+ cookie_io_functions_t io = { NULL };
+ io.write = fun_writer;
+ io.close = fun_closer;
+
+ fp = fopencookie (cookie, "w", io);
+ }
+#else /*!HAVE_FOPENCOOKIE*/
+ {
+ fp = funopen (cookie, NULL, fun_writer, NULL, fun_closer);
+ }
+#endif /*!HAVE_FOPENCOOKIE*/
+#else /* Neither fopencookie nor funopen. */
+ {
+ fprintf (stderr, "system does not support logging to a socket - "
+ "using stderr\n");
+ fp = stderr;
+ }
+#endif /* Neither fopencookie nor funopen. */
+ }
+ else
+ fp = (name && strcmp(name,"-"))? fopen (name, "a") : stderr;
+ if (!fp)
+ {
+ fprintf (stderr, "failed to open log file `%s': %s\n",
+ name? name:"[stderr]", strerror(errno));
+ return;
+ }
+ setvbuf (fp, NULL, _IOLBF, 0);
+
+ if (logstream && logstream != stderr && logstream != stdout)
+ fclose (logstream);
+ logstream = fp;
+ missing_lf = 0;
+}
+
void
log_set_fd (int fd)
@@ -221,6 +375,7 @@ do_logv( int level, const char *fmt, va_list arg_ptr )
default: fprintf(logstream,"[Unknown log level %d]: ", level ); break;
}
+
if (fmt)
{
vfprintf(logstream,fmt,arg_ptr) ;