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

« back to all changes in this revision

Viewing changes to rfc3195d.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
 
/** 
2
 
 * rfc3195d.c
3
 
 * This is an RFC 3195 listener. All data received is forwarded to
4
 
 * local UNIX domain socket, where it can be picked up by a
5
 
 * syslog daemon (like rsyslogd ;)).
6
 
 *
7
 
 * \author  Rainer Gerhards <rgerhards@adiscon.com>
8
 
 *
9
 
 * Copyright 2003-2005 Rainer Gerhards and Adiscon GmbH.
10
 
 *
11
 
 * This file is part of rsyslog.
12
 
 *
13
 
 * Rsyslog is free software: you can redistribute it and/or modify
14
 
 * it under the terms of the GNU General Public License as published by
15
 
 * the Free Software Foundation, either version 3 of the License, or
16
 
 * (at your option) any later version.
17
 
 *
18
 
 * Rsyslog is distributed in the hope that it will be useful,
19
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 
 * GNU General Public License for more details.
22
 
 *
23
 
 * You should have received a copy of the GNU General Public License
24
 
 * along with Rsyslog.  If not, see <http://www.gnu.org/licenses/>.
25
 
 *
26
 
 * A copy of the GPL can be found in the file "COPYING" in this distribution.
27
 
 */
28
 
#include "config.h"
29
 
 
30
 
#include <stdio.h>
31
 
#ifndef FEATURE_RFC3195
32
 
/* this is a trick: if RFC3195 is not to be supported, we just do an
33
 
 * error message.
34
 
 */
35
 
int main()
36
 
{
37
 
        fprintf(stderr, "error: not compiled with FEATURE_RFC3195 - terminating.\n");
38
 
        return(1);
39
 
}
40
 
#else
41
 
#include <unistd.h>
42
 
#include <signal.h>
43
 
#include <sys/socket.h>
44
 
#include <sys/errno.h>
45
 
#include "rsyslog.h"
46
 
#include "liblogging/liblogging.h"
47
 
#include "liblogging/srAPI.h"
48
 
#include "liblogging/syslogmessage.h"
49
 
 
50
 
/* configurable params! */
51
 
static char* pPathLogname = "/dev/log3195";
52
 
static char *PidFile;
53
 
static int NoFork = 0;
54
 
static int Debug = 0;
55
 
static int listenPort = 601;
56
 
 
57
 
/* we use a global API object below, because this listener is
58
 
 * not very complex. As such, this hack should not harm anything.
59
 
 * rgerhards, 2005-10-12
60
 
 */
61
 
static srAPIObj* pAPI;
62
 
 
63
 
static int      LogFile = -1;           /* fd for log */
64
 
static int      connected;              /* have done connect */
65
 
static struct sockaddr SyslogAddr;      /* AF_UNIX address of local logger */
66
 
 
67
 
/* small usage info */
68
 
static int usage()
69
 
{
70
 
        /* The following usage line is what we intend to have - it
71
 
         * is commented out as a reminder. The one below is what we
72
 
         * currently actually do...
73
 
         fprintf(stderr, "usage: rfc3195d [-dv] [-i pidfile] [-n] [-p path]\n");
74
 
         */
75
 
        fprintf(stderr, "usage: rfc3195d [-dv] [-r port] [-p path]\n");
76
 
        exit(1);
77
 
}
78
 
 
79
 
/* CLOSELOG -- close the system log
80
 
 */
81
 
static void closelog(void)
82
 
{
83
 
        close(LogFile);
84
 
        LogFile = -1;
85
 
        connected = 0;
86
 
}
87
 
 
88
 
/* OPENLOG -- open system log
89
 
 */
90
 
static void openlog()
91
 
{
92
 
        if (LogFile == -1) {
93
 
                SyslogAddr.sa_family = AF_UNIX;
94
 
                strncpy(SyslogAddr.sa_data, pPathLogname,
95
 
                    sizeof(SyslogAddr.sa_data));
96
 
                LogFile = socket(AF_UNIX, SOCK_DGRAM, 0);
97
 
                if(LogFile < 0) {
98
 
                        char errStr[1024];
99
 
                        printf("error opening '%s': %s\n", 
100
 
                               pPathLogname, rs_strerror_r(errno, errStr, sizeof(errStr)));
101
 
                }
102
 
        }
103
 
        if (LogFile != -1 && !connected &&
104
 
            connect(LogFile, &SyslogAddr, sizeof(SyslogAddr.sa_family)+
105
 
                        strlen(SyslogAddr.sa_data)) != -1)
106
 
                connected = 1;
107
 
        else {
108
 
                char errStr[1024];
109
 
                printf("error connecting '%s': %s\n", 
110
 
                       pPathLogname, rs_strerror_r(errno, errStr, sizeof(errStr)));
111
 
        }
112
 
}
113
 
 
114
 
 
115
 
/* This method is called when a message has been fully received.
116
 
 * It passes the received message to the specified unix domain
117
 
 * socket. Please note that this callback is synchronous, thus
118
 
 * liblogging will be on hold until it returns. This is important
119
 
 * to note because in an error case we might stay in this code
120
 
 * for an extended amount of time. So far, we think this is the
121
 
 * best solution, but real-world experience might tell us a
122
 
 * different truth ;)
123
 
 * rgerhards 2005-10-12
124
 
 */
125
 
void OnReceive(srAPIObj* pAPI, srSLMGObj* pSLMG)
126
 
{
127
 
        unsigned char *pszRawMsg;
128
 
        int iRetries; /* number of retries connecting to log socket */
129
 
        int iSleep;
130
 
        int iWriteOffset;
131
 
        ssize_t nToWrite;
132
 
        ssize_t nWritten;
133
 
 
134
 
        srSLMGGetRawMSG(pSLMG, &pszRawMsg);
135
 
 
136
 
        /* we need to loop writing the message. At least in
137
 
         * theory, a single write might not send all data to the
138
 
         * syslogd. So we need to continue until everything is written.
139
 
         * Also, we need to check if there are any socket erros, in 
140
 
         * which case we reconect. We will re-try indefinitely, if this
141
 
         * is not acceptable, you need to change the code.
142
 
         * rgerhards 2005-10-12
143
 
         */
144
 
        iRetries = 0;
145
 
        nToWrite = strlen(pszRawMsg);
146
 
        iWriteOffset = 0;
147
 
        while(nToWrite != 0) {
148
 
                if(LogFile < 0 || !connected)
149
 
                        openlog();
150
 
                if(LogFile < 0 || !connected) {
151
 
                        /* still not connected, retry */
152
 
                        if(iRetries > 0) {
153
 
                                iSleep = (iRetries < 30) ? iRetries : 30;
154
 
                                /* we sleep a little to prevent a thight loop */
155
 
                                if(Debug)
156
 
                                        printf("multiple retries connecting to log socket"
157
 
                                               " - doing sleep(%d)\n", iSleep);
158
 
                                sleep(iSleep);
159
 
                        }
160
 
                        ++iRetries;
161
 
                } else {
162
 
                        nWritten = write(LogFile, pszRawMsg, strlen(pszRawMsg));
163
 
                        if(nWritten < 0) {
164
 
                                /* error, recover! */
165
 
                                char errStr[1024];
166
 
                                printf("error writing to domain socket: %s\r\n", rs_strerror_r(errno, errStr, sizeof(errStr)));
167
 
                                closelog();
168
 
                        } else {
169
 
                                /* prepare for (potential) next write */
170
 
                                nToWrite -= nWritten;
171
 
                                iWriteOffset += nWritten;
172
 
                        }
173
 
                }
174
 
        }
175
 
 
176
 
        if(Debug) {
177
 
                static int largest = 0;
178
 
                int sz = strlen(pszRawMsg);
179
 
                if(sz > largest)
180
 
                        largest = sz;
181
 
                printf("Msg(%d/%d):%s\n\n", largest, sz, pszRawMsg);
182
 
        }
183
 
}
184
 
 
185
 
 
186
 
/* As we are single-threaded in this example, we need
187
 
 * one way to shut down the listener running on this
188
 
 * single thread. We use SIG_INT to do so - it effectively
189
 
 * provides a short-lived second thread ;-)
190
 
 */
191
 
void doShutdown(int i)
192
 
{
193
 
        printf("Shutting down rfc3195d. Be patient, this can take up to 30 seconds...\n");
194
 
        srAPIShutdownListener(pAPI);
195
 
}
196
 
 
197
 
 
198
 
/* on the the real program ;) */
199
 
int main(int argc, char* argv[])
200
 
{
201
 
        srRetVal iRet;
202
 
        int ch;
203
 
        struct sigaction sigAct;
204
 
 
205
 
        while ((ch = getopt(argc, argv, "di:np:r:v")) != EOF)
206
 
                switch((char)ch) {
207
 
                case 'd':               /* debug */
208
 
                        Debug = 1;
209
 
                        break;
210
 
                case 'i':               /* pid file name */
211
 
                        PidFile = optarg;
212
 
                        break;
213
 
                case 'n':               /* don't fork */
214
 
                        NoFork = 1;
215
 
                        break;
216
 
                case 'p':               /* path to regular log socket */
217
 
                        pPathLogname = optarg;
218
 
                        break;
219
 
                case 'r':               /* listen port */
220
 
                        listenPort = atoi(optarg);
221
 
                        if(listenPort < 1 || listenPort > 65535) {
222
 
                                printf("Error: invalid listen port '%s', using 601 instead\n",
223
 
                                        optarg);
224
 
                                listenPort = 601;
225
 
                        }
226
 
                        break;
227
 
                case 'v':
228
 
                        printf("rfc3195d %s.%s (using liblogging version %d.%d.%d).\n",
229
 
                               VERSION, PATCHLEVEL,
230
 
                               LIBLOGGING_VERSION_MAJOR, LIBLOGGING_VERSION_MINOR,
231
 
                               LIBLOGGING_VERSION_SUBMINOR);
232
 
                        printf("See http://www.rsyslog.com for more information.\n");
233
 
                        exit(0);
234
 
                case '?':
235
 
                default:
236
 
                        usage();
237
 
                }
238
 
        if ((argc -= optind))
239
 
                usage();
240
 
 
241
 
        memset(&sigAct, 0, sizeof(sigAct));
242
 
        sigemptyset(&sigAct.sa_mask);
243
 
        sigAct.sa_handler = doShutdown;
244
 
        sigaction(SIGUSR1, &sigAct, NULL);
245
 
        sigaction(SIGTERM, &sigAct, NULL);
246
 
 
247
 
        if(!Debug)
248
 
        {
249
 
                sigAct.sa_handler = SIG_IGN;
250
 
                sigaction(SIGINT, &sigAct, NULL);
251
 
        }
252
 
 
253
 
        if((pAPI = srAPIInitLib()) == NULL)
254
 
        {
255
 
                printf("Error initializing liblogging - aborting!\n");
256
 
                exit(1);
257
 
        }
258
 
 
259
 
        if((iRet = srAPISetOption(pAPI, srOPTION_BEEP_LISTENPORT, listenPort)) != SR_RET_OK)
260
 
        {
261
 
                printf("Error %d setting listen port - aborting\n", iRet);
262
 
                exit(100);
263
 
        }
264
 
 
265
 
        if((iRet = srAPISetupListener(pAPI, OnReceive)) != SR_RET_OK)
266
 
        {
267
 
                printf("Error %d setting up listener - aborting\n", iRet);
268
 
                exit(101);
269
 
        }
270
 
 
271
 
        /* now move the listener to running state. Control will only
272
 
         * return after SIGUSR1.
273
 
         */
274
 
        if((iRet = srAPIRunListener(pAPI)) != SR_RET_OK)
275
 
        {
276
 
                printf("Error %d running the listener - aborting\n", iRet);
277
 
                exit(102);
278
 
        }
279
 
 
280
 
        /** control will reach this point after shutdown */
281
 
 
282
 
        srAPIExitLib(pAPI);
283
 
        return 0;
284
 
}
285
 
#endif /* #ifndef FEATURE_RFC3195 - main wrapper */
286
 
 
287
 
/*
288
 
 * vi:set ai:
289
 
 */