~ubuntu-branches/ubuntu/karmic/rsyslog/karmic-200908151517

« back to all changes in this revision

Viewing changes to cfsysline.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Biebl
  • Date: 2008-04-23 16:46:39 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20080423164639-5acmt8a4vpxjgnxw
Tags: 3.14.2-3
* debian/rsyslog-doc.install
  - Fix a typo in the install path of the dia files. Closes: #477489
    Thanks to Justin B Rye for the patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
 *
4
4
 * File begun on 2007-07-30 by RGerhards
5
5
 *
6
 
 * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
7
 
 *
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.
12
 
 *
13
 
 * This program is distributed in the hope that it will be useful,
 
6
 * This file is part of rsyslog.
 
7
 *
 
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.
 
12
 *
 
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.
17
17
 *
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/>.
21
20
 *
22
21
 * A copy of the GPL can be found in the file "COPYING" in this distribution.
23
22
 */
35
34
 
36
35
#include "syslogd.h" /* TODO: when the module interface & library design is done, this should be able to go away */
37
36
#include "cfsysline.h"
 
37
#include "obj.h"
 
38
#include "errmsg.h"
38
39
#include "srUtils.h"
39
40
 
40
41
 
41
42
/* static data */
 
43
DEFobjCurrIf(obj)
 
44
DEFobjCurrIf(errmsg)
 
45
 
42
46
linkedList_t llCmdList; /* this is NOT a pointer - no typo here ;) */
43
47
 
44
48
/* --------------- START functions for handling canned syntaxes --------------- */
61
65
 
62
66
        /* if we are not at a '\0', we have our new char - no validity checks here... */
63
67
        if(**pp == '\0') {
64
 
                logerror("No character available");
 
68
                errmsg.LogError(NO_ERRCODE, "No character available");
65
69
                iRet = RS_RET_NOT_FOUND;
66
70
        } else {
67
71
                if(pSetHdlr == NULL) {
75
79
        }
76
80
 
77
81
finalize_it:
78
 
        return iRet;
 
82
        RETiRet;
79
83
}
80
84
 
81
85
 
93
97
        CHKiRet(pSetHdlr(pp, pVal));
94
98
 
95
99
finalize_it:
96
 
        return iRet;
 
100
        RETiRet;
97
101
}
98
102
 
99
103
 
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
102
108
 */
103
 
static rsRetVal doGetInt(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *pVal)
 
109
static rsRetVal parseIntVal(uchar **pp, int64 *pVal)
104
110
{
 
111
        DEFiRet;
105
112
        uchar *p;
106
 
        DEFiRet;
107
 
        int i;  
 
113
        int64 i;        
 
114
        int bWasNegative;
108
115
 
109
116
        assert(pp != NULL);
110
117
        assert(*pp != NULL);
 
118
        assert(pVal != NULL);
111
119
        
112
120
        skipWhiteSpace(pp); /* skip over any whitespace */
113
121
        p = *pp;
114
122
 
 
123
        if(*p == '-') {
 
124
                bWasNegative = 1;
 
125
                ++p; /* eat it */
 
126
        } else {
 
127
                bWasNegative = 0;
 
128
        }
 
129
 
115
130
        if(!isdigit((int) *p)) {
116
131
                errno = 0;
117
 
                logerror("invalid number");
 
132
                errmsg.LogError(NO_ERRCODE, "invalid number");
118
133
                ABORT_FINALIZE(RS_RET_INVALID_INT);
119
134
        }
120
135
 
121
136
        /* pull value */
122
 
        for(i = 0 ; *p && isdigit((int) *p) ; ++p)
123
 
                i = i * 10 + *p - '0';
124
 
 
125
 
        if(pSetHdlr == NULL) {
126
 
                /* we should set value directly to var */
127
 
                *((int*)pVal) = i;
 
137
        for(i = 0 ; *p && (isdigit((int) *p) || *p == '.' || *p == ',')  ; ++p) {
 
138
                if(isdigit((int) *p)) {
 
139
                        i = i * 10 + *p - '0';
 
140
                }
 
141
        }
 
142
 
 
143
        if(bWasNegative)
 
144
                i *= -1;
 
145
 
 
146
        *pVal = i;
 
147
        *pp = p;
 
148
 
 
149
finalize_it:
 
150
        RETiRet;
 
151
}
 
152
 
 
153
 
 
154
/* Parse a number from the configuration line.
 
155
 * rgerhards, 2007-07-31
 
156
 */
 
157
static rsRetVal doGetInt(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *pVal)
 
158
{
 
159
        uchar *p;
 
160
        DEFiRet;
 
161
        int64 i;        
 
162
 
 
163
        assert(pp != NULL);
 
164
        assert(*pp != NULL);
 
165
        
 
166
        CHKiRet(parseIntVal(pp, &i));
 
167
        p = *pp;
 
168
 
 
169
        if(pSetHdlr == NULL) {
 
170
                /* we should set value directly to var */
 
171
                *((int*)pVal) = (int) i;
 
172
        } else {
 
173
                /* we set value via a set function */
 
174
                CHKiRet(pSetHdlr(pVal, (int) i));
 
175
        }
 
176
 
 
177
        *pp = p;
 
178
 
 
179
finalize_it:
 
180
        RETiRet;
 
181
}
 
182
 
 
183
 
 
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
 
189
 */
 
190
static rsRetVal doGetSize(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *pVal)
 
191
{
 
192
        DEFiRet;
 
193
        int64 i;
 
194
 
 
195
        assert(pp != NULL);
 
196
        assert(*pp != NULL);
 
197
        
 
198
        CHKiRet(parseIntVal(pp, &i));
 
199
 
 
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.
 
203
         */
 
204
        switch(**pp) {
 
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 */
 
219
        }
 
220
 
 
221
        /* done */
 
222
        if(pSetHdlr == NULL) {
 
223
                /* we should set value directly to var */
 
224
                *((int64*)pVal) = i;
128
225
        } else {
129
226
                /* we set value via a set function */
130
227
                CHKiRet(pSetHdlr(pVal, i));
131
228
        }
132
229
 
133
 
        *pp = p;
134
 
 
135
230
finalize_it:
136
 
        return iRet;
 
231
        RETiRet;
137
232
}
138
233
 
139
234
 
173
268
                snprintf((char*) errMsg, sizeof(errMsg)/sizeof(uchar),
174
269
                         "value must be octal (e.g 0644).");
175
270
                errno = 0;
176
 
                logerror((char*) errMsg);
 
271
                errmsg.LogError(NO_ERRCODE, "%s", errMsg);
177
272
                ABORT_FINALIZE(RS_RET_INVALID_VALUE);
178
273
        }
179
274
 
194
289
        *pp = p;
195
290
 
196
291
finalize_it:
197
 
        return iRet;
 
292
        RETiRet;
198
293
}
199
294
 
200
295
 
218
313
        skipWhiteSpace(pp); /* skip over any whitespace */
219
314
 
220
315
        if(getSubString(pp, (char*) szOpt, sizeof(szOpt) / sizeof(uchar), ' ')  != 0) {
221
 
                logerror("Invalid $-configline - could not extract on/off option");
 
316
                errmsg.LogError(NO_ERRCODE, "Invalid $-configline - could not extract on/off option");
222
317
                return -1;
223
318
        }
224
319
        
227
322
        } else if(!strcmp((char*)szOpt, "off")) {
228
323
                return 0;
229
324
        } else {
230
 
                logerrorSz("Option value must be on or off, but is '%s'", (char*)pOptStart);
 
325
                errmsg.LogError(NO_ERRCODE, "Option value must be on or off, but is '%s'", (char*)pOptStart);
231
326
                return -1;
232
327
        }
233
328
}
248
343
        assert(*pp != NULL);
249
344
 
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);
253
348
        }
254
349
 
255
350
        getgrnam_r((char*)szName, &gBuf, stringBuf, sizeof(stringBuf), &pgBuf);
256
351
 
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;
260
355
        } else {
261
356
                if(pSetHdlr == NULL) {
271
366
        skipWhiteSpace(pp); /* skip over any whitespace */
272
367
 
273
368
finalize_it:
274
 
        return iRet;
 
369
        RETiRet;
275
370
}
276
371
 
277
372
 
290
385
        assert(*pp != NULL);
291
386
 
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);
295
390
        }
296
391
 
297
392
        getpwnam_r((char*)szName, &pwBuf, stringBuf, sizeof(stringBuf), &ppwBuf);
298
393
 
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;
302
397
        } else {
303
398
                if(pSetHdlr == NULL) {
313
408
        skipWhiteSpace(pp); /* skip over any whitespace */
314
409
 
315
410
finalize_it:
316
 
        return iRet;
 
411
        RETiRet;
317
412
}
318
413
 
319
414
 
344
439
        skipWhiteSpace(pp); /* skip over any whitespace */
345
440
 
346
441
finalize_it:
347
 
        return iRet;
348
 
}
349
 
 
350
 
 
351
 
/* Parse and a word config line option. A word is a consequitive
 
442
        RETiRet;
 
443
}
 
444
 
 
445
 
 
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
 
450
 */
 
451
static rsRetVal
 
452
getWord(uchar **pp, cstr_t **ppStrB)
 
453
{
 
454
        DEFiRet;
 
455
        uchar *p;
 
456
 
 
457
        ASSERT(pp != NULL);
 
458
        ASSERT(*pp != NULL);
 
459
        ASSERT(ppStrB != NULL);
 
460
 
 
461
        CHKiRet(rsCStrConstruct(ppStrB));
 
462
 
 
463
        /* parse out the word */
 
464
        p = *pp;
 
465
 
 
466
        while(*p && !isspace((int) *p)) {
 
467
                CHKiRet(rsCStrAppendChar(*ppStrB, *p++));
 
468
        }
 
469
        CHKiRet(rsCStrFinish(*ppStrB));
 
470
 
 
471
        *pp = p;
 
472
 
 
473
finalize_it:
 
474
        RETiRet;
 
475
}
 
476
 
 
477
 
 
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
356
492
 */
357
493
static rsRetVal doGetWord(uchar **pp, rsRetVal (*pSetHdlr)(void*, uchar*), void *pVal)
358
494
{
359
495
        DEFiRet;
360
 
        rsCStrObj *pStrB;
361
 
        uchar *p;
 
496
        cstr_t *pStrB;
362
497
        uchar *pNewVal;
363
498
 
364
 
        assert(pp != NULL);
365
 
        assert(*pp != NULL);
366
 
 
367
 
        if((pStrB = rsCStrConstruct()) == NULL) 
368
 
                return RS_RET_OUT_OF_MEMORY;
369
 
 
370
 
        /* parse out the word */
371
 
        p = *pp;
372
 
 
373
 
        while(*p && !isspace((int) *p)) {
374
 
                CHKiRet(rsCStrAppendChar(pStrB, *p++));
375
 
        }
376
 
        CHKiRet(rsCStrFinish(pStrB));
377
 
 
 
499
        ASSERT(pp != NULL);
 
500
        ASSERT(*pp != NULL);
 
501
 
 
502
        CHKiRet(getWord(pp, &pStrB));
378
503
        CHKiRet(rsCStrConvSzStrAndDestruct(pStrB, &pNewVal, 0));
 
504
        pStrB = NULL;
379
505
 
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 */
384
512
        } else {
385
513
                /* we set value via a set function */
386
514
                CHKiRet(pSetHdlr(pVal, pNewVal));
387
515
        }
388
516
 
389
 
        *pp = p;
390
517
        skipWhiteSpace(pp); /* skip over any whitespace */
391
518
 
392
519
finalize_it:
393
520
        if(iRet != RS_RET_OK) {
394
521
                if(pStrB != NULL)
395
 
                        rsCStrDestruct(pStrB);
396
 
        }
397
 
 
398
 
        return iRet;
 
522
                        rsCStrDestruct(&pStrB);
 
523
        }
 
524
 
 
525
        RETiRet;
 
526
}
 
527
 
 
528
 
 
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
 
533
 */
 
534
static rsRetVal
 
535
doSyslogName(uchar **pp, rsRetVal (*pSetHdlr)(void*, int), void *pVal, syslogName_t *pNameTable)
 
536
{
 
537
        DEFiRet;
 
538
        cstr_t *pStrB;
 
539
        int iNewVal;
 
540
 
 
541
        ASSERT(pp != NULL);
 
542
        ASSERT(*pp != NULL);
 
543
 
 
544
        CHKiRet(getWord(pp, &pStrB)); /* get word */
 
545
        iNewVal = decodeSyslogName(rsCStrGetSzStr(pStrB), pNameTable);
 
546
 
 
547
        if(pSetHdlr == NULL) {
 
548
                /* we should set value directly to var */
 
549
                *((int*)pVal) = iNewVal; /* set new one */
 
550
        } else {
 
551
                /* we set value via a set function */
 
552
                CHKiRet(pSetHdlr(pVal, iNewVal));
 
553
        }
 
554
 
 
555
        skipWhiteSpace(pp); /* skip over any whitespace */
 
556
 
 
557
finalize_it:
 
558
        if(pStrB != NULL)
 
559
                rsCStrDestruct(&pStrB);
 
560
 
 
561
        RETiRet;
 
562
}
 
563
 
 
564
 
 
565
/* Implements the facility syntax.
 
566
 * rgerhards, 2008-02-14
 
567
 */
 
568
static rsRetVal
 
569
doFacility(uchar **pp, rsRetVal (*pSetHdlr)(void*, int), void *pVal)
 
570
{
 
571
        DEFiRet;
 
572
        iRet = doSyslogName(pp, pSetHdlr, pVal, syslogFacNames);
 
573
        RETiRet;
 
574
}
 
575
 
 
576
 
 
577
/* Implements the severity syntax.
 
578
 * rgerhards, 2008-02-14
 
579
 */
 
580
static rsRetVal
 
581
doSeverity(uchar **pp, rsRetVal (*pSetHdlr)(void*, int), void *pVal)
 
582
{
 
583
        DEFiRet;
 
584
        iRet = doSyslogName(pp, pSetHdlr, pVal, syslogPriNames);
 
585
        RETiRet;
399
586
}
400
587
 
401
588
 
407
594
 */
408
595
static rsRetVal cslchDestruct(void *pThis)
409
596
{
410
 
        assert(pThis != NULL);
 
597
        ASSERT(pThis != NULL);
411
598
        free(pThis);
412
599
        
413
600
        return RS_RET_OK;
428
615
 
429
616
finalize_it:
430
617
        *ppThis = pThis;
431
 
        return iRet;
432
 
}
 
618
        RETiRet;
 
619
}
 
620
 
 
621
/* destructor for linked list keys. As we do not use any dynamic memory,
 
622
 * we simply return. However, this entry point must be defined for the 
 
623
 * linkedList class to make sure we have not forgotten a destructor.
 
624
 * rgerhards, 2007-11-21
 
625
 */
 
626
static rsRetVal cslchKeyDestruct(void __attribute__((unused)) *pData)
 
627
{
 
628
        return RS_RET_OK;
 
629
}
 
630
 
 
631
 
 
632
/* Key compare operation for linked list class. This compares two
 
633
 * owner cookies (void *).
 
634
 * rgerhards, 2007-11-21
 
635
 */
 
636
static int cslchKeyCompare(void *pKey1, void *pKey2)
 
637
{
 
638
        if(pKey1 == pKey2)
 
639
                return 0;
 
640
        else
 
641
                if(pKey1 < pKey2)
 
642
                        return -1;
 
643
                else
 
644
                        return 1;
 
645
}
 
646
 
433
647
 
434
648
/* set data members for this object
435
649
 */
474
688
        case eCmdHdlrInt:
475
689
                pHdlr = doGetInt;
476
690
                break;
 
691
        case eCmdHdlrSize:
 
692
                pHdlr = doGetSize;
 
693
                break;
477
694
        case eCmdHdlrGetChar:
478
695
                pHdlr = doGetChar;
479
696
                break;
 
697
        case eCmdHdlrFacility:
 
698
                pHdlr = doFacility;
 
699
                break;
 
700
        case eCmdHdlrSeverity:
 
701
                pHdlr = doSeverity;
 
702
                break;
480
703
        case eCmdHdlrGetWord:
481
704
                pHdlr = doGetWord;
482
705
                break;
490
713
        CHKiRet(pHdlr(ppConfLine, pThis->cslCmdHdlr, pThis->pData));
491
714
 
492
715
finalize_it:
493
 
        return iRet;
 
716
        RETiRet;
494
717
}
495
718
 
496
719
 
535
758
 
536
759
        pThis->bChainingPermitted = bChainingPermitted;
537
760
 
538
 
        CHKiRet(llInit(&pThis->llCmdHdlrs, cslchDestruct, NULL, NULL));
 
761
        CHKiRet(llInit(&pThis->llCmdHdlrs, cslchDestruct, cslchKeyDestruct, cslchKeyCompare));
539
762
 
540
763
finalize_it:
541
764
        *ppThis = pThis;
542
 
        return iRet;
 
765
        RETiRet;
543
766
}
544
767
 
545
768
 
546
769
/* add a handler entry to a known command
547
770
 */
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)
549
772
{
550
773
        DEFiRet;
551
774
        cslCmdHdlr_t *pCmdHdlr = NULL;
554
777
 
555
778
        CHKiRet(cslchConstruct(&pCmdHdlr));
556
779
        CHKiRet(cslchSetEntry(pCmdHdlr, eType, pHdlr, pData));
557
 
        CHKiRet(llAppend(&pThis->llCmdHdlrs, NULL, pCmdHdlr));
 
780
        CHKiRet(llAppend(&pThis->llCmdHdlrs, pOwnerCookie, pCmdHdlr));
558
781
 
559
782
finalize_it:
560
783
        if(iRet != RS_RET_OK) {
562
785
                        cslchDestruct(pCmdHdlr);
563
786
        }
564
787
 
565
 
        return iRet;
566
 
}
567
 
 
568
 
 
569
 
/* function that initializes this module here. This is primarily a hook
570
 
 * for syslogd.
571
 
 */
572
 
rsRetVal cfsyslineInit(void)
573
 
{
574
 
        DEFiRet;
575
 
 
576
 
        CHKiRet(llInit(&llCmdList, cslcDestruct, cslcKeyDestruct, strcasecmp));
577
 
 
578
 
finalize_it:
579
 
        return iRet;
 
788
        RETiRet;
580
789
}
581
790
 
582
791
 
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
588
797
 */
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,
 
799
                          void *pOwnerCookie)
590
800
{
 
801
        DEFiRet;
591
802
        cslCmd_t *pThis;
592
803
        uchar *pMyCmdName;
593
 
        DEFiRet;
594
804
 
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;
602
812
                }
616
826
                if(pThis->bChainingPermitted == 0 || bChainingPermitted == 0) {
617
827
                        ABORT_FINALIZE(RS_RET_CHAIN_NOT_PERMITTED);
618
828
                }
619
 
                CHKiRet_Hdlr(cslcAddHdlr(pThis, eType, pHdlr, pData)) {
 
829
                CHKiRet_Hdlr(cslcAddHdlr(pThis, eType, pHdlr, pData, pOwnerCookie)) {
620
830
                        cslcDestruct(pThis);
621
831
                        goto finalize_it;
622
832
                }
623
833
        }
624
834
 
625
835
finalize_it:
626
 
        return iRet;
 
836
        RETiRet;
627
837
}
628
838
 
629
839
 
633
843
}
634
844
 
635
845
 
 
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
 
851
 */
 
852
DEFFUNC_llExecFunc(unregHdlrsHeadExec)
 
853
{
 
854
        DEFiRet;
 
855
        cslCmd_t *pListHdr = (cslCmd_t*) pData;
 
856
        int iNumElts;
 
857
 
 
858
        /* first find element */
 
859
        iRet = llFindAndDelete(&(pListHdr->llCmdHdlrs), pParam);
 
860
 
 
861
        /* now go back and check how many elements are left */
 
862
        CHKiRet(llGetNumElts(&(pListHdr->llCmdHdlrs), &iNumElts));
 
863
 
 
864
        if(iNumElts == 0) {
 
865
                /* nothing left in header, so request to delete it */
 
866
                iRet = RS_RET_OK_DELETE_LISTENTRY;
 
867
        }
 
868
 
 
869
finalize_it:
 
870
        RETiRet;
 
871
}
 
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
 
877
 */
 
878
rsRetVal unregCfSysLineHdlrs4Owner(void *pOwnerCookie)
 
879
{
 
880
        DEFiRet;
 
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.
 
883
         */
 
884
        iRet = llExecFunc(&llCmdList, unregHdlrsHeadExec, pOwnerCookie);
 
885
 
 
886
        RETiRet;
 
887
}
 
888
 
 
889
 
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
638
892
 * updated.
651
905
        iRet = llFind(&llCmdList, (void *) pCmdName, (void*) &pCmd);
652
906
 
653
907
        if(iRet == RS_RET_NOT_FOUND) {
654
 
                logerror("invalid or yet-unknown config file command - have you forgotten to load a module?");
 
908
                errmsg.LogError(NO_ERRCODE, "invalid or yet-unknown config file command - have you forgotten to load a module?");
655
909
        }
656
910
 
657
911
        if(iRet != RS_RET_OK)
683
937
                iRet = iRetLL;
684
938
 
685
939
finalize_it:
686
 
        return iRet;
 
940
        RETiRet;
687
941
}
688
942
 
689
943
 
699
953
        linkedListCookie_t llCookieCmdHdlr;
700
954
        uchar *pKey;
701
955
 
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);
712
 
                        printf("\n");
 
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);
 
967
                        dbgprintf("\n");
713
968
                }
714
969
        }
715
 
        printf("\n");
716
 
 
717
 
}
718
 
 
719
 
/*
720
 
 * vi:set ai:
 
970
        dbgprintf("\n");
 
971
        ENDfunc
 
972
}
 
973
 
 
974
 
 
975
/* our init function. TODO: remove once converted to a class
 
976
 */
 
977
rsRetVal cfsyslineInit()
 
978
{
 
979
        DEFiRet;
 
980
        CHKiRet(objGetObjInterface(&obj));
 
981
        CHKiRet(objUse(errmsg, CORE_COMPONENT));
 
982
 
 
983
        CHKiRet(llInit(&llCmdList, cslcDestruct, cslcKeyDestruct, strcasecmp));
 
984
 
 
985
finalize_it:
 
986
        RETiRet;
 
987
}
 
988
 
 
989
/* vim:set ai:
721
990
 */