log.c revision 05b261ec
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{ 40405b261ecSmrg OsCleanup(TRUE); 40505b261ecSmrg CloseDownDevices(); 40605b261ecSmrg AbortDDX(); 40705b261ecSmrg fflush(stderr); 40805b261ecSmrg if (CoreDump) 40905b261ecSmrg abort(); 41005b261ecSmrg exit (1); 41105b261ecSmrg} 41205b261ecSmrg 41305b261ecSmrg#ifndef AUDIT_PREFIX 41405b261ecSmrg#define AUDIT_PREFIX "AUDIT: %s: %ld %s: " 41505b261ecSmrg#endif 41605b261ecSmrg#ifndef AUDIT_TIMEOUT 41705b261ecSmrg#define AUDIT_TIMEOUT ((CARD32)(120 * 1000)) /* 2 mn */ 41805b261ecSmrg#endif 41905b261ecSmrg 42005b261ecSmrgstatic int nrepeat = 0; 42105b261ecSmrgstatic int oldlen = -1; 42205b261ecSmrgstatic OsTimerPtr auditTimer = NULL; 42305b261ecSmrg 42405b261ecSmrgvoid 42505b261ecSmrgFreeAuditTimer(void) 42605b261ecSmrg{ 42705b261ecSmrg if (auditTimer != NULL) { 42805b261ecSmrg /* Force output of pending messages */ 42905b261ecSmrg TimerForce(auditTimer); 43005b261ecSmrg TimerFree(auditTimer); 43105b261ecSmrg auditTimer = NULL; 43205b261ecSmrg } 43305b261ecSmrg} 43405b261ecSmrg 43505b261ecSmrgstatic char * 43605b261ecSmrgAuditPrefix(void) 43705b261ecSmrg{ 43805b261ecSmrg time_t tm; 43905b261ecSmrg char *autime, *s; 44005b261ecSmrg char *tmpBuf; 44105b261ecSmrg int len; 44205b261ecSmrg 44305b261ecSmrg time(&tm); 44405b261ecSmrg autime = ctime(&tm); 44505b261ecSmrg if ((s = strchr(autime, '\n'))) 44605b261ecSmrg *s = '\0'; 44705b261ecSmrg if ((s = strrchr(argvGlobal[0], '/'))) 44805b261ecSmrg s++; 44905b261ecSmrg else 45005b261ecSmrg s = argvGlobal[0]; 45105b261ecSmrg len = strlen(AUDIT_PREFIX) + strlen(autime) + 10 + strlen(s) + 1; 45205b261ecSmrg tmpBuf = malloc(len); 45305b261ecSmrg if (!tmpBuf) 45405b261ecSmrg return NULL; 45505b261ecSmrg snprintf(tmpBuf, len, AUDIT_PREFIX, autime, (unsigned long)getpid(), s); 45605b261ecSmrg return tmpBuf; 45705b261ecSmrg} 45805b261ecSmrg 45905b261ecSmrgvoid 46005b261ecSmrgAuditF(const char * f, ...) 46105b261ecSmrg{ 46205b261ecSmrg va_list args; 46305b261ecSmrg 46405b261ecSmrg va_start(args, f); 46505b261ecSmrg 46605b261ecSmrg VAuditF(f, args); 46705b261ecSmrg va_end(args); 46805b261ecSmrg} 46905b261ecSmrg 47005b261ecSmrgstatic CARD32 47105b261ecSmrgAuditFlush(OsTimerPtr timer, CARD32 now, pointer arg) 47205b261ecSmrg{ 47305b261ecSmrg char *prefix; 47405b261ecSmrg 47505b261ecSmrg if (nrepeat > 0) { 47605b261ecSmrg prefix = AuditPrefix(); 47705b261ecSmrg ErrorF("%slast message repeated %d times\n", 47805b261ecSmrg prefix != NULL ? prefix : "", nrepeat); 47905b261ecSmrg nrepeat = 0; 48005b261ecSmrg if (prefix != NULL) 48105b261ecSmrg free(prefix); 48205b261ecSmrg return AUDIT_TIMEOUT; 48305b261ecSmrg } else { 48405b261ecSmrg /* if the timer expires without anything to print, flush the message */ 48505b261ecSmrg oldlen = -1; 48605b261ecSmrg return 0; 48705b261ecSmrg } 48805b261ecSmrg} 48905b261ecSmrg 49005b261ecSmrgvoid 49105b261ecSmrgVAuditF(const char *f, va_list args) 49205b261ecSmrg{ 49305b261ecSmrg char *prefix; 49405b261ecSmrg char buf[1024]; 49505b261ecSmrg int len; 49605b261ecSmrg static char oldbuf[1024]; 49705b261ecSmrg 49805b261ecSmrg prefix = AuditPrefix(); 49905b261ecSmrg len = vsnprintf(buf, sizeof(buf), f, args); 50005b261ecSmrg 50105b261ecSmrg#if 1 50205b261ecSmrg /* XXX Compressing duplicated messages is temporarily disabled to 50305b261ecSmrg * work around bugzilla 964: 50405b261ecSmrg * https://freedesktop.org/bugzilla/show_bug.cgi?id=964 50505b261ecSmrg */ 50605b261ecSmrg ErrorF("%s%s", prefix != NULL ? prefix : "", buf); 50705b261ecSmrg oldlen = -1; 50805b261ecSmrg nrepeat = 0; 50905b261ecSmrg#else 51005b261ecSmrg if (len == oldlen && strcmp(buf, oldbuf) == 0) { 51105b261ecSmrg /* Message already seen */ 51205b261ecSmrg nrepeat++; 51305b261ecSmrg } else { 51405b261ecSmrg /* new message */ 51505b261ecSmrg if (auditTimer != NULL) 51605b261ecSmrg TimerForce(auditTimer); 51705b261ecSmrg ErrorF("%s%s", prefix != NULL ? prefix : "", buf); 51805b261ecSmrg strlcpy(oldbuf, buf, sizeof(oldbuf)); 51905b261ecSmrg oldlen = len; 52005b261ecSmrg nrepeat = 0; 52105b261ecSmrg auditTimer = TimerSet(auditTimer, 0, AUDIT_TIMEOUT, AuditFlush, NULL); 52205b261ecSmrg } 52305b261ecSmrg#endif 52405b261ecSmrg if (prefix != NULL) 52505b261ecSmrg free(prefix); 52605b261ecSmrg} 52705b261ecSmrg 52805b261ecSmrg_X_EXPORT void 52905b261ecSmrgFatalError(const char *f, ...) 53005b261ecSmrg{ 53105b261ecSmrg va_list args; 53205b261ecSmrg static Bool beenhere = FALSE; 53305b261ecSmrg 53405b261ecSmrg if (beenhere) 53505b261ecSmrg ErrorF("\nFatalError re-entered, aborting\n"); 53605b261ecSmrg else 53705b261ecSmrg ErrorF("\nFatal server error:\n"); 53805b261ecSmrg 53905b261ecSmrg va_start(args, f); 54005b261ecSmrg VErrorF(f, args); 54105b261ecSmrg va_end(args); 54205b261ecSmrg ErrorF("\n"); 54305b261ecSmrg#ifdef DDXOSFATALERROR 54405b261ecSmrg if (!beenhere) 54505b261ecSmrg OsVendorFatalError(); 54605b261ecSmrg#endif 54705b261ecSmrg#ifdef ABORTONFATALERROR 54805b261ecSmrg abort(); 54905b261ecSmrg#endif 55005b261ecSmrg if (!beenhere) { 55105b261ecSmrg beenhere = TRUE; 55205b261ecSmrg AbortServer(); 55305b261ecSmrg } else 55405b261ecSmrg abort(); 55505b261ecSmrg /*NOTREACHED*/ 55605b261ecSmrg} 55705b261ecSmrg 55805b261ecSmrg_X_EXPORT void 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 57105b261ecSmrg_X_EXPORT void 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 58305b261ecSmrg#ifndef NEED_STRERROR 58405b261ecSmrg#ifdef SYSV 58505b261ecSmrg#if !defined(ISC) || defined(ISC202) || defined(ISC22) 58605b261ecSmrg#define NEED_STRERROR 58705b261ecSmrg#endif 58805b261ecSmrg#endif 58905b261ecSmrg#endif 59005b261ecSmrg 59105b261ecSmrg#if defined(NEED_STRERROR) && !defined(strerror) 59205b261ecSmrgextern char *sys_errlist[]; 59305b261ecSmrgextern int sys_nerr; 59405b261ecSmrg#define strerror(n) \ 59505b261ecSmrg ((n) >= 0 && (n) < sys_nerr) ? sys_errlist[(n)] : "unknown error" 59605b261ecSmrg#endif 59705b261ecSmrg 59805b261ecSmrg_X_EXPORT void 59905b261ecSmrgError(char *str) 60005b261ecSmrg{ 60105b261ecSmrg char *err = NULL; 60205b261ecSmrg int saveErrno = errno; 60305b261ecSmrg 60405b261ecSmrg if (str) { 60505b261ecSmrg err = malloc(strlen(strerror(saveErrno)) + strlen(str) + 2 + 1); 60605b261ecSmrg if (!err) 60705b261ecSmrg return; 60805b261ecSmrg sprintf(err, "%s: ", str); 60905b261ecSmrg strcat(err, strerror(saveErrno)); 61005b261ecSmrg LogWrite(-1, err); 61105b261ecSmrg } else 61205b261ecSmrg LogWrite(-1, strerror(saveErrno)); 61305b261ecSmrg} 61405b261ecSmrg 61505b261ecSmrgvoid 61605b261ecSmrgLogPrintMarkers(void) 61705b261ecSmrg{ 61805b261ecSmrg /* Show what the message marker symbols mean. */ 61905b261ecSmrg ErrorF("Markers: "); 62005b261ecSmrg LogMessageVerb(X_PROBED, -1, "probed, "); 62105b261ecSmrg LogMessageVerb(X_CONFIG, -1, "from config file, "); 62205b261ecSmrg LogMessageVerb(X_DEFAULT, -1, "default setting,\n\t"); 62305b261ecSmrg LogMessageVerb(X_CMDLINE, -1, "from command line, "); 62405b261ecSmrg LogMessageVerb(X_NOTICE, -1, "notice, "); 62505b261ecSmrg LogMessageVerb(X_INFO, -1, "informational,\n\t"); 62605b261ecSmrg LogMessageVerb(X_WARNING, -1, "warning, "); 62705b261ecSmrg LogMessageVerb(X_ERROR, -1, "error, "); 62805b261ecSmrg LogMessageVerb(X_NOT_IMPLEMENTED, -1, "not implemented, "); 62905b261ecSmrg LogMessageVerb(X_UNKNOWN, -1, "unknown.\n"); 63005b261ecSmrg} 63105b261ecSmrg 632