3
Copyright 1987, 1998 The Open Group
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
11
The above copyright notice and this permission notice shall be included
12
in all copies or substantial portions of the Software.
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.
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
28
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
29
Copyright 1994 Quarterdeck Office Systems.
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
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.
53
* Copyright (c) 1997-2003 by The XFree86 Project, Inc.
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:
62
* The above copyright notice and this permission notice shall be included in
63
* all copies or substantial portions of the Software.
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.
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).
79
/* $XFree86: xc/programs/Xserver/os/log.c,v 1.6 2003/11/07 13:45:27 tsi Exp $ */
81
#ifdef HAVE_DIX_CONFIG_H
82
#include <dix-config.h>
90
#include <stdlib.h> /* for malloc() */
98
#define getpid(x) _getpid(x)
103
void (*OsVendorVErrorFProc)(const char *, va_list args) = NULL;
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;
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;
117
/* Prefix strings for log messages. */
118
#ifndef X_UNKNOWN_STRING
119
#define X_UNKNOWN_STRING "(\?\?)"
121
#ifndef X_PROBE_STRING
122
#define X_PROBE_STRING "(--)"
124
#ifndef X_CONFIG_STRING
125
#define X_CONFIG_STRING "(**)"
127
#ifndef X_DEFAULT_STRING
128
#define X_DEFAULT_STRING "(==)"
130
#ifndef X_CMDLINE_STRING
131
#define X_CMDLINE_STRING "(++)"
133
#ifndef X_NOTICE_STRING
134
#define X_NOTICE_STRING "(!!)"
136
#ifndef X_ERROR_STRING
137
#define X_ERROR_STRING "(EE)"
139
#ifndef X_WARNING_STRING
140
#define X_WARNING_STRING "(WW)"
142
#ifndef X_INFO_STRING
143
#define X_INFO_STRING "(II)"
145
#ifndef X_NOT_IMPLEMENTED_STRING
146
#define X_NOT_IMPLEMENTED_STRING "(NI)"
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.
154
* %s, if present in the fname or backup strings, is expanded to the display
159
LogInit(const char *fname, const char *backup)
161
char *logFileName = NULL;
163
if (fname && *fname) {
164
/* xalloc() can't be used yet. */
165
logFileName = malloc(strlen(fname) + strlen(display) + 1);
167
FatalError("Cannot allocate space for the log file name\n");
168
sprintf(logFileName, fname, display);
170
if (backup && *backup) {
173
if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) {
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);
188
if (rename(logFileName, oldLog) == -1) {
189
FatalError("Cannot move old log file (\"%s\" to \"%s\"\n",
190
logFileName, oldLog);
195
if ((logFile = fopen(logFileName, "w")) == NULL)
196
FatalError("Cannot open log file \"%s\"\n", logFileName);
197
setvbuf(logFile, NULL, _IONBF, 0);
199
/* Flush saved log information. */
200
if (saveBuffer && bufferSize > 0) {
201
fwrite(saveBuffer, bufferPos, 1, logFile);
204
fsync(fileno(logFile));
210
* Unconditionally free the buffer, and flag that the buffer is no longer
213
if (saveBuffer && bufferSize > 0) {
214
free(saveBuffer); /* Must be free(), not xfree() */
233
LogSetParameter(LogParameter param, int value)
237
logFlush = value ? TRUE : FALSE;
240
logSync = value ? TRUE : FALSE;
243
logVerbosity = value;
245
case XLOG_FILE_VERBOSITY:
246
logFileVerbosity = value;
253
/* This function does the actual log message writes. */
256
LogVWrite(int verb, const char *f, va_list args)
258
static char tmpBuffer[1024];
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
266
if (verb < 0 || logFileVerbosity >= verb || logVerbosity >= verb) {
267
vsnprintf(tmpBuffer, sizeof(tmpBuffer), f, args);
268
len = strlen(tmpBuffer);
270
if ((verb < 0 || logVerbosity >= verb) && len > 0)
271
fwrite(tmpBuffer, len, 1, stderr);
272
if ((verb < 0 || logFileVerbosity >= verb) && len > 0) {
274
fwrite(tmpBuffer, len, 1, logFile);
279
fsync(fileno(logFile));
282
} else if (needBuffer) {
284
* Note, this code is used before OsInit() has been called, so
285
* xalloc() and friends can't be used.
287
if (len > bufferUnused) {
289
bufferUnused += 1024;
291
saveBuffer = realloc(saveBuffer, bufferSize);
293
saveBuffer = malloc(bufferSize);
295
FatalError("realloc() failed while saving log messages\n");
298
memcpy(saveBuffer + bufferPos, tmpBuffer, len);
305
LogWrite(int verb, const char *f, ...)
310
LogVWrite(verb, f, args);
315
LogVMessageVerb(MessageType type, int verb, const char *format, va_list args)
317
const char *s = X_UNKNOWN_STRING;
320
/* Ignore verbosity for X_ERROR */
321
if (logVerbosity >= verb || logFileVerbosity >= verb || type == X_ERROR) {
330
s = X_DEFAULT_STRING;
333
s = X_CMDLINE_STRING;
344
s = X_WARNING_STRING;
349
case X_NOT_IMPLEMENTED:
350
s = X_NOT_IMPLEMENTED_STRING;
353
s = X_UNKNOWN_STRING;
361
* Prefix the format string with the message type. We do it this way
362
* so that LogVWrite() is only called once per message.
365
tmpBuf = malloc(strlen(format) + strlen(s) + 1 + 1);
366
/* Silently return if malloc fails here. */
369
sprintf(tmpBuf, "%s ", s);
370
strcat(tmpBuf, format);
371
LogVWrite(verb, tmpBuf, args);
374
LogVWrite(verb, format, args);
378
/* Log message with verbosity level specified. */
380
LogMessageVerb(MessageType type, int verb, const char *format, ...)
384
va_start(ap, format);
385
LogVMessageVerb(type, verb, format, ap);
389
/* Log a message with the standard verbosity level of 1. */
391
LogMessage(MessageType type, const char *format, ...)
395
va_start(ap, format);
396
LogVMessageVerb(type, 1, format, ap);
401
void AbortServer(void) __attribute__((noreturn));
416
#define AUDIT_PREFIX "AUDIT: %s: %ld %s: "
418
#ifndef AUDIT_TIMEOUT
419
#define AUDIT_TIMEOUT ((CARD32)(120 * 1000)) /* 2 mn */
422
static int nrepeat = 0;
423
static int oldlen = -1;
424
static OsTimerPtr auditTimer = NULL;
429
if (auditTimer != NULL) {
430
/* Force output of pending messages */
431
TimerForce(auditTimer);
432
TimerFree(auditTimer);
447
if ((s = strchr(autime, '\n')))
449
if ((s = strrchr(argvGlobal[0], '/')))
453
len = strlen(AUDIT_PREFIX) + strlen(autime) + 10 + strlen(s) + 1;
454
tmpBuf = malloc(len);
457
snprintf(tmpBuf, len, AUDIT_PREFIX, autime, (unsigned long)getpid(), s);
462
AuditF(const char * f, ...)
473
AuditFlush(OsTimerPtr timer, CARD32 now, pointer arg)
478
prefix = AuditPrefix();
479
ErrorF("%slast message repeated %d times\n",
480
prefix != NULL ? prefix : "", nrepeat);
484
return AUDIT_TIMEOUT;
486
/* if the timer expires without anything to print, flush the message */
493
VAuditF(const char *f, va_list args)
498
static char oldbuf[1024];
500
prefix = AuditPrefix();
501
len = vsnprintf(buf, sizeof(buf), f, args);
504
/* XXX Compressing duplicated messages is temporarily disabled to
505
* work around bugzilla 964:
506
* https://freedesktop.org/bugzilla/show_bug.cgi?id=964
508
ErrorF("%s%s", prefix != NULL ? prefix : "", buf);
512
if (len == oldlen && strcmp(buf, oldbuf) == 0) {
513
/* Message already seen */
517
if (auditTimer != NULL)
518
TimerForce(auditTimer);
519
ErrorF("%s%s", prefix != NULL ? prefix : "", buf);
520
strlcpy(oldbuf, buf, sizeof(oldbuf));
523
auditTimer = TimerSet(auditTimer, 0, AUDIT_TIMEOUT, AuditFlush, NULL);
531
FatalError(const char *f, ...)
534
static Bool beenhere = FALSE;
537
ErrorF("\nFatalError re-entered, aborting\n");
539
ErrorF("\nFatal server error:\n");
545
#ifdef DDXOSFATALERROR
547
OsVendorFatalError();
549
#ifdef ABORTONFATALERROR
561
VErrorF(const char *f, va_list args)
564
if (OsVendorVErrorFProc)
565
OsVendorVErrorFProc(f, args);
567
LogVWrite(-1, f, args);
569
LogVWrite(-1, f, args);
574
ErrorF(const char * f, ...)
583
/* A perror() workalike. */
585
#ifndef NEED_STRERROR
587
#if !defined(ISC) || defined(ISC202) || defined(ISC22)
588
#define NEED_STRERROR
593
#if defined(NEED_STRERROR) && !defined(strerror)
594
extern char *sys_errlist[];
596
#define strerror(n) \
597
((n) >= 0 && (n) < sys_nerr) ? sys_errlist[(n)] : "unknown error"
604
int saveErrno = errno;
607
err = malloc(strlen(strerror(saveErrno)) + strlen(str) + 2 + 1);
610
sprintf(err, "%s: ", str);
611
strcat(err, strerror(saveErrno));
614
LogWrite(-1, strerror(saveErrno));
620
/* Show what the message marker symbols mean. */
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");