* 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.
This commit is contained in:
Werner Koch 2003-12-16 11:30:16 +00:00
parent 56530d2c39
commit dba63c0a0c
5 changed files with 189 additions and 17 deletions

View File

@ -1,3 +1,8 @@
2003-12-16 Werner Koch <wk@gnupg.org>
* configure.ac: Check for funopen and fopencookie as part of the
jnlib checks.
2003-12-09 Werner Koch <wk@gnupg.org>
* configure.ac: Add a min_automake_version.

8
NEWS
View File

@ -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)

View File

@ -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

View File

@ -1,3 +1,8 @@
2003-12-16 Werner Koch <wk@gnupg.org>
* logging.c (writen, fun_writer, fun_closer): New.
(log_set_file): Add feature to log to a socket.
2003-11-13 Werner Koch <wk@gnupg.org>
* strlist.c (strlist_copy): New.

View File

@ -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,23 +87,174 @@ log_inc_errorcount (void)
errorcount++;
}
void
log_set_file( const char *name )
{
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;
}
setvbuf( fp, NULL, _IOLBF, 0 );
if (logstream && logstream != stderr && logstream != stdout)
fclose( logstream );
logstream = fp;
missing_lf = 0;
/* 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)
{
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;
}
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;
}
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) ;