~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to os/log.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
Copyright 1987, 1998  The Open Group
 
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 OPEN GROUP 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 The Open Group 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 Open Group.
 
26
 
 
27
 
 
28
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
 
29
Copyright 1994 Quarterdeck Office Systems.
 
30
 
 
31
                        All Rights Reserved
 
32
 
 
33
Permission to use, copy, modify, and distribute this software and its
 
34
documentation for any purpose and without fee is hereby granted,
 
35
provided that the above copyright notice appear in all copies and that
 
36
both that copyright notice and this permission notice appear in
 
37
supporting documentation, and that the names of Digital and
 
38
Quarterdeck not be used in advertising or publicity pertaining to
 
39
distribution of the software without specific, written prior
 
40
permission.
 
41
 
 
42
DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
 
43
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 
44
FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
 
45
OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
 
46
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 
47
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
 
48
OR PERFORMANCE OF THIS SOFTWARE.
 
49
 
 
50
*/
 
51
 
 
52
/*
 
53
 * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
 
54
 *
 
55
 * Permission is hereby granted, free of charge, to any person obtaining a
 
56
 * copy of this software and associated documentation files (the "Software"),
 
57
 * to deal in the Software without restriction, including without limitation
 
58
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
59
 * and/or sell copies of the Software, and to permit persons to whom the
 
60
 * Software is furnished to do so, subject to the following conditions:
 
61
 *
 
62
 * The above copyright notice and this permission notice shall be included in
 
63
 * all copies or substantial portions of the Software.
 
64
 *
 
65
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
66
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
67
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
68
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 
69
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 
70
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 
71
 * OTHER DEALINGS IN THE SOFTWARE.
 
72
 *
 
73
 * Except as contained in this notice, the name of the copyright holder(s)
 
74
 * and author(s) shall not be used in advertising or otherwise to promote
 
75
 * the sale, use or other dealings in this Software without prior written
 
76
 * authorization from the copyright holder(s) and author(s).
 
77
 */
 
78
 
 
79
/* $XFree86: xc/programs/Xserver/os/log.c,v 1.6 2003/11/07 13:45:27 tsi Exp $ */
 
80
 
 
81
#ifdef HAVE_DIX_CONFIG_H
 
82
#include <dix-config.h>
 
83
#endif
 
84
 
 
85
#include <X11/Xos.h>
 
86
#include <stdio.h>
 
87
#include <time.h>
 
88
#include <sys/stat.h>
 
89
#include <stdarg.h>
 
90
#include <stdlib.h>     /* for malloc() */
 
91
#include <errno.h>
 
92
 
 
93
#include "site.h"
 
94
#include "opaque.h"
 
95
 
 
96
#ifdef WIN32
 
97
#include <process.h>
 
98
#define getpid(x) _getpid(x)
 
99
#endif
 
100
 
 
101
 
 
102
#ifdef DDXOSVERRORF
 
103
void (*OsVendorVErrorFProc)(const char *, va_list args) = NULL;
 
104
#endif
 
105
 
 
106
static FILE *logFile = NULL;
 
107
static Bool logFlush = FALSE;
 
108
static Bool logSync = FALSE;
 
109
static int logVerbosity = DEFAULT_LOG_VERBOSITY;
 
110
static int logFileVerbosity = DEFAULT_LOG_FILE_VERBOSITY;
 
111
 
 
112
/* Buffer to information logged before the log file is opened. */
 
113
static char *saveBuffer = NULL;
 
114
static int bufferSize = 0, bufferUnused = 0, bufferPos = 0;
 
115
static Bool needBuffer = TRUE;
 
116
 
 
117
/* Prefix strings for log messages. */
 
118
#ifndef X_UNKNOWN_STRING
 
119
#define X_UNKNOWN_STRING                "(\?\?)"
 
120
#endif
 
121
#ifndef X_PROBE_STRING
 
122
#define X_PROBE_STRING                  "(--)"
 
123
#endif
 
124
#ifndef X_CONFIG_STRING
 
125
#define X_CONFIG_STRING                 "(**)"
 
126
#endif
 
127
#ifndef X_DEFAULT_STRING
 
128
#define X_DEFAULT_STRING                "(==)"
 
129
#endif
 
130
#ifndef X_CMDLINE_STRING
 
131
#define X_CMDLINE_STRING                "(++)"
 
132
#endif
 
133
#ifndef X_NOTICE_STRING
 
134
#define X_NOTICE_STRING                 "(!!)"
 
135
#endif
 
136
#ifndef X_ERROR_STRING
 
137
#define X_ERROR_STRING                  "(EE)"
 
138
#endif
 
139
#ifndef X_WARNING_STRING
 
140
#define X_WARNING_STRING                "(WW)"
 
141
#endif
 
142
#ifndef X_INFO_STRING
 
143
#define X_INFO_STRING                   "(II)"
 
144
#endif
 
145
#ifndef X_NOT_IMPLEMENTED_STRING
 
146
#define X_NOT_IMPLEMENTED_STRING        "(NI)"
 
147
#endif
 
148
 
 
149
/*
 
150
 * LogInit is called to start logging to a file.  It is also called (with
 
151
 * NULL arguments) when logging to a file is not wanted.  It must always be
 
152
 * called, otherwise log messages will continue to accumulate in a buffer.
 
153
 *
 
154
 * %s, if present in the fname or backup strings, is expanded to the display
 
155
 * string.
 
156
 */
 
157
 
 
158
const char *
 
159
LogInit(const char *fname, const char *backup)
 
160
{
 
161
    char *logFileName = NULL;
 
162
 
 
163
    if (fname && *fname) {
 
164
        /* xalloc() can't be used yet. */
 
165
        logFileName = malloc(strlen(fname) + strlen(display) + 1);
 
166
        if (!logFileName)
 
167
            FatalError("Cannot allocate space for the log file name\n");
 
168
        sprintf(logFileName, fname, display);
 
169
 
 
170
        if (backup && *backup) {
 
171
            struct stat buf;
 
172
 
 
173
            if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) {
 
174
                char *suffix;
 
175
                char *oldLog;
 
176
 
 
177
                oldLog = malloc(strlen(logFileName) + strlen(backup) +
 
178
                                strlen(display) + 1);
 
179
                suffix = malloc(strlen(backup) + strlen(display) + 1);
 
180
                if (!oldLog || !suffix)
 
181
                    FatalError("Cannot allocate space for the log file name\n");
 
182
                sprintf(suffix, backup, display);
 
183
                sprintf(oldLog, "%s%s", logFileName, suffix);
 
184
                free(suffix);
 
185
#ifdef __UNIXOS2__
 
186
                remove(oldLog);
 
187
#endif
 
188
                if (rename(logFileName, oldLog) == -1) {
 
189
                    FatalError("Cannot move old log file (\"%s\" to \"%s\"\n",
 
190
                               logFileName, oldLog);
 
191
                }
 
192
                free(oldLog);
 
193
            }
 
194
        }
 
195
        if ((logFile = fopen(logFileName, "w")) == NULL)
 
196
            FatalError("Cannot open log file \"%s\"\n", logFileName);
 
197
        setvbuf(logFile, NULL, _IONBF, 0);
 
198
 
 
199
        /* Flush saved log information. */
 
200
        if (saveBuffer && bufferSize > 0) {
 
201
            fwrite(saveBuffer, bufferPos, 1, logFile);
 
202
            fflush(logFile);
 
203
#ifndef WIN32
 
204
            fsync(fileno(logFile));
 
205
#endif
 
206
        }
 
207
    }
 
208
 
 
209
    /*
 
210
     * Unconditionally free the buffer, and flag that the buffer is no longer
 
211
     * needed.
 
212
     */
 
213
    if (saveBuffer && bufferSize > 0) {
 
214
        free(saveBuffer);       /* Must be free(), not xfree() */
 
215
        saveBuffer = NULL;
 
216
        bufferSize = 0;
 
217
    }
 
218
    needBuffer = FALSE;
 
219
 
 
220
    return logFileName;
 
221
}
 
222
 
 
223
void
 
224
LogClose()
 
225
{
 
226
    if (logFile) {
 
227
        fclose(logFile);
 
228
        logFile = NULL;
 
229
    }
 
230
}
 
231
 
 
232
Bool
 
233
LogSetParameter(LogParameter param, int value)
 
234
{
 
235
    switch (param) {
 
236
    case XLOG_FLUSH:
 
237
        logFlush = value ? TRUE : FALSE;
 
238
        return TRUE;
 
239
    case XLOG_SYNC:
 
240
        logSync = value ? TRUE : FALSE;
 
241
        return TRUE;
 
242
    case XLOG_VERBOSITY:
 
243
        logVerbosity = value;
 
244
        return TRUE;
 
245
    case XLOG_FILE_VERBOSITY:
 
246
        logFileVerbosity = value;
 
247
        return TRUE;
 
248
    default:
 
249
        return FALSE;
 
250
    }
 
251
}
 
252
 
 
253
/* This function does the actual log message writes. */
 
254
 
 
255
void
 
256
LogVWrite(int verb, const char *f, va_list args)
 
257
{
 
258
    static char tmpBuffer[1024];
 
259
    int len = 0;
 
260
 
 
261
    /*
 
262
     * Since a va_list can only be processed once, write the string to a
 
263
     * buffer, and then write the buffer out to the appropriate output
 
264
     * stream(s).
 
265
     */
 
266
    if (verb < 0 || logFileVerbosity >= verb || logVerbosity >= verb) {
 
267
        vsnprintf(tmpBuffer, sizeof(tmpBuffer), f, args);
 
268
        len = strlen(tmpBuffer);
 
269
    }
 
270
    if ((verb < 0 || logVerbosity >= verb) && len > 0)
 
271
        fwrite(tmpBuffer, len, 1, stderr);
 
272
    if ((verb < 0 || logFileVerbosity >= verb) && len > 0) {
 
273
        if (logFile) {
 
274
            fwrite(tmpBuffer, len, 1, logFile);
 
275
            if (logFlush) {
 
276
                fflush(logFile);
 
277
#ifndef WIN32
 
278
                if (logSync)
 
279
                    fsync(fileno(logFile));
 
280
#endif
 
281
            }
 
282
        } else if (needBuffer) {
 
283
            /*
 
284
             * Note, this code is used before OsInit() has been called, so
 
285
             * xalloc() and friends can't be used.
 
286
             */
 
287
            if (len > bufferUnused) {
 
288
                bufferSize += 1024;
 
289
                bufferUnused += 1024;
 
290
                if (saveBuffer)
 
291
                    saveBuffer = realloc(saveBuffer, bufferSize);
 
292
                else
 
293
                    saveBuffer = malloc(bufferSize);
 
294
                if (!saveBuffer)
 
295
                    FatalError("realloc() failed while saving log messages\n");
 
296
            }
 
297
            bufferUnused -= len;
 
298
            memcpy(saveBuffer + bufferPos, tmpBuffer, len);
 
299
            bufferPos += len;
 
300
        }
 
301
    }
 
302
}
 
303
 
 
304
void
 
305
LogWrite(int verb, const char *f, ...)
 
306
{
 
307
    va_list args;
 
308
 
 
309
    va_start(args, f);
 
310
    LogVWrite(verb, f, args);
 
311
    va_end(args);
 
312
}
 
313
 
 
314
void
 
315
LogVMessageVerb(MessageType type, int verb, const char *format, va_list args)
 
316
{
 
317
    const char *s  = X_UNKNOWN_STRING;
 
318
    char *tmpBuf = NULL;
 
319
 
 
320
    /* Ignore verbosity for X_ERROR */
 
321
    if (logVerbosity >= verb || logFileVerbosity >= verb || type == X_ERROR) {
 
322
        switch (type) {
 
323
        case X_PROBED:
 
324
            s = X_PROBE_STRING;
 
325
            break;
 
326
        case X_CONFIG:
 
327
            s = X_CONFIG_STRING;
 
328
            break;
 
329
        case X_DEFAULT:
 
330
            s = X_DEFAULT_STRING;
 
331
            break;
 
332
        case X_CMDLINE:
 
333
            s = X_CMDLINE_STRING;
 
334
            break;
 
335
        case X_NOTICE:
 
336
            s = X_NOTICE_STRING;
 
337
            break;
 
338
        case X_ERROR:
 
339
            s = X_ERROR_STRING;
 
340
            if (verb > 0)
 
341
                verb = 0;
 
342
            break;
 
343
        case X_WARNING:
 
344
            s = X_WARNING_STRING;
 
345
            break;
 
346
        case X_INFO:
 
347
            s = X_INFO_STRING;
 
348
            break;
 
349
        case X_NOT_IMPLEMENTED:
 
350
            s = X_NOT_IMPLEMENTED_STRING;
 
351
            break;
 
352
        case X_UNKNOWN:
 
353
            s = X_UNKNOWN_STRING;
 
354
            break;
 
355
        case X_NONE:
 
356
            s = NULL;
 
357
            break;
 
358
        }
 
359
 
 
360
        /*
 
361
         * Prefix the format string with the message type.  We do it this way
 
362
         * so that LogVWrite() is only called once per message.
 
363
         */
 
364
        if (s) {
 
365
            tmpBuf = malloc(strlen(format) + strlen(s) + 1 + 1);
 
366
            /* Silently return if malloc fails here. */
 
367
            if (!tmpBuf)
 
368
                return;
 
369
            sprintf(tmpBuf, "%s ", s);
 
370
            strcat(tmpBuf, format);
 
371
            LogVWrite(verb, tmpBuf, args);
 
372
            free(tmpBuf);
 
373
        } else
 
374
            LogVWrite(verb, format, args);
 
375
    }
 
376
}
 
377
 
 
378
/* Log message with verbosity level specified. */
 
379
void
 
380
LogMessageVerb(MessageType type, int verb, const char *format, ...)
 
381
{
 
382
    va_list ap;
 
383
 
 
384
    va_start(ap, format);
 
385
    LogVMessageVerb(type, verb, format, ap);
 
386
    va_end(ap);
 
387
}
 
388
 
 
389
/* Log a message with the standard verbosity level of 1. */
 
390
void
 
391
LogMessage(MessageType type, const char *format, ...)
 
392
{
 
393
    va_list ap;
 
394
 
 
395
    va_start(ap, format);
 
396
    LogVMessageVerb(type, 1, format, ap);
 
397
    va_end(ap);
 
398
}
 
399
 
 
400
#ifdef __GNUC__
 
401
void AbortServer(void) __attribute__((noreturn));
 
402
#endif
 
403
 
 
404
void
 
405
AbortServer(void)
 
406
{
 
407
    OsCleanup(TRUE);
 
408
    AbortDDX();
 
409
    fflush(stderr);
 
410
    if (CoreDump)
 
411
        abort();
 
412
    exit (1);
 
413
}
 
414
 
 
415
#ifndef AUDIT_PREFIX
 
416
#define AUDIT_PREFIX "AUDIT: %s: %ld %s: "
 
417
#endif
 
418
#ifndef AUDIT_TIMEOUT
 
419
#define AUDIT_TIMEOUT ((CARD32)(120 * 1000)) /* 2 mn */
 
420
#endif
 
421
 
 
422
static int nrepeat = 0;
 
423
static int oldlen = -1;
 
424
static OsTimerPtr auditTimer = NULL;
 
425
 
 
426
void 
 
427
FreeAuditTimer(void)
 
428
{
 
429
    if (auditTimer != NULL) {
 
430
        /* Force output of pending messages */
 
431
        TimerForce(auditTimer);
 
432
        TimerFree(auditTimer);
 
433
        auditTimer = NULL;
 
434
    }
 
435
}
 
436
 
 
437
static char *
 
438
AuditPrefix(void)
 
439
{
 
440
    time_t tm;
 
441
    char *autime, *s;
 
442
    char *tmpBuf;
 
443
    int len;
 
444
 
 
445
    time(&tm);
 
446
    autime = ctime(&tm);
 
447
    if ((s = strchr(autime, '\n')))
 
448
        *s = '\0';
 
449
    if ((s = strrchr(argvGlobal[0], '/')))
 
450
        s++;
 
451
    else
 
452
        s = argvGlobal[0];
 
453
    len = strlen(AUDIT_PREFIX) + strlen(autime) + 10 + strlen(s) + 1;
 
454
    tmpBuf = malloc(len);
 
455
    if (!tmpBuf)
 
456
        return NULL;
 
457
    snprintf(tmpBuf, len, AUDIT_PREFIX, autime, (unsigned long)getpid(), s);
 
458
    return tmpBuf;
 
459
}
 
460
 
 
461
void
 
462
AuditF(const char * f, ...)
 
463
{
 
464
    va_list args;
 
465
 
 
466
    va_start(args, f);
 
467
 
 
468
    VAuditF(f, args);
 
469
    va_end(args);
 
470
}
 
471
 
 
472
static CARD32
 
473
AuditFlush(OsTimerPtr timer, CARD32 now, pointer arg)
 
474
{
 
475
    char *prefix;
 
476
 
 
477
    if (nrepeat > 0) {
 
478
        prefix = AuditPrefix();
 
479
        ErrorF("%slast message repeated %d times\n",
 
480
               prefix != NULL ? prefix : "", nrepeat);
 
481
        nrepeat = 0;
 
482
        if (prefix != NULL)
 
483
            free(prefix);
 
484
        return AUDIT_TIMEOUT;
 
485
    } else {
 
486
        /* if the timer expires without anything to print, flush the message */
 
487
        oldlen = -1;
 
488
        return 0;
 
489
    }
 
490
}
 
491
 
 
492
void
 
493
VAuditF(const char *f, va_list args)
 
494
{
 
495
    char *prefix;
 
496
    char buf[1024];
 
497
    int len;
 
498
    static char oldbuf[1024];
 
499
 
 
500
    prefix = AuditPrefix();
 
501
    len = vsnprintf(buf, sizeof(buf), f, args);
 
502
 
 
503
#if 1
 
504
    /* XXX Compressing duplicated messages is temporarily disabled to
 
505
     * work around bugzilla 964:
 
506
     *     https://freedesktop.org/bugzilla/show_bug.cgi?id=964
 
507
     */
 
508
    ErrorF("%s%s", prefix != NULL ? prefix : "", buf);
 
509
    oldlen = -1;
 
510
    nrepeat = 0;
 
511
#else
 
512
    if (len == oldlen && strcmp(buf, oldbuf) == 0) {
 
513
        /* Message already seen */
 
514
        nrepeat++;
 
515
    } else {
 
516
        /* new message */
 
517
        if (auditTimer != NULL)
 
518
            TimerForce(auditTimer);
 
519
        ErrorF("%s%s", prefix != NULL ? prefix : "", buf);
 
520
        strlcpy(oldbuf, buf, sizeof(oldbuf));
 
521
        oldlen = len;
 
522
        nrepeat = 0;
 
523
        auditTimer = TimerSet(auditTimer, 0, AUDIT_TIMEOUT, AuditFlush, NULL);
 
524
    }
 
525
#endif
 
526
    if (prefix != NULL)
 
527
        free(prefix);
 
528
}
 
529
 
 
530
void
 
531
FatalError(const char *f, ...)
 
532
{
 
533
    va_list args;
 
534
    static Bool beenhere = FALSE;
 
535
 
 
536
    if (beenhere)
 
537
        ErrorF("\nFatalError re-entered, aborting\n");
 
538
    else
 
539
        ErrorF("\nFatal server error:\n");
 
540
 
 
541
    va_start(args, f);
 
542
    VErrorF(f, args);
 
543
    va_end(args);
 
544
    ErrorF("\n");
 
545
#ifdef DDXOSFATALERROR
 
546
    if (!beenhere)
 
547
        OsVendorFatalError();
 
548
#endif
 
549
#ifdef ABORTONFATALERROR
 
550
    abort();
 
551
#endif
 
552
    if (!beenhere) {
 
553
        beenhere = TRUE;
 
554
        AbortServer();
 
555
    } else
 
556
        abort();
 
557
    /*NOTREACHED*/
 
558
}
 
559
 
 
560
void
 
561
VErrorF(const char *f, va_list args)
 
562
{
 
563
#ifdef DDXOSVERRORF
 
564
    if (OsVendorVErrorFProc)
 
565
        OsVendorVErrorFProc(f, args);
 
566
    else
 
567
        LogVWrite(-1, f, args);
 
568
#else
 
569
    LogVWrite(-1, f, args);
 
570
#endif
 
571
}
 
572
 
 
573
void
 
574
ErrorF(const char * f, ...)
 
575
{
 
576
    va_list args;
 
577
 
 
578
    va_start(args, f);
 
579
    VErrorF(f, args);
 
580
    va_end(args);
 
581
}
 
582
 
 
583
/* A perror() workalike. */
 
584
 
 
585
#ifndef NEED_STRERROR
 
586
#ifdef SYSV
 
587
#if !defined(ISC) || defined(ISC202) || defined(ISC22)
 
588
#define NEED_STRERROR
 
589
#endif
 
590
#endif
 
591
#endif
 
592
 
 
593
#if defined(NEED_STRERROR) && !defined(strerror)
 
594
extern char *sys_errlist[];
 
595
extern int sys_nerr;
 
596
#define strerror(n) \
 
597
        ((n) >= 0 && (n) < sys_nerr) ? sys_errlist[(n)] : "unknown error"
 
598
#endif
 
599
 
 
600
void
 
601
Error(char *str)
 
602
{
 
603
    char *err = NULL;
 
604
    int saveErrno = errno;
 
605
 
 
606
    if (str) {
 
607
        err = malloc(strlen(strerror(saveErrno)) + strlen(str) + 2 + 1);
 
608
        if (!err)
 
609
            return;
 
610
        sprintf(err, "%s: ", str);
 
611
        strcat(err, strerror(saveErrno));
 
612
        LogWrite(-1, err);
 
613
    } else
 
614
        LogWrite(-1, strerror(saveErrno));
 
615
}
 
616
 
 
617
void
 
618
LogPrintMarkers()
 
619
{
 
620
    /* Show what the message marker symbols mean. */
 
621
    ErrorF("Markers: ");
 
622
    LogMessageVerb(X_PROBED, -1, "probed, ");
 
623
    LogMessageVerb(X_CONFIG, -1, "from config file, ");
 
624
    LogMessageVerb(X_DEFAULT, -1, "default setting,\n\t");
 
625
    LogMessageVerb(X_CMDLINE, -1, "from command line, ");
 
626
    LogMessageVerb(X_NOTICE, -1, "notice, ");
 
627
    LogMessageVerb(X_INFO, -1, "informational,\n\t");
 
628
    LogMessageVerb(X_WARNING, -1, "warning, ");
 
629
    LogMessageVerb(X_ERROR, -1, "error, ");
 
630
    LogMessageVerb(X_NOT_IMPLEMENTED, -1, "not implemented, ");
 
631
    LogMessageVerb(X_UNKNOWN, -1, "unknown.\n");
 
632
}
 
633