1706f2543Smrg/*
2706f2543Smrg
3706f2543SmrgCopyright 1987, 1998  The Open Group
4706f2543Smrg
5706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its
6706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that
7706f2543Smrgthe above copyright notice appear in all copies and that both that
8706f2543Smrgcopyright notice and this permission notice appear in supporting
9706f2543Smrgdocumentation.
10706f2543Smrg
11706f2543SmrgThe above copyright notice and this permission notice shall be included
12706f2543Smrgin all copies or substantial portions of the Software.
13706f2543Smrg
14706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15706f2543SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16706f2543SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17706f2543SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18706f2543SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19706f2543SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20706f2543SmrgOTHER DEALINGS IN THE SOFTWARE.
21706f2543Smrg
22706f2543SmrgExcept as contained in this notice, the name of The Open Group shall
23706f2543Smrgnot be used in advertising or otherwise to promote the sale, use or
24706f2543Smrgother dealings in this Software without prior written authorization
25706f2543Smrgfrom The Open Group.
26706f2543Smrg
27706f2543Smrg
28706f2543SmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
29706f2543SmrgCopyright 1994 Quarterdeck Office Systems.
30706f2543Smrg
31706f2543Smrg                        All Rights Reserved
32706f2543Smrg
33706f2543SmrgPermission to use, copy, modify, and distribute this software and its
34706f2543Smrgdocumentation for any purpose and without fee is hereby granted,
35706f2543Smrgprovided that the above copyright notice appear in all copies and that
36706f2543Smrgboth that copyright notice and this permission notice appear in
37706f2543Smrgsupporting documentation, and that the names of Digital and
38706f2543SmrgQuarterdeck not be used in advertising or publicity pertaining to
39706f2543Smrgdistribution of the software without specific, written prior
40706f2543Smrgpermission.
41706f2543Smrg
42706f2543SmrgDIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
43706f2543SmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
44706f2543SmrgFITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
45706f2543SmrgOR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
46706f2543SmrgOF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
47706f2543SmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
48706f2543SmrgOR PERFORMANCE OF THIS SOFTWARE.
49706f2543Smrg
50706f2543Smrg*/
51706f2543Smrg
52706f2543Smrg/*
53706f2543Smrg * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
54706f2543Smrg *
55706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a
56706f2543Smrg * copy of this software and associated documentation files (the "Software"),
57706f2543Smrg * to deal in the Software without restriction, including without limitation
58706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
59706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the
60706f2543Smrg * Software is furnished to do so, subject to the following conditions:
61706f2543Smrg *
62706f2543Smrg * The above copyright notice and this permission notice shall be included in
63706f2543Smrg * all copies or substantial portions of the Software.
64706f2543Smrg *
65706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
66706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
67706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
68706f2543Smrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
69706f2543Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
70706f2543Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
71706f2543Smrg * OTHER DEALINGS IN THE SOFTWARE.
72706f2543Smrg *
73706f2543Smrg * Except as contained in this notice, the name of the copyright holder(s)
74706f2543Smrg * and author(s) shall not be used in advertising or otherwise to promote
75706f2543Smrg * the sale, use or other dealings in this Software without prior written
76706f2543Smrg * authorization from the copyright holder(s) and author(s).
77706f2543Smrg */
78706f2543Smrg
79706f2543Smrg
80706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
81706f2543Smrg#include <dix-config.h>
82706f2543Smrg#endif
83706f2543Smrg
84706f2543Smrg#include <X11/Xos.h>
85706f2543Smrg#include <stdio.h>
86706f2543Smrg#include <time.h>
87706f2543Smrg#include <sys/stat.h>
88706f2543Smrg#include <stdarg.h>
89706f2543Smrg#include <stdlib.h>	/* for malloc() */
90706f2543Smrg#include <errno.h>
91706f2543Smrg
92706f2543Smrg#include "input.h"
93706f2543Smrg#include "site.h"
94706f2543Smrg#include "opaque.h"
95706f2543Smrg
96706f2543Smrg#ifdef WIN32
97706f2543Smrg#include <process.h>
98706f2543Smrg#define getpid(x) _getpid(x)
99706f2543Smrg#endif
100706f2543Smrg
101706f2543Smrg#ifdef XF86BIGFONT
102706f2543Smrg#include "xf86bigfontsrv.h"
103706f2543Smrg#endif
104706f2543Smrg
105706f2543Smrg#ifdef __clang__
106706f2543Smrg#pragma clang diagnostic ignored "-Wformat-nonliteral"
107706f2543Smrg#endif
108706f2543Smrg
109706f2543Smrg#ifdef DDXOSVERRORF
110706f2543Smrgvoid (*OsVendorVErrorFProc)(const char *, va_list args) = NULL;
111706f2543Smrg#endif
112706f2543Smrg
113706f2543Smrgstatic FILE *logFile = NULL;
114706f2543Smrgstatic Bool logFlush = FALSE;
115706f2543Smrgstatic Bool logSync = FALSE;
116706f2543Smrgstatic int logVerbosity = DEFAULT_LOG_VERBOSITY;
117706f2543Smrgstatic int logFileVerbosity = DEFAULT_LOG_FILE_VERBOSITY;
118706f2543Smrg
119706f2543Smrg/* Buffer to information logged before the log file is opened. */
120706f2543Smrgstatic char *saveBuffer = NULL;
121706f2543Smrgstatic int bufferSize = 0, bufferUnused = 0, bufferPos = 0;
122706f2543Smrgstatic Bool needBuffer = TRUE;
123706f2543Smrg
124706f2543Smrg#ifdef __APPLE__
125706f2543Smrg#include <AvailabilityMacros.h>
126706f2543Smrg
127706f2543Smrgstatic char __crashreporter_info_buff__[4096] = {0};
128706f2543Smrgstatic const char *__crashreporter_info__ __attribute__((__used__)) = &__crashreporter_info_buff__[0];
129706f2543Smrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
130706f2543Smrg// This is actually a toolchain requirement, but I'm not sure the correct check,
131706f2543Smrg// but it should be fine to just only include it for Leopard and later.  This line
132706f2543Smrg// just tells the linker to never strip this symbol (such as for space optimization)
133706f2543Smrgasm (".desc ___crashreporter_info__, 0x10");
134706f2543Smrg#endif
135706f2543Smrg#endif
136706f2543Smrg
137706f2543Smrg/* Prefix strings for log messages. */
138706f2543Smrg#ifndef X_UNKNOWN_STRING
139706f2543Smrg#define X_UNKNOWN_STRING		"(\?\?)"
140706f2543Smrg#endif
141706f2543Smrg#ifndef X_PROBE_STRING
142706f2543Smrg#define X_PROBE_STRING			"(--)"
143706f2543Smrg#endif
144706f2543Smrg#ifndef X_CONFIG_STRING
145706f2543Smrg#define X_CONFIG_STRING			"(**)"
146706f2543Smrg#endif
147706f2543Smrg#ifndef X_DEFAULT_STRING
148706f2543Smrg#define X_DEFAULT_STRING		"(==)"
149706f2543Smrg#endif
150706f2543Smrg#ifndef X_CMDLINE_STRING
151706f2543Smrg#define X_CMDLINE_STRING		"(++)"
152706f2543Smrg#endif
153706f2543Smrg#ifndef X_NOTICE_STRING
154706f2543Smrg#define X_NOTICE_STRING			"(!!)"
155706f2543Smrg#endif
156706f2543Smrg#ifndef X_ERROR_STRING
157706f2543Smrg#define X_ERROR_STRING			"(EE)"
158706f2543Smrg#endif
159706f2543Smrg#ifndef X_WARNING_STRING
160706f2543Smrg#define X_WARNING_STRING		"(WW)"
161706f2543Smrg#endif
162706f2543Smrg#ifndef X_INFO_STRING
163706f2543Smrg#define X_INFO_STRING			"(II)"
164706f2543Smrg#endif
165706f2543Smrg#ifndef X_NOT_IMPLEMENTED_STRING
166706f2543Smrg#define X_NOT_IMPLEMENTED_STRING	"(NI)"
167706f2543Smrg#endif
168706f2543Smrg
169706f2543Smrg/*
170706f2543Smrg * LogInit is called to start logging to a file.  It is also called (with
171706f2543Smrg * NULL arguments) when logging to a file is not wanted.  It must always be
172706f2543Smrg * called, otherwise log messages will continue to accumulate in a buffer.
173706f2543Smrg *
174706f2543Smrg * %s, if present in the fname or backup strings, is expanded to the display
175706f2543Smrg * string.
176706f2543Smrg */
177706f2543Smrg
178706f2543Smrgconst char *
179706f2543SmrgLogInit(const char *fname, const char *backup)
180706f2543Smrg{
181706f2543Smrg    char *logFileName = NULL;
182706f2543Smrg
183706f2543Smrg    if (fname && *fname) {
184706f2543Smrg	if (asprintf(&logFileName, fname, display) == -1)
185706f2543Smrg	    FatalError("Cannot allocate space for the log file name\n");
186706f2543Smrg
187706f2543Smrg	if (backup && *backup) {
188706f2543Smrg	    struct stat buf;
189706f2543Smrg
190706f2543Smrg	    if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) {
191706f2543Smrg		char *suffix;
192706f2543Smrg		char *oldLog;
193706f2543Smrg
194706f2543Smrg		if ((asprintf(&suffix, backup, display) == -1) ||
195706f2543Smrg		    (asprintf(&oldLog, "%s%s", logFileName, suffix) == -1))
196706f2543Smrg		    FatalError("Cannot allocate space for the log file name\n");
197706f2543Smrg		free(suffix);
198706f2543Smrg		if (rename(logFileName, oldLog) == -1) {
199706f2543Smrg		    FatalError("Cannot move old log file \"%s\" to \"%s\"\n",
200706f2543Smrg			       logFileName, oldLog);
201706f2543Smrg		}
202706f2543Smrg		free(oldLog);
203706f2543Smrg	    }
204706f2543Smrg	}
205706f2543Smrg	if ((logFile = fopen(logFileName, "w")) == NULL)
206706f2543Smrg	    FatalError("Cannot open log file \"%s\"\n", logFileName);
207706f2543Smrg	setvbuf(logFile, NULL, _IONBF, 0);
208706f2543Smrg
209706f2543Smrg	/* Flush saved log information. */
210706f2543Smrg	if (saveBuffer && bufferSize > 0) {
211706f2543Smrg	    fwrite(saveBuffer, bufferPos, 1, logFile);
212706f2543Smrg	    fflush(logFile);
213706f2543Smrg#ifndef WIN32
214706f2543Smrg	    fsync(fileno(logFile));
215706f2543Smrg#endif
216706f2543Smrg	}
217706f2543Smrg    }
218706f2543Smrg
219706f2543Smrg    /*
220706f2543Smrg     * Unconditionally free the buffer, and flag that the buffer is no longer
221706f2543Smrg     * needed.
222706f2543Smrg     */
223706f2543Smrg    if (saveBuffer && bufferSize > 0) {
224706f2543Smrg	free(saveBuffer);	/* Must be free(), not free() */
225706f2543Smrg	saveBuffer = NULL;
226706f2543Smrg	bufferSize = 0;
227706f2543Smrg    }
228706f2543Smrg    needBuffer = FALSE;
229706f2543Smrg
230706f2543Smrg    return logFileName;
231706f2543Smrg}
232706f2543Smrg
233706f2543Smrgvoid
234706f2543SmrgLogClose(void)
235706f2543Smrg{
236706f2543Smrg    if (logFile) {
237706f2543Smrg	fclose(logFile);
238706f2543Smrg	logFile = NULL;
239706f2543Smrg    }
240706f2543Smrg}
241706f2543Smrg
242706f2543SmrgBool
243706f2543SmrgLogSetParameter(LogParameter param, int value)
244706f2543Smrg{
245706f2543Smrg    switch (param) {
246706f2543Smrg    case XLOG_FLUSH:
247706f2543Smrg	logFlush = value ? TRUE : FALSE;
248706f2543Smrg	return TRUE;
249706f2543Smrg    case XLOG_SYNC:
250706f2543Smrg	logSync = value ? TRUE : FALSE;
251706f2543Smrg	return TRUE;
252706f2543Smrg    case XLOG_VERBOSITY:
253706f2543Smrg	logVerbosity = value;
254706f2543Smrg	return TRUE;
255706f2543Smrg    case XLOG_FILE_VERBOSITY:
256706f2543Smrg	logFileVerbosity = value;
257706f2543Smrg	return TRUE;
258706f2543Smrg    default:
259706f2543Smrg	return FALSE;
260706f2543Smrg    }
261706f2543Smrg}
262706f2543Smrg
263706f2543Smrg/* This function does the actual log message writes. */
264706f2543Smrg
265706f2543Smrgvoid
266706f2543SmrgLogVWrite(int verb, const char *f, va_list args)
267706f2543Smrg{
268706f2543Smrg    static char tmpBuffer[1024];
269706f2543Smrg    int len = 0;
270706f2543Smrg    static Bool newline = TRUE;
271706f2543Smrg
272706f2543Smrg    if (newline) {
273706f2543Smrg	sprintf(tmpBuffer, "[%10.3f] ", GetTimeInMillis() / 1000.0);
274706f2543Smrg	len = strlen(tmpBuffer);
275706f2543Smrg	if (logFile)
276706f2543Smrg	    fwrite(tmpBuffer, len, 1, logFile);
277706f2543Smrg    }
278706f2543Smrg
279706f2543Smrg    /*
280706f2543Smrg     * Since a va_list can only be processed once, write the string to a
281706f2543Smrg     * buffer, and then write the buffer out to the appropriate output
282706f2543Smrg     * stream(s).
283706f2543Smrg     */
284706f2543Smrg    if (verb < 0 || logFileVerbosity >= verb || logVerbosity >= verb) {
285706f2543Smrg	vsnprintf(tmpBuffer, sizeof(tmpBuffer), f, args);
286706f2543Smrg	len = strlen(tmpBuffer);
287706f2543Smrg    }
288706f2543Smrg    newline = (tmpBuffer[len-1] == '\n');
289706f2543Smrg    if ((verb < 0 || logVerbosity >= verb) && len > 0)
290706f2543Smrg	fwrite(tmpBuffer, len, 1, stderr);
291706f2543Smrg    if ((verb < 0 || logFileVerbosity >= verb) && len > 0) {
292706f2543Smrg	if (logFile) {
293706f2543Smrg	    fwrite(tmpBuffer, len, 1, logFile);
294706f2543Smrg	    if (logFlush) {
295706f2543Smrg		fflush(logFile);
296706f2543Smrg#ifndef WIN32
297706f2543Smrg		if (logSync)
298706f2543Smrg		    fsync(fileno(logFile));
299706f2543Smrg#endif
300706f2543Smrg	    }
301706f2543Smrg	} else if (needBuffer) {
302706f2543Smrg	    if (len > bufferUnused) {
303706f2543Smrg		bufferSize += 1024;
304706f2543Smrg		bufferUnused += 1024;
305706f2543Smrg		saveBuffer = realloc(saveBuffer, bufferSize);
306706f2543Smrg		if (!saveBuffer)
307706f2543Smrg		    FatalError("realloc() failed while saving log messages\n");
308706f2543Smrg	    }
309706f2543Smrg	    bufferUnused -= len;
310706f2543Smrg	    memcpy(saveBuffer + bufferPos, tmpBuffer, len);
311706f2543Smrg	    bufferPos += len;
312706f2543Smrg	}
313706f2543Smrg    }
314706f2543Smrg}
315706f2543Smrg
316706f2543Smrgvoid
317706f2543SmrgLogWrite(int verb, const char *f, ...)
318706f2543Smrg{
319706f2543Smrg    va_list args;
320706f2543Smrg
321706f2543Smrg    va_start(args, f);
322706f2543Smrg    LogVWrite(verb, f, args);
323706f2543Smrg    va_end(args);
324706f2543Smrg}
325706f2543Smrg
326706f2543Smrgvoid
327706f2543SmrgLogVMessageVerb(MessageType type, int verb, const char *format, va_list args)
328706f2543Smrg{
329706f2543Smrg    const char *s  = X_UNKNOWN_STRING;
330706f2543Smrg    char tmpBuf[1024];
331706f2543Smrg
332706f2543Smrg    /* Ignore verbosity for X_ERROR */
333706f2543Smrg    if (logVerbosity >= verb || logFileVerbosity >= verb || type == X_ERROR) {
334706f2543Smrg	switch (type) {
335706f2543Smrg	case X_PROBED:
336706f2543Smrg	    s = X_PROBE_STRING;
337706f2543Smrg	    break;
338706f2543Smrg	case X_CONFIG:
339706f2543Smrg	    s = X_CONFIG_STRING;
340706f2543Smrg	    break;
341706f2543Smrg	case X_DEFAULT:
342706f2543Smrg	    s = X_DEFAULT_STRING;
343706f2543Smrg	    break;
344706f2543Smrg	case X_CMDLINE:
345706f2543Smrg	    s = X_CMDLINE_STRING;
346706f2543Smrg	    break;
347706f2543Smrg	case X_NOTICE:
348706f2543Smrg	    s = X_NOTICE_STRING;
349706f2543Smrg	    break;
350706f2543Smrg	case X_ERROR:
351706f2543Smrg	    s = X_ERROR_STRING;
352706f2543Smrg	    if (verb > 0)
353706f2543Smrg		verb = 0;
354706f2543Smrg	    break;
355706f2543Smrg	case X_WARNING:
356706f2543Smrg	    s = X_WARNING_STRING;
357706f2543Smrg	    break;
358706f2543Smrg	case X_INFO:
359706f2543Smrg	    s = X_INFO_STRING;
360706f2543Smrg	    break;
361706f2543Smrg	case X_NOT_IMPLEMENTED:
362706f2543Smrg	    s = X_NOT_IMPLEMENTED_STRING;
363706f2543Smrg	    break;
364706f2543Smrg	case X_UNKNOWN:
365706f2543Smrg	    s = X_UNKNOWN_STRING;
366706f2543Smrg	    break;
367706f2543Smrg	case X_NONE:
368706f2543Smrg	    s = NULL;
369706f2543Smrg	    break;
370706f2543Smrg	}
371706f2543Smrg
372706f2543Smrg        /* if s is not NULL we need a space before format */
373706f2543Smrg        snprintf(tmpBuf, sizeof(tmpBuf), "%s%s%s", s ? s : "",
374706f2543Smrg                                                   s ? " " : "",
375706f2543Smrg                                                   format);
376706f2543Smrg        LogVWrite(verb, tmpBuf, args);
377706f2543Smrg    }
378706f2543Smrg}
379706f2543Smrg
380706f2543Smrg/* Log message with verbosity level specified. */
381706f2543Smrgvoid
382706f2543SmrgLogMessageVerb(MessageType type, int verb, const char *format, ...)
383706f2543Smrg{
384706f2543Smrg    va_list ap;
385706f2543Smrg
386706f2543Smrg    va_start(ap, format);
387706f2543Smrg    LogVMessageVerb(type, verb, format, ap);
388706f2543Smrg    va_end(ap);
389706f2543Smrg}
390706f2543Smrg
391706f2543Smrg/* Log a message with the standard verbosity level of 1. */
392706f2543Smrgvoid
393706f2543SmrgLogMessage(MessageType type, const char *format, ...)
394706f2543Smrg{
395706f2543Smrg    va_list ap;
396706f2543Smrg
397706f2543Smrg    va_start(ap, format);
398706f2543Smrg    LogVMessageVerb(type, 1, format, ap);
399706f2543Smrg    va_end(ap);
400706f2543Smrg}
401706f2543Smrg
402706f2543Smrgvoid
403706f2543SmrgAbortServer(void) _X_NORETURN;
404706f2543Smrg
405706f2543Smrgvoid
406706f2543SmrgAbortServer(void)
407706f2543Smrg{
408706f2543Smrg#ifdef XF86BIGFONT
409706f2543Smrg    XF86BigfontCleanup();
410706f2543Smrg#endif
411706f2543Smrg    CloseWellKnownConnections();
412706f2543Smrg    OsCleanup(TRUE);
413706f2543Smrg    CloseDownDevices();
414706f2543Smrg    AbortDDX();
415706f2543Smrg    fflush(stderr);
416706f2543Smrg    if (CoreDump)
417706f2543Smrg	OsAbort();
418706f2543Smrg    exit (1);
419706f2543Smrg}
420706f2543Smrg
421706f2543Smrg#define AUDIT_PREFIX "AUDIT: %s: %ld: "
422706f2543Smrg#ifndef AUDIT_TIMEOUT
423706f2543Smrg#define AUDIT_TIMEOUT ((CARD32)(120 * 1000)) /* 2 mn */
424706f2543Smrg#endif
425706f2543Smrg
426706f2543Smrgstatic int nrepeat = 0;
427706f2543Smrgstatic int oldlen = -1;
428706f2543Smrgstatic OsTimerPtr auditTimer = NULL;
429706f2543Smrg
430706f2543Smrgvoid
431706f2543SmrgFreeAuditTimer(void)
432706f2543Smrg{
433706f2543Smrg    if (auditTimer != NULL) {
434706f2543Smrg	/* Force output of pending messages */
435706f2543Smrg	TimerForce(auditTimer);
436706f2543Smrg	TimerFree(auditTimer);
437706f2543Smrg	auditTimer = NULL;
438706f2543Smrg    }
439706f2543Smrg}
440706f2543Smrg
441706f2543Smrgstatic char *
442706f2543SmrgAuditPrefix(void)
443706f2543Smrg{
444706f2543Smrg    time_t tm;
445706f2543Smrg    char *autime, *s;
446706f2543Smrg    char *tmpBuf;
447706f2543Smrg    int len;
448706f2543Smrg
449706f2543Smrg    time(&tm);
450706f2543Smrg    autime = ctime(&tm);
451706f2543Smrg    if ((s = strchr(autime, '\n')))
452706f2543Smrg	*s = '\0';
453706f2543Smrg    len = strlen(AUDIT_PREFIX) + strlen(autime) + 10 + 1;
454706f2543Smrg    tmpBuf = malloc(len);
455706f2543Smrg    if (!tmpBuf)
456706f2543Smrg	return NULL;
457706f2543Smrg    snprintf(tmpBuf, len, AUDIT_PREFIX, autime, (unsigned long)getpid());
458706f2543Smrg    return tmpBuf;
459706f2543Smrg}
460706f2543Smrg
461706f2543Smrgvoid
462706f2543SmrgAuditF(const char * f, ...)
463706f2543Smrg{
464706f2543Smrg    va_list args;
465706f2543Smrg
466706f2543Smrg    va_start(args, f);
467706f2543Smrg
468706f2543Smrg    VAuditF(f, args);
469706f2543Smrg    va_end(args);
470706f2543Smrg}
471706f2543Smrg
472706f2543Smrgstatic CARD32
473706f2543SmrgAuditFlush(OsTimerPtr timer, CARD32 now, pointer arg)
474706f2543Smrg{
475706f2543Smrg    char *prefix;
476706f2543Smrg
477706f2543Smrg    if (nrepeat > 0) {
478706f2543Smrg	prefix = AuditPrefix();
479706f2543Smrg	ErrorF("%slast message repeated %d times\n",
480706f2543Smrg	       prefix != NULL ? prefix : "", nrepeat);
481706f2543Smrg	nrepeat = 0;
482706f2543Smrg	free(prefix);
483706f2543Smrg	return AUDIT_TIMEOUT;
484706f2543Smrg    } else {
485706f2543Smrg	/* if the timer expires without anything to print, flush the message */
486706f2543Smrg	oldlen = -1;
487706f2543Smrg	return 0;
488706f2543Smrg    }
489706f2543Smrg}
490706f2543Smrg
491706f2543Smrgvoid
492706f2543SmrgVAuditF(const char *f, va_list args)
493706f2543Smrg{
494706f2543Smrg    char *prefix;
495706f2543Smrg    char buf[1024];
496706f2543Smrg    int len;
497706f2543Smrg    static char oldbuf[1024];
498706f2543Smrg
499706f2543Smrg    prefix = AuditPrefix();
500706f2543Smrg    len = vsnprintf(buf, sizeof(buf), f, args);
501706f2543Smrg
502706f2543Smrg    if (len == oldlen && strcmp(buf, oldbuf) == 0) {
503706f2543Smrg	/* Message already seen */
504706f2543Smrg	nrepeat++;
505706f2543Smrg    } else {
506706f2543Smrg	/* new message */
507706f2543Smrg	if (auditTimer != NULL)
508706f2543Smrg	    TimerForce(auditTimer);
509706f2543Smrg	ErrorF("%s%s", prefix != NULL ? prefix : "", buf);
510706f2543Smrg	strlcpy(oldbuf, buf, sizeof(oldbuf));
511706f2543Smrg	oldlen = len;
512706f2543Smrg	nrepeat = 0;
513706f2543Smrg	auditTimer = TimerSet(auditTimer, 0, AUDIT_TIMEOUT, AuditFlush, NULL);
514706f2543Smrg    }
515706f2543Smrg    free(prefix);
516706f2543Smrg}
517706f2543Smrg
518706f2543Smrgvoid
519706f2543SmrgFatalError(const char *f, ...)
520706f2543Smrg{
521706f2543Smrg    va_list args;
522706f2543Smrg    static Bool beenhere = FALSE;
523706f2543Smrg
524706f2543Smrg    if (beenhere)
525706f2543Smrg	ErrorF("\nFatalError re-entered, aborting\n");
526706f2543Smrg    else
527706f2543Smrg	ErrorF("\nFatal server error:\n");
528706f2543Smrg
529706f2543Smrg    va_start(args, f);
530706f2543Smrg#ifdef __APPLE__
531706f2543Smrg    (void)vsnprintf(__crashreporter_info_buff__, sizeof(__crashreporter_info_buff__), f, args);
532706f2543Smrg#endif
533706f2543Smrg    VErrorF(f, args);
534706f2543Smrg    va_end(args);
535706f2543Smrg    ErrorF("\n");
536706f2543Smrg    if (!beenhere)
537706f2543Smrg	OsVendorFatalError();
538706f2543Smrg    if (!beenhere) {
539706f2543Smrg	beenhere = TRUE;
540706f2543Smrg	AbortServer();
541706f2543Smrg    } else
542706f2543Smrg	OsAbort();
543706f2543Smrg    /*NOTREACHED*/
544706f2543Smrg}
545706f2543Smrg
546706f2543Smrgvoid
547706f2543SmrgVErrorF(const char *f, va_list args)
548706f2543Smrg{
549706f2543Smrg#ifdef DDXOSVERRORF
550706f2543Smrg    if (OsVendorVErrorFProc)
551706f2543Smrg	OsVendorVErrorFProc(f, args);
552706f2543Smrg    else
553706f2543Smrg	LogVWrite(-1, f, args);
554706f2543Smrg#else
555706f2543Smrg    LogVWrite(-1, f, args);
556706f2543Smrg#endif
557706f2543Smrg}
558706f2543Smrg
559706f2543Smrgvoid
560706f2543SmrgErrorF(const char * f, ...)
561706f2543Smrg{
562706f2543Smrg    va_list args;
563706f2543Smrg
564706f2543Smrg    va_start(args, f);
565706f2543Smrg    VErrorF(f, args);
566706f2543Smrg    va_end(args);
567706f2543Smrg}
568706f2543Smrg
569706f2543Smrg/* A perror() workalike. */
570706f2543Smrg
571706f2543Smrgvoid
572706f2543SmrgError(const char *str)
573706f2543Smrg{
574706f2543Smrg    const char *err = strerror(errno);
575706f2543Smrg
576706f2543Smrg    if (str)
577706f2543Smrg	LogWrite(-1, "%s: %s", str, err);
578706f2543Smrg    else
579706f2543Smrg	LogWrite(-1, "%s", err);
580706f2543Smrg}
581706f2543Smrg
582706f2543Smrgvoid
583706f2543SmrgLogPrintMarkers(void)
584706f2543Smrg{
585706f2543Smrg    /* Show what the message marker symbols mean. */
586706f2543Smrg    LogWrite(0, "Markers: ");
587706f2543Smrg    LogMessageVerb(X_PROBED, 0, "probed, ");
588706f2543Smrg    LogMessageVerb(X_CONFIG, 0, "from config file, ");
589706f2543Smrg    LogMessageVerb(X_DEFAULT, 0, "default setting,\n\t");
590706f2543Smrg    LogMessageVerb(X_CMDLINE, 0, "from command line, ");
591706f2543Smrg    LogMessageVerb(X_NOTICE, 0, "notice, ");
592706f2543Smrg    LogMessageVerb(X_INFO, 0, "informational,\n\t");
593706f2543Smrg    LogMessageVerb(X_WARNING, 0, "warning, ");
594706f2543Smrg    LogMessageVerb(X_ERROR, 0, "error, ");
595706f2543Smrg    LogMessageVerb(X_NOT_IMPLEMENTED, 0, "not implemented, ");
596706f2543Smrg    LogMessageVerb(X_UNKNOWN, 0, "unknown.\n");
597706f2543Smrg}
598706f2543Smrg
599