log.c revision 4642e01f
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 10105b261ecSmrg 10205b261ecSmrg#ifdef DDXOSVERRORF 10305b261ecSmrgvoid (*OsVendorVErrorFProc)(const char *, va_list args) = NULL; 10405b261ecSmrg#endif 10505b261ecSmrg 10605b261ecSmrgstatic FILE *logFile = NULL; 10705b261ecSmrgstatic Bool logFlush = FALSE; 10805b261ecSmrgstatic Bool logSync = FALSE; 10905b261ecSmrgstatic int logVerbosity = DEFAULT_LOG_VERBOSITY; 11005b261ecSmrgstatic int logFileVerbosity = DEFAULT_LOG_FILE_VERBOSITY; 11105b261ecSmrg 11205b261ecSmrg/* Buffer to information logged before the log file is opened. */ 11305b261ecSmrgstatic char *saveBuffer = NULL; 11405b261ecSmrgstatic int bufferSize = 0, bufferUnused = 0, bufferPos = 0; 11505b261ecSmrgstatic Bool needBuffer = TRUE; 11605b261ecSmrg 11705b261ecSmrg/* Prefix strings for log messages. */ 11805b261ecSmrg#ifndef X_UNKNOWN_STRING 11905b261ecSmrg#define X_UNKNOWN_STRING "(\?\?)" 12005b261ecSmrg#endif 12105b261ecSmrg#ifndef X_PROBE_STRING 12205b261ecSmrg#define X_PROBE_STRING "(--)" 12305b261ecSmrg#endif 12405b261ecSmrg#ifndef X_CONFIG_STRING 12505b261ecSmrg#define X_CONFIG_STRING "(**)" 12605b261ecSmrg#endif 12705b261ecSmrg#ifndef X_DEFAULT_STRING 12805b261ecSmrg#define X_DEFAULT_STRING "(==)" 12905b261ecSmrg#endif 13005b261ecSmrg#ifndef X_CMDLINE_STRING 13105b261ecSmrg#define X_CMDLINE_STRING "(++)" 13205b261ecSmrg#endif 13305b261ecSmrg#ifndef X_NOTICE_STRING 13405b261ecSmrg#define X_NOTICE_STRING "(!!)" 13505b261ecSmrg#endif 13605b261ecSmrg#ifndef X_ERROR_STRING 13705b261ecSmrg#define X_ERROR_STRING "(EE)" 13805b261ecSmrg#endif 13905b261ecSmrg#ifndef X_WARNING_STRING 14005b261ecSmrg#define X_WARNING_STRING "(WW)" 14105b261ecSmrg#endif 14205b261ecSmrg#ifndef X_INFO_STRING 14305b261ecSmrg#define X_INFO_STRING "(II)" 14405b261ecSmrg#endif 14505b261ecSmrg#ifndef X_NOT_IMPLEMENTED_STRING 14605b261ecSmrg#define X_NOT_IMPLEMENTED_STRING "(NI)" 14705b261ecSmrg#endif 14805b261ecSmrg 14905b261ecSmrg/* 15005b261ecSmrg * LogInit is called to start logging to a file. It is also called (with 15105b261ecSmrg * NULL arguments) when logging to a file is not wanted. It must always be 15205b261ecSmrg * called, otherwise log messages will continue to accumulate in a buffer. 15305b261ecSmrg * 15405b261ecSmrg * %s, if present in the fname or backup strings, is expanded to the display 15505b261ecSmrg * string. 15605b261ecSmrg */ 15705b261ecSmrg 15805b261ecSmrgconst char * 15905b261ecSmrgLogInit(const char *fname, const char *backup) 16005b261ecSmrg{ 16105b261ecSmrg char *logFileName = NULL; 16205b261ecSmrg 16305b261ecSmrg if (fname && *fname) { 16405b261ecSmrg /* xalloc() can't be used yet. */ 16505b261ecSmrg logFileName = malloc(strlen(fname) + strlen(display) + 1); 16605b261ecSmrg if (!logFileName) 16705b261ecSmrg FatalError("Cannot allocate space for the log file name\n"); 16805b261ecSmrg sprintf(logFileName, fname, display); 16905b261ecSmrg 17005b261ecSmrg if (backup && *backup) { 17105b261ecSmrg struct stat buf; 17205b261ecSmrg 17305b261ecSmrg if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) { 17405b261ecSmrg char *suffix; 17505b261ecSmrg char *oldLog; 17605b261ecSmrg 17705b261ecSmrg oldLog = malloc(strlen(logFileName) + strlen(backup) + 17805b261ecSmrg strlen(display) + 1); 17905b261ecSmrg suffix = malloc(strlen(backup) + strlen(display) + 1); 18005b261ecSmrg if (!oldLog || !suffix) 18105b261ecSmrg FatalError("Cannot allocate space for the log file name\n"); 18205b261ecSmrg sprintf(suffix, backup, display); 18305b261ecSmrg sprintf(oldLog, "%s%s", logFileName, suffix); 18405b261ecSmrg free(suffix); 18505b261ecSmrg if (rename(logFileName, oldLog) == -1) { 18605b261ecSmrg FatalError("Cannot move old log file (\"%s\" to \"%s\"\n", 18705b261ecSmrg logFileName, oldLog); 18805b261ecSmrg } 18905b261ecSmrg free(oldLog); 19005b261ecSmrg } 19105b261ecSmrg } 19205b261ecSmrg if ((logFile = fopen(logFileName, "w")) == NULL) 19305b261ecSmrg FatalError("Cannot open log file \"%s\"\n", logFileName); 19405b261ecSmrg setvbuf(logFile, NULL, _IONBF, 0); 19505b261ecSmrg 19605b261ecSmrg /* Flush saved log information. */ 19705b261ecSmrg if (saveBuffer && bufferSize > 0) { 19805b261ecSmrg fwrite(saveBuffer, bufferPos, 1, logFile); 19905b261ecSmrg fflush(logFile); 20005b261ecSmrg#ifndef WIN32 20105b261ecSmrg fsync(fileno(logFile)); 20205b261ecSmrg#endif 20305b261ecSmrg } 20405b261ecSmrg } 20505b261ecSmrg 20605b261ecSmrg /* 20705b261ecSmrg * Unconditionally free the buffer, and flag that the buffer is no longer 20805b261ecSmrg * needed. 20905b261ecSmrg */ 21005b261ecSmrg if (saveBuffer && bufferSize > 0) { 21105b261ecSmrg free(saveBuffer); /* Must be free(), not xfree() */ 21205b261ecSmrg saveBuffer = NULL; 21305b261ecSmrg bufferSize = 0; 21405b261ecSmrg } 21505b261ecSmrg needBuffer = FALSE; 21605b261ecSmrg 21705b261ecSmrg return logFileName; 21805b261ecSmrg} 21905b261ecSmrg 22005b261ecSmrgvoid 22105b261ecSmrgLogClose(void) 22205b261ecSmrg{ 22305b261ecSmrg if (logFile) { 22405b261ecSmrg fclose(logFile); 22505b261ecSmrg logFile = NULL; 22605b261ecSmrg } 22705b261ecSmrg} 22805b261ecSmrg 22905b261ecSmrgBool 23005b261ecSmrgLogSetParameter(LogParameter param, int value) 23105b261ecSmrg{ 23205b261ecSmrg switch (param) { 23305b261ecSmrg case XLOG_FLUSH: 23405b261ecSmrg logFlush = value ? TRUE : FALSE; 23505b261ecSmrg return TRUE; 23605b261ecSmrg case XLOG_SYNC: 23705b261ecSmrg logSync = value ? TRUE : FALSE; 23805b261ecSmrg return TRUE; 23905b261ecSmrg case XLOG_VERBOSITY: 24005b261ecSmrg logVerbosity = value; 24105b261ecSmrg return TRUE; 24205b261ecSmrg case XLOG_FILE_VERBOSITY: 24305b261ecSmrg logFileVerbosity = value; 24405b261ecSmrg return TRUE; 24505b261ecSmrg default: 24605b261ecSmrg return FALSE; 24705b261ecSmrg } 24805b261ecSmrg} 24905b261ecSmrg 25005b261ecSmrg/* This function does the actual log message writes. */ 25105b261ecSmrg 25205b261ecSmrg_X_EXPORT void 25305b261ecSmrgLogVWrite(int verb, const char *f, va_list args) 25405b261ecSmrg{ 25505b261ecSmrg static char tmpBuffer[1024]; 25605b261ecSmrg int len = 0; 25705b261ecSmrg 25805b261ecSmrg /* 25905b261ecSmrg * Since a va_list can only be processed once, write the string to a 26005b261ecSmrg * buffer, and then write the buffer out to the appropriate output 26105b261ecSmrg * stream(s). 26205b261ecSmrg */ 26305b261ecSmrg if (verb < 0 || logFileVerbosity >= verb || logVerbosity >= verb) { 26405b261ecSmrg vsnprintf(tmpBuffer, sizeof(tmpBuffer), f, args); 26505b261ecSmrg len = strlen(tmpBuffer); 26605b261ecSmrg } 26705b261ecSmrg if ((verb < 0 || logVerbosity >= verb) && len > 0) 26805b261ecSmrg fwrite(tmpBuffer, len, 1, stderr); 26905b261ecSmrg if ((verb < 0 || logFileVerbosity >= verb) && len > 0) { 27005b261ecSmrg if (logFile) { 27105b261ecSmrg fwrite(tmpBuffer, len, 1, logFile); 27205b261ecSmrg if (logFlush) { 27305b261ecSmrg fflush(logFile); 27405b261ecSmrg#ifndef WIN32 27505b261ecSmrg if (logSync) 27605b261ecSmrg fsync(fileno(logFile)); 27705b261ecSmrg#endif 27805b261ecSmrg } 27905b261ecSmrg } else if (needBuffer) { 28005b261ecSmrg /* 28105b261ecSmrg * Note, this code is used before OsInit() has been called, so 28205b261ecSmrg * xalloc() and friends can't be used. 28305b261ecSmrg */ 28405b261ecSmrg if (len > bufferUnused) { 28505b261ecSmrg bufferSize += 1024; 28605b261ecSmrg bufferUnused += 1024; 28705b261ecSmrg if (saveBuffer) 28805b261ecSmrg saveBuffer = realloc(saveBuffer, bufferSize); 28905b261ecSmrg else 29005b261ecSmrg saveBuffer = malloc(bufferSize); 29105b261ecSmrg if (!saveBuffer) 29205b261ecSmrg FatalError("realloc() failed while saving log messages\n"); 29305b261ecSmrg } 29405b261ecSmrg bufferUnused -= len; 29505b261ecSmrg memcpy(saveBuffer + bufferPos, tmpBuffer, len); 29605b261ecSmrg bufferPos += len; 29705b261ecSmrg } 29805b261ecSmrg } 29905b261ecSmrg} 30005b261ecSmrg 30105b261ecSmrg_X_EXPORT void 30205b261ecSmrgLogWrite(int verb, const char *f, ...) 30305b261ecSmrg{ 30405b261ecSmrg va_list args; 30505b261ecSmrg 30605b261ecSmrg va_start(args, f); 30705b261ecSmrg LogVWrite(verb, f, args); 30805b261ecSmrg va_end(args); 30905b261ecSmrg} 31005b261ecSmrg 31105b261ecSmrg_X_EXPORT void 31205b261ecSmrgLogVMessageVerb(MessageType type, int verb, const char *format, va_list args) 31305b261ecSmrg{ 31405b261ecSmrg const char *s = X_UNKNOWN_STRING; 31505b261ecSmrg char *tmpBuf = NULL; 31605b261ecSmrg 31705b261ecSmrg /* Ignore verbosity for X_ERROR */ 31805b261ecSmrg if (logVerbosity >= verb || logFileVerbosity >= verb || type == X_ERROR) { 31905b261ecSmrg switch (type) { 32005b261ecSmrg case X_PROBED: 32105b261ecSmrg s = X_PROBE_STRING; 32205b261ecSmrg break; 32305b261ecSmrg case X_CONFIG: 32405b261ecSmrg s = X_CONFIG_STRING; 32505b261ecSmrg break; 32605b261ecSmrg case X_DEFAULT: 32705b261ecSmrg s = X_DEFAULT_STRING; 32805b261ecSmrg break; 32905b261ecSmrg case X_CMDLINE: 33005b261ecSmrg s = X_CMDLINE_STRING; 33105b261ecSmrg break; 33205b261ecSmrg case X_NOTICE: 33305b261ecSmrg s = X_NOTICE_STRING; 33405b261ecSmrg break; 33505b261ecSmrg case X_ERROR: 33605b261ecSmrg s = X_ERROR_STRING; 33705b261ecSmrg if (verb > 0) 33805b261ecSmrg verb = 0; 33905b261ecSmrg break; 34005b261ecSmrg case X_WARNING: 34105b261ecSmrg s = X_WARNING_STRING; 34205b261ecSmrg break; 34305b261ecSmrg case X_INFO: 34405b261ecSmrg s = X_INFO_STRING; 34505b261ecSmrg break; 34605b261ecSmrg case X_NOT_IMPLEMENTED: 34705b261ecSmrg s = X_NOT_IMPLEMENTED_STRING; 34805b261ecSmrg break; 34905b261ecSmrg case X_UNKNOWN: 35005b261ecSmrg s = X_UNKNOWN_STRING; 35105b261ecSmrg break; 35205b261ecSmrg case X_NONE: 35305b261ecSmrg s = NULL; 35405b261ecSmrg break; 35505b261ecSmrg } 35605b261ecSmrg 35705b261ecSmrg /* 35805b261ecSmrg * Prefix the format string with the message type. We do it this way 35905b261ecSmrg * so that LogVWrite() is only called once per message. 36005b261ecSmrg */ 36105b261ecSmrg if (s) { 36205b261ecSmrg tmpBuf = malloc(strlen(format) + strlen(s) + 1 + 1); 36305b261ecSmrg /* Silently return if malloc fails here. */ 36405b261ecSmrg if (!tmpBuf) 36505b261ecSmrg return; 36605b261ecSmrg sprintf(tmpBuf, "%s ", s); 36705b261ecSmrg strcat(tmpBuf, format); 36805b261ecSmrg LogVWrite(verb, tmpBuf, args); 36905b261ecSmrg free(tmpBuf); 37005b261ecSmrg } else 37105b261ecSmrg LogVWrite(verb, format, args); 37205b261ecSmrg } 37305b261ecSmrg} 37405b261ecSmrg 37505b261ecSmrg/* Log message with verbosity level specified. */ 37605b261ecSmrg_X_EXPORT void 37705b261ecSmrgLogMessageVerb(MessageType type, int verb, const char *format, ...) 37805b261ecSmrg{ 37905b261ecSmrg va_list ap; 38005b261ecSmrg 38105b261ecSmrg va_start(ap, format); 38205b261ecSmrg LogVMessageVerb(type, verb, format, ap); 38305b261ecSmrg va_end(ap); 38405b261ecSmrg} 38505b261ecSmrg 38605b261ecSmrg/* Log a message with the standard verbosity level of 1. */ 38705b261ecSmrg_X_EXPORT void 38805b261ecSmrgLogMessage(MessageType type, const char *format, ...) 38905b261ecSmrg{ 39005b261ecSmrg va_list ap; 39105b261ecSmrg 39205b261ecSmrg va_start(ap, format); 39305b261ecSmrg LogVMessageVerb(type, 1, format, ap); 39405b261ecSmrg va_end(ap); 39505b261ecSmrg} 39605b261ecSmrg 39705b261ecSmrg#ifdef __GNUC__ 39805b261ecSmrgvoid AbortServer(void) __attribute__((noreturn)); 39905b261ecSmrg#endif 40005b261ecSmrg 40105b261ecSmrgvoid 40205b261ecSmrgAbortServer(void) 40305b261ecSmrg{ 4044642e01fSmrg CloseWellKnownConnections(); 40505b261ecSmrg OsCleanup(TRUE); 40605b261ecSmrg CloseDownDevices(); 40705b261ecSmrg AbortDDX(); 40805b261ecSmrg fflush(stderr); 40905b261ecSmrg if (CoreDump) 41005b261ecSmrg abort(); 41105b261ecSmrg exit (1); 41205b261ecSmrg} 41305b261ecSmrg 4144642e01fSmrg#define AUDIT_PREFIX "AUDIT: %s: %ld: " 41505b261ecSmrg#ifndef AUDIT_TIMEOUT 41605b261ecSmrg#define AUDIT_TIMEOUT ((CARD32)(120 * 1000)) /* 2 mn */ 41705b261ecSmrg#endif 41805b261ecSmrg 41905b261ecSmrgstatic int nrepeat = 0; 42005b261ecSmrgstatic int oldlen = -1; 42105b261ecSmrgstatic OsTimerPtr auditTimer = NULL; 42205b261ecSmrg 42305b261ecSmrgvoid 42405b261ecSmrgFreeAuditTimer(void) 42505b261ecSmrg{ 42605b261ecSmrg if (auditTimer != NULL) { 42705b261ecSmrg /* Force output of pending messages */ 42805b261ecSmrg TimerForce(auditTimer); 42905b261ecSmrg TimerFree(auditTimer); 43005b261ecSmrg auditTimer = NULL; 43105b261ecSmrg } 43205b261ecSmrg} 43305b261ecSmrg 43405b261ecSmrgstatic char * 43505b261ecSmrgAuditPrefix(void) 43605b261ecSmrg{ 43705b261ecSmrg time_t tm; 43805b261ecSmrg char *autime, *s; 43905b261ecSmrg char *tmpBuf; 44005b261ecSmrg int len; 44105b261ecSmrg 44205b261ecSmrg time(&tm); 44305b261ecSmrg autime = ctime(&tm); 44405b261ecSmrg if ((s = strchr(autime, '\n'))) 44505b261ecSmrg *s = '\0'; 4464642e01fSmrg len = strlen(AUDIT_PREFIX) + strlen(autime) + 10 + 1; 44705b261ecSmrg tmpBuf = malloc(len); 44805b261ecSmrg if (!tmpBuf) 44905b261ecSmrg return NULL; 4504642e01fSmrg snprintf(tmpBuf, len, AUDIT_PREFIX, autime, (unsigned long)getpid()); 45105b261ecSmrg return tmpBuf; 45205b261ecSmrg} 45305b261ecSmrg 45405b261ecSmrgvoid 45505b261ecSmrgAuditF(const char * f, ...) 45605b261ecSmrg{ 45705b261ecSmrg va_list args; 45805b261ecSmrg 45905b261ecSmrg va_start(args, f); 46005b261ecSmrg 46105b261ecSmrg VAuditF(f, args); 46205b261ecSmrg va_end(args); 46305b261ecSmrg} 46405b261ecSmrg 46505b261ecSmrgstatic CARD32 46605b261ecSmrgAuditFlush(OsTimerPtr timer, CARD32 now, pointer arg) 46705b261ecSmrg{ 46805b261ecSmrg char *prefix; 46905b261ecSmrg 47005b261ecSmrg if (nrepeat > 0) { 47105b261ecSmrg prefix = AuditPrefix(); 47205b261ecSmrg ErrorF("%slast message repeated %d times\n", 47305b261ecSmrg prefix != NULL ? prefix : "", nrepeat); 47405b261ecSmrg nrepeat = 0; 47505b261ecSmrg if (prefix != NULL) 47605b261ecSmrg free(prefix); 47705b261ecSmrg return AUDIT_TIMEOUT; 47805b261ecSmrg } else { 47905b261ecSmrg /* if the timer expires without anything to print, flush the message */ 48005b261ecSmrg oldlen = -1; 48105b261ecSmrg return 0; 48205b261ecSmrg } 48305b261ecSmrg} 48405b261ecSmrg 48505b261ecSmrgvoid 48605b261ecSmrgVAuditF(const char *f, va_list args) 48705b261ecSmrg{ 48805b261ecSmrg char *prefix; 48905b261ecSmrg char buf[1024]; 49005b261ecSmrg int len; 49105b261ecSmrg static char oldbuf[1024]; 49205b261ecSmrg 49305b261ecSmrg prefix = AuditPrefix(); 49405b261ecSmrg len = vsnprintf(buf, sizeof(buf), f, args); 49505b261ecSmrg 49605b261ecSmrg if (len == oldlen && strcmp(buf, oldbuf) == 0) { 49705b261ecSmrg /* Message already seen */ 49805b261ecSmrg nrepeat++; 49905b261ecSmrg } else { 50005b261ecSmrg /* new message */ 50105b261ecSmrg if (auditTimer != NULL) 50205b261ecSmrg TimerForce(auditTimer); 50305b261ecSmrg ErrorF("%s%s", prefix != NULL ? prefix : "", buf); 50405b261ecSmrg strlcpy(oldbuf, buf, sizeof(oldbuf)); 50505b261ecSmrg oldlen = len; 50605b261ecSmrg nrepeat = 0; 50705b261ecSmrg auditTimer = TimerSet(auditTimer, 0, AUDIT_TIMEOUT, AuditFlush, NULL); 50805b261ecSmrg } 50905b261ecSmrg if (prefix != NULL) 51005b261ecSmrg free(prefix); 51105b261ecSmrg} 51205b261ecSmrg 51305b261ecSmrg_X_EXPORT void 51405b261ecSmrgFatalError(const char *f, ...) 51505b261ecSmrg{ 51605b261ecSmrg va_list args; 51705b261ecSmrg static Bool beenhere = FALSE; 51805b261ecSmrg 51905b261ecSmrg if (beenhere) 52005b261ecSmrg ErrorF("\nFatalError re-entered, aborting\n"); 52105b261ecSmrg else 52205b261ecSmrg ErrorF("\nFatal server error:\n"); 52305b261ecSmrg 52405b261ecSmrg va_start(args, f); 52505b261ecSmrg VErrorF(f, args); 52605b261ecSmrg va_end(args); 52705b261ecSmrg ErrorF("\n"); 52805b261ecSmrg if (!beenhere) 52905b261ecSmrg OsVendorFatalError(); 53005b261ecSmrg if (!beenhere) { 53105b261ecSmrg beenhere = TRUE; 53205b261ecSmrg AbortServer(); 53305b261ecSmrg } else 53405b261ecSmrg abort(); 53505b261ecSmrg /*NOTREACHED*/ 53605b261ecSmrg} 53705b261ecSmrg 53805b261ecSmrg_X_EXPORT void 53905b261ecSmrgVErrorF(const char *f, va_list args) 54005b261ecSmrg{ 54105b261ecSmrg#ifdef DDXOSVERRORF 54205b261ecSmrg if (OsVendorVErrorFProc) 54305b261ecSmrg OsVendorVErrorFProc(f, args); 54405b261ecSmrg else 54505b261ecSmrg LogVWrite(-1, f, args); 54605b261ecSmrg#else 54705b261ecSmrg LogVWrite(-1, f, args); 54805b261ecSmrg#endif 54905b261ecSmrg} 55005b261ecSmrg 55105b261ecSmrg_X_EXPORT void 55205b261ecSmrgErrorF(const char * f, ...) 55305b261ecSmrg{ 55405b261ecSmrg va_list args; 55505b261ecSmrg 55605b261ecSmrg va_start(args, f); 55705b261ecSmrg VErrorF(f, args); 55805b261ecSmrg va_end(args); 55905b261ecSmrg} 56005b261ecSmrg 56105b261ecSmrg/* A perror() workalike. */ 56205b261ecSmrg 56305b261ecSmrg_X_EXPORT void 56405b261ecSmrgError(char *str) 56505b261ecSmrg{ 56605b261ecSmrg char *err = NULL; 56705b261ecSmrg int saveErrno = errno; 56805b261ecSmrg 56905b261ecSmrg if (str) { 57005b261ecSmrg err = malloc(strlen(strerror(saveErrno)) + strlen(str) + 2 + 1); 57105b261ecSmrg if (!err) 57205b261ecSmrg return; 57305b261ecSmrg sprintf(err, "%s: ", str); 57405b261ecSmrg strcat(err, strerror(saveErrno)); 5754642e01fSmrg LogWrite(-1, "%s", err); 5764642e01fSmrg free(err); 57705b261ecSmrg } else 5784642e01fSmrg LogWrite(-1, "%s", strerror(saveErrno)); 57905b261ecSmrg} 58005b261ecSmrg 58105b261ecSmrgvoid 58205b261ecSmrgLogPrintMarkers(void) 58305b261ecSmrg{ 58405b261ecSmrg /* Show what the message marker symbols mean. */ 58505b261ecSmrg ErrorF("Markers: "); 58605b261ecSmrg LogMessageVerb(X_PROBED, -1, "probed, "); 58705b261ecSmrg LogMessageVerb(X_CONFIG, -1, "from config file, "); 58805b261ecSmrg LogMessageVerb(X_DEFAULT, -1, "default setting,\n\t"); 58905b261ecSmrg LogMessageVerb(X_CMDLINE, -1, "from command line, "); 59005b261ecSmrg LogMessageVerb(X_NOTICE, -1, "notice, "); 59105b261ecSmrg LogMessageVerb(X_INFO, -1, "informational,\n\t"); 59205b261ecSmrg LogMessageVerb(X_WARNING, -1, "warning, "); 59305b261ecSmrg LogMessageVerb(X_ERROR, -1, "error, "); 59405b261ecSmrg LogMessageVerb(X_NOT_IMPLEMENTED, -1, "not implemented, "); 59505b261ecSmrg LogMessageVerb(X_UNKNOWN, -1, "unknown.\n"); 59605b261ecSmrg} 59705b261ecSmrg 598