~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to kdm/backend/printf.c

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
Copyright 2001,2002,2004 Oswald Buddenhagen <ossi@kde.org>
 
4
 
 
5
Permission to use, copy, modify, distribute, and sell this software and its
 
6
documentation for any purpose is hereby granted without fee, provided that
 
7
the above copyright notice appear in all copies and that both that
 
8
copyright notice and this permission notice appear in supporting
 
9
documentation.
 
10
 
 
11
The above copyright notice and this permission notice shall be included
 
12
in all copies or substantial portions of the Software.
 
13
 
 
14
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
15
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
16
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
17
IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 
18
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 
19
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 
20
OTHER DEALINGS IN THE SOFTWARE.
 
21
 
 
22
Except as contained in this notice, the name of a copyright holder shall
 
23
not be used in advertising or otherwise to promote the sale, use or
 
24
other dealings in this Software without prior written authorization
 
25
from the copyright holder.
 
26
 
 
27
*/
 
28
 
 
29
/*
 
30
 * xdm - display manager daemon
 
31
 * Author: Keith Packard, MIT X Consortium
 
32
 *
 
33
 * printf.c - working horse of error.c
 
34
 */
 
35
 
 
36
/*
 
37
 * NOTE: this file is meant to be included, not linked,
 
38
 * so it can be used in the helper programs without much voodoo.
 
39
 */
 
40
 
 
41
/* ########## printf core implementation with some extensions ########## */
 
42
/*
 
43
 * How to use the extensions:
 
44
 * - put ' or " in the flags field to quote a string with this char and
 
45
 *   escape special characters (only available, if PRINT_QUOTES is defined)
 
46
 * - put \\ in the flags field to quote special characters and leading and
 
47
 *   trailing spaces (only available, if PRINT_QUOTES is defined)
 
48
 * - arrays (only available, if PRINT_ARRAYS is defined)
 
49
 *   - the array modifier [ comes after the maximal field width specifier
 
50
 *   - the array length can be specified literally, with the '*' modifier
 
51
 *     (in which case an argument is expected) or will be automatically
 
52
 *     determined (stop values are -1 for ints and 0 for strings)
 
53
 *   - these modifiers expect their argument to be an in-line string quoted
 
54
 *     with an arbitrary character:
 
55
 *     - (,) -> array pre-/suf-fix; default ""
 
56
 *     - <, > -> element pre-/suf-fix; default ""
 
57
 *     - | -> element separator; default " "
 
58
 *   - these modifiers expect no argument:
 
59
 *     - : -> print '<number of elements>: ' before an array
 
60
 *     - , -> short for |','
 
61
 *     - { -> short for ('{')' }'<' '|''
 
62
 *   - the pointer to the array is the last argument to the format
 
63
 * - the %m conversion from syslog() is supported
 
64
 *   (extended by -ENOSPC meaning "partial write")
 
65
 */
 
66
 
 
67
/**************************************************************
 
68
 * Partially stolen from OpenSSH's OpenBSD compat directory.
 
69
 * (C) Patrick Powell, Brandon Long, Thomas Roessler,
 
70
 *     Michael Elkins, Ben Lindstrom
 
71
 **************************************************************/
 
72
 
 
73
#include <ctype.h>
 
74
#include <string.h>
 
75
#include <stdarg.h>
 
76
 
 
77
/* format flags - Bits */
 
78
#define DP_F_MINUS     (1 << 0)
 
79
#define DP_F_PLUS      (1 << 1)
 
80
#define DP_F_SPACE     (1 << 2)
 
81
#define DP_F_NUM       (1 << 3)
 
82
#define DP_F_ZERO      (1 << 4)
 
83
#define DP_F_UPCASE    (1 << 5)
 
84
#define DP_F_UNSIGNED  (1 << 6)
 
85
#define DP_F_SQUOTE    (1 << 7)
 
86
#define DP_F_DQUOTE    (1 << 8)
 
87
#define DP_F_BACKSL    (1 << 9)
 
88
#define DP_F_ARRAY     (1 << 10)
 
89
#define DP_F_COLON     (1 << 11)
 
90
 
 
91
/* Conversion Flags */
 
92
#define DP_C_INT    0
 
93
#define DP_C_BYTE   1
 
94
#define DP_C_SHORT  2
 
95
#define DP_C_LONG   3
 
96
#define DP_C_STR    10
 
97
 
 
98
typedef void (*OutCh)(void *bp, char c);
 
99
 
 
100
 
 
101
static void
 
102
fmtint(OutCh dopr_outch, void *bp,
 
103
       long value, int base, int min, int max, int flags)
 
104
{
 
105
    const char *ctab;
 
106
    unsigned long uvalue;
 
107
    int signvalue = 0;
 
108
    int place = 0;
 
109
    int spadlen = 0; /* amount to space pad */
 
110
    int zpadlen = 0; /* amount to zero pad */
 
111
    char convert[20];
 
112
 
 
113
    if (max < 0)
 
114
        max = 0;
 
115
 
 
116
    uvalue = value;
 
117
 
 
118
    if (!(flags & DP_F_UNSIGNED)) {
 
119
        if (value < 0) {
 
120
            signvalue = '-';
 
121
            uvalue = -value;
 
122
        } else if (flags & DP_F_PLUS) { /* Do a sign (+/i) */
 
123
            signvalue = '+';
 
124
        } else if (flags & DP_F_SPACE) {
 
125
            signvalue = ' ';
 
126
        }
 
127
    }
 
128
 
 
129
    ctab = (flags & DP_F_UPCASE) ? "0123456789ABCDEF" : "0123456789abcdef";
 
130
    do {
 
131
        convert[place++] = ctab[uvalue % (unsigned)base];
 
132
        uvalue = uvalue / (unsigned)base;
 
133
    } while (uvalue);
 
134
 
 
135
    zpadlen = max - place;
 
136
    spadlen = min - (max > place ? max : place) -
 
137
              (signvalue ? 1 : 0) - ((flags & DP_F_NUM) ? 2 : 0);
 
138
    if (zpadlen < 0)
 
139
        zpadlen = 0;
 
140
    if (spadlen < 0)
 
141
        spadlen = 0;
 
142
    if (flags & DP_F_ZERO) {
 
143
        zpadlen = zpadlen > spadlen ? zpadlen : spadlen;
 
144
        spadlen = 0;
 
145
    }
 
146
    if (flags & DP_F_MINUS)
 
147
        spadlen = -spadlen; /* Left Justifty */
 
148
 
 
149
 
 
150
    /* Spaces */
 
151
    while (spadlen > 0) {
 
152
        dopr_outch(bp, ' ');
 
153
        --spadlen;
 
154
    }
 
155
 
 
156
    /* Sign */
 
157
    if (signvalue)
 
158
        dopr_outch(bp, signvalue);
 
159
 
 
160
    /* Prefix */
 
161
    if (flags & DP_F_NUM) {
 
162
        dopr_outch(bp, '0');
 
163
        dopr_outch(bp, 'x');
 
164
    }
 
165
 
 
166
    /* Zeros */
 
167
    if (zpadlen > 0)
 
168
        while (zpadlen > 0) {
 
169
            dopr_outch(bp, '0');
 
170
            --zpadlen;
 
171
        }
 
172
 
 
173
    /* Digits */
 
174
    while (place > 0)
 
175
        dopr_outch(bp, convert[--place]);
 
176
 
 
177
    /* Left Justified spaces */
 
178
    while (spadlen < 0) {
 
179
        dopr_outch(bp, ' ');
 
180
        ++spadlen;
 
181
    }
 
182
}
 
183
 
 
184
typedef struct {
 
185
    const char *str;
 
186
    size_t len;
 
187
} str_t;
 
188
 
 
189
static void
 
190
putstr(OutCh dopr_outch, void *bp, str_t *st)
 
191
{
 
192
    size_t pt;
 
193
 
 
194
    for (pt = 0; pt < st->len; pt++)
 
195
        dopr_outch(bp, st->str[pt]);
 
196
}
 
197
 
 
198
static str_t _null_parents = { "(null)", 6 };
 
199
#ifdef PRINT_ARRAYS
 
200
static str_t _null_dparents = { "((null))", 8 };
 
201
#endif
 
202
#if defined(PRINT_QUOTES) || defined(PRINT_ARRAYS)
 
203
static str_t _null_caps = { "NULL", 4 };
 
204
#endif
 
205
 
 
206
static void
 
207
fmtstr(OutCh dopr_outch, void *bp,
 
208
       const char *value, int flags, int min, int max)
 
209
{
 
210
    int padlen, strln, curcol;
 
211
#ifdef PRINT_QUOTES
 
212
    int lastcol;
 
213
#endif
 
214
    char ch;
 
215
 
 
216
    if (!value) {
 
217
#ifdef PRINT_QUOTES
 
218
        if (flags & (DP_F_SQUOTE | DP_F_DQUOTE))
 
219
            putstr(dopr_outch, bp, &_null_caps);
 
220
        else
 
221
#endif
 
222
            putstr(dopr_outch, bp, &_null_parents);
 
223
        return;
 
224
    }
 
225
 
 
226
    for (strln = 0; (unsigned)strln < (unsigned)max && value[strln]; strln++);
 
227
    padlen = min - strln;
 
228
    if (padlen < 0)
 
229
        padlen = 0;
 
230
    if (flags & DP_F_MINUS)
 
231
        padlen = -padlen; /* Left Justify */
 
232
 
 
233
    for (; padlen > 0; padlen--)
 
234
        dopr_outch(bp, ' ');
 
235
#ifdef PRINT_QUOTES
 
236
    lastcol = 0;
 
237
    if (flags & DP_F_SQUOTE)
 
238
        dopr_outch(bp, '\'');
 
239
    else if (flags & DP_F_DQUOTE)
 
240
        dopr_outch(bp, '"');
 
241
    else if (flags & DP_F_BACKSL)
 
242
        for (lastcol = strln; lastcol && value[lastcol - 1] == ' '; lastcol--);
 
243
#endif
 
244
    for (curcol = 0; curcol < strln; curcol++) {
 
245
        ch = value[curcol];
 
246
#ifdef PRINT_QUOTES
 
247
        if (flags & (DP_F_SQUOTE | DP_F_DQUOTE | DP_F_BACKSL)) {
 
248
            switch (ch) {
 
249
            case '\r': ch = 'r'; break;
 
250
            case '\n': ch = 'n'; break;
 
251
            case '\t': ch = 't'; break;
 
252
            case '\a': ch = 'a'; break;
 
253
            case '\b': ch = 'b'; break;
 
254
            case '\v': ch = 'v'; break;
 
255
            case '\f': ch = 'f'; break;
 
256
            default:
 
257
                if (ch < 32 ||
 
258
                    ((unsigned char)ch >= 0x7f && (unsigned char)ch < 0xa0))
 
259
                {
 
260
                    dopr_outch(bp, '\\');
 
261
                    fmtint(dopr_outch, bp, (unsigned char)ch, 8, 3, 3, DP_F_ZERO);
 
262
                    continue;
 
263
                } else {
 
264
                    if ((ch == '\'' && (flags & DP_F_SQUOTE)) ||
 
265
                        (ch == '"' && (flags & DP_F_DQUOTE)) ||
 
266
                        (ch == ' ' && (flags & DP_F_BACKSL) &&
 
267
                         (!curcol || curcol >= lastcol)) ||
 
268
                        ch == '\\')
 
269
                    {
 
270
                        dopr_outch(bp, '\\');
 
271
                    }
 
272
                    dopr_outch(bp, ch);
 
273
                    continue;
 
274
                }
 
275
            }
 
276
            dopr_outch(bp, '\\');
 
277
        }
 
278
#endif
 
279
        dopr_outch(bp, ch);
 
280
    }
 
281
#ifdef PRINT_QUOTES
 
282
    if (flags & DP_F_SQUOTE)
 
283
        dopr_outch(bp, '\'');
 
284
    else if (flags & DP_F_DQUOTE)
 
285
        dopr_outch(bp, '"');
 
286
#endif
 
287
    for (; padlen < 0; padlen++)
 
288
        dopr_outch(bp, ' ');
 
289
}
 
290
 
 
291
static void
 
292
doPrint(OutCh dopr_outch, void *bp, const char *format, va_list args)
 
293
{
 
294
    const char *strvalue;
 
295
#ifdef PRINT_ARRAYS
 
296
    str_t arpr, arsf, arepr, aresf, aresp, *arp;
 
297
    void *arptr;
 
298
#endif
 
299
    unsigned long value;
 
300
    int radix, min, max, flags, cflags, errn;
 
301
#ifdef PRINT_ARRAYS
 
302
    int arlen;
 
303
    unsigned aridx;
 
304
    char sch;
 
305
#endif
 
306
    char ch;
 
307
#define NCHR if (!(ch = *format++)) return
 
308
 
 
309
# ifdef PRINT_ARRAYS
 
310
    arlen = 0;
 
311
# endif
 
312
    radix = 0;
 
313
    errn = errno;
 
314
    for (;;) {
 
315
        for (;;) {
 
316
            NCHR;
 
317
            if (ch == '%')
 
318
                break;
 
319
            dopr_outch(bp, ch);
 
320
        }
 
321
        flags = cflags = min = 0;
 
322
        max = -1;
 
323
        for (;;) {
 
324
            NCHR;
 
325
            switch (ch) {
 
326
            case '#': flags |= DP_F_NUM; continue;
 
327
            case '-': flags |= DP_F_MINUS; continue;
 
328
            case '+': flags |= DP_F_PLUS; continue;
 
329
            case ' ': flags |= DP_F_SPACE; continue;
 
330
            case '0': flags |= DP_F_ZERO; continue;
 
331
#ifdef PRINT_QUOTES
 
332
            case '"': flags |= DP_F_DQUOTE; continue;
 
333
            case '\'': flags |= DP_F_SQUOTE; continue;
 
334
            case '\\': flags |= DP_F_BACKSL; continue;
 
335
#endif
 
336
            }
 
337
            break;
 
338
        }
 
339
        for (;;) {
 
340
            if (isdigit((unsigned char)ch)) {
 
341
                min = 10 * min + (ch - '0');
 
342
                NCHR;
 
343
                continue;
 
344
            } else if (ch == '*') {
 
345
                min = va_arg(args, int);
 
346
                NCHR;
 
347
            }
 
348
            break;
 
349
        }
 
350
        if (ch == '.') {
 
351
            max = 0;
 
352
            for (;;) {
 
353
                NCHR;
 
354
                if (isdigit((unsigned char)ch)) {
 
355
                    max = 10 * max + (ch - '0');
 
356
                    continue;
 
357
                } else if (ch == '*') {
 
358
                    max = va_arg(args, int);
 
359
                    NCHR;
 
360
                }
 
361
                break;
 
362
            }
 
363
        }
 
364
#ifdef PRINT_ARRAYS
 
365
        if (ch == '[') {
 
366
            flags |= DP_F_ARRAY;
 
367
            arlen = -1;
 
368
            arpr.len = arsf.len = arepr.len = aresf.len = 0;
 
369
            aresp.len = 1, aresp.str = " ";
 
370
            for (;;) {
 
371
                NCHR;
 
372
                if (isdigit((unsigned char)ch)) {
 
373
                    arlen = 0;
 
374
                    for (;;) {
 
375
                        arlen += (ch - '0');
 
376
                        NCHR;
 
377
                        if (!isdigit((unsigned char)ch))
 
378
                            break;
 
379
                        arlen *= 10;
 
380
                    }
 
381
                }
 
382
                switch (ch) {
 
383
                case ':': flags |= DP_F_COLON; continue;
 
384
                case '*': arlen = va_arg(args, int); continue;
 
385
                case '(': arp = &arpr; goto rar;
 
386
                case ')': arp = &arsf; goto rar;
 
387
                case '<': arp = &arepr; goto rar;
 
388
                case '>': arp = &aresf; goto rar;
 
389
                case '|': arp = &aresp;
 
390
                  rar:
 
391
                    NCHR;
 
392
                    sch = ch;
 
393
                    arp->str = format;
 
394
                    do {
 
395
                        NCHR;
 
396
                    } while (ch != sch);
 
397
                    arp->len = format - arp->str - 1;
 
398
                    continue;
 
399
                case ',':
 
400
                    aresp.len = 1, aresp.str = ",";
 
401
                    continue;
 
402
                case '{':
 
403
                    aresp.len = 0, arpr.len = arepr.len = 1, arsf.len = 2;
 
404
                    arpr.str = "{", arepr.str = " ", arsf.str = " }";
 
405
                    continue;
 
406
                }
 
407
                break;
 
408
            }
 
409
        }
 
410
#endif
 
411
        for (;;) {
 
412
            switch (ch) {
 
413
            case 'h':
 
414
                cflags = DP_C_SHORT;
 
415
                NCHR;
 
416
                if (ch == 'h') {
 
417
                    cflags = DP_C_BYTE;
 
418
                    NCHR;
 
419
                }
 
420
                continue;
 
421
            case 'l':
 
422
                cflags = DP_C_LONG;
 
423
                NCHR;
 
424
                continue;
 
425
            }
 
426
            break;
 
427
        }
 
428
        switch (ch) {
 
429
        case '%':
 
430
            dopr_outch(bp, ch);
 
431
            break;
 
432
        case 'm':
 
433
            strvalue = (errn == -ENOSPC) ? "partial write" : strerror(errn);
 
434
            fmtstr(dopr_outch, bp, strvalue, flags, min, max);
 
435
            break;
 
436
        case 'c':
 
437
            dopr_outch(bp, va_arg(args, int));
 
438
            break;
 
439
        case 's':
 
440
#ifdef PRINT_ARRAYS
 
441
            cflags = DP_C_STR;
 
442
            goto printit;
 
443
#else
 
444
            strvalue = va_arg(args, char *);
 
445
            fmtstr(dopr_outch, bp, strvalue, flags, min, max);
 
446
            break;
 
447
#endif
 
448
        case 'u':
 
449
            flags |= DP_F_UNSIGNED;
 
450
        case 'd':
 
451
        case 'i':
 
452
            radix = 10;
 
453
            goto printit;
 
454
        case 'X':
 
455
            flags |= DP_F_UPCASE;
 
456
        case 'x':
 
457
            flags |= DP_F_UNSIGNED;
 
458
            radix = 16;
 
459
          printit:
 
460
#ifdef PRINT_ARRAYS
 
461
            if (flags & DP_F_ARRAY) {
 
462
                if (!(arptr = va_arg(args, void *))) {
 
463
                    putstr(dopr_outch, bp,
 
464
                           arpr.len ? &_null_caps : &_null_dparents);
 
465
                } else {
 
466
                    if (arlen == -1) {
 
467
                        arlen = 0;
 
468
                        switch (cflags) {
 
469
                        case DP_C_STR: while (((char **)arptr)[arlen]) arlen++; break;
 
470
                        case DP_C_BYTE: while (((unsigned char *)arptr)[arlen] != (unsigned char)-1) arlen++; break;
 
471
                        case DP_C_SHORT: while (((unsigned short int *)arptr)[arlen] != (unsigned short int)-1) arlen++; break;
 
472
                        case DP_C_LONG: while (((unsigned long int *)arptr)[arlen] != (unsigned long int)-1) arlen++; break;
 
473
                        default: while (((unsigned int *)arptr)[arlen] != (unsigned int)-1) arlen++; break;
 
474
                        }
 
475
                    }
 
476
                    if (flags & DP_F_COLON) {
 
477
                        fmtint(dopr_outch, bp, (long)arlen, 10, 0, -1, DP_F_UNSIGNED);
 
478
                        dopr_outch(bp, ':');
 
479
                        dopr_outch(bp, ' ');
 
480
                    }
 
481
                    putstr(dopr_outch, bp, &arpr);
 
482
                    for (aridx = 0; aridx < (unsigned)arlen; aridx++) {
 
483
                        if (aridx)
 
484
                            putstr(dopr_outch, bp, &aresp);
 
485
                        putstr(dopr_outch, bp, &arepr);
 
486
                        if (cflags == DP_C_STR) {
 
487
                            strvalue = ((char **)arptr)[aridx];
 
488
                            fmtstr(dopr_outch, bp, strvalue, flags, min, max);
 
489
                        } else {
 
490
                            if (flags & DP_F_UNSIGNED) {
 
491
                                switch (cflags) {
 
492
                                case DP_C_BYTE: value = ((unsigned char *)arptr)[aridx]; break;
 
493
                                case DP_C_SHORT: value = ((unsigned short int *)arptr)[aridx]; break;
 
494
                                case DP_C_LONG: value = ((unsigned long int *)arptr)[aridx]; break;
 
495
                                default: value = ((unsigned int *)arptr)[aridx]; break;
 
496
                                }
 
497
                            } else {
 
498
                                switch (cflags) {
 
499
                                case DP_C_BYTE: value = ((signed char *)arptr)[aridx]; break;
 
500
                                case DP_C_SHORT: value = ((short int *)arptr)[aridx]; break;
 
501
                                case DP_C_LONG: value = ((long int *)arptr)[aridx]; break;
 
502
                                default: value = ((int *)arptr)[aridx]; break;
 
503
                                }
 
504
                            }
 
505
                            fmtint(dopr_outch, bp, value, radix, min, max, flags);
 
506
                        }
 
507
                        putstr(dopr_outch, bp, &aresf);
 
508
                    }
 
509
                    putstr(dopr_outch, bp, &arsf);
 
510
                }
 
511
            } else {
 
512
                if (cflags == DP_C_STR) {
 
513
                    strvalue = va_arg(args, char *);
 
514
                    fmtstr(dopr_outch, bp, strvalue, flags, min, max);
 
515
                } else {
 
516
#endif
 
517
                    if (flags & DP_F_UNSIGNED) {
 
518
                        switch (cflags) {
 
519
                        case DP_C_LONG: value = va_arg(args, unsigned long int); break;
 
520
                        default: value = va_arg(args, unsigned int); break;
 
521
                        }
 
522
                    } else {
 
523
                        switch (cflags) {
 
524
                        case DP_C_LONG: value = va_arg(args, long int); break;
 
525
                        default: value = va_arg(args, int); break;
 
526
                        }
 
527
                    }
 
528
                    fmtint(dopr_outch, bp, value, radix, min, max, flags);
 
529
#ifdef PRINT_ARRAYS
 
530
                }
 
531
            }
 
532
#endif
 
533
            break;
 
534
        case 'p':
 
535
            value = (long)va_arg(args, void *);
 
536
            fmtint(dopr_outch, bp, value, 16, sizeof(long) * 2 + 2,
 
537
                   max, flags | DP_F_UNSIGNED | DP_F_ZERO | DP_F_NUM);
 
538
            break;
 
539
        }
 
540
    }
 
541
}
 
542
 
 
543
/* ########## end of printf core implementation ########## */
 
544
 
 
545
 
 
546
/*
 
547
 * Logging function for xdm and helper programs.
 
548
 */
 
549
#ifndef NO_LOGGER
 
550
 
 
551
#include <stdio.h>
 
552
#include <time.h>
 
553
 
 
554
#ifdef USE_SYSLOG
 
555
# include <syslog.h>
 
556
# ifdef LOG_NAME
 
557
#  define InitLog() openlog(LOG_NAME, LOG_PID, LOG_DAEMON)
 
558
# else
 
559
#  define InitLog() openlog(prog, LOG_PID, LOG_DAEMON)
 
560
# endif
 
561
static int lognums[] = { LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERR, LOG_CRIT };
 
562
#else
 
563
# define InitLog() while(0)
 
564
#endif
 
565
 
 
566
static const char *lognams[] = { "debug", "info", "warning", "error", "panic" };
 
567
 
 
568
static void
 
569
logTime(char *dbuf)
 
570
{
 
571
    time_t tim;
 
572
    (void)time(&tim);
 
573
    strftime(dbuf, 20, "%b %e %H:%M:%S", localtime(&tim));
 
574
}
 
575
 
 
576
#if defined(LOG_DEBUG_MASK) || defined(USE_SYSLOG)
 
577
STATIC int debugLevel;
 
578
#endif
 
579
 
 
580
#define OOMSTR "Out of memory. Expect problems.\n"
 
581
 
 
582
STATIC void
 
583
logOutOfMem(void)
 
584
{
 
585
    static time_t last;
 
586
    time_t tnow;
 
587
 
 
588
    time(&tnow);
 
589
    if (last + 100 > tnow) { /* don't log bursts */
 
590
        last = tnow;
 
591
        return;
 
592
    }
 
593
    last = tnow;
 
594
#ifdef USE_SYSLOG
 
595
    if (!(debugLevel & DEBUG_NOSYSLOG))
 
596
        syslog(LOG_CRIT, OOMSTR);
 
597
    else
 
598
#endif
 
599
    {
 
600
        int el;
 
601
        char dbuf[24], sbuf[128];
 
602
        logTime(dbuf);
 
603
        el = sprintf(sbuf, "%s "
 
604
#ifdef LOG_NAME
 
605
                     LOG_NAME "[%ld]: " OOMSTR, dbuf,
 
606
#else
 
607
                     "%s[%ld]: " OOMSTR, dbuf, prog,
 
608
#endif
 
609
                     (long)getpid());
 
610
        write(2, sbuf, el);
 
611
    }
 
612
}
 
613
 
 
614
typedef struct {
 
615
    char *buf;
 
616
    int clen, blen, type;
 
617
    char lmbuf[128];
 
618
} OCLBuf;
 
619
 
 
620
static void
 
621
flush_OCL(OCLBuf *oclbp)
 
622
{
 
623
    if (oclbp->clen) {
 
624
#ifdef USE_SYSLOG
 
625
        if (!(debugLevel & DEBUG_NOSYSLOG))
 
626
            syslog(lognums[oclbp->type], "%.*s", oclbp->clen, oclbp->buf);
 
627
        else
 
628
#endif
 
629
        {
 
630
            oclbp->buf[oclbp->clen] = '\n';
 
631
            write(2, oclbp->buf, oclbp->clen + 1);
 
632
        }
 
633
        oclbp->clen = 0;
 
634
    }
 
635
}
 
636
 
 
637
static void
 
638
outCh_OCL(void *bp, char c)
 
639
{
 
640
    OCLBuf *oclbp = (OCLBuf *)bp;
 
641
    char *nbuf;
 
642
    int nlen;
 
643
 
 
644
    if (c == '\n') {
 
645
        flush_OCL(oclbp);
 
646
    } else {
 
647
        if (oclbp->clen >= oclbp->blen - 1) {
 
648
            if (oclbp->buf == oclbp->lmbuf) {
 
649
                flush_OCL(oclbp);
 
650
                oclbp->buf = 0;
 
651
                oclbp->blen = 0;
 
652
            }
 
653
            nlen = oclbp->blen * 3 / 2 + 128;
 
654
            nbuf = Realloc(oclbp->buf, nlen);
 
655
            if (nbuf) {
 
656
                oclbp->buf = nbuf;
 
657
                oclbp->blen = nlen;
 
658
            } else {
 
659
                flush_OCL(oclbp);
 
660
                oclbp->buf = oclbp->lmbuf;
 
661
                oclbp->blen = sizeof(oclbp->lmbuf);
 
662
            }
 
663
        }
 
664
#ifdef USE_SYSLOG
 
665
        if (!oclbp->clen && (debugLevel & DEBUG_NOSYSLOG)) {
 
666
#else
 
667
        if (!oclbp->clen) {
 
668
#endif
 
669
            char dbuf[24];
 
670
            logTime(dbuf);
 
671
            oclbp->clen = sprintf(oclbp->buf, "%s "
 
672
#ifdef LOG_NAME
 
673
                                  LOG_NAME "[%ld] %s: ", dbuf,
 
674
#else
 
675
                                  "%s[%ld] %s: ", dbuf, prog,
 
676
#endif
 
677
                                  (long)getpid(), lognams[oclbp->type]);
 
678
        }
 
679
        oclbp->buf[oclbp->clen++] = c;
 
680
    }
 
681
}
 
682
 
 
683
static void
 
684
logger(int type, const char *fmt, va_list args)
 
685
{
 
686
    OCLBuf oclb;
 
687
 
 
688
    oclb.buf = 0;
 
689
    oclb.blen = oclb.clen = 0;
 
690
    oclb.type = type;
 
691
    doPrint(outCh_OCL, &oclb, fmt, args);
 
692
    /* no flush, every message is supposed to be \n-terminated */
 
693
    if (oclb.buf && oclb.buf != oclb.lmbuf)
 
694
        free(oclb.buf);
 
695
}
 
696
 
 
697
#ifdef LOG_DEBUG_MASK
 
698
STATIC void
 
699
debug(const char *fmt, ...)
 
700
{
 
701
    if (debugLevel & LOG_DEBUG_MASK) {
 
702
        va_list args;
 
703
        int olderrno = errno;
 
704
        va_start(args, fmt);
 
705
        logger(DM_DEBUG, fmt, args);
 
706
        va_end(args);
 
707
        errno = olderrno;
 
708
    }
 
709
}
 
710
#endif
 
711
 
 
712
#ifndef LOG_NO_INFO
 
713
STATIC void
 
714
logInfo(const char *fmt, ...)
 
715
{
 
716
    va_list args;
 
717
 
 
718
    va_start(args, fmt);
 
719
    logger(DM_INFO, fmt, args);
 
720
    va_end(args);
 
721
}
 
722
#endif
 
723
 
 
724
#ifndef LOG_NO_WARN
 
725
STATIC void
 
726
logWarn(const char *fmt, ...)
 
727
{
 
728
    va_list args;
 
729
 
 
730
    va_start(args, fmt);
 
731
    logger(DM_WARN, fmt, args);
 
732
    va_end(args);
 
733
}
 
734
#endif
 
735
 
 
736
#ifndef LOG_NO_ERROR
 
737
STATIC void
 
738
logError(const char *fmt, ...)
 
739
{
 
740
    va_list args;
 
741
 
 
742
    va_start(args, fmt);
 
743
    logger(DM_ERR, fmt, args);
 
744
    va_end(args);
 
745
}
 
746
#endif
 
747
 
 
748
#ifdef LOG_PANIC_EXIT
 
749
STATIC void
 
750
logPanic(const char *fmt, ...)
 
751
{
 
752
    va_list args;
 
753
 
 
754
    va_start(args, fmt);
 
755
    logger(DM_PANIC, fmt, args);
 
756
    va_end(args);
 
757
    exit(LOG_PANIC_EXIT);
 
758
}
 
759
#endif
 
760
 
 
761
#endif /* NO_LOGGER */
 
762
 
 
763
#ifdef NEED_FDPRINTF
 
764
 
 
765
typedef struct {
 
766
    char *buf;
 
767
    int clen, blen, tlen;
 
768
} OCFBuf;
 
769
 
 
770
static void
 
771
outCh_OCF(void *bp, char c)
 
772
{
 
773
    OCFBuf *ocfbp = (OCFBuf *)bp;
 
774
    char *nbuf;
 
775
    int nlen;
 
776
 
 
777
    ocfbp->tlen++;
 
778
    if (ocfbp->clen >= ocfbp->blen) {
 
779
        if (ocfbp->blen < 0)
 
780
            return;
 
781
        nlen = ocfbp->blen * 3 / 2 + 100;
 
782
        nbuf = Realloc(ocfbp->buf, nlen);
 
783
        if (!nbuf) {
 
784
            free(ocfbp->buf);
 
785
            ocfbp->blen = -1;
 
786
            ocfbp->buf = 0;
 
787
            ocfbp->clen = 0;
 
788
            return;
 
789
        }
 
790
        ocfbp->blen = nlen;
 
791
        ocfbp->buf = nbuf;
 
792
    }
 
793
    ocfbp->buf[ocfbp->clen++] = c;
 
794
}
 
795
 
 
796
STATIC int
 
797
FdPrintf(int fd, const char *fmt, ...)
 
798
{
 
799
    va_list args;
 
800
    OCFBuf ocfb = { 0, 0, 0, -1 };
 
801
 
 
802
    va_start(args, fmt);
 
803
    doPrint(outCh_OCF, &ocfb, fmt, args);
 
804
    va_end(args);
 
805
    if (ocfb.buf) {
 
806
        debug("FdPrintf %\".*s to %d\n", ocfb.clen, ocfb.buf, fd);
 
807
        (void)write(fd, ocfb.buf, ocfb.clen);
 
808
        free(ocfb.buf);
 
809
    }
 
810
    return ocfb.tlen;
 
811
}
 
812
 
 
813
#endif /* NEED_FDPRINTF */
 
814
 
 
815
#ifdef NEED_ASPRINTF
 
816
 
 
817
typedef struct {
 
818
    char *buf;
 
819
    int clen, blen, tlen;
 
820
} OCABuf;
 
821
 
 
822
static void
 
823
outCh_OCA(void *bp, char c)
 
824
{
 
825
    OCABuf *ocabp = (OCABuf *)bp;
 
826
    char *nbuf;
 
827
    int nlen;
 
828
 
 
829
    ocabp->tlen++;
 
830
    if (ocabp->clen >= ocabp->blen) {
 
831
        if (ocabp->blen < 0)
 
832
            return;
 
833
        nlen = ocabp->blen * 3 / 2 + 100;
 
834
        nbuf = Realloc(ocabp->buf, nlen);
 
835
        if (!nbuf) {
 
836
            free(ocabp->buf);
 
837
            ocabp->blen = -1;
 
838
            ocabp->buf = 0;
 
839
            ocabp->clen = 0;
 
840
            return;
 
841
        }
 
842
        ocabp->blen = nlen;
 
843
        ocabp->buf = nbuf;
 
844
    }
 
845
    ocabp->buf[ocabp->clen++] = c;
 
846
}
 
847
 
 
848
STATIC int
 
849
VASPrintf(char **strp, const char *fmt, va_list args)
 
850
{
 
851
    OCABuf ocab = { 0, 0, 0, -1 };
 
852
 
 
853
    doPrint(outCh_OCA, &ocab, fmt, args);
 
854
    outCh_OCA(&ocab, 0);
 
855
    *strp = Realloc(ocab.buf, ocab.clen);
 
856
    if (!*strp)
 
857
        *strp = ocab.buf;
 
858
    return ocab.tlen;
 
859
}
 
860
 
 
861
STATIC int
 
862
ASPrintf(char **strp, const char *fmt, ...)
 
863
{
 
864
    va_list args;
 
865
    int len;
 
866
 
 
867
    va_start(args, fmt);
 
868
    len = VASPrintf(strp, fmt, args);
 
869
    va_end(args);
 
870
    return len;
 
871
}
 
872
 
 
873
#endif /* NEED_ASPRINTF */