log.c revision 9ace9065
105b261ecSmrg/*
205b261ecSmrg
305b261ecSmrgCopyright 1987, 1998  The Open Group
405b261ecSmrg
505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its
605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that
705b261ecSmrgthe above copyright notice appear in all copies and that both that
805b261ecSmrgcopyright notice and this permission notice appear in supporting
905b261ecSmrgdocumentation.
1005b261ecSmrg
1105b261ecSmrgThe above copyright notice and this permission notice shall be included
1205b261ecSmrgin all copies or substantial portions of the Software.
1305b261ecSmrg
1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1505b261ecSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1605b261ecSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1705b261ecSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
1805b261ecSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1905b261ecSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2005b261ecSmrgOTHER DEALINGS IN THE SOFTWARE.
2105b261ecSmrg
2205b261ecSmrgExcept as contained in this notice, the name of The Open Group shall
2305b261ecSmrgnot be used in advertising or otherwise to promote the sale, use or
2405b261ecSmrgother dealings in this Software without prior written authorization
2505b261ecSmrgfrom The Open Group.
2605b261ecSmrg
2705b261ecSmrg
2805b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
2905b261ecSmrgCopyright 1994 Quarterdeck Office Systems.
3005b261ecSmrg
3105b261ecSmrg                        All Rights Reserved
3205b261ecSmrg
3305b261ecSmrgPermission to use, copy, modify, and distribute this software and its
3405b261ecSmrgdocumentation for any purpose and without fee is hereby granted,
3505b261ecSmrgprovided that the above copyright notice appear in all copies and that
3605b261ecSmrgboth that copyright notice and this permission notice appear in
3705b261ecSmrgsupporting documentation, and that the names of Digital and
3805b261ecSmrgQuarterdeck not be used in advertising or publicity pertaining to
3905b261ecSmrgdistribution of the software without specific, written prior
4005b261ecSmrgpermission.
4105b261ecSmrg
4205b261ecSmrgDIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
4305b261ecSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
4405b261ecSmrgFITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
4505b261ecSmrgOR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
4605b261ecSmrgOF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
4705b261ecSmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
4805b261ecSmrgOR PERFORMANCE OF THIS SOFTWARE.
4905b261ecSmrg
5005b261ecSmrg*/
5105b261ecSmrg
5205b261ecSmrg/*
5305b261ecSmrg * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
5405b261ecSmrg *
5505b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a
5605b261ecSmrg * copy of this software and associated documentation files (the "Software"),
5705b261ecSmrg * to deal in the Software without restriction, including without limitation
5805b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
5905b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the
6005b261ecSmrg * Software is furnished to do so, subject to the following conditions:
6105b261ecSmrg *
6205b261ecSmrg * The above copyright notice and this permission notice shall be included in
6305b261ecSmrg * all copies or substantial portions of the Software.
6405b261ecSmrg *
6505b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6605b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6705b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
6805b261ecSmrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
6905b261ecSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
7005b261ecSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
7105b261ecSmrg * OTHER DEALINGS IN THE SOFTWARE.
7205b261ecSmrg *
7305b261ecSmrg * Except as contained in this notice, the name of the copyright holder(s)
7405b261ecSmrg * and author(s) shall not be used in advertising or otherwise to promote
7505b261ecSmrg * the sale, use or other dealings in this Software without prior written
7605b261ecSmrg * authorization from the copyright holder(s) and author(s).
7705b261ecSmrg */
7805b261ecSmrg
7905b261ecSmrg
8005b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
8105b261ecSmrg#include <dix-config.h>
8205b261ecSmrg#endif
8305b261ecSmrg
8405b261ecSmrg#include <X11/Xos.h>
8505b261ecSmrg#include <stdio.h>
8605b261ecSmrg#include <time.h>
8705b261ecSmrg#include <sys/stat.h>
8805b261ecSmrg#include <stdarg.h>
8905b261ecSmrg#include <stdlib.h>	/* for malloc() */
9005b261ecSmrg#include <errno.h>
9105b261ecSmrg
9205b261ecSmrg#include "input.h"
9305b261ecSmrg#include "site.h"
9405b261ecSmrg#include "opaque.h"
9505b261ecSmrg
9605b261ecSmrg#ifdef WIN32
9705b261ecSmrg#include <process.h>
9805b261ecSmrg#define getpid(x) _getpid(x)
9905b261ecSmrg#endif
10005b261ecSmrg
1016747b715Smrg#ifdef XF86BIGFONT
1026747b715Smrg#include "xf86bigfontsrv.h"
1036747b715Smrg#endif
10405b261ecSmrg
1059ace9065Smrg#ifdef __clang__
1069ace9065Smrg#pragma clang diagnostic ignored "-Wformat-nonliteral"
1079ace9065Smrg#endif
1089ace9065Smrg
10905b261ecSmrg#ifdef DDXOSVERRORF
11005b261ecSmrgvoid (*OsVendorVErrorFProc)(const char *, va_list args) = NULL;
11105b261ecSmrg#endif
11205b261ecSmrg
11305b261ecSmrgstatic FILE *logFile = NULL;
11405b261ecSmrgstatic Bool logFlush = FALSE;
11505b261ecSmrgstatic Bool logSync = FALSE;
11605b261ecSmrgstatic int logVerbosity = DEFAULT_LOG_VERBOSITY;
11705b261ecSmrgstatic int logFileVerbosity = DEFAULT_LOG_FILE_VERBOSITY;
11805b261ecSmrg
11905b261ecSmrg/* Buffer to information logged before the log file is opened. */
12005b261ecSmrgstatic char *saveBuffer = NULL;
12105b261ecSmrgstatic int bufferSize = 0, bufferUnused = 0, bufferPos = 0;
12205b261ecSmrgstatic Bool needBuffer = TRUE;
12305b261ecSmrg
1246747b715Smrg#ifdef __APPLE__
1256747b715Smrg#include <AvailabilityMacros.h>
1266747b715Smrg
1276747b715Smrgstatic char __crashreporter_info_buff__[4096] = {0};
1288223e2f2Smrgstatic const char *__crashreporter_info__ __attribute__((__used__)) = &__crashreporter_info_buff__[0];
1296747b715Smrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
1306747b715Smrg// This is actually a toolchain requirement, but I'm not sure the correct check,
1316747b715Smrg// but it should be fine to just only include it for Leopard and later.  This line
1326747b715Smrg// just tells the linker to never strip this symbol (such as for space optimization)
1336747b715Smrgasm (".desc ___crashreporter_info__, 0x10");
1346747b715Smrg#endif
1356747b715Smrg#endif
1366747b715Smrg
13705b261ecSmrg/* Prefix strings for log messages. */
13805b261ecSmrg#ifndef X_UNKNOWN_STRING
13905b261ecSmrg#define X_UNKNOWN_STRING		"(\?\?)"
14005b261ecSmrg#endif
14105b261ecSmrg#ifndef X_PROBE_STRING
14205b261ecSmrg#define X_PROBE_STRING			"(--)"
14305b261ecSmrg#endif
14405b261ecSmrg#ifndef X_CONFIG_STRING
14505b261ecSmrg#define X_CONFIG_STRING			"(**)"
14605b261ecSmrg#endif
14705b261ecSmrg#ifndef X_DEFAULT_STRING
14805b261ecSmrg#define X_DEFAULT_STRING		"(==)"
14905b261ecSmrg#endif
15005b261ecSmrg#ifndef X_CMDLINE_STRING
15105b261ecSmrg#define X_CMDLINE_STRING		"(++)"
15205b261ecSmrg#endif
15305b261ecSmrg#ifndef X_NOTICE_STRING
15405b261ecSmrg#define X_NOTICE_STRING			"(!!)"
15505b261ecSmrg#endif
15605b261ecSmrg#ifndef X_ERROR_STRING
15705b261ecSmrg#define X_ERROR_STRING			"(EE)"
15805b261ecSmrg#endif
15905b261ecSmrg#ifndef X_WARNING_STRING
16005b261ecSmrg#define X_WARNING_STRING		"(WW)"
16105b261ecSmrg#endif
16205b261ecSmrg#ifndef X_INFO_STRING
16305b261ecSmrg#define X_INFO_STRING			"(II)"
16405b261ecSmrg#endif
16505b261ecSmrg#ifndef X_NOT_IMPLEMENTED_STRING
16605b261ecSmrg#define X_NOT_IMPLEMENTED_STRING	"(NI)"
16705b261ecSmrg#endif
16805b261ecSmrg
16905b261ecSmrg/*
17005b261ecSmrg * LogInit is called to start logging to a file.  It is also called (with
17105b261ecSmrg * NULL arguments) when logging to a file is not wanted.  It must always be
17205b261ecSmrg * called, otherwise log messages will continue to accumulate in a buffer.
17305b261ecSmrg *
17405b261ecSmrg * %s, if present in the fname or backup strings, is expanded to the display
17505b261ecSmrg * string.
17605b261ecSmrg */
17705b261ecSmrg
17805b261ecSmrgconst char *
17905b261ecSmrgLogInit(const char *fname, const char *backup)
18005b261ecSmrg{
18105b261ecSmrg    char *logFileName = NULL;
18205b261ecSmrg
18305b261ecSmrg    if (fname && *fname) {
1849ace9065Smrg	if (asprintf(&logFileName, fname, display) == -1)
18505b261ecSmrg	    FatalError("Cannot allocate space for the log file name\n");
18605b261ecSmrg
18705b261ecSmrg	if (backup && *backup) {
18805b261ecSmrg	    struct stat buf;
18905b261ecSmrg
19005b261ecSmrg	    if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) {
19105b261ecSmrg		char *suffix;
19205b261ecSmrg		char *oldLog;
19305b261ecSmrg
1949ace9065Smrg		if ((asprintf(&suffix, backup, display) == -1) ||
1959ace9065Smrg		    (asprintf(&oldLog, "%s%s", logFileName, suffix) == -1))
19605b261ecSmrg		    FatalError("Cannot allocate space for the log file name\n");
19705b261ecSmrg		free(suffix);
19805b261ecSmrg		if (rename(logFileName, oldLog) == -1) {
1996747b715Smrg		    FatalError("Cannot move old log file \"%s\" to \"%s\"\n",
20005b261ecSmrg			       logFileName, oldLog);
20105b261ecSmrg		}
20205b261ecSmrg		free(oldLog);
20305b261ecSmrg	    }
20405b261ecSmrg	}
20505b261ecSmrg	if ((logFile = fopen(logFileName, "w")) == NULL)
20605b261ecSmrg	    FatalError("Cannot open log file \"%s\"\n", logFileName);
20705b261ecSmrg	setvbuf(logFile, NULL, _IONBF, 0);
20805b261ecSmrg
20905b261ecSmrg	/* Flush saved log information. */
21005b261ecSmrg	if (saveBuffer && bufferSize > 0) {
21105b261ecSmrg	    fwrite(saveBuffer, bufferPos, 1, logFile);
21205b261ecSmrg	    fflush(logFile);
21305b261ecSmrg#ifndef WIN32
21405b261ecSmrg	    fsync(fileno(logFile));
21505b261ecSmrg#endif
21605b261ecSmrg	}
21705b261ecSmrg    }
21805b261ecSmrg
21905b261ecSmrg    /*
22005b261ecSmrg     * Unconditionally free the buffer, and flag that the buffer is no longer
22105b261ecSmrg     * needed.
22205b261ecSmrg     */
22305b261ecSmrg    if (saveBuffer && bufferSize > 0) {
2246747b715Smrg	free(saveBuffer);	/* Must be free(), not free() */
22505b261ecSmrg	saveBuffer = NULL;
22605b261ecSmrg	bufferSize = 0;
22705b261ecSmrg    }
22805b261ecSmrg    needBuffer = FALSE;
22905b261ecSmrg
23005b261ecSmrg    return logFileName;
23105b261ecSmrg}
23205b261ecSmrg
23305b261ecSmrgvoid
23405b261ecSmrgLogClose(void)
23505b261ecSmrg{
23605b261ecSmrg    if (logFile) {
23705b261ecSmrg	fclose(logFile);
23805b261ecSmrg	logFile = NULL;
23905b261ecSmrg    }
24005b261ecSmrg}
24105b261ecSmrg
24205b261ecSmrgBool
24305b261ecSmrgLogSetParameter(LogParameter param, int value)
24405b261ecSmrg{
24505b261ecSmrg    switch (param) {
24605b261ecSmrg    case XLOG_FLUSH:
24705b261ecSmrg	logFlush = value ? TRUE : FALSE;
24805b261ecSmrg	return TRUE;
24905b261ecSmrg    case XLOG_SYNC:
25005b261ecSmrg	logSync = value ? TRUE : FALSE;
25105b261ecSmrg	return TRUE;
25205b261ecSmrg    case XLOG_VERBOSITY:
25305b261ecSmrg	logVerbosity = value;
25405b261ecSmrg	return TRUE;
25505b261ecSmrg    case XLOG_FILE_VERBOSITY:
25605b261ecSmrg	logFileVerbosity = value;
25705b261ecSmrg	return TRUE;
25805b261ecSmrg    default:
25905b261ecSmrg	return FALSE;
26005b261ecSmrg    }
26105b261ecSmrg}
26205b261ecSmrg
26305b261ecSmrg/* This function does the actual log message writes. */
26405b261ecSmrg
2656747b715Smrgvoid
26605b261ecSmrgLogVWrite(int verb, const char *f, va_list args)
26705b261ecSmrg{
26805b261ecSmrg    static char tmpBuffer[1024];
26905b261ecSmrg    int len = 0;
2706747b715Smrg    static Bool newline = TRUE;
2716747b715Smrg
2726747b715Smrg    if (newline) {
2736747b715Smrg	sprintf(tmpBuffer, "[%10.3f] ", GetTimeInMillis() / 1000.0);
2746747b715Smrg	len = strlen(tmpBuffer);
2756747b715Smrg	if (logFile)
2766747b715Smrg	    fwrite(tmpBuffer, len, 1, logFile);
2776747b715Smrg    }
27805b261ecSmrg
27905b261ecSmrg    /*
28005b261ecSmrg     * Since a va_list can only be processed once, write the string to a
28105b261ecSmrg     * buffer, and then write the buffer out to the appropriate output
28205b261ecSmrg     * stream(s).
28305b261ecSmrg     */
28405b261ecSmrg    if (verb < 0 || logFileVerbosity >= verb || logVerbosity >= verb) {
28505b261ecSmrg	vsnprintf(tmpBuffer, sizeof(tmpBuffer), f, args);
28605b261ecSmrg	len = strlen(tmpBuffer);
28705b261ecSmrg    }
2886747b715Smrg    newline = (tmpBuffer[len-1] == '\n');
28905b261ecSmrg    if ((verb < 0 || logVerbosity >= verb) && len > 0)
29005b261ecSmrg	fwrite(tmpBuffer, len, 1, stderr);
29105b261ecSmrg    if ((verb < 0 || logFileVerbosity >= verb) && len > 0) {
29205b261ecSmrg	if (logFile) {
29305b261ecSmrg	    fwrite(tmpBuffer, len, 1, logFile);
29405b261ecSmrg	    if (logFlush) {
29505b261ecSmrg		fflush(logFile);
29605b261ecSmrg#ifndef WIN32
29705b261ecSmrg		if (logSync)
29805b261ecSmrg		    fsync(fileno(logFile));
29905b261ecSmrg#endif
30005b261ecSmrg	    }
30105b261ecSmrg	} else if (needBuffer) {
30205b261ecSmrg	    if (len > bufferUnused) {
30305b261ecSmrg		bufferSize += 1024;
30405b261ecSmrg		bufferUnused += 1024;
3059ace9065Smrg		saveBuffer = realloc(saveBuffer, bufferSize);
30605b261ecSmrg		if (!saveBuffer)
30705b261ecSmrg		    FatalError("realloc() failed while saving log messages\n");
30805b261ecSmrg	    }
30905b261ecSmrg	    bufferUnused -= len;
31005b261ecSmrg	    memcpy(saveBuffer + bufferPos, tmpBuffer, len);
31105b261ecSmrg	    bufferPos += len;
31205b261ecSmrg	}
31305b261ecSmrg    }
31405b261ecSmrg}
31505b261ecSmrg
3166747b715Smrgvoid
31705b261ecSmrgLogWrite(int verb, const char *f, ...)
31805b261ecSmrg{
31905b261ecSmrg    va_list args;
32005b261ecSmrg
32105b261ecSmrg    va_start(args, f);
32205b261ecSmrg    LogVWrite(verb, f, args);
32305b261ecSmrg    va_end(args);
32405b261ecSmrg}
32505b261ecSmrg
3266747b715Smrgvoid
32705b261ecSmrgLogVMessageVerb(MessageType type, int verb, const char *format, va_list args)
32805b261ecSmrg{
32905b261ecSmrg    const char *s  = X_UNKNOWN_STRING;
33052397711Smrg    char tmpBuf[1024];
33105b261ecSmrg
33205b261ecSmrg    /* Ignore verbosity for X_ERROR */
33305b261ecSmrg    if (logVerbosity >= verb || logFileVerbosity >= verb || type == X_ERROR) {
33405b261ecSmrg	switch (type) {
33505b261ecSmrg	case X_PROBED:
33605b261ecSmrg	    s = X_PROBE_STRING;
33705b261ecSmrg	    break;
33805b261ecSmrg	case X_CONFIG:
33905b261ecSmrg	    s = X_CONFIG_STRING;
34005b261ecSmrg	    break;
34105b261ecSmrg	case X_DEFAULT:
34205b261ecSmrg	    s = X_DEFAULT_STRING;
34305b261ecSmrg	    break;
34405b261ecSmrg	case X_CMDLINE:
34505b261ecSmrg	    s = X_CMDLINE_STRING;
34605b261ecSmrg	    break;
34705b261ecSmrg	case X_NOTICE:
34805b261ecSmrg	    s = X_NOTICE_STRING;
34905b261ecSmrg	    break;
35005b261ecSmrg	case X_ERROR:
35105b261ecSmrg	    s = X_ERROR_STRING;
35205b261ecSmrg	    if (verb > 0)
35305b261ecSmrg		verb = 0;
35405b261ecSmrg	    break;
35505b261ecSmrg	case X_WARNING:
35605b261ecSmrg	    s = X_WARNING_STRING;
35705b261ecSmrg	    break;
35805b261ecSmrg	case X_INFO:
35905b261ecSmrg	    s = X_INFO_STRING;
36005b261ecSmrg	    break;
36105b261ecSmrg	case X_NOT_IMPLEMENTED:
36205b261ecSmrg	    s = X_NOT_IMPLEMENTED_STRING;
36305b261ecSmrg	    break;
36405b261ecSmrg	case X_UNKNOWN:
36505b261ecSmrg	    s = X_UNKNOWN_STRING;
36605b261ecSmrg	    break;
36705b261ecSmrg	case X_NONE:
36805b261ecSmrg	    s = NULL;
36905b261ecSmrg	    break;
37005b261ecSmrg	}
37105b261ecSmrg
37252397711Smrg        /* if s is not NULL we need a space before format */
37352397711Smrg        snprintf(tmpBuf, sizeof(tmpBuf), "%s%s%s", s ? s : "",
37452397711Smrg                                                   s ? " " : "",
37552397711Smrg                                                   format);
37652397711Smrg        LogVWrite(verb, tmpBuf, args);
37705b261ecSmrg    }
37805b261ecSmrg}
37905b261ecSmrg
38005b261ecSmrg/* Log message with verbosity level specified. */
3816747b715Smrgvoid
38205b261ecSmrgLogMessageVerb(MessageType type, int verb, const char *format, ...)
38305b261ecSmrg{
38405b261ecSmrg    va_list ap;
38505b261ecSmrg
38605b261ecSmrg    va_start(ap, format);
38705b261ecSmrg    LogVMessageVerb(type, verb, format, ap);
38805b261ecSmrg    va_end(ap);
38905b261ecSmrg}
39005b261ecSmrg
39105b261ecSmrg/* Log a message with the standard verbosity level of 1. */
3926747b715Smrgvoid
39305b261ecSmrgLogMessage(MessageType type, const char *format, ...)
39405b261ecSmrg{
39505b261ecSmrg    va_list ap;
39605b261ecSmrg
39705b261ecSmrg    va_start(ap, format);
39805b261ecSmrg    LogVMessageVerb(type, 1, format, ap);
39905b261ecSmrg    va_end(ap);
40005b261ecSmrg}
40105b261ecSmrg
4026747b715Smrgvoid
4036747b715SmrgAbortServer(void) _X_NORETURN;
40405b261ecSmrg
40505b261ecSmrgvoid
40605b261ecSmrgAbortServer(void)
40705b261ecSmrg{
4086747b715Smrg#ifdef XF86BIGFONT
4096747b715Smrg    XF86BigfontCleanup();
4106747b715Smrg#endif
4114642e01fSmrg    CloseWellKnownConnections();
41205b261ecSmrg    OsCleanup(TRUE);
41305b261ecSmrg    CloseDownDevices();
41405b261ecSmrg    AbortDDX();
41505b261ecSmrg    fflush(stderr);
41605b261ecSmrg    if (CoreDump)
4176747b715Smrg	OsAbort();
41805b261ecSmrg    exit (1);
41905b261ecSmrg}
42005b261ecSmrg
4214642e01fSmrg#define AUDIT_PREFIX "AUDIT: %s: %ld: "
42205b261ecSmrg#ifndef AUDIT_TIMEOUT
42305b261ecSmrg#define AUDIT_TIMEOUT ((CARD32)(120 * 1000)) /* 2 mn */
42405b261ecSmrg#endif
42505b261ecSmrg
42605b261ecSmrgstatic int nrepeat = 0;
42705b261ecSmrgstatic int oldlen = -1;
42805b261ecSmrgstatic OsTimerPtr auditTimer = NULL;
42905b261ecSmrg
4306747b715Smrgvoid
43105b261ecSmrgFreeAuditTimer(void)
43205b261ecSmrg{
43305b261ecSmrg    if (auditTimer != NULL) {
43405b261ecSmrg	/* Force output of pending messages */
43505b261ecSmrg	TimerForce(auditTimer);
43605b261ecSmrg	TimerFree(auditTimer);
43705b261ecSmrg	auditTimer = NULL;
43805b261ecSmrg    }
43905b261ecSmrg}
44005b261ecSmrg
44105b261ecSmrgstatic char *
44205b261ecSmrgAuditPrefix(void)
44305b261ecSmrg{
44405b261ecSmrg    time_t tm;
44505b261ecSmrg    char *autime, *s;
44605b261ecSmrg    char *tmpBuf;
44705b261ecSmrg    int len;
44805b261ecSmrg
44905b261ecSmrg    time(&tm);
45005b261ecSmrg    autime = ctime(&tm);
45105b261ecSmrg    if ((s = strchr(autime, '\n')))
45205b261ecSmrg	*s = '\0';
4534642e01fSmrg    len = strlen(AUDIT_PREFIX) + strlen(autime) + 10 + 1;
45405b261ecSmrg    tmpBuf = malloc(len);
45505b261ecSmrg    if (!tmpBuf)
45605b261ecSmrg	return NULL;
4574642e01fSmrg    snprintf(tmpBuf, len, AUDIT_PREFIX, autime, (unsigned long)getpid());
45805b261ecSmrg    return tmpBuf;
45905b261ecSmrg}
46005b261ecSmrg
46105b261ecSmrgvoid
46205b261ecSmrgAuditF(const char * f, ...)
46305b261ecSmrg{
46405b261ecSmrg    va_list args;
46505b261ecSmrg
46605b261ecSmrg    va_start(args, f);
46705b261ecSmrg
46805b261ecSmrg    VAuditF(f, args);
46905b261ecSmrg    va_end(args);
47005b261ecSmrg}
47105b261ecSmrg
47205b261ecSmrgstatic CARD32
47305b261ecSmrgAuditFlush(OsTimerPtr timer, CARD32 now, pointer arg)
47405b261ecSmrg{
47505b261ecSmrg    char *prefix;
47605b261ecSmrg
47705b261ecSmrg    if (nrepeat > 0) {
47805b261ecSmrg	prefix = AuditPrefix();
47905b261ecSmrg	ErrorF("%slast message repeated %d times\n",
48005b261ecSmrg	       prefix != NULL ? prefix : "", nrepeat);
48105b261ecSmrg	nrepeat = 0;
4829ace9065Smrg	free(prefix);
48305b261ecSmrg	return AUDIT_TIMEOUT;
48405b261ecSmrg    } else {
48505b261ecSmrg	/* if the timer expires without anything to print, flush the message */
48605b261ecSmrg	oldlen = -1;
48705b261ecSmrg	return 0;
48805b261ecSmrg    }
48905b261ecSmrg}
49005b261ecSmrg
49105b261ecSmrgvoid
49205b261ecSmrgVAuditF(const char *f, va_list args)
49305b261ecSmrg{
49405b261ecSmrg    char *prefix;
49505b261ecSmrg    char buf[1024];
49605b261ecSmrg    int len;
49705b261ecSmrg    static char oldbuf[1024];
49805b261ecSmrg
49905b261ecSmrg    prefix = AuditPrefix();
50005b261ecSmrg    len = vsnprintf(buf, sizeof(buf), f, args);
50105b261ecSmrg
50205b261ecSmrg    if (len == oldlen && strcmp(buf, oldbuf) == 0) {
50305b261ecSmrg	/* Message already seen */
50405b261ecSmrg	nrepeat++;
50505b261ecSmrg    } else {
50605b261ecSmrg	/* new message */
50705b261ecSmrg	if (auditTimer != NULL)
50805b261ecSmrg	    TimerForce(auditTimer);
50905b261ecSmrg	ErrorF("%s%s", prefix != NULL ? prefix : "", buf);
51005b261ecSmrg	strlcpy(oldbuf, buf, sizeof(oldbuf));
51105b261ecSmrg	oldlen = len;
51205b261ecSmrg	nrepeat = 0;
51305b261ecSmrg	auditTimer = TimerSet(auditTimer, 0, AUDIT_TIMEOUT, AuditFlush, NULL);
51405b261ecSmrg    }
5159ace9065Smrg    free(prefix);
51605b261ecSmrg}
51705b261ecSmrg
5186747b715Smrgvoid
51905b261ecSmrgFatalError(const char *f, ...)
52005b261ecSmrg{
52105b261ecSmrg    va_list args;
52205b261ecSmrg    static Bool beenhere = FALSE;
52305b261ecSmrg
52405b261ecSmrg    if (beenhere)
52505b261ecSmrg	ErrorF("\nFatalError re-entered, aborting\n");
52605b261ecSmrg    else
52705b261ecSmrg	ErrorF("\nFatal server error:\n");
52805b261ecSmrg
52905b261ecSmrg    va_start(args, f);
5306747b715Smrg#ifdef __APPLE__
5316747b715Smrg    (void)vsnprintf(__crashreporter_info_buff__, sizeof(__crashreporter_info_buff__), f, args);
5326747b715Smrg#endif
53305b261ecSmrg    VErrorF(f, args);
53405b261ecSmrg    va_end(args);
53505b261ecSmrg    ErrorF("\n");
53605b261ecSmrg    if (!beenhere)
53705b261ecSmrg	OsVendorFatalError();
53805b261ecSmrg    if (!beenhere) {
53905b261ecSmrg	beenhere = TRUE;
54005b261ecSmrg	AbortServer();
54105b261ecSmrg    } else
5426747b715Smrg	OsAbort();
54305b261ecSmrg    /*NOTREACHED*/
54405b261ecSmrg}
54505b261ecSmrg
5466747b715Smrgvoid
54705b261ecSmrgVErrorF(const char *f, va_list args)
54805b261ecSmrg{
54905b261ecSmrg#ifdef DDXOSVERRORF
55005b261ecSmrg    if (OsVendorVErrorFProc)
55105b261ecSmrg	OsVendorVErrorFProc(f, args);
55205b261ecSmrg    else
55305b261ecSmrg	LogVWrite(-1, f, args);
55405b261ecSmrg#else
55505b261ecSmrg    LogVWrite(-1, f, args);
55605b261ecSmrg#endif
55705b261ecSmrg}
55805b261ecSmrg
5596747b715Smrgvoid
56005b261ecSmrgErrorF(const char * f, ...)
56105b261ecSmrg{
56205b261ecSmrg    va_list args;
56305b261ecSmrg
56405b261ecSmrg    va_start(args, f);
56505b261ecSmrg    VErrorF(f, args);
56605b261ecSmrg    va_end(args);
56705b261ecSmrg}
56805b261ecSmrg
56905b261ecSmrg/* A perror() workalike. */
57005b261ecSmrg
5716747b715Smrgvoid
5729ace9065SmrgError(const char *str)
57305b261ecSmrg{
5749ace9065Smrg    const char *err = strerror(errno);
5759ace9065Smrg
5769ace9065Smrg    if (str)
5779ace9065Smrg	LogWrite(-1, "%s: %s", str, err);
5789ace9065Smrg    else
5794642e01fSmrg	LogWrite(-1, "%s", err);
58005b261ecSmrg}
58105b261ecSmrg
58205b261ecSmrgvoid
58305b261ecSmrgLogPrintMarkers(void)
58405b261ecSmrg{
58505b261ecSmrg    /* Show what the message marker symbols mean. */
5866747b715Smrg    LogWrite(0, "Markers: ");
5876747b715Smrg    LogMessageVerb(X_PROBED, 0, "probed, ");
5886747b715Smrg    LogMessageVerb(X_CONFIG, 0, "from config file, ");
5896747b715Smrg    LogMessageVerb(X_DEFAULT, 0, "default setting,\n\t");
5906747b715Smrg    LogMessageVerb(X_CMDLINE, 0, "from command line, ");
5916747b715Smrg    LogMessageVerb(X_NOTICE, 0, "notice, ");
5926747b715Smrg    LogMessageVerb(X_INFO, 0, "informational,\n\t");
5936747b715Smrg    LogMessageVerb(X_WARNING, 0, "warning, ");
5946747b715Smrg    LogMessageVerb(X_ERROR, 0, "error, ");
5956747b715Smrg    LogMessageVerb(X_NOT_IMPLEMENTED, 0, "not implemented, ");
5966747b715Smrg    LogMessageVerb(X_UNKNOWN, 0, "unknown.\n");
59705b261ecSmrg}
59805b261ecSmrg
599