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