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