diff options
Diffstat (limited to 'contrib/amd/libamu/xutil.c')
-rw-r--r-- | contrib/amd/libamu/xutil.c | 103 |
1 files changed, 87 insertions, 16 deletions
diff --git a/contrib/amd/libamu/xutil.c b/contrib/amd/libamu/xutil.c index a8b15bf..998d0d8 100644 --- a/contrib/amd/libamu/xutil.c +++ b/contrib/amd/libamu/xutil.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-1999 Erez Zadok + * Copyright (c) 1997-2001 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -38,7 +38,7 @@ * * %W% (Berkeley) %G% * - * $Id: xutil.c,v 1.8 1999/09/30 21:01:42 ezk Exp $ + * $Id: xutil.c,v 1.11.2.6 2001/01/10 03:23:41 ezk Exp $ * */ @@ -80,7 +80,11 @@ static int orig_mem_bytes; #endif /* DEBUG_MEM */ /* forward definitions */ -static void real_plog(int lvl, char *fmt, va_list vargs); +static void real_plog(int lvl, const char *fmt, va_list vargs) + __attribute__((__format__(__printf__, 2, 0))); +/* for GCC format string auditing */ +static const char *expand_error(const char *f, char *e, int maxlen) + __attribute__((__format_arg__(1))); #ifdef DEBUG /* @@ -93,15 +97,20 @@ struct opt_tab dbg_opt[] = {"daemon", D_DAEMON}, /* Enter daemon mode */ {"fork", D_FORK}, /* Fork server (nofork = don't fork) */ {"full", D_FULL}, /* Program trace */ +#ifdef HAVE_CLOCK_GETTIME + {"hrtime", D_HRTIME}, /* Print high resolution time stamps */ +#endif /* HAVE_CLOCK_GETTIME */ /* info service specific debugging (hesiod, nis, etc) */ {"info", D_INFO}, # ifdef DEBUG_MEM {"mem", D_MEM}, /* Trace memory allocations */ # endif /* DEBUG_MEM */ {"mtab", D_MTAB}, /* Use local mtab file */ + {"readdir", D_READDIR}, /* check on browsable_dirs progress */ {"str", D_STR}, /* Debug string munging */ {"test", D_TEST}, /* Full debug - but no daemon */ {"trace", D_TRACE}, /* Protocol trace */ + {"xdrtrace", D_XDRTRACE}, /* Trace xdr routines */ {0, 0} }; #endif /* DEBUG */ @@ -280,18 +289,31 @@ checkup_mem(void) * with the current error code taken from errno. Make sure * 'e' never gets longer than maxlen characters. */ -static void -expand_error(char *f, char *e, int maxlen) +static const char * +expand_error(const char *f, char *e, int maxlen) { +#ifndef HAVE_STRERROR + /* + * XXX: we are assuming that if a system doesn't has strerror, + * then it has sys_nerr. If this assumption turns out to be wrong on + * some systems, we'll have to write a separate test to detect if + * a system has sys_nerr. -Erez + */ extern int sys_nerr; - char *p, *q; +#endif /* not HAVE_STRERROR */ + const char *p; + char *q; int error = errno; int len = 0; for (p = f, q = e; (*q = *p) && len < maxlen; len++, q++, p++) { if (p[0] == '%' && p[1] == 'm') { const char *errstr; +#ifdef HAVE_STRERROR + if (error < 0) +#else /* not HAVE_STRERROR */ if (error < 0 || error >= sys_nerr) +#endif /* not HAVE_STRERROR */ errstr = NULL; else #ifdef HAVE_STRERROR @@ -309,6 +331,7 @@ expand_error(char *f, char *e, int maxlen) } } e[maxlen-1] = '\0'; /* null terminate, to be sure */ + return e; } @@ -320,13 +343,34 @@ show_time_host_and_name(int lvl) { static time_t last_t = 0; static char *last_ctime = 0; - time_t t = clocktime(); + time_t t; +#ifdef HAVE_CLOCK_GETTIME + struct timespec ts; +#endif /* HAVE_CLOCK_GETTIME */ + char nsecs[11] = ""; /* '.' + 9 digits + '\0' */ char *sev; +#ifdef HAVE_CLOCK_GETTIME + /* + * Some systems (AIX 4.3) seem to implement clock_gettime() as stub + * returning ENOSYS. + */ + if (clock_gettime(CLOCK_REALTIME, &ts) == 0) { + t = ts.tv_sec; +#ifdef DEBUG + amuDebug(D_HRTIME) + sprintf(nsecs, ".%09ld", ts.tv_nsec); +#endif /* DEBUG */ + } + else +#endif /* HAVE_CLOCK_GETTIME */ + t = clocktime(); + if (t != last_t) { last_ctime = ctime(&t); last_t = t; } + switch (lvl) { case XLOG_FATAL: sev = "fatal:"; @@ -356,8 +400,8 @@ show_time_host_and_name(int lvl) sev = "hmm: "; break; } - fprintf(logfp, "%15.15s %s %s[%ld]/%s ", - last_ctime + 4, am_get_hostname(), + fprintf(logfp, "%15.15s%s %s %s[%ld]/%s ", + last_ctime + 4, nsecs, am_get_hostname(), am_get_progname(), (long) am_mypid, sev); @@ -376,7 +420,7 @@ debug_option(char *opt) void -dplog(char *fmt, ...) +dplog(const char *fmt, ...) { va_list ap; @@ -391,7 +435,7 @@ dplog(char *fmt, ...) void -plog(int lvl, char *fmt, ...) +plog(int lvl, const char *fmt, ...) { va_list ap; @@ -405,7 +449,7 @@ plog(int lvl, char *fmt, ...) static void -real_plog(int lvl, char *fmt, va_list vargs) +real_plog(int lvl, const char *fmt, va_list vargs) { char msg[1024]; char efmt[1024]; @@ -420,17 +464,21 @@ real_plog(int lvl, char *fmt, va_list vargs) checkup_mem(); #endif /* DEBUG_MEM */ - expand_error(fmt, efmt, 1024); - #ifdef HAVE_VSNPRINTF - vsnprintf(ptr, 1024, efmt, vargs); + /* + * XXX: ptr is 1024 bytes long, but we may write to ptr[strlen(ptr) + 2] + * (to add an '\n', see code below) so we have to limit the string copy + * to 1023 (including the '\0'). + */ + vsnprintf(ptr, 1023, expand_error(fmt, efmt, 1024), vargs); + msg[1022] = '\0'; /* null terminate, to be sure */ #else /* not HAVE_VSNPRINTF */ /* * XXX: ptr is 1024 bytes long. It is possible to write into it * more than 1024 bytes, if efmt is already large, and vargs expand * as well. This is not as safe as using vsnprintf(). */ - vsprintf(ptr, efmt, vargs); + vsprintf(ptr, expand_error(fmt, efmt, 1023), vargs); msg[1023] = '\0'; /* null terminate, to be sure */ #endif /* not HAVE_VSNPRINTF */ @@ -873,6 +921,7 @@ amu_release_controlling_tty(void) #ifdef TIOCNOTTY int fd; #endif /* TIOCNOTTY */ + int tempfd; #ifdef HAVE_SETSID /* XXX: one day maybe use vhangup(2) */ @@ -884,6 +933,28 @@ amu_release_controlling_tty(void) } #endif /* HAVE_SETSID */ + /* + * In daemon mode, leaving open file descriptors to terminals or pipes + * can be a really bad idea. + * Case in point: the redhat startup script calls us through their 'initlog' + * program, which exits as soon as the original amd process exits. If, at some + * point, a misbehaved library function decides to print something to the screen, + * we get a SIGPIPE and die. + * More precisely: NIS libc functions will attempt to print to stderr + * "YPBINDPROC_DOMAIN: Domain not bound" if ypbind is running but can't find + * a ypserver. + * + * So we close all of our "terminal" filedescriptors, i.e. 0, 1 and 2, then + * reopen them as /dev/null. + * + * XXX We should also probably set the SIGPIPE handler to SIG_IGN. + */ + tempfd = open("/dev/null", O_RDWR); + fflush(stdin); close(0); dup2(tempfd, 0); + fflush(stdout); close(1); dup2(tempfd, 1); + fflush(stderr); close(2); dup2(tempfd, 2); + close(tempfd); + #ifdef TIOCNOTTY fd = open("/dev/tty", O_RDWR); if (fd < 0) { |