diff options
author | Werner Koch <wk@gnupg.org> | 2004-10-22 11:41:24 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2004-10-22 11:41:24 +0200 |
commit | 23d73cdeb8e5e3f0a56189c25a362f258de1f7d1 (patch) | |
tree | 00d15d65d7616aac52506deb61c6c62d05663086 /jnlib | |
parent | Updated from 1.3 (diff) | |
download | gnupg2-23d73cdeb8e5e3f0a56189c25a362f258de1f7d1.tar.xz gnupg2-23d73cdeb8e5e3f0a56189c25a362f258de1f7d1.zip |
* logging.c (do_logv): Use set_log_stream to setup a default.
(log_set_file): Factored code out to ..
(set_file_fd): .. New function to allow using a file descriptor.
(log_set_fd): Make use of new fucntion.
(fun_writer): Reworked.
Diffstat (limited to 'jnlib')
-rw-r--r-- | jnlib/ChangeLog | 8 | ||||
-rw-r--r-- | jnlib/logging.c | 304 |
2 files changed, 193 insertions, 119 deletions
diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index db9b68d0d..3c2d6d84a 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,11 @@ +2004-10-21 Werner Koch <wk@g10code.com> + + * logging.c (do_logv): Use set_log_stream to setup a default. + (log_set_file): Factored code out to .. + (set_file_fd): .. New function to allow using a file descriptor. + (log_set_fd): Make use of new fucntion. + (fun_writer): Reworked. + 2004-08-18 Werner Koch <wk@g10code.de> * stringhelp.c (print_sanitized_utf8_string): Actually implement diff --git a/jnlib/logging.c b/jnlib/logging.c index f91339687..7a5e1552e 100644 --- a/jnlib/logging.c +++ b/jnlib/logging.c @@ -37,14 +37,20 @@ #include <sys/socket.h> #include <sys/un.h> #include <unistd.h> +#include <fcntl.h> +#include <assert.h> #ifdef __MINGW32__ # include <io.h> #endif + #define JNLIB_NEED_LOG_LOGV 1 #include "libjnlib-config.h" #include "logging.h" +#if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN) +#define USE_FUNWRITER 1 +#endif static FILE *logstream; static int log_socket = -1; @@ -94,10 +100,12 @@ log_inc_errorcount (void) /* The follwing 3 functions are used by funopen to write logs to a socket. */ -#if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN) +#ifdef USE_FUNWRITER struct fun_cookie_s { int fd; int quiet; + int want_socket; + int is_socket; char name[1]; }; @@ -135,64 +143,78 @@ fun_writer (void *cookie_arg, const char *buffer, size_t size) processes often close stderr and by writing to file descriptor 2 we might send the log message to a file not intended for logging (e.g. a pipe or network connection). */ - if (cookie->fd == -1) + if (cookie->want_socket && cookie->fd == -1) { /* Not yet open or meanwhile closed due to an error. */ - struct sockaddr_un addr; - size_t addrlen; - + cookie->is_socket = 0; cookie->fd = socket (PF_LOCAL, SOCK_STREAM, 0); if (cookie->fd == -1) { if (!cookie->quiet && !running_detached) fprintf (stderr, "failed to create socket for logging: %s\n", strerror(errno)); - goto failure; } - log_socket = cookie->fd; + else + { + struct sockaddr_un addr; + size_t addrlen; + + 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); - 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 && !running_detached) + fprintf (stderr, "can't connect to `%s': %s\n", + cookie->name, strerror(errno)); + close (cookie->fd); + cookie->fd = -1; + } + } - if (connect (cookie->fd, (struct sockaddr *) &addr, addrlen) == -1) + if (cookie->fd == -1) { - log_socket = -1; - if (!cookie->quiet && !running_detached) - fprintf (stderr, "can't connect to `%s': %s\n", - cookie->name, strerror(errno)); - close (cookie->fd); - cookie->fd = -1; - goto failure; + if (!running_detached) + { + if (!cookie->quiet) + { + fputs ("switching logging to stderr\n", stderr); + cookie->quiet = 1; + } + cookie->fd = fileno (stderr); + } + } + else /* Connection has been established. */ + { + cookie->quiet = 0; + cookie->is_socket = 1; } - /* Connection established. */ - cookie->quiet = 0; } - - if (!writen (cookie->fd, buffer, size)) + + log_socket = cookie->fd; + if (cookie->fd != -1 && !writen (cookie->fd, buffer, size)) return size; /* Okay. */ - log_socket = -1; - if (!running_detached) - fprintf (stderr, "error writing to `%s': %s\n", - cookie->name, strerror(errno)); - close (cookie->fd); - cookie->fd = -1; - - failure: - if (!running_detached) + if (!running_detached && cookie->fd != -1) { - if (!cookie->quiet) - { - fputs ("switching logging to stderr\n", stderr); - cookie->quiet = 1; - } - - fwrite (buffer, size, 1, stderr); + if (*cookie->name) + fprintf (stderr, "error writing to `%s': %s\n", + cookie->name, strerror(errno)); + else + fprintf (stderr, "error writing to file descriptor %d: %s\n", + cookie->fd, strerror(errno)); } + if (cookie->is_socket && cookie->fd != -1) + { + close (cookie->fd); + cookie->fd = -1; + log_socket = -1; + } + return size; } @@ -204,110 +226,148 @@ fun_closer (void *cookie_arg) if (cookie->fd != -1) close (cookie->fd); jnlib_free (cookie); + log_socket = -1; return 0; } -#endif /* HAVE_FOPENCOOKIE || HAVE_FUNOPEN */ - +#endif /*USE_FUNWRITER*/ -/* Set the file to write log to. The special 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) +/* Common function to either set the logging to a file or a file + descriptor. */ +static void +set_file_fd (const char *name, int fd) { FILE *fp; + int want_socket; +#ifdef USE_FUNWRITER + struct fun_cookie_s *cookie; +#endif + + if (name && !strcmp (name, "-")) + { + name = NULL; + fd = fileno (stderr); + } - force_prefixes = 0; - if (name && !strncmp (name, "socket://", 9) && name[9]) + if (name) + { + want_socket = (!strncmp (name, "socket://", 9) && name[9]); + if (want_socket) + name += 9; + } + else { -#if defined (HAVE_FOPENCOOKIE)|| defined (HAVE_FUNOPEN) - struct fun_cookie_s *cookie; + want_socket = 0; + } - cookie = jnlib_xmalloc (sizeof *cookie + strlen (name+9)); - cookie->fd = -1; - cookie->quiet = 0; - strcpy (cookie->name, name+9); +#ifdef USE_FUNWRITER + cookie = jnlib_xmalloc (sizeof *cookie + (name? strlen (name):0)); + strcpy (cookie->name, name? name:""); + cookie->quiet = 0; + cookie->is_socket = 0; + cookie->want_socket = want_socket; + if (!name) + cookie->fd = fd; + else if (want_socket) + cookie->fd = -1; + else + { + do + cookie->fd = open (name, O_WRONLY|O_APPEND|O_CREAT, + (S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH)); + while (cookie->fd == -1 && errno == EINTR); + } + log_socket = cookie->fd; #ifdef HAVE_FOPENCOOKIE - { - cookie_io_functions_t io = { NULL }; - io.write = fun_writer; - io.close = fun_closer; - - fp = fopencookie (cookie, "w", io); - } + { + 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); - } + 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. */ - - /* We always need to print the prefix and the pid, so that the - server reading the socket can do something meaningful. */ - force_prefixes = 1; - /* On success close the old logstream right now, so that we are - really sure it has been closed. */ - if (fp && logstream) - { - if (logstream != stderr && logstream != stdout) - fclose (logstream); - logstream = NULL; - } + +#else /*!USE_FUNWRITER*/ + + /* The system does not feature custom streams. Thus fallback to + plain stdio. */ + if (want_socket) + { + fprintf (stderr, "system does not support logging to a socket - " + "using stderr\n"); + fp = stderr; } + else if (name) + fp = fopen (name, "a"); + else if (fd == 1) + fp = stdout; + else if (fd == 2) + fp = stderr; else - fp = (name && strcmp(name,"-"))? fopen (name, "a") : stderr; + fp = fdopen (fd, "a"); + + log_socket = -1; + +#endif /*!USE_FUNWRITER*/ + + /* On success close the old logstream right now, so that we are + really sure it has been closed. */ + if (fp && logstream) + { + if (logstream != stderr && logstream != stdout) + fclose (logstream); + logstream = NULL; + } + if (!fp) { - fprintf (stderr, "failed to open log file `%s': %s\n", - name? name:"[stderr]", strerror(errno)); - return; + if (name) + fprintf (stderr, "failed to open log file `%s': %s\n", + name, strerror(errno)); + else + fprintf (stderr, "failed to fdopen file descriptor %d: %s\n", + fd, strerror(errno)); + /* We need to make sure that there is a log stream. We use stderr. */ + fp = stderr; } - setvbuf (fp, NULL, _IOLBF, 0); + else + setvbuf (fp, NULL, _IOLBF, 0); if (logstream && logstream != stderr && logstream != stdout) fclose (logstream); logstream = fp; + + /* We always need to print the prefix and the pid for socket mode, + so that the server reading the socket can do something + meaningful. */ + force_prefixes = want_socket; + missing_lf = 0; } +/* Set the file to write log to. The special 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_fd (int fd) +log_set_file (const char *name) { - FILE *fp; + set_file_fd (name? name: "-", -1); +} - force_prefixes = 0; - if (fd == 1) - fp = stdout; - else if (fd == 2) - fp = stderr; - else - fp = fdopen (fd, "a"); - if (!fp) - { - fprintf (stderr, "failed to fdopen log fd %d: %s\n", - fd, 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) +{ + set_file_fd (NULL, fd); } @@ -351,9 +411,10 @@ log_get_prefix (unsigned int *flags) int log_test_fd (int fd) { - if (fileno (logstream?logstream:stderr) == fd) + int tmp = fileno (logstream); + if ( tmp != -1 && tmp == fd) return 1; - if (log_socket == fd) + if (log_socket != -1 && log_socket == fd) return 1; return 0; } @@ -367,15 +428,20 @@ log_get_fd () FILE * log_get_stream () { + /* FIXME: We should not return stderr here but initialize the log + stream properly. This might break more things than using stderr, + though */ return logstream?logstream:stderr; } - static void do_logv (int level, const char *fmt, va_list arg_ptr) { if (!logstream) - logstream = stderr; + { + log_set_file (NULL); /* Make sure a log stream has been set. */ + assert (logstream); + } if (missing_lf && level != JNLIB_LOG_CONT) putc('\n', logstream ); |