summaryrefslogtreecommitdiffstats
path: root/plugins/omprog/omprog.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/omprog/omprog.c')
-rw-r--r--plugins/omprog/omprog.c173
1 files changed, 142 insertions, 31 deletions
diff --git a/plugins/omprog/omprog.c b/plugins/omprog/omprog.c
index d821ff16..1060b5c3 100644
--- a/plugins/omprog/omprog.c
+++ b/plugins/omprog/omprog.c
@@ -6,7 +6,7 @@
*
* File begun on 2009-04-01 by RGerhards
*
- * Copyright 2009-2012 Adiscon GmbH.
+ * Copyright 2009-2013 Adiscon GmbH.
*
* This file is part of rsyslog.
*
@@ -35,6 +35,7 @@
#include <errno.h>
#include <unistd.h>
#include <wait.h>
+#include <pthread.h>
#include "conf.h"
#include "syslogd-types.h"
#include "srUtils.h"
@@ -54,12 +55,19 @@ DEFobjCurrIf(errmsg)
typedef struct _instanceData {
uchar *szBinary; /* name of binary to call */
+ char **aParams; /* Optional Parameters for binary command */
uchar *tplName; /* assigned output template */
- pid_t pid; /* pid of currently running process */
- int fdPipe; /* file descriptor to write to */
+ 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 */
+ int iParams; /* Holds the count of parameters if set*/
+ pthread_mutex_t mut; /* make sure only one instance is active */
} instanceData;
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
typedef struct configSettings_s {
uchar *szBinary; /* name of binary to call */
} configSettings_t;
@@ -87,8 +95,13 @@ ENDinitConfVars
BEGINcreateInstance
CODESTARTcreateInstance
+ pthread_mutex_init(&pData->mut, NULL);
ENDcreateInstance
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
BEGINisCompatibleWithFeature
CODESTARTisCompatibleWithFeature
@@ -98,11 +111,23 @@ ENDisCompatibleWithFeature
BEGINfreeInstance
+ int i;
CODESTARTfreeInstance
+ pthread_mutex_destroy(&pData->mut);
if(pData->szBinary != NULL)
free(pData->szBinary);
+ if(pData->aParams != NULL) {
+ for (i = 0; i < pData->iParams; i++) {
+ free(pData->aParams[i]);
+ }
+ free(pData->aParams);
+ }
ENDfreeInstance
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
BEGINdbgPrintInstInfo
CODESTARTdbgPrintInstInfo
@@ -120,10 +145,9 @@ ENDtryResume
static void execBinary(instanceData *pData, int fdStdin)
{
- int i;
+ int i, iRet;
struct sigaction sigAct;
sigset_t set;
- char *newargv[] = { NULL };
char *newenviron[] = { NULL };
assert(pData != NULL);
@@ -135,7 +159,7 @@ static void execBinary(instanceData *pData, int fdStdin)
* gets some more widespread use...
*/
}
- //fclose(stdout);
+ /*fclose(stdout);*/
/* we close all file handles as we fork soon
* Is there a better way to do this? - mail me! rgerhards@adiscon.com
@@ -157,11 +181,11 @@ static void execBinary(instanceData *pData, int fdStdin)
alarm(0);
/* finally exec child */
- execve((char*)pData->szBinary, newargv, newenviron);
- /* switch to?
- execlp((char*)program, (char*) program, (char*)arg, NULL);
- */
-
+ iRet = execve((char*)pData->szBinary, pData->aParams, newenviron);
+ if (iRet == -1) {
+ dbgprintf("omprog: failed to execute binary '%s' with return code: %d\n", pData->szBinary, errno);
+ }
+
/* we should never reach this point, but if we do, we terminate */
exit(1);
}
@@ -183,7 +207,7 @@ openPipe(instanceData *pData)
ABORT_FINALIZE(RS_RET_ERR_CREAT_PIPE);
}
- DBGPRINTF("executing program '%s'\n", pData->szBinary);
+ DBGPRINTF("omprog: executing program '%s' with '%d' parameters\n", pData->szBinary, pData->iParams);
/* NO OUTPUT AFTER FORK! */
@@ -201,7 +225,7 @@ openPipe(instanceData *pData)
/*NO CODE HERE - WILL NEVER BE REACHED!*/
}
- DBGPRINTF("child has pid %d\n", (int) cpid);
+ DBGPRINTF("omprog: child has pid %d\n", (int) cpid);
pData->fdPipe = pipefd[1];
pData->pid = cpid;
close(pipefd[0]);
@@ -226,11 +250,11 @@ cleanup(instanceData *pData)
ret = waitpid(pData->pid, &status, 0);
if(ret != pData->pid) {
/* if waitpid() fails, we can not do much - try to ignore it... */
- DBGPRINTF("waitpid() returned state %d[%s], future malfunction may happen\n", ret,
+ DBGPRINTF("omprog: waitpid() returned state %d[%s], future malfunction may happen\n", ret,
rs_strerror_r(errno, errStr, sizeof(errStr)));
} else {
/* check if we should print out some diagnostic information */
- DBGPRINTF("waitpid status return for program '%s': %2.2x\n",
+ DBGPRINTF("omprog: waitpid status return for program '%s': %2.2x\n",
pData->szBinary, status);
if(WIFEXITED(status)) {
errmsg.LogError(0, NO_ERRCODE, "program '%s' exited normally, state %d",
@@ -279,22 +303,21 @@ writePipe(instanceData *pData, uchar *szMsg)
lenWrite = strlen((char*)szMsg);
writeOffset = 0;
- do
- {
+ do {
lenWritten = write(pData->fdPipe, ((char*)szMsg)+writeOffset, lenWrite);
if(lenWritten == -1) {
switch(errno) {
- case EPIPE:
- DBGPRINTF("Program '%s' terminated, trying to restart\n",
- pData->szBinary);
- CHKiRet(cleanup(pData));
- CHKiRet(tryRestart(pData));
- break;
- default:
- DBGPRINTF("error %d writing to pipe: %s\n", errno,
- rs_strerror_r(errno, errStr, sizeof(errStr)));
- ABORT_FINALIZE(RS_RET_ERR_WRITE_PIPE);
- break;
+ case EPIPE:
+ DBGPRINTF("omprog: Program '%s' terminated, trying to restart\n",
+ pData->szBinary);
+ CHKiRet(cleanup(pData));
+ CHKiRet(tryRestart(pData));
+ break;
+ default:
+ DBGPRINTF("omprog: error %d writing to pipe: %s\n", errno,
+ rs_strerror_r(errno, errStr, sizeof(errStr)));
+ ABORT_FINALIZE(RS_RET_ERR_WRITE_PIPE);
+ break;
}
} else {
writeOffset += lenWritten;
@@ -308,7 +331,10 @@ finalize_it:
BEGINdoAction
+ instanceData *pData;
CODESTARTdoAction
+ pData = pWrkrData->pData;
+ pthread_mutex_lock(&pData->mut);
if(pData->bIsRunning == 0) {
openPipe(pData);
}
@@ -317,6 +343,7 @@ CODESTARTdoAction
if(iRet != RS_RET_OK)
iRet = RS_RET_SUSPENDED;
+ pthread_mutex_unlock(&pData->mut);
ENDdoAction
@@ -324,13 +351,23 @@ static inline void
setInstParamDefaults(instanceData *pData)
{
pData->szBinary = NULL;
+ pData->aParams = NULL;
+ pData->iParams = 0;
pData->fdPipe = -1;
pData->bIsRunning = 0;
}
BEGINnewActInst
struct cnfparamvals *pvals;
+ sbool bInQuotes;
int i;
+ int iPrm;
+ unsigned char *c;
+ es_size_t iCnt;
+ es_size_t iStr;
+ es_str_t *estrBinary;
+ es_str_t *estrParams;
+ es_str_t *estrTmp;
CODESTARTnewActInst
if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
@@ -344,12 +381,85 @@ CODESTARTnewActInst
if(!pvals[i].bUsed)
continue;
if(!strcmp(actpblk.descr[i].name, "binary")) {
- pData->szBinary = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ estrBinary = pvals[i].val.d.estr;
+ estrParams = NULL;
+
+ /* Search for space */
+ c = es_getBufAddr(pvals[i].val.d.estr);
+ iCnt = 0;
+ while(iCnt < es_strlen(pvals[i].val.d.estr) ) {
+ if (c[iCnt] == ' ') {
+ /* Split binary name from parameters */
+ estrBinary = es_newStrFromSubStr ( pvals[i].val.d.estr, 0, iCnt );
+ estrParams = es_newStrFromSubStr ( pvals[i].val.d.estr, iCnt+1, es_strlen(pvals[i].val.d.estr));
+ break;
+ }
+ iCnt++;
+ }
+ /* Assign binary and params */
+ pData->szBinary = (uchar*)es_str2cstr(estrBinary, NULL);
+ dbgprintf("omprog: szBinary = '%s'\n", pData->szBinary);
+ /* Check for Params! */
+ if (estrParams != NULL) {
+ dbgprintf("omprog: szParams = '%s'\n", es_str2cstr(estrParams, NULL) );
+
+ /* Count parameters if set */
+ c = es_getBufAddr(estrParams); /* Reset to beginning */
+ pData->iParams = 2; /* Set default to 2, first parameter for binary and second parameter at least from config*/
+ iCnt = 0;
+ while(iCnt < es_strlen(estrParams) ) {
+ if (c[iCnt] == ' ' && c[iCnt-1] != '\\')
+ pData->iParams++;
+ iCnt++;
+ }
+ dbgprintf("omprog: iParams = '%d'\n", pData->iParams);
+
+ /* Create argv Array */
+ CHKmalloc(pData->aParams = malloc( (pData->iParams+1) * sizeof(char*))); /* One more for first param */
+
+ /* Second Loop, create parameter array*/
+ c = es_getBufAddr(estrParams); /* Reset to beginning */
+ iCnt = iStr = iPrm = 0;
+ estrTmp = NULL;
+ bInQuotes = FALSE;
+ /* Set first parameter to binary */
+ pData->aParams[iPrm] = strdup((char*)pData->szBinary);
+ dbgprintf("omprog: Param (%d): '%s'\n", iPrm, pData->aParams[iPrm]);
+ iPrm++;
+ while(iCnt < es_strlen(estrParams) ) {
+ if ( c[iCnt] == ' ' && !bInQuotes ) {
+ /* Copy into Param Array! */
+ estrTmp = es_newStrFromSubStr( estrParams, iStr, iCnt-iStr);
+ }
+ else if ( iCnt+1 >= es_strlen(estrParams) ) {
+ /* Copy rest of string into Param Array! */
+ estrTmp = es_newStrFromSubStr( estrParams, iStr, iCnt-iStr+1);
+ }
+ else if (c[iCnt] == '"') {
+ /* switch inQuotes Mode */
+ bInQuotes = !bInQuotes;
+ }
+
+ if ( estrTmp != NULL ) {
+ pData->aParams[iPrm] = es_str2cstr(estrTmp, NULL);
+ iStr = iCnt+1; /* Set new start */
+ dbgprintf("omprog: Param (%d): '%s'\n", iPrm, pData->aParams[iPrm]);
+ es_deleteStr( estrTmp );
+ estrTmp = NULL;
+ iPrm++;
+ }
+
+ /*Next char*/
+ iCnt++;
+ }
+ /* NULL last parameter! */
+ pData->aParams[iPrm] = NULL;
+
+ }
} else if(!strcmp(actpblk.descr[i].name, "template")) {
pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
} else {
- dbgprintf("omprog: program error, non-handled "
- "param '%s'\n", actpblk.descr[i].name);
+ dbgprintf("omprog: program error, non-handled param '%s'\n", actpblk.descr[i].name);
}
}
@@ -405,6 +515,7 @@ ENDmodExit
BEGINqueryEtryPt
CODESTARTqueryEtryPt
CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES
CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
ENDqueryEtryPt