Loading...
Searching...
No Matches
XrdOucLogging.cc
Go to the documentation of this file.
/******************************************************************************/
/* */
/* X r d O u c L o g g i n g . c c */
/* */
/* (c) 2016 by the Board of Trustees of the Leland Stanford, Jr., University */
/* All Rights Reserved */
/* Produced by Andrew Hanushevsky for Stanford University under contract */
/* DE-AC02-76-SFO0515 with the Department of Energy */
/* */
/* This file is part of the XRootD software suite. */
/* */
/* XRootD is free software: you can redistribute it and/or modify it under */
/* the terms of the GNU Lesser General Public License as published by the */
/* Free Software Foundation, either version 3 of the License, or (at your */
/* option) any later version. */
/* */
/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
/* License for more details. */
/* */
/* You should have received a copy of the GNU Lesser General Public License */
/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
/* */
/* The copyright holder's institutional names and contributor's names may not */
/* be used to endorse or promote products derived from this software without */
/* specific prior written permission of the institution or contributor. */
/******************************************************************************/
#include <cerrno>
#include <cstdio>
#include <cstring>
#include "XrdVersion.hh"
#include "XrdOuc/XrdOuca2x.hh"
#include "XrdOuc/XrdOucEnv.hh"
#include "XrdOuc/XrdOucLogging.hh"
#include "XrdOuc/XrdOucPinLoader.hh"
#include "XrdOuc/XrdOucStream.hh"
#include "XrdOuc/XrdOucUtils.hh"
#include "XrdSys/XrdSysError.hh"
#include "XrdSys/XrdSysFD.hh"
#include "XrdSys/XrdSysLogging.hh"
#include "XrdSys/XrdSysLogPI.hh"
#include "XrdSys/XrdSysPthread.hh"
/******************************************************************************/
/* T h r e a d I n t e r f a c e s */
/******************************************************************************/
namespace
{
int cseLvl = 0;
int stdErr = 0;
struct dbgHdr
{char theDate[6]; // yymmdd
char sep1; // single space
char theHH[2]; // hh
char colon1; // :
char theMM[2]; // mm
char colon2; // :
char theSS[2]; // SS
};
bool BadHdr(dbgHdr *dLine)
{if (dLine->sep1 != ' ' || dLine->colon1 != ':' || dLine->colon2 != ':')
return true;
if (dLine->theHH[0] < '0' || dLine->theHH[0] > '2'
|| dLine->theHH[1] < '0' || dLine->theHH[0] > '3'
|| dLine->theMM[0] < '0' || dLine->theMM[0] > '5'
|| dLine->theMM[1] < '0' || dLine->theMM[1] > '9'
|| dLine->theSS[0] < '0' || dLine->theSS[0] > '5'
|| dLine->theSS[1] < '0' || dLine->theSS[1] > '9') return true;
for (int i = 0; i < 6; i++)
if (dLine->theDate[i] < '0' || dLine->theDate[i] > '9') return true;
return false;
}
void *LoggingStdErr(void *carg)
{(void)carg;
XrdOucStream seStream;
struct timeval seTime = {0,0};
struct iovec ioV;
seStream.Attach(stdErr, 4096);
do {if ((ioV.iov_base = seStream.GetLine()))
{ioV.iov_len = strlen((const char *)ioV.iov_base);
if (cseLvl == 1)
{if (ioV.iov_len < (int)sizeof(dbgHdr)
|| BadHdr((dbgHdr *)ioV.iov_base)) continue;
}
XrdSysLogging::Forward(seTime, 0, &ioV, 1);
}
} while(true);
return 0;
}
}
/******************************************************************************/
/* c o n f i g L o g */
/******************************************************************************/
bool XrdOucLogging:: configLog(XrdSysError &eDest,
XrdOucLogging::configLogInfo &logInfo)
{
struct tmpstr {char *arg; char *arg2, *arg3;
tmpstr(const char *str) : arg(strdup(str)),
arg2(0), arg3(0) {}
~tmpstr() {if (arg) free(arg);
if (arg2) free(arg2);
if (arg3) free(arg3);
}
};
static XrdVERSIONINFODEF(myVersion, XrdLogConfig, XrdVNUMBER, XrdVERSION);
XrdSysLogging::Parms logParms;
char *logPI = 0, *logFN = 0;
int argc;
// Check for stderr output
//
if (!strcmp(logInfo.logArg, "-")) return true;
tmpstr opt(logInfo.logArg);
// Check if this specified a plugin
//
if (*opt.arg == '@')
{char *parms = index(opt.arg, ',');
logPI = opt.arg+1;
if (!(*logPI))
{eDest.Emsg("Config", "Log plugin library not specified.");
return false;
}
if (parms)
{char *eol, *pval;
int rc;
opt.arg3 = strdup(parms); *parms = 0; parms = opt.arg3;
if ((pval = varVal(",bsz=", parms, eol, ',')))
{long long bsz;
rc = XrdOuca2x::a2sz(eDest,"-l bsz",pval,&bsz,0,1048576);
if (eol) *eol = ',';
if (rc < 0) return false;
if (bsz && bsz < 8192) bsz = 8192;
logParms.bufsz = static_cast<int>(bsz);
}
if ((pval = varVal(",cse=", parms, eol, ',')))
{rc = XrdOuca2x::a2i(eDest,"-l cse",pval,&cseLvl,0,2);
if (eol) *eol = ',';
if (rc < 0) return false;
}
logFN = varVal(",logfn=", parms, eol, ',');
}
} else logFN = opt.arg;
// Handle any logfile name
//
if (logFN)
{ if (*logFN == '=')
{if (*(logFN+1) == '\0')
{eDest.Emsg("Config", "Logfile name not specified.");
return false;
}
logParms.logfn = ++logFN;
}
else if (strcmp(logFN, "-"))
{if (!(logFN = XrdOucUtils::subLogfn(eDest,logInfo.iName,strdup(logFN))))
return false;
logParms.logfn = opt.arg2 = logFN;
}
else logParms.logfn = logFN;
}
// Handle plugin, if any
//
if (logPI)
{XrdSysLogPInit_t logPInit;
XrdOucPinLoader lpiLib(&eDest, &myVersion, "logging", logPI);
char **lpiArgs = configLPIArgs(logInfo.xrdEnv, argc);
if (!(logPInit = (XrdSysLogPInit_t)lpiLib.Resolve("XrdSysLogPInit")))
{eDest.Emsg("Config","Unable to find logging plugin object in",logPI);
lpiLib.Unload();
return false;
}
if (!(logParms.logpi = (*logPInit)(logInfo.cfgFn, lpiArgs, argc)))
{eDest.Emsg("Config", "Logging plugin initialization failed.");
lpiLib.Unload();
return false;
}
}
// Now complete logging configuration
//
logParms.keepV = logInfo.keepV;
logParms.hiRes = logInfo.hiRes;
if (!XrdSysLogging::Configure(*(eDest.logger()), logParms))
{eDest.Emsg("Config", "Log configuration failed.");
return false;
}
// Export the directory where the log file exists. We can modify the logfn
// as it should have been copied. Note logFN is the same as logParms.logfn.
//
if (logFN && (logPI = rindex(logFN,'/'))) *(logPI+1) = '\0';
else logParms.logfn = "./";
XrdOucEnv::Export("XRDLOGDIR", logParms.logfn);
// If there is a plugin but alternate output has not been specified, then we
// must capture stderr output and feed it to the logging plugin.
//
if (logPI && !logFN && cseLvl)
{pthread_t tid;
int pipeFD[2], dupStdErr = XrdSysFD_Dup(STDERR_FILENO);
if (dupStdErr < 0 || XrdSysFD_Pipe(pipeFD) < 0
|| XrdSysFD_Dup2(pipeFD[1], STDERR_FILENO) < 0)
{eDest.Emsg("Config",errno, "creating a pipe to capture stderr.");
close(dupStdErr);
return false;
}
close(pipeFD[1]);
if (XrdSysThread::Run(&tid,LoggingStdErr,(void *)0,0,"stderr router"))
{XrdSysFD_Dup2(dupStdErr, STDERR_FILENO);
eDest.Emsg("Config", errno, "start stderr router");
close(pipeFD[0]); close(dupStdErr); return false;
}
stdErr = pipeFD[0];
close(dupStdErr);
}
// All done
//
return true;
}
/******************************************************************************/
/* Private: c o n f i g L P I A r g s */
/******************************************************************************/
char **XrdOucLogging::configLPIArgs(XrdOucEnv *envP, int &argc)
{
static char theLPI[] = {'l', 'o', 'g', 0};
static char *dfltArgv[] = {0, 0};
char **lpiArgv = 0;
// Find our arguments, if any
//
if (envP && (lpiArgv = (char **)envP->GetPtr("xrdlog.argv**")))
argc = envP->GetInt("xrdlog.argc");
// Verify that we have some and substitute if not
//
if (!lpiArgv || argc < 1)
{if (!envP || !(dfltArgv[0] = (char *)envP->GetPtr("argv[0]")))
dfltArgv[0] = theLPI;
lpiArgv = dfltArgv;
argc = 1;
}
// Return the argv pointer
//
return lpiArgv;
}
/******************************************************************************/
/* Private: v a r V a l */
/******************************************************************************/
char *XrdOucLogging::varVal(const char *var, char *line, char *&eol, char delim)
{
// Find variable in the line
//
char *result = strstr(line, var);
if (!result) return 0;
// Push up to the value and find the end
//
result += strlen(var);
if (!delim) eol = 0;
else if ((eol = index(result, delim))) *eol = 0;
// All done
//
return result;
}
eDest
static XrdSysError eDest(0,"crypto_")
XrdVERSIONINFODEF
static XrdVERSIONINFODEF(compiledVer, XrdHttpProtocolTest, XrdVNUMBER, XrdVERSION)
XrdOucEnv.hh
XrdOucLogging.hh
XrdOucPinLoader.hh
XrdOucStream.hh
XrdOucUtils.hh
XrdOuca2x.hh
close
#define close(a)
Definition XrdPosix.hh:48
XrdSysError.hh
XrdSysFD.hh
XrdSysLogPI.hh
XrdSysLogPInit_t
XrdSysLogPI_t(* XrdSysLogPInit_t)(const char *cfgn, char **argv, int argc)
Definition XrdSysLogPI.hh:77
XrdSysLogging.hh
XrdSysPthread.hh
XrdOucEnv
Definition XrdOucEnv.hh:42
XrdOucEnv::GetInt
long GetInt(const char *varname)
Definition XrdOucEnv.cc:235
XrdOucEnv::Export
static int Export(const char *Var, const char *Val)
Definition XrdOucEnv.cc:170
XrdOucEnv::GetPtr
void * GetPtr(const char *varname)
Definition XrdOucEnv.cc:263
XrdOucLogging::configLog
static bool configLog(XrdSysError &eDest, configLogInfo &logInfo)
Definition XrdOucLogging.cc:111
XrdOucPinLoader
Definition XrdOucPinLoader.hh:50
XrdOucPinLoader::Resolve
void * Resolve(const char *symbl, int mcnt=1)
Definition XrdOucPinLoader.cc:267
XrdOucPinLoader::Unload
void Unload(bool dodel=false)
Definition XrdOucPinLoader.cc:305
XrdOucStream
Definition XrdOucStream.hh:47
XrdOucStream::GetLine
char * GetLine()
Definition XrdOucStream.cc:554
XrdOucStream::Attach
int Attach(int FileDescriptor, int bsz=2047)
Definition XrdOucStream.cc:252
XrdOucUtils::subLogfn
static char * subLogfn(XrdSysError &eDest, const char *inst, char *logfn)
Definition XrdOucUtils.cc:1198
XrdOuca2x::a2i
static int a2i(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
Definition XrdOuca2x.cc:45
XrdOuca2x::a2sz
static int a2sz(XrdSysError &, const char *emsg, const char *item, long long *val, long long minv=-1, long long maxv=-1)
Definition XrdOuca2x.cc:257
XrdSysError
Definition XrdSysError.hh:90
XrdSysLogging::Forward
static bool Forward(struct timeval mtime, unsigned long tID, struct iovec *iov, int iovcnt)
Definition XrdSysLogging.cc:172
XrdSysLogging::Configure
static bool Configure(XrdSysLogger &logr, Parms &parms)
Definition XrdSysLogging.cc:72
XrdSysThread::Run
static int Run(pthread_t *, void *(*proc)(void *), void *arg, int opts=0, const char *desc=0)
Definition XrdSysPthread.cc:307
XrdProxy::envP
XrdOucEnv * envP
Definition XrdPss.cc:109
XrdOucLogging::configLogInfo
Definition XrdOucLogging.hh:41
XrdOucLogging::configLogInfo::logArg
const char * logArg
Definition XrdOucLogging.hh:41
XrdOucLogging::configLogInfo::keepV
int keepV
Definition XrdOucLogging.hh:45
XrdOucLogging::configLogInfo::hiRes
bool hiRes
Definition XrdOucLogging.hh:46
XrdOucLogging::configLogInfo::xrdEnv
XrdOucEnv * xrdEnv
Definition XrdOucLogging.hh:42
XrdOucLogging::configLogInfo::cfgFn
const char * cfgFn
Definition XrdOucLogging.hh:44
XrdOucLogging::configLogInfo::iName
const char * iName
Definition XrdOucLogging.hh:43
XrdSysLogging::Parms
Parameters to be passed to configure.
Definition XrdSysLogging.hh:65
XrdSysLogging::Parms::logpi
XrdSysLogPI_t logpi
-> log plugin object or nil if none
Definition XrdSysLogging.hh:66
XrdSysLogging::Parms::keepV
int keepV
log keep argument
Definition XrdSysLogging.hh:68
XrdSysLogging::Parms::logfn
const char * logfn
-> log file name or nil if none.
Definition XrdSysLogging.hh:65
XrdSysLogging::Parms::hiRes
bool hiRes
log using high resolution timestamp
Definition XrdSysLogging.hh:69
XrdSysLogging::Parms::bufsz
int bufsz
size of message buffer, -1 default, or 0
Definition XrdSysLogging.hh:67