/* omprog.c
* This output plugin enables rsyslog to execute a program and
* feed it the message stream as standard input.
*
* NOTE: read comments in module-template.h for more specifics!
*
* File begun on 2009-04-01 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
typedef struct _instanceData {
uchar *szBinary; /* name of binary to call */
pid_t pid; /* pid of currently running process */
int fdPipe; /* file descriptor to write to */
int bIsRunning; /* is binary currently running? 0-no, 1-yes */
} instanceData;
/* config settings */
static uchar *szBinary = NULL; /* name of binary to call */
BEGINcreateInstance
CODESTARTcreateInstance
ENDcreateInstance
BEGINisCompatibleWithFeature
CODESTARTisCompatibleWithFeature
if(eFeat == sFEATURERepeatedMsgReduction)
iRet = RS_RET_OK;
ENDisCompatibleWithFeature
BEGINfreeInstance
CODESTARTfreeInstance
ENDfreeInstance
BEGINdbgPrintInstInfo
CODESTARTdbgPrintInstInfo
ENDdbgPrintInstInfo
BEGINtryResume
CODESTARTtryResume
ENDtryResume
/* creates a pipe and starts program, uses pipe as stdin for program.
* rgerhards, 2009-04-01
*/
static rsRetVal
openPipe(instanceData *pData)
{
int pipefd[2];
pid_t cpid;
char *newargv[] = { NULL };
char *newenviron[] = { NULL };
DEFiRet;
assert(pData != NULL);
if(pipe(pipefd) == -1) {
ABORT_FINALIZE(RS_RET_ERR_CREAT_PIPE);
}
cpid = fork();
if(cpid == -1) {
ABORT_FINALIZE(RS_RET_ERR_FORK);
}
if(cpid == 0) {
/* we are now the child, just set the right selectors and
* exec the binary. If that fails, there is not much we can do.
*/
fclose(stdin);
dup(pipefd[0]);
close(pipefd[1]);
//fclose(stdout);
fprintf(stderr, "Program to exec '%s', fdPipe: %d\n", pData->szBinary, pipefd[0]);
execve((char*)pData->szBinary, newargv, newenviron);
}
pData->fdPipe = pipefd[1];
pData->pid = cpid;
close(pipefd[0]);
pData->bIsRunning = 1;
finalize_it:
RETiRet;
}
BEGINdoAction
CODESTARTdoAction
if(pData->bIsRunning == 0) {
openPipe(pData);
}
write(pData->fdPipe, (char*)ppString[0], strlen((char*)ppString[0]));
ENDdoAction
BEGINparseSelectorAct
CODESTARTparseSelectorAct
CODE_STD_STRING_REQUESTparseSelectorAct(1)
/* first check if this config line is actually for us */
if(strncmp((char*) p, ":omprog:", sizeof(":omprog:") - 1)) {
ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
}
/* ok, if we reach this point, we have something for us */
p += sizeof(":omprog:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
CHKiRet(createInstance(&pData));
CHKmalloc(pData->szBinary = (uchar*) strdup((char*)szBinary));
/* check if a non-standard template is to be applied */
if(*(p-1) == ';')
--p;
CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, 0, (uchar*) "RSYSLOG_FileFormat"));
CODE_STD_FINALIZERparseSelectorAct
ENDparseSelectorAct
BEGINmodExit
CODESTARTmodExit
if(szBinary != NULL) {
free(szBinary);
szBinary = NULL;
}
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;
if(szBinary != NULL) {
free(szBinary);
szBinary = NULL;
}
RETiRet;
}
BEGINmodInit()
CODESTARTmodInit
*ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionomprogbinary", 0, eCmdHdlrGetWord, NULL, &szBinary, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
CODEmodInit_QueryRegCFSLineHdlr
ENDmodInit
/* vi:set ai:
*/