log.c revision 8223e2f2
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
10505b261ecSmrg#ifdef DDXOSVERRORF
10605b261ecSmrgvoid (*OsVendorVErrorFProc)(const char *, va_list args) = NULL;
10705b261ecSmrg#endif
10805b261ecSmrg
10905b261ecSmrgstatic FILE *logFile = NULL;
11005b261ecSmrgstatic Bool logFlush = FALSE;
11105b261ecSmrgstatic Bool logSync = FALSE;
11205b261ecSmrgstatic int logVerbosity = DEFAULT_LOG_VERBOSITY;
11305b261ecSmrgstatic int logFileVerbosity = DEFAULT_LOG_FILE_VERBOSITY;
11405b261ecSmrg
11505b261ecSmrg/* Buffer to information logged before the log file is opened. */
11605b261ecSmrgstatic char *saveBuffer = NULL;
11705b261ecSmrgstatic int bufferSize = 0, bufferUnused = 0, bufferPos = 0;
11805b261ecSmrgstatic Bool needBuffer = TRUE;
11905b261ecSmrg
1206747b715Smrg#ifdef __APPLE__
1216747b715Smrg#include <AvailabilityMacros.h>
1226747b715Smrg
1236747b715Smrgstatic char __crashreporter_info_buff__[4096] = {0};
1248223e2f2Smrgstatic const char *__crashreporter_info__ __attribute__((__used__)) = &__crashreporter_info_buff__[0];
1256747b715Smrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
1266747b715Smrg// This is actually a toolchain requirement, but I'm not sure the correct check,
1276747b715Smrg// but it should be fine to just only include it for Leopard and later.  This line
1286747b715Smrg// just tells the linker to never strip this symbol (such as for space optimization)
1296747b715Smrgasm (".desc ___crashreporter_info__, 0x10");
1306747b715Smrg#endif
1316747b715Smrg#endif
1326747b715Smrg
13305b261ecSmrg/* Prefix strings for log messages. */
13405b261ecSmrg#ifndef X_UNKNOWN_STRING
13505b261ecSmrg#define X_UNKNOWN_STRING		"(\?\?)"
13605b261ecSmrg#endif
13705b261ecSmrg#ifndef X_PROBE_STRING
13805b261ecSmrg#define X_PROBE_STRING			"(--)"
13905b261ecSmrg#endif
14005b261ecSmrg#ifndef X_CONFIG_STRING
14105b261ecSmrg#define X_CONFIG_STRING			"(**)"
14205b261ecSmrg#endif
14305b261ecSmrg#ifndef X_DEFAULT_STRING
14405b261ecSmrg#define X_DEFAULT_STRING		"(==)"
14505b261ecSmrg#endif
14605b261ecSmrg#ifndef X_CMDLINE_STRING
14705b261ecSmrg#define X_CMDLINE_STRING		"(++)"
14805b261ecSmrg#endif
14905b261ecSmrg#ifndef X_NOTICE_STRING
15005b261ecSmrg#define X_NOTICE_STRING			"(!!)"
15105b261ecSmrg#endif
15205b261ecSmrg#ifndef X_ERROR_STRING
15305b261ecSmrg#define X_ERROR_STRING			"(EE)"
15405b261ecSmrg#endif
15505b261ecSmrg#ifndef X_WARNING_STRING
15605b261ecSmrg#define X_WARNING_STRING		"(WW)"
15705b261ecSmrg#endif
15805b261ecSmrg#ifndef X_INFO_STRING
15905b261ecSmrg#define X_INFO_STRING			"(II)"
16005b261ecSmrg#endif
16105b261ecSmrg#ifndef X_NOT_IMPLEMENTED_STRING
16205b261ecSmrg#define X_NOT_IMPLEMENTED_STRING	"(NI)"
16305b261ecSmrg#endif
16405b261ecSmrg
16505b261ecSmrg/*
16605b261ecSmrg * LogInit is called to start logging to a file.  It is also called (with
16705b261ecSmrg * NULL arguments) when logging to a file is not wanted.  It must always be
16805b261ecSmrg * called, otherwise log messages will continue to accumulate in a buffer.
16905b261ecSmrg *
17005b261ecSmrg * %s, if present in the fname or backup strings, is expanded to the display
17105b261ecSmrg * string.
17205b261ecSmrg */
17305b261ecSmrg
17405b261ecSmrgconst char *
17505b261ecSmrgLogInit(const char *fname, const char *backup)
17605b261ecSmrg{
17705b261ecSmrg    char *logFileName = NULL;
17805b261ecSmrg
17905b261ecSmrg    if (fname && *fname) {
1806747b715Smrg	/* malloc() can't be used yet. */
18105b261ecSmrg	logFileName = malloc(strlen(fname) + strlen(display) + 1);
18205b261ecSmrg	if (!logFileName)
18305b261ecSmrg	    FatalError("Cannot allocate space for the log file name\n");
18405b261ecSmrg	sprintf(logFileName, fname, display);
18505b261ecSmrg
18605b261ecSmrg	if (backup && *backup) {
18705b261ecSmrg	    struct stat buf;
18805b261ecSmrg
18905b261ecSmrg	    if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) {
19005b261ecSmrg		char *suffix;
19105b261ecSmrg		char *oldLog;
19205b261ecSmrg
19305b261ecSmrg		oldLog = malloc(strlen(logFileName) + strlen(backup) +
19405b261ecSmrg				strlen(display) + 1);
19505b261ecSmrg		suffix = malloc(strlen(backup) + strlen(display) + 1);
19605b261ecSmrg		if (!oldLog || !suffix)
19705b261ecSmrg		    FatalError("Cannot allocate space for the log file name\n");
19805b261ecSmrg		sprintf(suffix, backup, display);
19905b261ecSmrg		sprintf(oldLog, "%s%s", logFileName, suffix);
20005b261ecSmrg		free(suffix);
20105b261ecSmrg		if (rename(logFileName, oldLog) == -1) {
2026747b715Smrg		    FatalError("Cannot move old log file \"%s\" to \"%s\"\n",
20305b261ecSmrg			       logFileName, oldLog);
20405b261ecSmrg		}
20505b261ecSmrg		free(oldLog);
20605b261ecSmrg	    }
20705b261ecSmrg	}
20805b261ecSmrg	if ((logFile = fopen(logFileName, "w")) == NULL)
20905b261ecSmrg	    FatalError("Cannot open log file \"%s\"\n", logFileName);
21005b261ecSmrg	setvbuf(logFile, NULL, _IONBF, 0);
21105b261ecSmrg
21205b261ecSmrg	/* Flush saved log information. */
21305b261ecSmrg	if (saveBuffer && bufferSize > 0) {
21405b261ecSmrg	    fwrite(saveBuffer, bufferPos, 1, logFile);
21505b261ecSmrg	    fflush(logFile);
21605b261ecSmrg#ifndef WIN32
21705b261ecSmrg	    fsync(fileno(logFile));
21805b261ecSmrg#endif
21905b261ecSmrg	}
22005b261ecSmrg    }
22105b261ecSmrg
22205b261ecSmrg    /*
22305b261ecSmrg     * Unconditionally free the buffer, and flag that the buffer is no longer
22405b261ecSmrg     * needed.
22505b261ecSmrg     */
22605b261ecSmrg    if (saveBuffer && bufferSize > 0) {
2276747b715Smrg	free(saveBuffer);	/* Must be free(), not free() */
22805b261ecSmrg	saveBuffer = NULL;
22905b261ecSmrg	bufferSize = 0;
23005b261ecSmrg    }
23105b261ecSmrg    needBuffer = FALSE;
23205b261ecSmrg
23305b261ecSmrg    return logFileName;
23405b261ecSmrg}
23505b261ecSmrg
23605b261ecSmrgvoid
23705b261ecSmrgLogClose(void)
23805b261ecSmrg{
23905b261ecSmrg    if (logFile) {
24005b261ecSmrg	fclose(logFile);
24105b261ecSmrg	logFile = NULL;
24205b261ecSmrg    }
24305b261ecSmrg}
24405b261ecSmrg
24505b261ecSmrgBool
24605b261ecSmrgLogSetParameter(LogParameter param, int value)
24705b261ecSmrg{
24805b261ecSmrg    switch (param) {
24905b261ecSmrg    case XLOG_FLUSH:
25005b261ecSmrg	logFlush = value ? TRUE : FALSE;
25105b261ecSmrg	return TRUE;
25205b261ecSmrg    case XLOG_SYNC:
25305b261ecSmrg	logSync = value ? TRUE : FALSE;
25405b261ecSmrg	return TRUE;
25505b261ecSmrg    case XLOG_VERBOSITY:
25605b261ecSmrg	logVerbosity = value;
25705b261ecSmrg	return TRUE;
25805b261ecSmrg    case XLOG_FILE_VERBOSITY:
25905b261ecSmrg	logFileVerbosity = value;
26005b261ecSmrg	return TRUE;
26105b261ecSmrg    default:
26205b261ecSmrg	return FALSE;
26305b261ecSmrg    }
26405b261ecSmrg}
26505b261ecSmrg
26605b261ecSmrg/* This function does the actual log message writes. */
26705b261ecSmrg
2686747b715Smrgvoid
26905b261ecSmrgLogVWrite(int verb, const char *f, va_list args)
27005b261ecSmrg{
27105b261ecSmrg    static char tmpBuffer[1024];
27205b261ecSmrg    int len = 0;
2736747b715Smrg    static Bool newline = TRUE;
2746747b715Smrg
2756747b715Smrg    if (newline) {
2766747b715Smrg	sprintf(tmpBuffer, "[%10.3f] ", GetTimeInMillis() / 1000.0);
2776747b715Smrg	len = strlen(tmpBuffer);
2786747b715Smrg	if (logFile)
2796747b715Smrg	    fwrite(tmpBuffer, len, 1, logFile);
2806747b715Smrg    }
28105b261ecSmrg
28205b261ecSmrg    /*
28305b261ecSmrg     * Since a va_list can only be processed once, write the string to a
28405b261ecSmrg     * buffer, and then write the buffer out to the appropriate output
28505b261ecSmrg     * stream(s).
28605b261ecSmrg     */
28705b261ecSmrg    if (verb < 0 || logFileVerbosity >= verb || logVerbosity >= verb) {
28805b261ecSmrg	vsnprintf(tmpBuffer, sizeof(tmpBuffer), f, args);
28905b261ecSmrg	len = strlen(tmpBuffer);
29005b261ecSmrg    }
2916747b715Smrg    newline = (tmpBuffer[len-1] == '\n');
29205b261ecSmrg    if ((verb < 0 || logVerbosity >= verb) && len > 0)
29305b261ecSmrg	fwrite(tmpBuffer, len, 1, stderr);
29405b261ecSmrg    if ((verb < 0 || logFileVerbosity >= verb) && len > 0) {
29505b261ecSmrg	if (logFile) {
29605b261ecSmrg	    fwrite(tmpBuffer, len, 1, logFile);
29705b261ecSmrg	    if (logFlush) {
29805b261ecSmrg		fflush(logFile);
29905b261ecSmrg#ifndef WIN32
30005b261ecSmrg		if (logSync)
30105b261ecSmrg		    fsync(fileno(logFile));
30205b261ecSmrg#endif
30305b261ecSmrg	    }
30405b261ecSmrg	} else if (needBuffer) {
30505b261ecSmrg	    /*
30605b261ecSmrg	     * Note, this code is used before OsInit() has been called, so
3076747b715Smrg	     * malloc() and friends can't be used.
30805b261ecSmrg	     */
30905b261ecSmrg	    if (len > bufferUnused) {
31005b261ecSmrg		bufferSize += 1024;
31105b261ecSmrg		bufferUnused += 1024;
31205b261ecSmrg		if (saveBuffer)
31305b261ecSmrg		    saveBuffer = realloc(saveBuffer, bufferSize);
31405b261ecSmrg		else
31505b261ecSmrg		    saveBuffer = malloc(bufferSize);
31605b261ecSmrg		if (!saveBuffer)
31705b261ecSmrg		    FatalError("realloc() failed while saving log messages\n");
31805b261ecSmrg	    }
31905b261ecSmrg	    bufferUnused -= len;
32005b261ecSmrg	    memcpy(saveBuffer + bufferPos, tmpBuffer, len);
32105b261ecSmrg	    bufferPos += len;
32205b261ecSmrg	}
32305b261ecSmrg    }
32405b261ecSmrg}
32505b261ecSmrg
3266747b715Smrgvoid
32705b261ecSmrgLogWrite(int verb, const char *f, ...)
32805b261ecSmrg{
32905b261ecSmrg    va_list args;
33005b261ecSmrg
33105b261ecSmrg    va_start(args, f);
33205b261ecSmrg    LogVWrite(verb, f, args);
33305b261ecSmrg    va_end(args);
33405b261ecSmrg}
33505b261ecSmrg
3366747b715Smrgvoid
33705b261ecSmrgLogVMessageVerb(MessageType type, int verb, const char *format, va_list args)
33805b261ecSmrg{
33905b261ecSmrg    const char *s  = X_UNKNOWN_STRING;
34052397711Smrg    char tmpBuf[1024];
34105b261ecSmrg
34205b261ecSmrg    /* Ignore verbosity for X_ERROR */
34305b261ecSmrg    if (logVerbosity >= verb || logFileVerbosity >= verb || type == X_ERROR) {
34405b261ecSmrg	switch (type) {
34505b261ecSmrg	case X_PROBED:
34605b261ecSmrg	    s = X_PROBE_STRING;
34705b261ecSmrg	    break;
34805b261ecSmrg	case X_CONFIG:
34905b261ecSmrg	    s = X_CONFIG_STRING;
35005b261ecSmrg	    break;
35105b261ecSmrg	case X_DEFAULT:
35205b261ecSmrg	    s = X_DEFAULT_STRING;
35305b261ecSmrg	    break;
35405b261ecSmrg	case X_CMDLINE:
35505b261ecSmrg	    s = X_CMDLINE_STRING;
35605b261ecSmrg	    break;
35705b261ecSmrg	case X_NOTICE:
35805b261ecSmrg	    s = X_NOTICE_STRING;
35905b261ecSmrg	    break;
36005b261ecSmrg	case X_ERROR:
36105b261ecSmrg	    s = X_ERROR_STRING;
36205b261ecSmrg	    if (verb > 0)
36305b261ecSmrg		verb = 0;
36405b261ecSmrg	    break;
36505b261ecSmrg	case X_WARNING:
36605b261ecSmrg	    s = X_WARNING_STRING;
36705b261ecSmrg	    break;
36805b261ecSmrg	case X_INFO:
36905b261ecSmrg	    s = X_INFO_STRING;
37005b261ecSmrg	    break;
37105b261ecSmrg	case X_NOT_IMPLEMENTED:
37205b261ecSmrg	    s = X_NOT_IMPLEMENTED_STRING;
37305b261ecSmrg	    break;
37405b261ecSmrg	case X_UNKNOWN:
37505b261ecSmrg	    s = X_UNKNOWN_STRING;
37605b261ecSmrg	    break;
37705b261ecSmrg	case X_NONE:
37805b261ecSmrg	    s = NULL;
37905b261ecSmrg	    break;
38005b261ecSmrg	}
38105b261ecSmrg
38252397711Smrg        /* if s is not NULL we need a space before format */
38352397711Smrg        snprintf(tmpBuf, sizeof(tmpBuf), "%s%s%s", s ? s : "",
38452397711Smrg                                                   s ? " " : "",
38552397711Smrg                                                   format);
38652397711Smrg        LogVWrite(verb, tmpBuf, args);
38705b261ecSmrg    }
38805b261ecSmrg}
38905b261ecSmrg
39005b261ecSmrg/* Log message with verbosity level specified. */
3916747b715Smrgvoid
39205b261ecSmrgLogMessageVerb(MessageType type, int verb, const char *format, ...)
39305b261ecSmrg{
39405b261ecSmrg    va_list ap;
39505b261ecSmrg
39605b261ecSmrg    va_start(ap, format);
39705b261ecSmrg    LogVMessageVerb(type, verb, format, ap);
39805b261ecSmrg    va_end(ap);
39905b261ecSmrg}
40005b261ecSmrg
40105b261ecSmrg/* Log a message with the standard verbosity level of 1. */
4026747b715Smrgvoid
40305b261ecSmrgLogMessage(MessageType type, const char *format, ...)
40405b261ecSmrg{
40505b261ecSmrg    va_list ap;
40605b261ecSmrg
40705b261ecSmrg    va_start(ap, format);
40805b261ecSmrg    LogVMessageVerb(type, 1, format, ap);
40905b261ecSmrg    va_end(ap);
41005b261ecSmrg}
41105b261ecSmrg
4126747b715Smrgvoid
4136747b715SmrgAbortServer(void) _X_NORETURN;
41405b261ecSmrg
41505b261ecSmrgvoid
41605b261ecSmrgAbortServer(void)
41705b261ecSmrg{
4186747b715Smrg#ifdef XF86BIGFONT
4196747b715Smrg    XF86BigfontCleanup();
4206747b715Smrg#endif
4214642e01fSmrg    CloseWellKnownConnections();
42205b261ecSmrg    OsCleanup(TRUE);
42305b261ecSmrg    CloseDownDevices();
42405b261ecSmrg    AbortDDX();
42505b261ecSmrg    fflush(stderr);
42605b261ecSmrg    if (CoreDump)
4276747b715Smrg	OsAbort();
42805b261ecSmrg    exit (1);
42905b261ecSmrg}
43005b261ecSmrg
4314642e01fSmrg#define AUDIT_PREFIX "AUDIT: %s: %ld: "
43205b261ecSmrg#ifndef AUDIT_TIMEOUT
43305b261ecSmrg#define AUDIT_TIMEOUT ((CARD32)(120 * 1000)) /* 2 mn */
43405b261ecSmrg#endif
43505b261ecSmrg
43605b261ecSmrgstatic int nrepeat = 0;
43705b261ecSmrgstatic int oldlen = -1;
43805b261ecSmrgstatic OsTimerPtr auditTimer = NULL;
43905b261ecSmrg
4406747b715Smrgvoid
44105b261ecSmrgFreeAuditTimer(void)
44205b261ecSmrg{
44305b261ecSmrg    if (auditTimer != NULL) {
44405b261ecSmrg	/* Force output of pending messages */
44505b261ecSmrg	TimerForce(auditTimer);
44605b261ecSmrg	TimerFree(auditTimer);
44705b261ecSmrg	auditTimer = NULL;
44805b261ecSmrg    }
44905b261ecSmrg}
45005b261ecSmrg
45105b261ecSmrgstatic char *
45205b261ecSmrgAuditPrefix(void)
45305b261ecSmrg{
45405b261ecSmrg    time_t tm;
45505b261ecSmrg    char *autime, *s;
45605b261ecSmrg    char *tmpBuf;
45705b261ecSmrg    int len;
45805b261ecSmrg
45905b261ecSmrg    time(&tm);
46005b261ecSmrg    autime = ctime(&tm);
46105b261ecSmrg    if ((s = strchr(autime, '\n')))
46205b261ecSmrg	*s = '\0';
4634642e01fSmrg    len = strlen(AUDIT_PREFIX) + strlen(autime) + 10 + 1;
46405b261ecSmrg    tmpBuf = malloc(len);
46505b261ecSmrg    if (!tmpBuf)
46605b261ecSmrg	return NULL;
4674642e01fSmrg    snprintf(tmpBuf, len, AUDIT_PREFIX, autime, (unsigned long)getpid());
46805b261ecSmrg    return tmpBuf;
46905b261ecSmrg}
47005b261ecSmrg
47105b261ecSmrgvoid
47205b261ecSmrgAuditF(const char * f, ...)
47305b261ecSmrg{
47405b261ecSmrg    va_list args;
47505b261ecSmrg
47605b261ecSmrg    va_start(args, f);
47705b261ecSmrg
47805b261ecSmrg    VAuditF(f, args);
47905b261ecSmrg    va_end(args);
48005b261ecSmrg}
48105b261ecSmrg
48205b261ecSmrgstatic CARD32
48305b261ecSmrgAuditFlush(OsTimerPtr timer, CARD32 now, pointer arg)
48405b261ecSmrg{
48505b261ecSmrg    char *prefix;
48605b261ecSmrg
48705b261ecSmrg    if (nrepeat > 0) {
48805b261ecSmrg	prefix = AuditPrefix();
48905b261ecSmrg	ErrorF("%slast message repeated %d times\n",
49005b261ecSmrg	       prefix != NULL ? prefix : "", nrepeat);
49105b261ecSmrg	nrepeat = 0;
49205b261ecSmrg	if (prefix != NULL)
49305b261ecSmrg	    free(prefix);
49405b261ecSmrg	return AUDIT_TIMEOUT;
49505b261ecSmrg    } else {
49605b261ecSmrg	/* if the timer expires without anything to print, flush the message */
49705b261ecSmrg	oldlen = -1;
49805b261ecSmrg	return 0;
49905b261ecSmrg    }
50005b261ecSmrg}
50105b261ecSmrg
50205b261ecSmrgvoid
50305b261ecSmrgVAuditF(const char *f, va_list args)
50405b261ecSmrg{
50505b261ecSmrg    char *prefix;
50605b261ecSmrg    char buf[1024];
50705b261ecSmrg    int len;
50805b261ecSmrg    static char oldbuf[1024];
50905b261ecSmrg
51005b261ecSmrg    prefix = AuditPrefix();
51105b261ecSmrg    len = vsnprintf(buf, sizeof(buf), f, args);
51205b261ecSmrg
51305b261ecSmrg    if (len == oldlen && strcmp(buf, oldbuf) == 0) {
51405b261ecSmrg	/* Message already seen */
51505b261ecSmrg	nrepeat++;
51605b261ecSmrg    } else {
51705b261ecSmrg	/* new message */
51805b261ecSmrg	if (auditTimer != NULL)
51905b261ecSmrg	    TimerForce(auditTimer);
52005b261ecSmrg	ErrorF("%s%s", prefix != NULL ? prefix : "", buf);
52105b261ecSmrg	strlcpy(oldbuf, buf, sizeof(oldbuf));
52205b261ecSmrg	oldlen = len;
52305b261ecSmrg	nrepeat = 0;
52405b261ecSmrg	auditTimer = TimerSet(auditTimer, 0, AUDIT_TIMEOUT, AuditFlush, NULL);
52505b261ecSmrg    }
52605b261ecSmrg    if (prefix != NULL)
52705b261ecSmrg	free(prefix);
52805b261ecSmrg}
52905b261ecSmrg
5306747b715Smrgvoid
53105b261ecSmrgFatalError(const char *f, ...)
53205b261ecSmrg{
53305b261ecSmrg    va_list args;
53405b261ecSmrg    static Bool beenhere = FALSE;
53505b261ecSmrg
53605b261ecSmrg    if (beenhere)
53705b261ecSmrg	ErrorF("\nFatalError re-entered, aborting\n");
53805b261ecSmrg    else
53905b261ecSmrg	ErrorF("\nFatal server error:\n");
54005b261ecSmrg
54105b261ecSmrg    va_start(args, f);
5426747b715Smrg#ifdef __APPLE__
5436747b715Smrg    (void)vsnprintf(__crashreporter_info_buff__, sizeof(__crashreporter_info_buff__), f, args);
5446747b715Smrg#endif
54505b261ecSmrg    VErrorF(f, args);
54605b261ecSmrg    va_end(args);
54705b261ecSmrg    ErrorF("\n");
54805b261ecSmrg    if (!beenhere)
54905b261ecSmrg	OsVendorFatalError();
55005b261ecSmrg    if (!beenhere) {
55105b261ecSmrg	beenhere = TRUE;
55205b261ecSmrg	AbortServer();
55305b261ecSmrg    } else
5546747b715Smrg	OsAbort();
55505b261ecSmrg    /*NOTREACHED*/
55605b261ecSmrg}
55705b261ecSmrg
5586747b715Smrgvoid
55905b261ecSmrgVErrorF(const char *f, va_list args)
56005b261ecSmrg{
56105b261ecSmrg#ifdef DDXOSVERRORF
56205b261ecSmrg    if (OsVendorVErrorFProc)
56305b261ecSmrg	OsVendorVErrorFProc(f, args);
56405b261ecSmrg    else
56505b261ecSmrg	LogVWrite(-1, f, args);
56605b261ecSmrg#else
56705b261ecSmrg    LogVWrite(-1, f, args);
56805b261ecSmrg#endif
56905b261ecSmrg}
57005b261ecSmrg
5716747b715Smrgvoid
57205b261ecSmrgErrorF(const char * f, ...)
57305b261ecSmrg{
57405b261ecSmrg    va_list args;
57505b261ecSmrg
57605b261ecSmrg    va_start(args, f);
57705b261ecSmrg    VErrorF(f, args);
57805b261ecSmrg    va_end(args);
57905b261ecSmrg}
58005b261ecSmrg
58105b261ecSmrg/* A perror() workalike. */
58205b261ecSmrg
5836747b715Smrgvoid
58405b261ecSmrgError(char *str)
58505b261ecSmrg{
58605b261ecSmrg    char *err = NULL;
58705b261ecSmrg    int saveErrno = errno;
58805b261ecSmrg
58905b261ecSmrg    if (str) {
59005b261ecSmrg	err = malloc(strlen(strerror(saveErrno)) + strlen(str) + 2 + 1);
59105b261ecSmrg	if (!err)
59205b261ecSmrg	    return;
59305b261ecSmrg	sprintf(err, "%s: ", str);
59405b261ecSmrg	strcat(err, strerror(saveErrno));
5954642e01fSmrg	LogWrite(-1, "%s", err);
5964642e01fSmrg	free(err);
59705b261ecSmrg    } else
5984642e01fSmrg	LogWrite(-1, "%s", strerror(saveErrno));
59905b261ecSmrg}
60005b261ecSmrg
60105b261ecSmrgvoid
60205b261ecSmrgLogPrintMarkers(void)
60305b261ecSmrg{
60405b261ecSmrg    /* Show what the message marker symbols mean. */
6056747b715Smrg    LogWrite(0, "Markers: ");
6066747b715Smrg    LogMessageVerb(X_PROBED, 0, "probed, ");
6076747b715Smrg    LogMessageVerb(X_CONFIG, 0, "from config file, ");
6086747b715Smrg    LogMessageVerb(X_DEFAULT, 0, "default setting,\n\t");
6096747b715Smrg    LogMessageVerb(X_CMDLINE, 0, "from command line, ");
6106747b715Smrg    LogMessageVerb(X_NOTICE, 0, "notice, ");
6116747b715Smrg    LogMessageVerb(X_INFO, 0, "informational,\n\t");
6126747b715Smrg    LogMessageVerb(X_WARNING, 0, "warning, ");
6136747b715Smrg    LogMessageVerb(X_ERROR, 0, "error, ");
6146747b715Smrg    LogMessageVerb(X_NOT_IMPLEMENTED, 0, "not implemented, ");
6156747b715Smrg    LogMessageVerb(X_UNKNOWN, 0, "unknown.\n");
61605b261ecSmrg}
61705b261ecSmrg
618