~ubuntu-branches/ubuntu/feisty/clamav/feisty

« back to all changes in this revision

Viewing changes to shared/output.c

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2007-02-20 10:33:44 UTC
  • mto: This revision was merged to the branch mainline in revision 16.
  • Revision ID: james.westby@ubuntu.com-20070220103344-zgcu2psnx9d98fpa
Tags: upstream-0.90
ImportĀ upstreamĀ versionĀ 0.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 *  Copyright (C) 2007-2009 Sourcefire, Inc.
3
 
 *
4
 
 *  Authors: Tomasz Kojm
 
2
 *  Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>
5
3
 *
6
4
 *  This program is free software; you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License version 2 as
8
 
 *  published by the Free Software Foundation.
 
5
 *  it under the terms of the GNU General Public License as published by
 
6
 *  the Free Software Foundation; either version 2 of the License, or
 
7
 *  (at your option) any later version.
9
8
 *
10
9
 *  This program is distributed in the hope that it will be useful,
11
10
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
22
21
#include "clamav-config.h"
23
22
#endif
24
23
 
 
24
#ifdef CL_NOTHREADS
 
25
#undef CL_THREAD_SAFE
 
26
#endif
 
27
 
25
28
#include <stdio.h>
26
29
#include <stdarg.h>
27
30
#include <stdlib.h>
28
31
#include <string.h>
29
32
#include <ctype.h>
30
 
#ifdef HAVE_UNISTD_H
31
33
#include <unistd.h>
32
 
#endif
33
34
#include <fcntl.h>
34
35
#include <time.h>
35
36
#include <sys/stat.h>
36
37
#include <errno.h>
37
 
#ifndef _WIN32
38
38
#include <sys/time.h>
39
39
#include <sys/socket.h>
40
 
#endif
41
40
#if HAVE_SYS_TYPES_H
42
41
#include <sys/types.h>
43
42
#endif
44
43
 
45
 
#ifdef HAVE_SYS_SELECT_H
46
 
#include <sys/select.h>
47
 
#endif
48
 
 
49
44
#if defined(USE_SYSLOG) && !defined(C_AIX)
50
45
#include <syslog.h>
51
46
#endif
52
47
 
53
48
#include "output.h"
54
 
#include "libclamav/others.h"
55
 
 
56
 
#ifdef CL_NOTHREADS
57
 
#undef CL_THREAD_SAFE
58
 
#endif
 
49
#include "memory.h"
59
50
 
60
51
#ifdef CL_THREAD_SAFE
61
52
#include <pthread.h>
62
53
pthread_mutex_t logg_mutex = PTHREAD_MUTEX_INITIALIZER;
63
 
pthread_mutex_t mdprintf_mutex = PTHREAD_MUTEX_INITIALIZER;
64
54
#endif
65
55
 
66
56
#ifdef  C_LINUX
78
68
 
79
69
#endif
80
70
 
81
 
FILE *logg_fp = NULL;
 
71
FILE *logg_fd = NULL;
82
72
 
83
 
short int logg_verbose = 0, logg_nowarn = 0, logg_lock = 1, logg_time = 0, logg_foreground = 1, logg_noflush = 0;
84
 
unsigned int logg_size = 0;
 
73
short int logg_verbose = 0, logg_lock = 1, logg_time = 0, logg_foreground = 1;
 
74
int logg_size = 0;
85
75
const char *logg_file = NULL;
86
76
#if defined(USE_SYSLOG) && !defined(C_AIX)
87
77
short logg_syslog;
88
78
#endif
89
79
 
90
80
short int mprintf_disabled = 0, mprintf_verbose = 0, mprintf_quiet = 0,
91
 
          mprintf_stdout = 0, mprintf_nowarn = 0, mprintf_send_timeout = 100;
92
 
 
93
 
#define ARGLEN(args, str, len)                      \
94
 
{                                                   \
95
 
        size_t arglen = 1, i;                       \
96
 
        char *pt;                                   \
97
 
    va_start(args, str);                            \
98
 
    len = strlen(str);                              \
99
 
    for(i = 0; i < len - 1; i++) {                  \
100
 
        if(str[i] == '%') {                         \
101
 
            switch(str[++i]) {                      \
102
 
                case 's':                           \
103
 
                    pt  = va_arg(args, char *);     \
104
 
                    if(pt)                          \
105
 
                        arglen += strlen(pt);       \
106
 
                    break;                          \
107
 
                case 'f':                           \
108
 
                    va_arg(args, double);           \
109
 
                    arglen += 25;                   \
110
 
                    break;                          \
111
 
                case 'l':                           \
112
 
                    va_arg(args, long);             \
113
 
                    arglen += 20;                   \
114
 
                    break;                          \
115
 
                default:                            \
116
 
                    va_arg(args, int);              \
117
 
                    arglen += 10;                   \
118
 
                    break;                          \
119
 
            }                                       \
120
 
        }                                           \
121
 
    }                                               \
122
 
    va_end(args);                                   \
123
 
    len += arglen;                                  \
124
 
}
 
81
          mprintf_stdout = 0;
125
82
 
126
83
int mdprintf(int desc, const char *str, ...)
127
84
{
128
85
        va_list args;
129
 
        char buffer[512], *abuffer = NULL, *buff;
130
 
        int bytes, todo, ret=0;
131
 
        size_t len;
 
86
        char buff[512];
 
87
        int bytes;
132
88
 
133
 
    ARGLEN(args, str, len);
134
 
    if(len <= sizeof(buffer)) {
135
 
        len = sizeof(buffer);
136
 
        buff = buffer;
137
 
    } else {
138
 
        abuffer = malloc(len);
139
 
        if(!abuffer) {
140
 
            len = sizeof(buffer);
141
 
            buff = buffer;
142
 
        } else {
143
 
            buff = abuffer;
144
 
        }
145
 
    }
146
89
    va_start(args, str);
147
 
    bytes = vsnprintf(buff, len, str, args);
 
90
    bytes = vsnprintf(buff, sizeof(buff), str, args);
148
91
    va_end(args);
149
 
    buff[len - 1] = 0;
150
92
 
151
 
    if(bytes < 0) {
152
 
        if(len > sizeof(buffer))
153
 
            free(abuffer);
 
93
    if(bytes == -1)
154
94
        return bytes;
155
 
    }
156
 
    if((size_t) bytes >= len)
157
 
        bytes = len - 1;
158
 
 
159
 
    todo = bytes;
160
 
#ifdef CL_THREAD_SAFE
161
 
    /* make sure we don't mix sends from multiple threads,
162
 
     * important for IDSESSION */
163
 
    pthread_mutex_lock(&mdprintf_mutex);
164
 
#endif
165
 
    while (todo > 0) {
166
 
        ret = send(desc, buff, bytes, 0);
167
 
        if (ret < 0) {
168
 
            struct timeval tv;
169
 
            if (errno != EWOULDBLOCK)
170
 
                break;
171
 
            /* didn't send anything yet */
172
 
#ifdef CL_THREAD_SAFE
173
 
            pthread_mutex_unlock(&mdprintf_mutex);
174
 
#endif
175
 
            tv.tv_sec = 0;
176
 
            tv.tv_usec = mprintf_send_timeout*1000;
177
 
            do {
178
 
                fd_set wfds;
179
 
                FD_ZERO(&wfds);
180
 
                FD_SET(desc, &wfds);
181
 
                ret = select(desc+1, NULL, &wfds, NULL, &tv);
182
 
            } while (ret < 0 && errno == EINTR);
183
 
#ifdef CL_THREAD_SAFE
184
 
            pthread_mutex_lock(&mdprintf_mutex);
185
 
#endif
186
 
            if (!ret) {
187
 
                /* timed out */
188
 
                ret = -1;
189
 
                break;
190
 
            }
191
 
        } else {
192
 
            todo -= ret;
193
 
            buff += ret;
194
 
        }
195
 
    }
196
 
#ifdef CL_THREAD_SAFE
197
 
    pthread_mutex_unlock(&mdprintf_mutex);
198
 
#endif
199
 
 
200
 
    if(len > sizeof(buffer))
201
 
        free(abuffer);
202
 
 
203
 
    return ret < 0 ? -1 : bytes;
 
95
 
 
96
    if(bytes >= (int) sizeof(buff))
 
97
        bytes = sizeof(buff) - 1;
 
98
 
 
99
    return send(desc, buff, bytes, 0);
204
100
}
205
101
 
206
 
void logg_close(void)
207
 
{
 
102
void logg_close(void) {
 
103
 
 
104
#ifdef CL_THREAD_SAFE
 
105
    pthread_mutex_lock(&logg_mutex);
 
106
#endif
 
107
    if (logg_fd) {
 
108
        fclose(logg_fd);
 
109
        logg_fd = NULL;
 
110
    }
 
111
#ifdef CL_THREAD_SAFE
 
112
    pthread_mutex_unlock(&logg_mutex);
 
113
#endif
 
114
 
208
115
#if defined(USE_SYSLOG) && !defined(C_AIX)
209
 
    if(logg_syslog)
 
116
    if(logg_syslog) {
210
117
        closelog();
211
 
#endif
212
 
 
213
 
#ifdef CL_THREAD_SAFE
214
 
    pthread_mutex_lock(&logg_mutex);
215
 
#endif
216
 
    if(logg_fp) {
217
 
        fclose(logg_fp);
218
 
        logg_fp = NULL;
219
118
    }
220
 
#ifdef CL_THREAD_SAFE
221
 
    pthread_mutex_unlock(&logg_mutex);
222
119
#endif
223
120
}
224
121
 
225
 
/*
226
 
 * legend:
227
 
 *  ! - ERROR:
228
 
 *  ^ - WARNING:
229
 
 *  ~ - normal
230
 
 *  # - normal, not foreground (logfile and syslog only)
231
 
 *  * - verbose
232
 
 *  $ - debug
233
 
 *  none - normal
234
 
 *
235
 
 *      Default  Foreground LogVerbose Debug  Syslog
236
 
 *  !     yes      mprintf     yes      yes   LOG_ERR
237
 
 *  ^     yes      mprintf     yes      yes   LOG_WARNING
238
 
 *  ~     yes      mprintf     yes      yes   LOG_INFO
239
 
 *  #     yes        no        yes      yes   LOG_INFO
240
 
 *  *     no       mprintf     yes      yes   LOG_DEBUG
241
 
 *  $     no       mprintf     no       yes   LOG_DEBUG
242
 
 *  none  yes      mprintf     yes      yes   LOG_INFO
243
 
 */
244
122
int logg(const char *str, ...)
245
123
{
246
 
        va_list args;
247
 
#ifdef F_WRLCK
 
124
        va_list args, argscpy, argsout;
248
125
        struct flock fl;
249
 
#endif
250
 
        char buffer[1025], *abuffer = NULL, *buff;
 
126
        char *pt, *timestr, vbuff[1025];
251
127
        time_t currtime;
252
128
        struct stat sb;
253
129
        mode_t old_umask;
254
 
        size_t len;
255
 
 
256
 
    if ((*str == '$' && logg_verbose < 2) ||
257
 
        (*str == '*' && !logg_verbose))
258
 
        return 0;
259
 
 
260
 
    ARGLEN(args, str, len);
261
 
    if(len <= sizeof(buffer)) {
262
 
        len = sizeof(buffer);
263
 
        buff = buffer;
264
 
    } else {
265
 
        abuffer = malloc(len);
266
 
        if(!abuffer) {
267
 
            len = sizeof(buffer);
268
 
            buff = buffer;
269
 
        } else {
270
 
            buff = abuffer;
271
 
        }
272
 
    }
 
130
 
 
131
 
273
132
    va_start(args, str);
274
 
    vsnprintf(buff, len, str, args);
275
 
    va_end(args);
276
 
    buff[len - 1] = 0;
 
133
    /* va_copy is less portable so we just use va_start once more */
 
134
    va_start(argscpy, str);
 
135
    va_start(argsout, str);
277
136
 
278
137
#ifdef CL_THREAD_SAFE
279
138
    pthread_mutex_lock(&logg_mutex);
280
139
#endif
281
140
    if(logg_file) {
282
 
        if(!logg_fp) {
 
141
        if(!logg_fd) {
283
142
            old_umask = umask(0037);
284
 
            if((logg_fp = fopen(logg_file, "at")) == NULL) {
 
143
            if((logg_fd = fopen(logg_file, "a")) == NULL) {
285
144
                umask(old_umask);
286
145
#ifdef CL_THREAD_SAFE
287
146
                pthread_mutex_unlock(&logg_mutex);
288
147
#endif
289
148
                printf("ERROR: Can't open %s in append mode (check permissions!).\n", logg_file);
290
 
                if(len > sizeof(buffer))
291
 
                    free(abuffer);
292
149
                return -1;
293
150
            } else umask(old_umask);
294
151
 
295
 
#ifdef F_WRLCK
296
152
            if(logg_lock) {
297
153
                memset(&fl, 0, sizeof(fl));
298
154
                fl.l_type = F_WRLCK;
299
 
                if(fcntl(fileno(logg_fp), F_SETLK, &fl) == -1) {
300
 
#ifdef EOPNOTSUPP
301
 
                    if(errno == EOPNOTSUPP)
302
 
                        printf("WARNING: File locking not supported (NFS?)\n");
303
 
                    else
304
 
#endif
305
 
                    {
 
155
                if(fcntl(fileno(logg_fd), F_SETLK, &fl) == -1) {
306
156
#ifdef CL_THREAD_SAFE
307
 
                        pthread_mutex_unlock(&logg_mutex);
 
157
                    pthread_mutex_unlock(&logg_mutex);
308
158
#endif
309
 
                        printf("ERROR: %s is locked by another process\n", logg_file);
310
 
                        if(len > sizeof(buffer))
311
 
                            free(abuffer);
312
 
                        return -1;
313
 
                    }
314
 
                }
 
159
                    return -1;
 
160
                }
315
161
            }
316
 
#endif
317
162
        }
318
163
 
319
164
        if(logg_size) {
320
165
            if(stat(logg_file, &sb) != -1) {
321
 
                if((unsigned int) sb.st_size > logg_size) {
 
166
                if(sb.st_size > logg_size) {
322
167
                    logg_file = NULL;
323
 
                    fprintf(logg_fp, "Log size = %u, max = %u\n", (unsigned int) sb.st_size, logg_size);
324
 
                    fprintf(logg_fp, "LOGGING DISABLED (Maximal log file size exceeded).\n");
325
 
                    fclose(logg_fp);
326
 
                    logg_fp = NULL;
 
168
                    fprintf(logg_fd, "Log size = %d, maximal = %d\n", (int) sb.st_size, logg_size);
 
169
                    fprintf(logg_fd, "LOGGING DISABLED (Maximal log file size exceeded).\n");
 
170
                    fclose(logg_fd);
 
171
                    logg_fd = NULL;
327
172
                }
328
173
            }
329
174
        }
330
175
 
331
 
        if(logg_fp) {
332
 
            char flush = !logg_noflush;
 
176
        if(logg_fd) {
333
177
            /* Need to avoid logging time for verbose messages when logverbose
334
178
               is not set or we get a bunch of timestamps in the log without
335
179
               newlines... */
336
 
            if(logg_time && ((*buff != '*') || logg_verbose)) {
337
 
                char timestr[32];
 
180
            if(logg_time && ((*str != '*') || logg_verbose)) {
338
181
                time(&currtime);
339
 
                cli_ctime(&currtime, timestr, sizeof(timestr));
340
 
                /* cut trailing \n */
341
 
                timestr[strlen(timestr)-1] = '\0';
342
 
                fprintf(logg_fp, "%s -> ", timestr);
 
182
                pt = ctime(&currtime);
 
183
                timestr = mcalloc(strlen(pt), sizeof(char));
 
184
                strncpy(timestr, pt, strlen(pt) - 1);
 
185
                fprintf(logg_fd, "%s -> ", timestr);
 
186
                free(timestr);
343
187
            }
344
188
 
345
 
            if(*buff == '!') {
346
 
                fprintf(logg_fp, "ERROR: %s", buff + 1);
347
 
                flush = 1;
348
 
            } else if(*buff == '^') {
349
 
                if(!logg_nowarn)
350
 
                    fprintf(logg_fp, "WARNING: %s", buff + 1);
351
 
                flush = 1;
352
 
            } else if(*buff == '*' || *buff == '$') {
353
 
                    fprintf(logg_fp, "%s", buff + 1);
354
 
            } else if(*buff == '#' || *buff == '~') {
355
 
                fprintf(logg_fp, "%s", buff + 1);
356
 
            } else
357
 
                fprintf(logg_fp, "%s", buff);
358
 
 
359
 
            if (flush)
360
 
                fflush(logg_fp);
 
189
            _(str);
 
190
            if(*str == '!') {
 
191
                fprintf(logg_fd, "ERROR: ");
 
192
                vfprintf(logg_fd, str + 1, args);
 
193
            } else if(*str == '^') {
 
194
                fprintf(logg_fd, "WARNING: ");
 
195
                vfprintf(logg_fd, str + 1, args);
 
196
            } else if(*str == '*') {
 
197
                if(logg_verbose)
 
198
                    vfprintf(logg_fd, str + 1, args);
 
199
            } else if(*str == '#') {
 
200
                vfprintf(logg_fd, str + 1, args);
 
201
            } else vfprintf(logg_fd, str, args);
 
202
 
 
203
 
 
204
            fflush(logg_fd);
361
205
        }
362
206
    }
363
207
 
364
208
#if defined(USE_SYSLOG) && !defined(C_AIX)
365
209
    if(logg_syslog) {
366
 
        if(buff[0] == '!') {
367
 
            syslog(LOG_ERR, "%s", buff + 1);
368
 
        } else if(buff[0] == '^') {
369
 
            if(!logg_nowarn)
370
 
                syslog(LOG_WARNING, "%s", buff + 1);
371
 
        } else if(buff[0] == '*' || buff[0] == '$') {
372
 
            syslog(LOG_DEBUG, "%s", buff + 1);
373
 
        } else if(buff[0] == '#' || buff[0] == '~') {
374
 
            syslog(LOG_INFO, "%s", buff + 1);
375
 
        } else syslog(LOG_INFO, "%s", buff);
 
210
        _(str);
 
211
        vsnprintf(vbuff, 1024, str, argscpy);
 
212
        vbuff[1024] = 0;
 
213
 
 
214
        if(vbuff[0] == '!') {
 
215
            syslog(LOG_ERR, "%s", vbuff + 1);
 
216
        } else if(vbuff[0] == '^') {
 
217
            syslog(LOG_WARNING, "%s", vbuff + 1);
 
218
        } else if(vbuff[0] == '*') {
 
219
            if(logg_verbose) {
 
220
                syslog(LOG_DEBUG, "%s", vbuff + 1);
 
221
            }
 
222
        } else if(vbuff[0] == '#') {
 
223
            syslog(LOG_INFO, "%s", vbuff + 1);
 
224
        } else syslog(LOG_INFO, "%s", vbuff);
376
225
 
377
226
    }
378
227
#endif
379
228
 
380
229
    if(logg_foreground) {
381
 
        if(buff[0] != '#')
382
 
            mprintf("%s", buff);
 
230
        _(str);
 
231
        vsnprintf(vbuff, 1024, str, argsout);
 
232
        vbuff[1024] = 0;
 
233
        if(vbuff[0] != '#')
 
234
            mprintf("%s", vbuff);
383
235
    }
384
236
 
385
237
#ifdef CL_THREAD_SAFE
386
238
    pthread_mutex_unlock(&logg_mutex);
387
239
#endif
388
240
 
389
 
    if(len > sizeof(buffer))
390
 
        free(abuffer);
 
241
    va_end(args);
 
242
    va_end(argscpy);
 
243
    va_end(argsout);
391
244
    return 0;
392
245
}
393
246
 
395
248
{
396
249
        va_list args;
397
250
        FILE *fd;
398
 
        char buffer[512], *abuffer = NULL, *buff;
399
 
        size_t len;
 
251
        char buff[512];
400
252
 
401
253
 
402
254
    if(mprintf_disabled) 
419
271
 * quiet       stderr     no         no
420
272
 */
421
273
 
422
 
    ARGLEN(args, str, len);
423
 
    if(len <= sizeof(buffer)) {
424
 
        len = sizeof(buffer);
425
 
        buff = buffer;
426
 
    } else {
427
 
        abuffer = malloc(len);
428
 
        if(!abuffer) {
429
 
            len = sizeof(buffer);
430
 
            buff = buffer;
431
 
        } else {
432
 
            buff = abuffer;
433
 
        }
434
 
    }
435
274
    va_start(args, str);
436
 
    vsnprintf(buff, len, str, args);
 
275
    vsnprintf(buff, sizeof(buff), str, args);
437
276
    va_end(args);
438
 
    buff[len - 1] = 0;
439
277
 
440
278
    if(buff[0] == '!') {
441
279
       if(!mprintf_stdout)
447
285
        fprintf(fd, "ERROR: %s", &buff[1]);
448
286
    } else if(!mprintf_quiet) {
449
287
        if(buff[0] == '^') {
450
 
            if(!mprintf_nowarn) {
451
 
                if(!mprintf_stdout)
452
 
                    fd = stderr;
453
 
                fprintf(fd, "WARNING: %s", &buff[1]);
454
 
            }
 
288
           if(!mprintf_stdout)
 
289
               fd = stderr;
 
290
            fprintf(fd, "WARNING: %s", &buff[1]);
455
291
        } else if(buff[0] == '*') {
456
292
            if(mprintf_verbose)
457
293
                fprintf(fd, "%s", &buff[1]);
458
 
        } else if(buff[0] == '~') {
459
 
            fprintf(fd, "%s", &buff[1]);
460
294
        } else fprintf(fd, "%s", buff);
461
295
    }
462
296
 
463
297
    if(fd == stdout)
464
298
        fflush(stdout);
465
 
 
466
 
    if(len > sizeof(buffer))
467
 
        free(abuffer);
468
299
}
469
300
 
470
301
struct facstruct {