From c837e1b03d964e2bcf86e6618f813305326e1c41 Mon Sep 17 00:00:00 2001 From: David Smith Date: Wed, 16 Mar 2011 12:55:43 -0500 Subject: [PATCH] Read the list of logfiles from a config file in the logger PMDA. * pcp/src/pmdas/logger/logger.c (read_config): New function to read the config file. (main): Remove the '-m' option and accept a config file. * pcp/src/pmdas/logger/Install: Add the capability to specify a config file or create one. --- pcp/src/pmdas/logger/Install | 109 +++++++++++++++++++++++++---- pcp/src/pmdas/logger/logger.c | 128 ++++++++++++++++++++++++++++++++-- 2 files changed, 218 insertions(+), 19 deletions(-) diff --git a/pcp/src/pmdas/logger/Install b/pcp/src/pmdas/logger/Install index 53270b76b..44552eed3 100644 --- a/pcp/src/pmdas/logger/Install +++ b/pcp/src/pmdas/logger/Install @@ -39,25 +39,110 @@ pmda_interface=4 # pmdaSetup -# Get logfile to monitor +# be careful that mortals cannot write any configuration files, as +# these would present a security problem +# +umask 022 + + +# PMDA variables +# +configfile="" + +_parsedefaults() +{ + echo "Extracting options from current installation ..." + while getopts D:d:l c + do + case $c in + \?) echo "Warning: Unrecognized option in $PCP_PMCDCONF_PATH" + echo " Remove line for the $iam PMDA in $PCP_PMCDCONF_PATH and re-run ./Install" + exit 2;; + * ) ;; + esac + done + eval configfile='$'$OPTIND + echo "_parsedefaults found $configfile" +} + +# Get logfile(s) to monitor if $do_pmda then - args="" - - $PCP_ECHO_PROG $PCP_ECHO_N "Logfile path to monintor? ""$PCP_ECHO_C" - read value + # set options from $PCP_PMCDCONF_PATH, if possible + # + ans=`$PCP_AWK_PROG <$PCP_PMCDCONF_PATH ' +$1 == "'$iam'" { printf "%s",$6 + for (i=7;i<=NF;i++) printf " %s",$i + print "" + }'` + if [ ! -z "$ans" ] + then + _parsedefaults $ans + fi - if [ -z "$value" ] + # go figure out which configuration file to use ... + # + #default_configfile=./sample.conf + default_configfile='' + pmdaChooseConfigFile + if [ ! -f "$configfile" ] then - echo "Error: logfile path must be specifed." >&2 - exit 1 - else - if [ ! -e $value ] + $PCP_ECHO_PROG $PCP_ECHO_N "Do you wish to enter logfile names manually? [y] ""$PCP_ECHO_C" + read ans + if [ "X$ans" = "Xy" -o "X$ans" = "XY" -o -z "$ans" ] then - echo "Warning: logfile $value doesn't exist! Reinstall to change." + configfile="$configdir/$iam.conf" + if [ -f $configfile ] + then + echo "Removing old configuration file \"$configfile\"" + rm -f $configfile + if [ -f $configfile ] + then + echo "Cannot remove \"$configfile\"" + _quit 1 + fi + fi + + echo + echo \ +'Enter one logfile name per line. An empty line terminates the +logfile selection process and there must be at least one logfile specified. +' + + args="" + touch $configfile + if [ ! -f $configfile ] + then + echo "Installation aborted." + _quit 1 + fi + + while [ ! -s "$configfile" ] + do + while true + do + $PCP_ECHO_PROG $PCP_ECHO_N "Logfile name: ""$PCP_ECHO_C" + read logfile + [ -z "$logfile" ] && break + if grep "^$logfile$" $configfile >/dev/null + then + echo "Sorry, logfile \"$logfile\" already specified. Please try again." + continue + fi + if [ ! -e "$logfile" ]; then + echo "Error: logfile $value doesn't exist! Reinstall to change." + fi + echo "$logfile" >>$configfile + done + done + else + echo "" + echo "Error: Abandoning installation as no configuration file was specified." + _quit 1 fi - args="$args -m $value" fi + + args="$configfile" fi pmdaInstall diff --git a/pcp/src/pmdas/logger/logger.c b/pcp/src/pmdas/logger/logger.c index ffd849306..2c706adaa 100644 --- a/pcp/src/pmdas/logger/logger.c +++ b/pcp/src/pmdas/logger/logger.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "domain.h" #include "percontext.h" #include "event.h" @@ -39,6 +40,19 @@ * logger.clients - number of attached clients */ +struct LogfileData { + char pathname[MAXPATHLEN]; + int numclients; + /* current client list - allocated? */ + /* char *pathname; - stored in pmdaInstid */ + /* int fd; */ + /* head of event queue */ + /* perhaps a 'void *' for event.c to store stuff in? */ +}; + +static struct LogfileData *logfiles = NULL; +static int numlogfiles = 0; + /* * all metrics supported in this PMDA - one table entry for each */ @@ -60,7 +74,7 @@ static pmdaMetric metrictab[] = { static char mypath[MAXPATHLEN]; static int isDSO = 1; /* ==0 if I am a daemon */ -char *monitor_path = NULL; +char *configfile = NULL; void logger_end_contextCallBack(int ctx) @@ -159,7 +173,94 @@ logger_init(pmdaInterface *dp) pmdaInit(dp, NULL, 0, metrictab, sizeof(metrictab)/sizeof(metrictab[0])); - event_init(dp, monitor_path); + /* For now, only handle the 1st logfile. */ + event_init(dp, logfiles[0].pathname); +} + +static int +read_config(const char *filename) +{ + FILE *configFile; + struct LogfileData *data; + int rc = 0; + size_t len; + char tmp[MAXPATHLEN]; + char *endptr; + + configFile = fopen(filename, "r"); + if (configFile == NULL) { + fprintf(stderr, "%s: %s: %s\n", __FUNCTION__, filename, + strerror(errno)); + return -1; + } + + while (! feof(configFile)) { + if (fgets(tmp, sizeof(tmp), configFile) == NULL) { + if (feof(configFile)) { + break; + } + else { + fprintf(stderr, "%s: fgets failed: %s\n", __FUNCTION__, + strerror(errno)); + rc = -1; + break; + } + } + + /* fgets() puts the '\n' at the end of the buffer. Remove + * it. If it isn't there, that must mean that the pathname + * is longer than MAXPATHLEN. */ + len = strlen(tmp); + if (len == 0) { /* Ignore empty string. */ + continue; + } + else if (tmp[len - 1] != '\n') { /* String must be too long */ + fprintf(stderr, "%s: pathname too long: %s\n", __FUNCTION__, + tmp); + rc = -1; + break; + } + tmp[len - 1] = '\0'; /* Remove the '\n'. */ + + /* Remove all trailing whitespace. Set endptr to last char of + * string. */ + endptr = tmp + strlen(tmp) - 1; + /* While trailing whitespace, move back. */ + while (endptr >= tmp && isspace(*endptr)) { + --endptr; + } + *(endptr+1) = '\0'; /* Now set '\0' as terminal byte. */ + + /* If the string is now empty, just ignore the line. */ + len = strlen(tmp); + if (len == 0) { + continue; + } + + /* Now we've got a reasonable logfile pathname. Save it. */ + numlogfiles++; + logfiles = realloc(logfiles, numlogfiles * sizeof(struct LogfileData)); + if (logfiles == NULL) { + fprintf(stderr, "%s: realloc failed: %s\n", __FUNCTION__, + strerror(errno)); + rc = -1; + break; + } + data = &logfiles[numlogfiles - 1]; + data->numclients = 0; + strcpy(data->pathname, tmp); + + __pmNotifyErr(LOG_INFO, "%s: saw logfile %s\n", __FUNCTION__, + data->pathname); + } + if (rc != 0) { + free(logfiles); + logfiles = NULL; + numlogfiles = 0; + } + + fclose(configFile); + return rc; } static void @@ -193,20 +294,33 @@ main(int argc, char **argv) pmdaDaemon(&desc, PMDA_INTERFACE_5, pmProgname, LOGGER, "logger.log", mypath); - while ((c = pmdaGetOpt(argc, argv, "D:d:l:m:?", &desc, &err)) != EOF) { + while ((c = pmdaGetOpt(argc, argv, "D:d:l:?", &desc, &err)) != EOF) { switch (c) { - case 'm': - monitor_path = optarg; - break; default: err++; break; } } - if (err || monitor_path == NULL) + if (err || optind != argc -1) { usage(); + } + + configfile = argv[optind]; pmdaOpenLog(&desc); + if (read_config(configfile) != 0) { + exit(1); + } + + /* For now, only allow 1 logfile. */ + if (numlogfiles == 0) { + usage(); + } + if (numlogfiles > 1) { + __pmNotifyErr(LOG_INFO, "%s: Only handling first logfile\n", + __FUNCTION__); + } + logger_init(&desc); pmdaConnect(&desc); -- 2.43.5