6
6
* Work originally begun on 2008-02-01 by Rainer Gerhards
8
* Copyright 2008 Rainer Gerhards and Adiscon GmbH.
8
* Copyright 2008,2009 Rainer Gerhards and Adiscon GmbH.
10
10
* This file is part of rsyslog.
67
71
uchar *pszStateFile; /* file in which state between runs is to be stored */
74
int nRecords; /**< How many records did we process before persisting the stream? */
75
int iPersistStateInterval; /**< how often should state be persisted? (0=on close only) */
70
76
strm_t *pStrm; /* its stream (NULL if not assigned) */
77
int readMode; /* which mode to use in ReadMulteLine call? */
78
ruleset_t *pRuleset; /* ruleset to bind listener to (use system default if unspecified) */
82
/* forward definitions */
83
static rsRetVal persistStrmState(fileInfo_t *pInfo);
74
85
/* config variables */
75
86
static uchar *pszFileName = NULL;
76
87
static uchar *pszFileTag = NULL;
77
88
static uchar *pszStateFile = NULL;
78
89
static int iPollInterval = 10; /* number of seconds to sleep when there was no file activity */
90
static int iPersistStateInterval = 0; /* how often if state file to be persisted? (default 0->never) */
79
91
static int iFacility = 128; /* local0 */
80
92
static int iSeverity = 5; /* notice, as of rfc 3164 */
93
static int readMode = 0; /* mode to use for ReadMultiLine call */
94
static ruleset_t *pBindRuleset = NULL; /* ruleset to bind listener to (use system default if unspecified) */
82
96
static int iFilPtr = 0; /* number of files to be monitored; pointer to next free spot during config */
83
97
#define MAX_INPUT_FILES 100
107
121
MsgSetTAG(pMsg, pInfo->pszTag, pInfo->lenTag);
108
122
pMsg->iFacility = LOG_FAC(pInfo->iFacility);
109
123
pMsg->iSeverity = LOG_PRI(pInfo->iSeverity);
110
pMsg->bParseHOSTNAME = 0;
124
MsgSetRuleset(pMsg, pInfo->pRuleset);
111
125
CHKiRet(submitMsg(pMsg));
155
169
CHKiRet(strm.SeekCurrOffs(pThis->pStrm));
157
/* OK, we could successfully read the file, so we now can request that it be deleted.
158
* If we need it again, it will be written on the next shutdown.
171
/* note: we do not delete the state file, so that the last position remains
172
* known even in the case that rsyslogd aborts for some reason (like powerfail)
160
psSF->bDeleteOnClose = 1;
208
221
/* loop below will be exited when strmReadLine() returns EOF */
210
CHKiRet(strm.ReadLine(pThis->pStrm, &pCStr));
222
while(glbl.GetGlobalInputTermState() == 0) {
223
CHKiRet(strm.ReadLine(pThis->pStrm, &pCStr, pThis->readMode));
211
224
*pbHadFileData = 1; /* this is just a flag, so set it and forget it */
212
225
CHKiRet(enqLine(pThis, pCStr)); /* process line */
213
226
rsCStrDestruct(&pCStr); /* discard string (must be done by us!) */
227
if(pThis->iPersistStateInterval > 0 && pThis->nRecords++ >= pThis->iPersistStateInterval) {
228
persistStrmState(pThis);
217
/*EMPTY - just to keep the compiler happy, do NOT remove*/;
234
; /*EMPTY STATEMENT - needed to keep compiler happy - see below! */
218
235
/* Note: the problem above is that pthread:cleanup_pop() is a macro which
219
236
* evaluates to something like "} while(0);". So the code would become
220
237
* "finalize_it: }", that is a label without a statement. The C standard does
244
261
* IMPORTANT: the calling interface of this function can NOT be modified. It actually is
245
262
* called by pthreads. The provided argument is currently not being used.
247
/* ------------------------------------------------------------------------------------------ *
248
* DO NOT TOUCH the following code - it will soon be part of the module generation macros! */
250
265
inputModuleCleanup(void __attribute__((unused)) *arg)
253
/* END no-touch zone *
254
* ------------------------------------------------------------------------------------------ */
258
/* so far not needed */
262
/* ------------------------------------------------------------------------------------------ *
263
* DO NOT TOUCH the following code - it will soon be part of the module generation macros! */
266
/* END no-touch zone *
267
* ------------------------------------------------------------------------------------------ */
270
272
/* This function is called by the framework to gather the input. The module stays
293
295
int bHadFileData; /* were there at least one file with data during this run? */
294
296
CODESTARTrunInput
295
/* ------------------------------------------------------------------------------------------ *
296
* DO NOT TOUCH the following code - it will soon be part of the module generation macros! */
297
297
pthread_cleanup_push(inputModuleCleanup, NULL);
298
while(1) { /* endless loop - do NOT break; out of it! */
299
/* END no-touch zone *
300
* ------------------------------------------------------------------------------------------ */
304
for(i = 0 ; i < iFilPtr ; ++i) {
305
pollFile(&files[i], &bHadFileData);
307
} while(iFilPtr > 1 && bHadFileData == 1); /* waring: do...while()! */
309
/* Note: the additional 10ns wait is vitally important. It guards rsyslog against totally
310
* hogging the CPU if the users selects a polling interval of 0 seconds. It doesn't hurt any
311
* other valid scenario. So do not remove. -- rgerhards, 2008-02-14
313
srSleep(iPollInterval, 10);
315
/* ------------------------------------------------------------------------------------------ *
316
* DO NOT TOUCH the following code - it will soon be part of the module generation macros! */
298
while(glbl.GetGlobalInputTermState() == 0) {
301
for(i = 0 ; i < iFilPtr ; ++i) {
302
if(glbl.GetGlobalInputTermState() == 1)
303
break; /* terminate input! */
304
pollFile(&files[i], &bHadFileData);
306
} while(iFilPtr > 1 && bHadFileData == 1 && glbl.GetGlobalInputTermState() == 0); /* warning: do...while()! */
308
/* Note: the additional 10ns wait is vitally important. It guards rsyslog against totally
309
* hogging the CPU if the users selects a polling interval of 0 seconds. It doesn't hurt any
310
* other valid scenario. So do not remove. -- rgerhards, 2008-02-14
312
if(glbl.GetGlobalInputTermState() == 0)
313
srSleep(iPollInterval, 10);
315
DBGPRINTF("imfile: terminating upon request of rsyslog core\n");
320
317
pthread_cleanup_pop(0); /* just for completeness, but never called... */
321
318
RETiRet; /* use it to make sure the housekeeping is done! */
361
363
strm_t *psSF = NULL; /* state file (stream) */
363
366
ASSERT(pInfo != NULL);
365
368
/* TODO: create a function persistObj in obj.c? */
366
369
CHKiRet(strm.Construct(&psSF));
367
CHKiRet(strm.SetDir(psSF, glbl.GetWorkDir(), strlen((char*)glbl.GetWorkDir())));
370
lenDir = ustrlen(glbl.GetWorkDir());
372
CHKiRet(strm.SetDir(psSF, glbl.GetWorkDir(), lenDir));
368
373
CHKiRet(strm.SettOperationsMode(psSF, STREAMMODE_WRITE_TRUNC));
369
374
CHKiRet(strm.SetsType(psSF, STREAMTYPE_FILE_SINGLE));
370
375
CHKiRet(strm.SetFName(psSF, pInfo->pszStateFile, strlen((char*) pInfo->pszStateFile)));
416
BEGINisCompatibleWithFeature
417
CODESTARTisCompatibleWithFeature
418
if(eFeat == sFEATURENonCancelInputTermination)
420
ENDisCompatibleWithFeature
408
423
/* The following entry points are defined in module-template.h.
409
424
* In general, they need to be present, but you do NOT need to provide
417
432
objRelease(glbl, CORE_COMPONENT);
418
433
objRelease(errmsg, CORE_COMPONENT);
419
434
objRelease(prop, CORE_COMPONENT);
435
objRelease(ruleset, CORE_COMPONENT);
424
440
CODESTARTqueryEtryPt
425
441
CODEqueryEtryPt_STD_IMOD_QUERIES
442
CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
497
516
pThis->iSeverity = iSeverity;
498
517
pThis->iFacility = iFacility;
518
pThis->iPersistStateInterval = iPersistStateInterval;
520
pThis->readMode = readMode;
521
pThis->pRuleset = pBindRuleset;
522
iPersistStateInterval = 0;
500
524
errmsg.LogError(0, RS_RET_OUT_OF_DESRIPTORS, "Too many file monitors configured - ignoring this one");
501
525
ABORT_FINALIZE(RS_RET_OUT_OF_DESRIPTORS);
538
/* accept a new ruleset to bind. Checks if it exists and complains, if not */
540
setRuleset(void __attribute__((unused)) *pVal, uchar *pszName)
546
localRet = ruleset.GetRuleset(&pRuleset, pszName);
547
if(localRet == RS_RET_NOT_FOUND) {
548
errmsg.LogError(0, NO_ERRCODE, "error: ruleset '%s' not found - ignored", pszName);
551
pBindRuleset = pRuleset;
552
DBGPRINTF("imfile current bind ruleset %p: '%s'\n", pRuleset, pszName);
555
free(pszName); /* no longer needed */
513
560
/* modInit() is called once the module is loaded. It must perform all module-wide
514
561
* initialization tasks. There are also a number of housekeeping tasks that the
515
562
* framework requires. These are handled by the macros. Please note that the
527
574
CHKiRet(objUse(glbl, CORE_COMPONENT));
528
575
CHKiRet(objUse(datetime, CORE_COMPONENT));
529
576
CHKiRet(objUse(strm, CORE_COMPONENT));
577
CHKiRet(objUse(ruleset, CORE_COMPONENT));
530
578
CHKiRet(objUse(prop, CORE_COMPONENT));
580
DBGPRINTF("imfile: version %s initializing\n", VERSION);
532
581
CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilename", 0, eCmdHdlrGetWord,
533
582
NULL, &pszFileName, STD_LOADABLE_MODULE_ID));
534
583
CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfiletag", 0, eCmdHdlrGetWord,
541
590
NULL, &iFacility, STD_LOADABLE_MODULE_ID));
542
591
CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepollinterval", 0, eCmdHdlrInt,
543
592
NULL, &iPollInterval, STD_LOADABLE_MODULE_ID));
593
CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilereadmode", 0, eCmdHdlrInt,
594
NULL, &readMode, STD_LOADABLE_MODULE_ID));
595
CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepersiststateinterval", 0, eCmdHdlrInt,
596
NULL, &iPersistStateInterval, STD_LOADABLE_MODULE_ID));
597
CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilebindruleset", 0, eCmdHdlrGetWord,
598
setRuleset, NULL, STD_LOADABLE_MODULE_ID));
544
599
/* that command ads a new file! */
545
600
CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputrunfilemonitor", 0, eCmdHdlrGetWord,
546
601
addMonitor, NULL, STD_LOADABLE_MODULE_ID));