--- fsl.c 2003/05/20 15:47:23 1.57
+++ fsl.c 2003/05/22 12:30:35 1.58
@@ -53,6 +53,11 @@
/* autoconfiguration */
#include "config.h"
+/* use l2_ut_[v]sprintf() as a portable [v]snprintf() replacement for debugging */
+#ifdef FSL_DEBUGLOGCODE
+#include "l2_ut_format.h"
+#endif
+
/* version */
#define _FSL_VERSION_C_AS_HEADER_
#include "fsl_version.c"
@@ -61,6 +66,9 @@
/* pcre static vector size */
#define OVECSIZE 30
+/* maximum atomic write size, maximum log message size */
+#define MAXWRITESIZE 512
+
/* backward compatibility */
#ifndef LOG_PRIMASK
#define LOG_PRIMASK (LOG_EMERG|LOG_ALERT|LOG_CRIT|LOG_ERR|\
@@ -179,88 +187,123 @@
static struct {
l2_env_t *l2_env;
l2_channel_t *l2_nch;
+ char *cpISF;
levelmap_t *levelmap;
int maskpri;
int logopt;
int delayopen;
int triedopenlog;
- /* fsl debugging */
+#ifdef FSL_DEBUGLOGCODE
l2_env_t *fsldebug_l2_env;
l2_channel_t *fsldebug_l2_nch;
int fsldebug_transientproblem;
int fsldebug_permanentproblem;
+#endif /* ifdef FSL_DEBUGLOGCODE */
+ char *fsl_config;
} ctx = {
NULL,
NULL,
NULL,
+ NULL,
LOG_UPTO(LOG_DEBUG),
0,
TRUE,
FALSE,
- /* fsl debugging */
+#ifdef FSL_DEBUGLOGCODE
NULL,
NULL,
FALSE,
- FALSE
+ FALSE,
+#endif /* ifdef FSL_DEBUGLOGCODE */
+ "@(#)OSSP fsl config "
+ "cfgdir=\"" FSL_CFGDIR "\"" " "
+ "prefix=\"" FSL_PREFIX "\""
+ "\n"
+ "@(#)OSSP fsl debug "
+#ifdef FSL_DEBUGLOGCODE
+ "logfile=\"" FSL_DEBUGLOGFILE "\"" " "
+ "logmask=\"" FSL_DEBUGLOGMASK "\""
+#else /* ifdef FSL_DEBUGLOGCODE */
+ "code omitted;"
+#endif /* ifdef FSL_DEBUGLOGCODE */
+ "\n"
};
-/* internal debugging prototypes */
-static void fsldebugcreate (void);
-static void fsldebug (l2_level_t, const char *, ...);
-static int fsldebugl2 (l2_level_t, const char *, va_list);
-static int fsldebugf2 (l2_level_t, const char *, va_list);
-static void fsldebugdestroy(void);
-
-/* internal debugging functions */
-static void fsldebugcreate()
+#ifdef FSL_DEBUGLOGCODE
+static void vfsldebug(l2_level_t level, const char *message, va_list ap)
{
- int rc = FSL_OK;
- char *argl2spec;
- l2_result_t l2rv;
- char *cp; /* scratch variable */
- l2_channel_t *ch; /* scratch variable */
-
- /* identify previous fault and avoid repetition */
- if (ctx.fsldebug_permanentproblem || ctx.fsldebug_transientproblem)
- return;
-
- /* create OSSP l2 environment for fsl itself (internal logging) */
- if ((argl2spec = getenv("FSL_DEBUG")) == NULL)
- argl2spec = FSL_DEBUG;
- if (strlen(argl2spec) > 0) {
- if ((l2rv = l2_env_create(&ctx.fsldebug_l2_env)) != L2_OK) {
- cp = l2_env_strerror(ctx.fsldebug_l2_env, l2rv); fsldebug(L2_LEVEL_ERROR, "openlog: failed to create L2 environment (%d) for fsl", l2rv); CU(FSL_ERR_INT); }
- if ((l2rv = l2_env_levels(ctx.fsldebug_l2_env, L2_LEVEL_ALL, L2_LEVEL_NONE)) != L2_OK) {
- cp = l2_env_strerror(ctx.fsldebug_l2_env, l2rv); fsldebug(L2_LEVEL_ERROR, "openlog: logging failed to set global logging level defaults %s(%d) for fsl", cp, l2rv); CU(FSL_ERR_INT); }
- if ((l2rv = l2_env_formatter(ctx.fsldebug_l2_env, 'D', l2_util_fmt_dump, NULL)) != L2_OK) {
- cp = l2_env_strerror(ctx.fsldebug_l2_env, l2rv); fsldebug(L2_LEVEL_ERROR, "openlog: logging failed to register dump formatter %s(%d) for fsl", cp, l2rv); CU(FSL_ERR_INT); }
- if ((l2rv = l2_env_formatter(ctx.fsldebug_l2_env, 'S', l2_util_fmt_string, NULL)) != L2_OK) {
- cp = l2_env_strerror(ctx.fsldebug_l2_env, l2rv); fsldebug(L2_LEVEL_ERROR, "openlog: logging failed to register string formatter %s(%d) for fsl", cp, l2rv); CU(FSL_ERR_INT); }
- if ((l2rv = l2_env_formatter(ctx.fsldebug_l2_env, 'm', l2_util_fmt_errno, NULL)) != L2_OK) {
- cp = l2_env_strerror(ctx.fsldebug_l2_env, l2rv); fsldebug(L2_LEVEL_ERROR, "openlog: logging failed to register errno formatter %s(%d) for fsl", cp, l2rv); CU(FSL_ERR_INT); }
- if ((l2rv = l2_channel_create(&ctx.fsldebug_l2_nch, ctx.fsldebug_l2_env, "noop")) != L2_OK) {
- cp = l2_env_strerror(ctx.fsldebug_l2_env, l2rv); fsldebug(L2_LEVEL_ERROR, "openlog: logging failed to create noop channel; %s(%d) for fsl", cp, l2rv); CU(FSL_ERR_INT); }
- if ((l2rv = l2_spec(&ch, ctx.fsldebug_l2_env, "%s", argl2spec)) != L2_OK) {
- cp = l2_env_strerror(ctx.fsldebug_l2_env, l2rv); fsldebug(L2_LEVEL_ERROR, "openlog: logging failed to create stream from spec %s(%d) for fsl", cp, l2rv);
- if (l2rv == L2_ERR_ARG)
- CU(FSL_ERR_ARG);
- else
- CU(FSL_ERR_INT);
- }
- if ((l2rv = l2_channel_link(ctx.fsldebug_l2_nch, L2_LINK_CHILD, ch, NULL)) != L2_OK) {
- cp = l2_env_strerror(ctx.fsldebug_l2_env, l2rv); fsldebug(L2_LEVEL_ERROR, "openlog: logging failed to link child channel %s(%d) for fsl", cp, l2rv); CU(FSL_ERR_INT); }
- if ((~ctx.logopt & LOG_NDELAY) && (ctx.delayopen == TRUE)) {
- fsldebug(L2_LEVEL_ERROR, "openlog: LOG_NDELAY unused forces debugging to use stealth mode until first syslog"); }
- else {
- if ((l2rv = l2_channel_open(ctx.fsldebug_l2_nch)) != L2_OK) {
- cp = l2_env_strerror(ctx.fsldebug_l2_env, l2rv); fsldebug(L2_LEVEL_ERROR, "openlog: logging failed to open channel stream %s(%d) for fsl", cp, l2rv); CU(FSL_ERR_INT); }
+ /* sizing cp temporary buffer is max out of
+ strlen "(panic,critical,error,warning,notice,info,trace,debug)" + terminating NUL and
+ strlen "bbb dd HH:MM:SS " + terminating NUL
+ = 56
+ */
+ static char cp[56]; /* FIXME */
+ static char cpo[MAXWRITESIZE];
+ int cpn;
+ int n;
+ struct stat sb;
+ unsigned int levelmask;
+ time_t t;
+ struct tm *tm;
+ int fd = 0;
+
+ /* determine level mask */
+ if ((n = readlink(FSL_DEBUGLOGMASK, cp, sizeof(cp))) == -1)
+ VCU;
+ if (cp[0] == '(' && cp[n-1] == ')') { /* level mask in round brackets like l2spec */
+ if(l2_util_s2l(&cp[1], n-2, ',', &levelmask) != L2_OK)
+ VCU;
+ }
+ else if (strchr(cp, ',') != NULL) { /* level mask automatic because comma detected */
+ if(l2_util_s2l(&cp[0], n , ',', &levelmask) != L2_OK)
+ VCU;
+ }
+ else { /* upto level like l2spec */
+ if(l2_util_s2l(&cp[0], n , 0 , &levelmask) != L2_OK)
+ VCU;
+ levelmask = L2_LEVEL_UPTO(levelmask);
+ }
+
+ if (level & levelmask) {
+
+ cpn = 0;
+
+ /* date and time */
+ t = time(NULL);
+ tm = localtime(&t);
+ if ((n = strftime(cp, sizeof(cp), "%b %d %H:%M:%S ", tm)) == 0)
+ VCU;
+ l2_util_sprintf( &cpo[cpn], MAXWRITESIZE-cpn, "%s", cp);
+ cpn = strlen(cpo);
+
+ /* level */
+ l2_util_sprintf( &cpo[cpn], MAXWRITESIZE-cpn, "<%s> ", l2_util_l2s(cp, sizeof(cp), '\0', level) == L2_OK ? cp : "unknown");
+ cpn = strlen(cpo);
+
+ /* program "name" and pid */
+ l2_util_sprintf( &cpo[cpn], MAXWRITESIZE-cpn, "%s[%lu^%lu] ", ctx.cpISF != NULL ? ctx.cpISF : "unknown", (unsigned long)getpid(), (unsigned long)getppid());
+ cpn = strlen(cpo);
+
+ /* message */
+ l2_util_vsprintf(&cpo[cpn], MAXWRITESIZE-cpn, message, ap);
+ cpn = strlen(cpo);
+ l2_util_sprintf( &cpo[cpn], MAXWRITESIZE-cpn, "\n");
+ cpn = strlen(cpo);
+
+ /* write the log */
+ if (cpn >= 1) {
+ if ((fd = open(FSL_DEBUGLOGFILE, O_WRONLY|O_CREAT|O_APPEND|O_NONBLOCK, 0644)) == -1)
+ VCU;
+ if (fstat(fd, &sb) == -1)
+ VCU;
+ if (sb.st_size >= FSL_DEBUGLOGSTOP)
+ VCU;
+ write(fd, cpo, cpn);
}
}
CUS:
- if (rc == FSL_ERR_ARG)
- ctx.fsldebug_permanentproblem = TRUE;
- if (rc != FSL_OK)
- fsldebugdestroy();
+ if (fd)
+ (void)close(fd);
}
static void fsldebug(l2_level_t level, const char *message, ...)
@@ -268,82 +311,16 @@
va_list ap;
va_start(ap, message);
- fsldebugl2(level, message, ap) || fsldebugf2(level, message, ap);
+ vfsldebug(level, message, ap);
va_end(ap);
return;
}
-
-static int fsldebugl2(l2_level_t level, const char *message, va_list ap)
-{
- int rc = FALSE; /* the pessimist */
- l2_result_t l2rv;
- char *cp;
-
- /* identify previous fault and avoid repetition */
- if (ctx.fsldebug_permanentproblem || ctx.fsldebug_transientproblem)
- return rc;
-
- /* nothing has been prepared, so do it now */
- if (ctx.fsldebug_l2_nch == NULL)
- fsldebugcreate();
-
- /* identify previous fault and avoid repetition */
- if (ctx.fsldebug_permanentproblem || ctx.fsldebug_transientproblem)
- return rc;
-
- /* preparation failed */
- if (ctx.fsldebug_l2_nch == NULL)
- return rc;
-
- /* try logging, L2_ERR_USE only occurs if channel is not yet open */
- if ((l2rv = l2_channel_vlog(ctx.fsldebug_l2_nch, level, message, ap)) == L2_ERR_USE) {
- if ((l2rv = l2_channel_open(ctx.fsldebug_l2_nch)) != L2_OK) {
- ctx.fsldebug_transientproblem = TRUE; /* avoid loop from fsldebug() in next line */
- cp = l2_env_strerror(ctx.fsldebug_l2_env, l2rv); fsldebug(L2_LEVEL_ERROR, "openlog: logging failed to open channel stream %s(%d) for fsl", cp, l2rv);
- ctx.fsldebug_transientproblem = FALSE; /* opening the channel might work at next attempt */
- return rc;
- }
- l2rv = l2_channel_vlog(ctx.fsldebug_l2_nch, level, message, ap);
- }
-
- if (l2rv == L2_OK)
- rc = TRUE;
-
- /* if openlog(3) "did not request LOG_NDELAY" aka "did request delay" (~ctx.logopt & LOG_NDELAY),
- * until a syslog(3) was tried (ctx.delayopen == TRUE), operate in stealth mode by closing channel
- */
- if ((~ctx.logopt & LOG_NDELAY) && (ctx.delayopen == TRUE))
- (void)l2_channel_close(ctx.fsldebug_l2_nch);
-
- return rc;
-}
-
-static int fsldebugf2(l2_level_t level, const char *message, va_list ap)
-{
- int rc = TRUE; /* the optimist */
- char cp[8];
-
- if (level & L2_LEVEL_UPTO(L2_LEVEL_ERROR)) {
- fprintf( stderr, "%s: ", l2_util_l2s(cp, sizeof(cp), '\0', level) == L2_OK ? cp[0]&=0xDF, cp : "Log");
- vfprintf(stderr, message, ap);
- fprintf( stderr, "\n");
- }
- return rc;
-}
-
-static void fsldebugdestroy()
+#else /* ifdef FSL_DEBUGLOGCODE */
+static void fsldebug(l2_level_t level, const char *message, ...)
{
- if (ctx.fsldebug_l2_nch != NULL) {
- l2_channel_destroy(ctx.fsldebug_l2_nch);
- ctx.fsldebug_l2_nch = NULL;
- }
- if (ctx.fsldebug_l2_env != NULL) {
- l2_env_destroy(ctx.fsldebug_l2_env);
- ctx.fsldebug_l2_env = NULL;
- }
- ctx.fsldebug_transientproblem = FALSE;
- /* fsldebug_permanentproblem kept */
+ return;
}
+#endif /* ifdef FSL_DEBUGLOGCODE */
/* append contents of a file to buffer */
static fsl_rc_t appendfiletobuffer(buf_t *buffer, const char *filename)
@@ -408,10 +385,8 @@
if (buffer == NULL)
CU(FSL_ERR_ARG);
- if ((cfgdir = getenv("FSL_CFGDIR")) == NULL)
- cfgdir = FSL_CFGDIR;
- if ((prefix = getenv("FSL_PREFIX")) == NULL)
- prefix = FSL_PREFIX;
+ cfgdir = FSL_CFGDIR;
+ prefix = FSL_PREFIX;
fsldebug(L2_LEVEL_TRACE, "readallfiles() globbing \"%s/%s*\"", cfgdir, prefix);
@@ -750,7 +725,6 @@
int i; /* scratch variable */
char *cpIdent;
char *cpFacility;
- char *cpISF;
l2_result_t l2rv;
/* initialization */
@@ -759,7 +733,6 @@
buf.used = 0;
buf.size = 0;
cpIdent = NULL;
- cpISF = NULL;
/* properly prepare for repeated execution */
closelog();
@@ -822,12 +795,12 @@
break;
}
}
- if ((cpISF = (char *)malloc(strlen(cpIdent) + 1 + strlen(cpFacility) + 1)) == NULL) {
+ if ((ctx.cpISF = (char *)malloc(strlen(cpIdent) + 1 + strlen(cpFacility) + 1)) == NULL) {
fsldebug(L2_LEVEL_ERROR, "openlog: malloc() failed"); CU(1); }
- cpISF[0] = '\0';
- strcat(cpISF, cpIdent);
- strcat(cpISF, "/");
- strcat(cpISF, cpFacility);
+ ctx.cpISF[0] = '\0';
+ strcat(ctx.cpISF, cpIdent);
+ strcat(ctx.cpISF, "/");
+ strcat(ctx.cpISF, cpFacility);
/* read configuration file(s) into buffer */
if ((rv = readallfiles(&buf)) != FSL_OK) {
@@ -840,11 +813,11 @@
(void)cfg_error(cfg, cfgrv, &cp); fsldebug(L2_LEVEL_ERROR, "openlog: cfg_import() failed with error %s (%d)", cp, cfgrv); CU(1); }
/* process OSSP cfg node tree "map" and "ident" directives */
- if ((rv = processcfg(cfg, cpISF, 0)) != FSL_OK && (rv != FSL_NOIDENT)) {
+ if ((rv = processcfg(cfg, ctx.cpISF, 0)) != FSL_OK && (rv != FSL_NOIDENT)) {
fsldebug(L2_LEVEL_ERROR, "openlog: processcfg() failed with an unrecoverable error (%d)", rv); CU(1); }
/* optionally process OSSP cfg node tree "default" directives */
- if ((rv == FSL_NOIDENT) && ((rv = processcfg(cfg, cpISF, 1)) != FSL_OK)) {
+ if ((rv == FSL_NOIDENT) && ((rv = processcfg(cfg, ctx.cpISF, 1)) != FSL_OK)) {
fsldebug(L2_LEVEL_ERROR, "openlog: processcfg() failed with an unrecoverable error (%d)", rv); CU(1); }
/* open logging now or prepare for delayed open */
@@ -859,8 +832,10 @@
CU(0);
CUS:
- if (cpISF != NULL)
- free(cpISF);
+ if (ctx.cpISF != NULL) {
+ free(ctx.cpISF);
+ ctx.cpISF = NULL;
+ }
if (cpIdent != NULL)
free(cpIdent);
if (cfg != NULL)
@@ -879,7 +854,6 @@
/* tracing */
fsldebug(L2_LEVEL_TRACE, "fsl in closelog(3)");
- fsldebugdestroy();
if (ctx.l2_nch != NULL) {
l2_channel_destroy(ctx.l2_nch);
ctx.l2_nch = NULL;
@@ -892,6 +866,10 @@
free(ctx.levelmap);
ctx.levelmap = NULL;
}
+ if (ctx.cpISF != NULL) {
+ free(ctx.cpISF);
+ ctx.cpISF = NULL;
+ }
ctx.maskpri = LOG_UPTO(LOG_DEBUG);
ctx.logopt = 0;
ctx.delayopen = TRUE;
|