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

« back to all changes in this revision

Viewing changes to runtime/rsyslog.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Biebl
  • Date: 2009-04-08 00:59:14 UTC
  • mfrom: (1.1.9 upstream) (3.2.6 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090408005914-gfyay7o45szt05zl
Tags: 3.20.5-1
* New upstream release.
* debian/rsyslog.logcheck.ignore.server
  - Install a logcheck ignore file for rsyslog (using dh_installlogcheck).
    Thanks to Kim Holviala for the patch. Closes: #522164

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* rsyslog.c - the main entry point into rsyslog's runtime library (RTL)
 
2
 *
 
3
 * This module contains all function which work on a RTL global level. It's
 
4
 * name is abbreviated to "rsrt" (rsyslog runtime).
 
5
 *
 
6
 * Please note that the runtime library tends to be plugin-safe. That is, it must be
 
7
 * initialized by calling a global initialization function. However, that 
 
8
 * function checks if the library is already initialized and, if so, does
 
9
 * nothing except incrementing a refeence count. Similarly, the deinit
 
10
 * function does nothing as long as there are still other users (which
 
11
 * is tracked via the refcount). As such, it is safe to call init and
 
12
 * exit multiple times, as long as this are always matching calls. This
 
13
 * capability is needed for a plugin system, where one plugin never
 
14
 * knows what the other did. HOWEVER, as of this writing, not all runtime
 
15
 * library objects may work cleanly without static global data (the
 
16
 * debug system is a very good example of this). So while we aim at the
 
17
 * ability to work well in a plugin environment, things may not really work
 
18
 * out. If you intend to use the rsyslog runtime library inside plugins,
 
19
 * you should investigate the situation in detail. Please note that the
 
20
 * rsyslog project itself does not yet need this functionality - thus you
 
21
 * can safely assume it is totally untested ;).
 
22
 *
 
23
 * rgerhards, 2008-04-17: I have now once again checked on the plugin-safety.
 
24
 * Unfortunately, there is currently no hook at all with which we could
 
25
 * abstract a global data instance class. As such, we can NOT make the
 
26
 * runtime plugin-safe in the above-described sense. As the rsyslog
 
27
 * project itself does not need this functionality (and it is quesationable
 
28
 * if someone else ever will), we do currently do not make an effort to
 
29
 * support it. So if you intend to use rsyslog runtime inside a non-rsyslog
 
30
 * plugin system, be careful!
 
31
 *
 
32
 * The rsyslog runtime library is in general reentrant and thread-safe. There
 
33
 * are some intentional exceptions (e.g. inside the msg object). These are
 
34
 * documented. Any other threading and reentrency issue can be considered a bug.
 
35
 *
 
36
 * Module begun 2008-04-16 by Rainer Gerhards
 
37
 *
 
38
 * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
 
39
 *
 
40
 * This file is part of the rsyslog runtime library.
 
41
 *
 
42
 * The rsyslog runtime library is free software: you can redistribute it and/or modify
 
43
 * it under the terms of the GNU Lesser General Public License as published by
 
44
 * the Free Software Foundation, either version 3 of the License, or
 
45
 * (at your option) any later version.
 
46
 *
 
47
 * The rsyslog runtime library is distributed in the hope that it will be useful,
 
48
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
49
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
50
 * GNU Lesser General Public License for more details.
 
51
 *
 
52
 * You should have received a copy of the GNU Lesser General Public License
 
53
 * along with the rsyslog runtime library.  If not, see <http://www.gnu.org/licenses/>.
 
54
 *
 
55
 * A copy of the GPL can be found in the file "COPYING" in this distribution.
 
56
 * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
 
57
 */
 
58
#include "config.h"
 
59
#include <stdio.h>
 
60
#include <stdlib.h>
 
61
#include <assert.h>
 
62
 
 
63
#include "rsyslog.h"
 
64
#include "obj.h"
 
65
#include "vm.h"
 
66
#include "sysvar.h"
 
67
#include "stringbuf.h"
 
68
#include "wti.h"
 
69
#include "wtp.h"
 
70
#include "expr.h"
 
71
#include "ctok.h"
 
72
#include "vmop.h"
 
73
#include "vmstk.h"
 
74
#include "vmprg.h"
 
75
#include "datetime.h"
 
76
#include "queue.h"
 
77
#include "conf.h"
 
78
#include "glbl.h"
 
79
#include "errmsg.h"
 
80
 
 
81
/* forward definitions */
 
82
static rsRetVal dfltErrLogger(int, uchar *errMsg);
 
83
 
 
84
/* globally visible static data - see comment in rsyslog.h for details */
 
85
uchar *glblModPath; /* module load path */
 
86
rsRetVal (*glblErrLogger)(int, uchar*) = dfltErrLogger; /* the error logger to use by the errmsg module */
 
87
 
 
88
/* static data */
 
89
static int iRefCount = 0; /* our refcount - it MUST exist only once inside a process (not thread)
 
90
                             thus it is perfectly OK to use a static. MUST be initialized to 0! */
 
91
 
 
92
/* This is the default instance of the error logger. It simply writes the message
 
93
 * to stderr. It is expected that this is replaced by the runtime user very early
 
94
 * during startup (at least if the default is unsuitable). However, we provide a
 
95
 * default so that we can log errors during the intial phase, most importantly
 
96
 * during initialization. -- rgerhards. 2008-04-17
 
97
 */
 
98
static rsRetVal dfltErrLogger(int iErr, uchar *errMsg)
 
99
{
 
100
        DEFiRet;
 
101
        fprintf(stderr, "rsyslog runtime error(%d): %s\n", iErr, errMsg);
 
102
        RETiRet;
 
103
}
 
104
 
 
105
 
 
106
/* set the error log function
 
107
 * rgerhards, 2008-04-18
 
108
 */
 
109
rsRetVal
 
110
rsrtSetErrLogger(rsRetVal (*errLogger)(int, uchar*))
 
111
{
 
112
        DEFiRet;
 
113
        assert(errLogger != NULL);
 
114
        glblErrLogger = errLogger;
 
115
        RETiRet;
 
116
}
 
117
 
 
118
 
 
119
/* globally initialze the runtime system
 
120
 * NOTE: this is NOT thread safe and must not be called concurrently. If that
 
121
 * ever poses a problem, we may use proper mutex calls - not considered needed yet.
 
122
 * If ppErrObj is provided, it receives a char pointer to the name of the object that
 
123
 * caused the problem (if one occured). The caller must never free this pointer. If
 
124
 * ppErrObj is NULL, no such information will be provided. pObjIF is the pointer to
 
125
 * the "obj" object interface, which may be used to query any other rsyslog objects.
 
126
 * rgerhards, 2008-04-16
 
127
 */
 
128
rsRetVal
 
129
rsrtInit(char **ppErrObj, obj_if_t *pObjIF)
 
130
{
 
131
        DEFiRet;
 
132
 
 
133
        if(iRefCount == 0) {
 
134
                /* init runtime only if not yet done */
 
135
                if(ppErrObj != NULL) *ppErrObj = "obj";
 
136
                CHKiRet(objClassInit(NULL)); /* *THIS* *MUST* always be the first class initilizer being called! */
 
137
                CHKiRet(objGetObjInterface(pObjIF)); /* this provides the root pointer for all other queries */
 
138
 
 
139
                /* initialize core classes. We must be very careful with the order of events. Some
 
140
                 * classes use others and if we do not initialize them in the right order, we may end
 
141
                 * up with an invalid call. The most important thing that can happen is that an error
 
142
                 * is detected and needs to be logged, wich in turn requires a broader number of classes
 
143
                 * to be available. The solution is that we take care in the order of calls AND use a
 
144
                 * class immediately after it is initialized. And, of course, we load those classes
 
145
                 * first that we use ourselfs... -- rgerhards, 2008-03-07
 
146
                 */
 
147
                if(ppErrObj != NULL) *ppErrObj = "glbl";
 
148
                CHKiRet(glblClassInit(NULL));
 
149
                if(ppErrObj != NULL) *ppErrObj = "datetime";
 
150
                CHKiRet(datetimeClassInit(NULL));
 
151
                if(ppErrObj != NULL) *ppErrObj = "msg";
 
152
                CHKiRet(msgClassInit(NULL));
 
153
                if(ppErrObj != NULL) *ppErrObj = "str,";
 
154
                CHKiRet(strmClassInit(NULL));
 
155
                if(ppErrObj != NULL) *ppErrObj = "wti";
 
156
                CHKiRet(wtiClassInit(NULL));
 
157
                if(ppErrObj != NULL) *ppErrObj = "wtp";
 
158
                CHKiRet(wtpClassInit(NULL));
 
159
                if(ppErrObj != NULL) *ppErrObj = "queue";
 
160
                CHKiRet(queueClassInit(NULL));
 
161
                if(ppErrObj != NULL) *ppErrObj = "vmstk";
 
162
                CHKiRet(vmstkClassInit(NULL));
 
163
                if(ppErrObj != NULL) *ppErrObj = "sysvar";
 
164
                CHKiRet(sysvarClassInit(NULL));
 
165
                if(ppErrObj != NULL) *ppErrObj = "vm";
 
166
                CHKiRet(vmClassInit(NULL));
 
167
                if(ppErrObj != NULL) *ppErrObj = "vmop";
 
168
                CHKiRet(vmopClassInit(NULL));
 
169
                if(ppErrObj != NULL) *ppErrObj = "vmprg";
 
170
                CHKiRet(vmprgClassInit(NULL));
 
171
                if(ppErrObj != NULL) *ppErrObj = "ctok_token";
 
172
                CHKiRet(ctok_tokenClassInit(NULL));
 
173
                if(ppErrObj != NULL) *ppErrObj = "ctok";
 
174
                CHKiRet(ctokClassInit(NULL));
 
175
                if(ppErrObj != NULL) *ppErrObj = "expr";
 
176
                CHKiRet(exprClassInit(NULL));
 
177
                if(ppErrObj != NULL) *ppErrObj = "conf";
 
178
                CHKiRet(confClassInit(NULL));
 
179
 
 
180
                /* dummy "classes" */
 
181
                if(ppErrObj != NULL) *ppErrObj = "str";
 
182
                CHKiRet(strInit());
 
183
        }
 
184
 
 
185
        ++iRefCount;
 
186
        dbgprintf("rsyslog runtime initialized, version %s, current users %d\n", VERSION, iRefCount);
 
187
 
 
188
finalize_it:
 
189
        RETiRet;
 
190
}
 
191
 
 
192
 
 
193
/* globally de-initialze the runtime system
 
194
 * NOTE: this is NOT thread safe and must not be called concurrently. If that
 
195
 * ever poses a problem, we may use proper mutex calls - not considered needed yet.
 
196
 * This function must be provided with the caller's obj object pointer. This is
 
197
 * automatically deinitialized by the runtime system.
 
198
 * rgerhards, 2008-04-16
 
199
 */
 
200
rsRetVal
 
201
rsrtExit(void)
 
202
{
 
203
        DEFiRet;
 
204
 
 
205
        if(iRefCount == 1) {
 
206
                /* do actual de-init only if we are the last runtime user */
 
207
                confClassExit();
 
208
                glblClassExit();
 
209
                objClassExit(); /* *THIS* *MUST/SHOULD?* always be the first class initilizer being called (except debug)! */
 
210
        }
 
211
 
 
212
        --iRefCount;
 
213
        /* TODO we must deinit this pointer! pObjIF = NULL; / * no longer exists for this caller */
 
214
 
 
215
        dbgprintf("rsyslog runtime de-initialized, current users %d\n", iRefCount);
 
216
 
 
217
        RETiRet;
 
218
}
 
219
 
 
220
 
 
221
/* returns 0 if the rsyslog runtime is not initialized and another value
 
222
 * if it is. This function is primarily meant to be used by runtime functions
 
223
 * itself. However, it is safe to call it before initializing the runtime.
 
224
 * Plugins should NOT rely on this function. The reason is that another caller
 
225
 * may have already initialized it but deinits it before this plugin is done.
 
226
 * So for plugins and like architectures, the right course of action is to
 
227
 * call rsrtInit() and rsrtExit(), which can be called by multiple callers.
 
228
 * rgerhards, 2008-04-16
 
229
 */
 
230
int rsrtIsInit(void)
 
231
{
 
232
        return iRefCount;
 
233
}
 
234
 
 
235
 
 
236
/* vim:set ai:
 
237
 */