4
4
* File begun on 2007-07-30 by RGerhards
6
* Copyright 2007 Rainer Gerhards and Adiscon GmbH.
8
* This program is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU General Public License
10
* as published by the Free Software Foundation; either version 2
11
* of the License, or (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
6
* This file is part of rsyslog.
8
* Rsyslog is free software: you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation, either version 3 of the License, or
11
* (at your option) any later version.
13
* Rsyslog is distributed in the hope that it will be useful,
14
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
16
* GNU General Public License for more details.
18
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
* along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
22
21
* A copy of the GPL can be found in the file "COPYING" in this distribution.
93
97
CHKiRet(pSetHdlr(pp, pVal));
100
/* Parse a number from the configuration line.
101
* rgerhards, 2007-07-31
104
/* Parse a number from the configuration line. This functions just parses
105
* the number and does NOT call any handlers or set any values. It is just
106
* for INTERNAL USE by other parse functions!
107
* rgerhards, 2008-01-08
103
static rsRetVal doGetInt(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *pVal)
109
static rsRetVal parseIntVal(uchar **pp, int64 *pVal)
109
116
assert(pp != NULL);
110
117
assert(*pp != NULL);
118
assert(pVal != NULL);
112
120
skipWhiteSpace(pp); /* skip over any whitespace */
115
130
if(!isdigit((int) *p)) {
117
logerror("invalid number");
132
errmsg.LogError(NO_ERRCODE, "invalid number");
118
133
ABORT_FINALIZE(RS_RET_INVALID_INT);
122
for(i = 0 ; *p && isdigit((int) *p) ; ++p)
123
i = i * 10 + *p - '0';
125
if(pSetHdlr == NULL) {
126
/* we should set value directly to var */
137
for(i = 0 ; *p && (isdigit((int) *p) || *p == '.' || *p == ',') ; ++p) {
138
if(isdigit((int) *p)) {
139
i = i * 10 + *p - '0';
154
/* Parse a number from the configuration line.
155
* rgerhards, 2007-07-31
157
static rsRetVal doGetInt(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *pVal)
166
CHKiRet(parseIntVal(pp, &i));
169
if(pSetHdlr == NULL) {
170
/* we should set value directly to var */
171
*((int*)pVal) = (int) i;
173
/* we set value via a set function */
174
CHKiRet(pSetHdlr(pVal, (int) i));
184
/* Parse a size from the configuration line. This is basically an integer
185
* syntax, but modifiers may be added after the integer (e.g. 1k to mean
186
* 1024). The size must immediately follow the number. Note that the
187
* param value must be int64!
188
* rgerhards, 2008-01-09
190
static rsRetVal doGetSize(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *pVal)
198
CHKiRet(parseIntVal(pp, &i));
200
/* we now check if the next character is one of our known modifiers.
201
* If so, we accept it as such. If not, we leave it alone. tera and
202
* above does not make any sense as that is above a 32-bit int value.
205
/* traditional binary-based definitions */
206
case 'k': i *= 1024; ++(*pp); break;
207
case 'm': i *= 1024 * 1024; ++(*pp); break;
208
case 'g': i *= 1024 * 1024 * 1024; ++(*pp); break;
209
case 't': i *= (int64) 1024 * 1024 * 1024 * 1024; ++(*pp); break; /* tera */
210
case 'p': i *= (int64) 1024 * 1024 * 1024 * 1024 * 1024; ++(*pp); break; /* peta */
211
case 'e': i *= (int64) 1024 * 1024 * 1024 * 1024 * 1024 * 1024; ++(*pp); break; /* exa */
212
/* and now the "new" 1000-based definitions */
213
case 'K': i *= 1000; ++(*pp); break;
214
case 'M': i *= 10000; ++(*pp); break;
215
case 'G': i *= 100000; ++(*pp); break;
216
case 'T': i *= 1000000; ++(*pp); break; /* tera */
217
case 'P': i *= 10000000; ++(*pp); break; /* peta */
218
case 'E': i *= 100000000; ++(*pp); break; /* exa */
222
if(pSetHdlr == NULL) {
223
/* we should set value directly to var */
129
226
/* we set value via a set function */
130
227
CHKiRet(pSetHdlr(pVal, i));
248
343
assert(*pp != NULL);
250
345
if(getSubString(pp, (char*) szName, sizeof(szName) / sizeof(uchar), ' ') != 0) {
251
logerror("could not extract group name");
346
errmsg.LogError(NO_ERRCODE, "could not extract group name");
252
347
ABORT_FINALIZE(RS_RET_NOT_FOUND);
255
350
getgrnam_r((char*)szName, &gBuf, stringBuf, sizeof(stringBuf), &pgBuf);
257
352
if(pgBuf == NULL) {
258
logerrorSz("ID for group '%s' could not be found or error", (char*)szName);
353
errmsg.LogError(NO_ERRCODE, "ID for group '%s' could not be found or error", (char*)szName);
259
354
iRet = RS_RET_NOT_FOUND;
261
356
if(pSetHdlr == NULL) {
290
385
assert(*pp != NULL);
292
387
if(getSubString(pp, (char*) szName, sizeof(szName) / sizeof(uchar), ' ') != 0) {
293
logerror("could not extract user name");
388
errmsg.LogError(NO_ERRCODE, "could not extract user name");
294
389
ABORT_FINALIZE(RS_RET_NOT_FOUND);
297
392
getpwnam_r((char*)szName, &pwBuf, stringBuf, sizeof(stringBuf), &ppwBuf);
299
394
if(ppwBuf == NULL) {
300
logerrorSz("ID for user '%s' could not be found or error", (char*)szName);
395
errmsg.LogError(NO_ERRCODE, "ID for user '%s' could not be found or error", (char*)szName);
301
396
iRet = RS_RET_NOT_FOUND;
303
398
if(pSetHdlr == NULL) {
344
439
skipWhiteSpace(pp); /* skip over any whitespace */
351
/* Parse and a word config line option. A word is a consequitive
446
/* parse a whitespace-delimited word from the provided string. This is a
447
* helper function for a number of syntaxes. The parsed value is returned
448
* in ppStrB (which must be provided by caller).
449
* rgerhards, 2008-02-14
452
getWord(uchar **pp, cstr_t **ppStrB)
459
ASSERT(ppStrB != NULL);
461
CHKiRet(rsCStrConstruct(ppStrB));
463
/* parse out the word */
466
while(*p && !isspace((int) *p)) {
467
CHKiRet(rsCStrAppendChar(*ppStrB, *p++));
469
CHKiRet(rsCStrFinish(*ppStrB));
478
/* Parse and a word config line option. A word is a consequtive
352
479
* sequence of non-whitespace characters. pVal must be
353
480
* a pointer to a string which is to receive the option
354
481
* value. The returned string must be freed by the caller.
355
482
* rgerhards, 2007-09-07
483
* To facilitate multiple instances of the same command line
484
* directive, doGetWord() now checks if pVal is already a
485
* non-NULL pointer. If so, we assume it was created by a previous
486
* incarnation and is automatically freed. This happens only when
487
* no custom handler is defined. If it is, the customer handler
488
* must do the cleanup. I have checked and this was al also memory
489
* leak with some code. Obviously, not a large one. -- rgerhards, 2007-12-20
490
* Just to clarify: if pVal is parsed to a custom handler, this handler
491
* is responsible for freeing pVal. -- rgerhards, 2008-03-20
357
493
static rsRetVal doGetWord(uchar **pp, rsRetVal (*pSetHdlr)(void*, uchar*), void *pVal)
367
if((pStrB = rsCStrConstruct()) == NULL)
368
return RS_RET_OUT_OF_MEMORY;
370
/* parse out the word */
373
while(*p && !isspace((int) *p)) {
374
CHKiRet(rsCStrAppendChar(pStrB, *p++));
376
CHKiRet(rsCStrFinish(pStrB));
502
CHKiRet(getWord(pp, &pStrB));
378
503
CHKiRet(rsCStrConvSzStrAndDestruct(pStrB, &pNewVal, 0));
380
506
/* we got the word, now set it */
381
507
if(pSetHdlr == NULL) {
382
508
/* we should set value directly to var */
383
*((uchar**)pVal) = pNewVal;
509
if(*((uchar**)pVal) != NULL)
510
free(*((uchar**)pVal)); /* free previous entry */
511
*((uchar**)pVal) = pNewVal; /* set new one */
385
513
/* we set value via a set function */
386
514
CHKiRet(pSetHdlr(pVal, pNewVal));
390
517
skipWhiteSpace(pp); /* skip over any whitespace */
393
520
if(iRet != RS_RET_OK) {
394
521
if(pStrB != NULL)
395
rsCStrDestruct(pStrB);
522
rsCStrDestruct(&pStrB);
529
/* parse a syslog name from the string. This is the generic code that is
530
* called by the facility/severity functions. Note that we do not check the
531
* validity of numerical values, something that should probably change over
532
* time (TODO). -- rgerhards, 2008-02-14
535
doSyslogName(uchar **pp, rsRetVal (*pSetHdlr)(void*, int), void *pVal, syslogName_t *pNameTable)
544
CHKiRet(getWord(pp, &pStrB)); /* get word */
545
iNewVal = decodeSyslogName(rsCStrGetSzStr(pStrB), pNameTable);
547
if(pSetHdlr == NULL) {
548
/* we should set value directly to var */
549
*((int*)pVal) = iNewVal; /* set new one */
551
/* we set value via a set function */
552
CHKiRet(pSetHdlr(pVal, iNewVal));
555
skipWhiteSpace(pp); /* skip over any whitespace */
559
rsCStrDestruct(&pStrB);
565
/* Implements the facility syntax.
566
* rgerhards, 2008-02-14
569
doFacility(uchar **pp, rsRetVal (*pSetHdlr)(void*, int), void *pVal)
572
iRet = doSyslogName(pp, pSetHdlr, pVal, syslogFacNames);
577
/* Implements the severity syntax.
578
* rgerhards, 2008-02-14
581
doSeverity(uchar **pp, rsRetVal (*pSetHdlr)(void*, int), void *pVal)
584
iRet = doSyslogName(pp, pSetHdlr, pVal, syslogPriNames);
536
759
pThis->bChainingPermitted = bChainingPermitted;
538
CHKiRet(llInit(&pThis->llCmdHdlrs, cslchDestruct, NULL, NULL));
761
CHKiRet(llInit(&pThis->llCmdHdlrs, cslchDestruct, cslchKeyDestruct, cslchKeyCompare));
546
769
/* add a handler entry to a known command
548
static rsRetVal cslcAddHdlr(cslCmd_t *pThis, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData)
771
static rsRetVal cslcAddHdlr(cslCmd_t *pThis, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData, void *pOwnerCookie)
551
774
cslCmdHdlr_t *pCmdHdlr = NULL;
586
795
* caller does not need to take care of that. The caller must, however,
587
796
* free pCmdName if he allocated it dynamically! -- rgerhards, 2007-08-09
589
rsRetVal regCfSysLineHdlr(uchar *pCmdName, int bChainingPermitted, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData)
798
rsRetVal regCfSysLineHdlr(uchar *pCmdName, int bChainingPermitted, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData,
592
803
uchar *pMyCmdName;
595
805
iRet = llFind(&llCmdList, (void *) pCmdName, (void*) &pThis);
596
806
if(iRet == RS_RET_NOT_FOUND) {
597
807
/* new command */
598
808
CHKiRet(cslcConstruct(&pThis, bChainingPermitted));
599
CHKiRet_Hdlr(cslcAddHdlr(pThis, eType, pHdlr, pData)) {
809
CHKiRet_Hdlr(cslcAddHdlr(pThis, eType, pHdlr, pData, pOwnerCookie)) {
600
810
cslcDestruct(pThis);
601
811
goto finalize_it;
846
/* helper function for unregCfSysLineHdlrs4Owner(). This is used to see if there is
847
* a handler of this owner inside the element and, if so, remove it. Please note that
848
* it keeps track of a pointer to the last linked list entry, as this is needed to
849
* remove an entry from the list.
850
* rgerhards, 2007-11-21
852
DEFFUNC_llExecFunc(unregHdlrsHeadExec)
855
cslCmd_t *pListHdr = (cslCmd_t*) pData;
858
/* first find element */
859
iRet = llFindAndDelete(&(pListHdr->llCmdHdlrs), pParam);
861
/* now go back and check how many elements are left */
862
CHKiRet(llGetNumElts(&(pListHdr->llCmdHdlrs), &iNumElts));
865
/* nothing left in header, so request to delete it */
866
iRet = RS_RET_OK_DELETE_LISTENTRY;
872
/* unregister and destroy cfSysLineHandlers for a specific owner. This method is
873
* most importantly used before unloading a loadable module providing some handlers.
874
* The full list of handlers is searched. If the to-be removed handler was the only
875
* handler for a directive name, the directive header, too, is deleted.
876
* rgerhards, 2007-11-21
878
rsRetVal unregCfSysLineHdlrs4Owner(void *pOwnerCookie)
881
/* we need to walk through all directive names, as the linked list
882
* class does not provide a way to just search the lower-level handlers.
884
iRet = llExecFunc(&llCmdList, unregHdlrsHeadExec, pOwnerCookie);
636
890
/* process a cfsysline command (based on handler structure)
637
891
* param "p" is a pointer to the command line after the command. Should be
699
953
linkedListCookie_t llCookieCmdHdlr;
702
printf("\nSytem Line Configuration Commands:\n");
956
dbgprintf("Sytem Line Configuration Commands:\n");
703
957
llCookieCmd = NULL;
704
958
while((iRet = llGetNextElt(&llCmdList, &llCookieCmd, (void*)&pCmd)) == RS_RET_OK) {
705
959
llGetKey(llCookieCmd, (void*) &pKey); /* TODO: using the cookie is NOT clean! */
706
printf("\tCommand '%s':\n", pKey);
960
dbgprintf("\tCommand '%s':\n", pKey);
707
961
llCookieCmdHdlr = NULL;
708
962
while((iRet = llGetNextElt(&pCmd->llCmdHdlrs, &llCookieCmdHdlr, (void*)&pCmdHdlr)) == RS_RET_OK) {
709
printf("\t\ttype : %d\n", pCmdHdlr->eType);
710
printf("\t\tpData: 0x%x\n", (unsigned) pCmdHdlr->pData);
711
printf("\t\tHdlr : 0x%x\n", (unsigned) pCmdHdlr->cslCmdHdlr);
963
dbgprintf("\t\ttype : %d\n", pCmdHdlr->eType);
964
dbgprintf("\t\tpData: 0x%lx\n", (unsigned long) pCmdHdlr->pData);
965
dbgprintf("\t\tHdlr : 0x%lx\n", (unsigned long) pCmdHdlr->cslCmdHdlr);
966
dbgprintf("\t\tOwner: 0x%lx\n", (unsigned long) llCookieCmdHdlr->pKey);
975
/* our init function. TODO: remove once converted to a class
977
rsRetVal cfsyslineInit()
980
CHKiRet(objGetObjInterface(&obj));
981
CHKiRet(objUse(errmsg, CORE_COMPONENT));
983
CHKiRet(llInit(&llCmdList, cslcDestruct, cslcKeyDestruct, strcasecmp));