/* 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 "conf.h" #include "syslogd-types.h" #include "srUtils.h" #include "template.h" #include "module-template.h" #include "errmsg.h" #include "cfsysline.h" MODULE_TYPE_OUTPUT MODULE_TYPE_NOKEEP /* 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: */