/* omtemplate.c
* This is a template for an output module. It implements a very
* simple single-threaded output, just as thought of by the output
* plugin interface.
*
* NOTE: read comments in module-template.h for more specifics!
*
* File begun on 2009-03-16 by RGerhards
*
* Copyright 2009 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of rsyslog.
*
* Rsyslog is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Rsyslog 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Rsyslog. If not, see .
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
*/
#include "config.h"
#include "rsyslog.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include "dirty.h"
#include "syslogd-types.h"
#include "srUtils.h"
#include "template.h"
#include "module-template.h"
#include "errmsg.h"
#include "cfsysline.h"
MODULE_TYPE_OUTPUT
/* internal structures
*/
DEF_OMOD_STATIC_DATA
DEFobjCurrIf(errmsg)
typedef struct _instanceData {
/* here you need to define all action-specific data. A record of type
* instanceData will be handed over to each instance of the action. Keep
* in mind that there may be several invocations of the same type of action
* inside rsyslog.conf, and this is what keeps them apart. Do NOT use
* static data for this!
*/
unsigned iSrvPort; /* sample: server port */
} instanceData;
/* config variables
* For the configuration interface, we need to keep track of some settings. This
* is done in global variables. It works as follows: when configuration statements
* are entered, the config file handler (or custom function) sets the global
* variable here. When the action then actually is instantiated, this handler
* copies over to instanceData whatever configuration settings (from the global
* variables) apply. The global variables are NEVER used inside an action
* instance (at least this is how it is supposed to work ;)
*/
static int iSrvPort = 0; /* sample: server port */
BEGINcreateInstance
CODESTARTcreateInstance
ENDcreateInstance
BEGINisCompatibleWithFeature
CODESTARTisCompatibleWithFeature
/* use this to specify if select features are supported by this
* plugin. If not, the framework will handle that. Currently, only
* RepeatedMsgReduction ("last message repeated n times") is optional.
*/
if(eFeat == sFEATURERepeatedMsgReduction)
iRet = RS_RET_OK;
ENDisCompatibleWithFeature
BEGINfreeInstance
CODESTARTfreeInstance
/* this is a cleanup callback. All dynamically-allocated resources
* in instance data must be cleaned up here. Prime examples are
* malloc()ed memory, file & database handles and the like.
*/
ENDfreeInstance
BEGINdbgPrintInstInfo
CODESTARTdbgPrintInstInfo
/* permits to spit out some debug info */
ENDdbgPrintInstInfo
BEGINtryResume
CODESTARTtryResume
/* this is called when an action has been suspended and the
* rsyslog core tries to resume it. The action must then
* retry (if possible) and report RS_RET_OK if it succeeded
* or RS_RET_SUSPENDED otherwise.
* Note that no data can be written in this callback, as it is
* not present. Prime examples of what can be retried are
* reconnects to remote hosts, reconnects to database,
* opening of files and the like.
* If there is no retry-type of operation, the action may
* return RS_RET_OK, so that it will get called on its doAction
* entry point (where it receives data), retries there, and
* immediately returns RS_RET_SUSPENDED if that does not work
* out. This disables some optimizations in the core's retry logic,
* but is a valid and expected behaviour. Note that it is also OK
* for the retry entry point to return OK but the immediately following
* doAction call to fail. In real life, for example, a buggy com line
* may cause such behaviour.
* Note that there is no guarantee that the core will very quickly
* call doAction after the retry succeeded. Today, it does, but that may
* not always be the case.
*/
ENDtryResume
BEGINdoAction
CODESTARTdoAction
/* this is where you receive the message and need to carry out the
* action. Data is provided in ppString[i] where 0 <= i <= num of strings
* requested.
* Return RS_RET_OK if all goes well, RS_RET_SUSPENDED if the action can
* currently not complete, or an error code or RS_RET_DISABLED. The later
* two should only be returned if there is no hope that the action can be
* restored unless an rsyslog restart (prime example is an invalid config).
* Error code or RS_RET_DISABLED permanently disables the action, up to
* the next restart.
*/
ENDdoAction
BEGINparseSelectorAct
CODESTARTparseSelectorAct
CODE_STD_STRING_REQUESTparseSelectorAct(1)
/* first check if this config line is actually for us
* This is a clumpsy interface. We receive the action-part of the selector line
* and need to look at the first characters. If they match our signature
* ":omtemplate:", then we need to instantiate an action. It is recommended that
* newer actions just watch for the template and all other parameters are passed in
* via $-config-lines, this will hopefully be compatbile with future config syntaxes.
* If we do not detect our signature, we must return with RS_RET_CONFLINE_UNPROCESSED
* and NOT do anything else.
*/
if(strncmp((char*) p, ":omtemplate:", sizeof(":omtemplate:") - 1)) {
ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
}
/* ok, if we reach this point, we have something for us */
p += sizeof(":omtemplate:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
CHKiRet(createInstance(&pData));
/* check if a non-standard template is to be applied */
if(*(p-1) == ';')
--p;
/* if we have, call rsyslog runtime to get us template. Note that StdFmt below is
* the standard name. Currently, we may need to patch tools/syslogd.c if we need
* to add a new standard template.
*/
CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_RQD_TPL_OPT_SQL, (uchar*) " StdFmt"));
/* if we reach this point, all went well, and we can copy over to instanceData
* those configuration elements that we need.
*/
pData->iSrvPort = (unsigned) iSrvPort; /* set configured port */
CODE_STD_FINALIZERparseSelectorAct
ENDparseSelectorAct
BEGINmodExit
CODESTARTmodExit
ENDmodExit
BEGINqueryEtryPt
CODESTARTqueryEtryPt
CODEqueryEtryPt_STD_OMOD_QUERIES
ENDqueryEtryPt
/* Reset config variables for this module to default values.
*/
static rsRetVal
resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
{
DEFiRet;
iSrvPort = 0; /* zero is the default port */
RETiRet;
}
BEGINmodInit()
CODESTARTmodInit
*ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(objUse(errmsg, CORE_COMPONENT));
/* register our config handlers */
/* confguration parameters MUST always be specified in lower case! */
CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionomtemplteserverport", 0, eCmdHdlrInt, NULL, &iSrvPort, STD_LOADABLE_MODULE_ID));
/* "resetconfigvariables" should be provided. Notat that it is a chained directive */
CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
ENDmodInit
/* vi:set ai:
*/