3 Copyright 1987, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of The Open Group shall
23 not be used in advertising or otherwise to promote the sale, use or
24 other dealings in this Software without prior written authorization
27 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
28 Copyright 1994 Quarterdeck Office Systems.
32 Permission to use, copy, modify, and distribute this software and its
33 documentation for any purpose and without fee is hereby granted,
34 provided that the above copyright notice appear in all copies and that
35 both that copyright notice and this permission notice appear in
36 supporting documentation, and that the names of Digital and
37 Quarterdeck not be used in advertising or publicity pertaining to
38 distribution of the software without specific, written prior
41 DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
42 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
43 FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
44 OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
45 OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
46 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
47 OR PERFORMANCE OF THIS SOFTWARE.
52 * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
54 * Permission is hereby granted, free of charge, to any person obtaining a
55 * copy of this software and associated documentation files (the "Software"),
56 * to deal in the Software without restriction, including without limitation
57 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
58 * and/or sell copies of the Software, and to permit persons to whom the
59 * Software is furnished to do so, subject to the following conditions:
61 * The above copyright notice and this permission notice shall be included in
62 * all copies or substantial portions of the Software.
64 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
65 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
66 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
67 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
68 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
69 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
70 * OTHER DEALINGS IN THE SOFTWARE.
72 * Except as contained in this notice, the name of the copyright holder(s)
73 * and author(s) shall not be used in advertising or otherwise to promote
74 * the sale, use or other dealings in this Software without prior written
75 * authorization from the copyright holder(s) and author(s).
78 #ifdef HAVE_DIX_CONFIG_H
79 #include <dix-config.h>
87 #include <stdlib.h> /* for malloc() */
95 #define getpid(x) _getpid(x)
99 #include "xf86bigfontsrv.h"
103 #pragma clang diagnostic ignored "-Wformat-nonliteral"
107 void (*OsVendorVErrorFProc) (const char *, va_list args) = NULL;
110 static FILE *logFile = NULL;
111 static int logFileFd = -1;
112 static Bool logFlush = FALSE;
113 static Bool logSync = FALSE;
114 static int logVerbosity = DEFAULT_LOG_VERBOSITY;
115 static int logFileVerbosity = DEFAULT_LOG_FILE_VERBOSITY;
117 /* Buffer to information logged before the log file is opened. */
118 static char *saveBuffer = NULL;
119 static int bufferSize = 0, bufferUnused = 0, bufferPos = 0;
120 static Bool needBuffer = TRUE;
123 #include <AvailabilityMacros.h>
125 static char __crashreporter_info_buff__[4096] = { 0 };
127 static const char *__crashreporter_info__ __attribute__ ((__used__)) =
128 &__crashreporter_info_buff__[0];
129 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
130 // This is actually a toolchain requirement, but I'm not sure the correct check,
131 // but it should be fine to just only include it for Leopard and later. This line
132 // just tells the linker to never strip this symbol (such as for space optimization)
133 asm(".desc ___crashreporter_info__, 0x10");
137 /* Prefix strings for log messages. */
138 #ifndef X_UNKNOWN_STRING
139 #define X_UNKNOWN_STRING "(\?\?)"
141 #ifndef X_PROBE_STRING
142 #define X_PROBE_STRING "(--)"
144 #ifndef X_CONFIG_STRING
145 #define X_CONFIG_STRING "(**)"
147 #ifndef X_DEFAULT_STRING
148 #define X_DEFAULT_STRING "(==)"
150 #ifndef X_CMDLINE_STRING
151 #define X_CMDLINE_STRING "(++)"
153 #ifndef X_NOTICE_STRING
154 #define X_NOTICE_STRING "(!!)"
156 #ifndef X_ERROR_STRING
157 #define X_ERROR_STRING "(EE)"
159 #ifndef X_WARNING_STRING
160 #define X_WARNING_STRING "(WW)"
162 #ifndef X_INFO_STRING
163 #define X_INFO_STRING "(II)"
165 #ifndef X_NOT_IMPLEMENTED_STRING
166 #define X_NOT_IMPLEMENTED_STRING "(NI)"
168 #ifndef X_DEBUG_STRING
169 #define X_DEBUG_STRING "(DB)"
171 #ifndef X_NONE_STRING
172 #define X_NONE_STRING ""
176 strlen_sigsafe(const char *s)
179 for (len = 0; s[len]; len++);
184 * LogInit is called to start logging to a file. It is also called (with
185 * NULL arguments) when logging to a file is not wanted. It must always be
186 * called, otherwise log messages will continue to accumulate in a buffer.
188 * %s, if present in the fname or backup strings, is expanded to the display
193 LogInit(const char *fname, const char *backup)
195 char *logFileName = NULL;
197 if (fname && *fname) {
198 if (asprintf(&logFileName, fname, display) == -1)
199 FatalError("Cannot allocate space for the log file name\n");
201 if (backup && *backup) {
204 if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) {
208 if ((asprintf(&suffix, backup, display) == -1) ||
209 (asprintf(&oldLog, "%s%s", logFileName, suffix) == -1))
210 FatalError("Cannot allocate space for the log file name\n");
212 if (rename(logFileName, oldLog) == -1) {
213 FatalError("Cannot move old log file \"%s\" to \"%s\"\n",
214 logFileName, oldLog);
219 if ((logFile = fopen(logFileName, "w")) == NULL)
220 FatalError("Cannot open log file \"%s\"\n", logFileName);
221 setvbuf(logFile, NULL, _IONBF, 0);
223 logFileFd = fileno(logFile);
225 /* Flush saved log information. */
226 if (saveBuffer && bufferSize > 0) {
227 fwrite(saveBuffer, bufferPos, 1, logFile);
230 fsync(fileno(logFile));
236 * Unconditionally free the buffer, and flag that the buffer is no longer
239 if (saveBuffer && bufferSize > 0) {
250 LogClose(enum ExitCode error)
253 ErrorF("Server terminated %s (%d). Closing log file.\n",
254 (error == EXIT_NO_ERROR) ? "successfully" : "with error", error);
262 LogSetParameter(LogParameter param, int value)
266 logFlush = value ? TRUE : FALSE;
269 logSync = value ? TRUE : FALSE;
272 logVerbosity = value;
274 case XLOG_FILE_VERBOSITY:
275 logFileVerbosity = value;
283 pnprintf(char *string, size_t size, const char *f, va_list args)
287 int f_len = strlen_sigsafe(f);
295 for (; f_idx < f_len && s_idx < size - 1; f_idx++) {
296 if (f[f_idx] != '%') {
297 string[s_idx++] = f[f_idx];
301 switch (f[++f_idx]) {
303 string_arg = va_arg(args, char*);
304 p_len = strlen_sigsafe(string_arg);
306 for (i = 0; i < p_len && s_idx < size - 1; i++)
307 string[s_idx++] = string_arg[i];
311 ui = va_arg(args, unsigned);
312 FormatUInt64(ui, number);
313 p_len = strlen_sigsafe(number);
315 for (i = 0; i < p_len && s_idx < size - 1; i++)
316 string[s_idx++] = number[i];
320 si = va_arg(args, int);
321 FormatInt64(si, number);
322 p_len = strlen_sigsafe(number);
324 for (i = 0; i < p_len && s_idx < size - 1; i++)
325 string[s_idx++] = number[i];
329 string[s_idx++] = '0';
330 if (s_idx < size - 1)
331 string[s_idx++] = 'x';
332 ui = (uintptr_t)va_arg(args, void*);
333 FormatUInt64Hex(ui, number);
334 p_len = strlen_sigsafe(number);
336 for (i = 0; i < p_len && s_idx < size - 1; i++)
337 string[s_idx++] = number[i];
341 ui = va_arg(args, unsigned);
342 FormatUInt64Hex(ui, number);
343 p_len = strlen_sigsafe(number);
345 for (i = 0; i < p_len && s_idx < size - 1; i++)
346 string[s_idx++] = number[i];
351 string[s_idx++] = '%';
352 if (s_idx < size - 1)
353 string[s_idx++] = f[f_idx];
358 string[s_idx] = '\0';
363 /* This function does the actual log message writes. It must be signal safe.
364 * When attempting to call non-signal-safe functions, guard them with a check
365 * of the inSignalContext global variable. */
367 LogSWrite(int verb, const char *buf, size_t len, Bool end_line)
369 static Bool newline = TRUE;
371 if (verb < 0 || logVerbosity >= verb)
374 if (verb < 0 || logFileVerbosity >= verb) {
375 if (inSignalContext && logFileFd >= 0) {
376 write(logFileFd, buf, len);
378 if (logFlush && logSync)
382 else if (!inSignalContext && logFile) {
384 fprintf(logFile, "[%10.3f] ", GetTimeInMillis() / 1000.0);
386 fwrite(buf, len, 1, logFile);
391 fsync(fileno(logFile));
395 else if (!inSignalContext && needBuffer) {
396 if (len > bufferUnused) {
398 bufferUnused += 1024;
399 saveBuffer = realloc(saveBuffer, bufferSize);
401 FatalError("realloc() failed while saving log messages\n");
404 memcpy(saveBuffer + bufferPos, buf, len);
411 LogVWrite(int verb, const char *f, va_list args)
413 return LogVMessageVerb(X_NONE, verb, f, args);
417 LogWrite(int verb, const char *f, ...)
422 LogVWrite(verb, f, args);
426 /* Returns the Message Type string to prepend to a logging message, or NULL
427 * if the message will be dropped due to insufficient verbosity. */
429 LogMessageTypeVerbString(MessageType type, int verb)
434 if (logVerbosity < verb && logFileVerbosity < verb)
439 return X_PROBE_STRING;
441 return X_CONFIG_STRING;
443 return X_DEFAULT_STRING;
445 return X_CMDLINE_STRING;
447 return X_NOTICE_STRING;
449 return X_ERROR_STRING;
451 return X_WARNING_STRING;
453 return X_INFO_STRING;
454 case X_NOT_IMPLEMENTED:
455 return X_NOT_IMPLEMENTED_STRING;
457 return X_UNKNOWN_STRING;
459 return X_NONE_STRING;
461 return X_DEBUG_STRING;
463 return X_UNKNOWN_STRING;
468 LogVMessageVerb(MessageType type, int verb, const char *format, va_list args)
470 static unsigned int warned;
471 const char *type_str;
473 const size_t size = sizeof(buf);
477 if (inSignalContext) {
479 BUG_WARN_MSG(inSignalContext,
480 "Warning: attempting to log data in a signal unsafe "
481 "manner while in signal context.\nPlease update to check "
482 "inSignalContext and/or use LogMessageVerbSigSafe() or "
483 "ErrorFSigSafe().\nThe offending log format message is:\n"
487 LogMessageVerbSigSafe(X_WARNING, -1, "Warned %u times about sigsafe logging. Will be quiet now.\n", warned);
491 type_str = LogMessageTypeVerbString(type, verb);
495 /* if type_str is not "", prepend it and ' ', to message */
496 if (type_str[0] != '\0')
497 len += Xscnprintf(&buf[len], size - len, "%s ", type_str);
500 len += Xvscnprintf(&buf[len], size - len, format, args);
502 /* Force '\n' at end of truncated line */
506 newline = (buf[len - 1] == '\n');
507 LogSWrite(verb, buf, len, newline);
510 /* Log message with verbosity level specified. */
512 LogMessageVerb(MessageType type, int verb, const char *format, ...)
516 va_start(ap, format);
517 LogVMessageVerb(type, verb, format, ap);
521 /* Log a message with the standard verbosity level of 1. */
523 LogMessage(MessageType type, const char *format, ...)
527 va_start(ap, format);
528 LogVMessageVerb(type, 1, format, ap);
532 /* Log a message using only signal safe functions. */
534 LogMessageVerbSigSafe(MessageType type, int verb, const char *format, ...)
537 va_start(ap, format);
538 LogVMessageVerbSigSafe(type, verb, format, ap);
543 LogVMessageVerbSigSafe(MessageType type, int verb, const char *format, va_list args)
545 const char *type_str;
550 type_str = LogMessageTypeVerbString(type, verb);
554 /* if type_str is not "", prepend it and ' ', to message */
555 if (type_str[0] != '\0') {
556 LogSWrite(verb, type_str, strlen_sigsafe(type_str), FALSE);
557 LogSWrite(verb, " ", 1, FALSE);
560 len = pnprintf(buf, sizeof(buf), format, args);
562 /* Force '\n' at end of truncated line */
563 if (sizeof(buf) - len == 1)
566 newline = (buf[len - 1] == '\n');
567 LogSWrite(verb, buf, len, newline);
571 LogVHdrMessageVerb(MessageType type, int verb, const char *msg_format,
572 va_list msg_args, const char *hdr_format, va_list hdr_args)
574 static unsigned int warned;
575 const char *type_str;
577 const size_t size = sizeof(buf);
581 if (inSignalContext) {
583 BUG_WARN_MSG(inSignalContext,
584 "Warning: attempting to log data in a signal unsafe "
585 "manner while in signal context.\nPlease update to check "
586 "inSignalContext and/or use LogMessageVerbSigSafe().\nThe "
587 "offending header and log message formats are:\n%s %s\n",
588 hdr_format, msg_format);
591 LogMessageVerbSigSafe(X_WARNING, -1, "Warned %u times about sigsafe logging. Will be quiet now.\n", warned);
595 type_str = LogMessageTypeVerbString(type, verb);
599 /* if type_str is not "", prepend it and ' ', to message */
600 if (type_str[0] != '\0')
601 len += Xscnprintf(&buf[len], size - len, "%s ", type_str);
603 if (hdr_format && size - len > 1)
604 len += Xvscnprintf(&buf[len], size - len, hdr_format, hdr_args);
606 if (msg_format && size - len > 1)
607 len += Xvscnprintf(&buf[len], size - len, msg_format, msg_args);
609 /* Force '\n' at end of truncated line */
613 newline = (buf[len - 1] == '\n');
614 LogSWrite(verb, buf, len, newline);
618 LogHdrMessageVerb(MessageType type, int verb, const char *msg_format,
619 va_list msg_args, const char *hdr_format, ...)
623 va_start(hdr_args, hdr_format);
624 LogVHdrMessageVerb(type, verb, msg_format, msg_args, hdr_format, hdr_args);
629 LogHdrMessage(MessageType type, const char *msg_format, va_list msg_args,
630 const char *hdr_format, ...)
634 va_start(hdr_args, hdr_format);
635 LogVHdrMessageVerb(type, 1, msg_format, msg_args, hdr_format, hdr_args);
647 XF86BigfontCleanup();
649 CloseWellKnownConnections();
652 AbortDDX(EXIT_ERR_ABORT);
659 #define AUDIT_PREFIX "AUDIT: %s: %ld: "
660 #ifndef AUDIT_TIMEOUT
661 #define AUDIT_TIMEOUT ((CARD32)(120 * 1000)) /* 2 mn */
664 static int nrepeat = 0;
665 static int oldlen = -1;
666 static OsTimerPtr auditTimer = NULL;
671 if (auditTimer != NULL) {
672 /* Force output of pending messages */
673 TimerForce(auditTimer);
674 TimerFree(auditTimer);
689 if ((s = strchr(autime, '\n')))
691 len = strlen(AUDIT_PREFIX) + strlen(autime) + 10 + 1;
692 tmpBuf = malloc(len);
695 snprintf(tmpBuf, len, AUDIT_PREFIX, autime, (unsigned long) getpid());
700 AuditF(const char *f, ...)
711 AuditFlush(OsTimerPtr timer, CARD32 now, pointer arg)
716 prefix = AuditPrefix();
717 ErrorF("%slast message repeated %d times\n",
718 prefix != NULL ? prefix : "", nrepeat);
721 return AUDIT_TIMEOUT;
724 /* if the timer expires without anything to print, flush the message */
731 VAuditF(const char *f, va_list args)
736 static char oldbuf[1024];
738 prefix = AuditPrefix();
739 len = vsnprintf(buf, sizeof(buf), f, args);
741 if (len == oldlen && strcmp(buf, oldbuf) == 0) {
742 /* Message already seen */
747 if (auditTimer != NULL)
748 TimerForce(auditTimer);
749 ErrorF("%s%s", prefix != NULL ? prefix : "", buf);
750 strlcpy(oldbuf, buf, sizeof(oldbuf));
753 auditTimer = TimerSet(auditTimer, 0, AUDIT_TIMEOUT, AuditFlush, NULL);
759 FatalError(const char *f, ...)
763 static Bool beenhere = FALSE;
766 ErrorF("\nFatalError re-entered, aborting\n");
768 ErrorF("\nFatal server error:\n");
772 /* Make a copy for OsVendorFatalError */
773 va_copy(args2, args);
779 va_copy(apple_args, args);
780 (void)vsnprintf(__crashreporter_info_buff__,
781 sizeof(__crashreporter_info_buff__), f, apple_args);
789 OsVendorFatalError(f, args2);
800 VErrorF(const char *f, va_list args)
803 if (OsVendorVErrorFProc)
804 OsVendorVErrorFProc(f, args);
806 LogVWrite(-1, f, args);
808 LogVWrite(-1, f, args);
813 ErrorF(const char *f, ...)
823 VErrorFSigSafe(const char *f, va_list args)
825 LogVMessageVerbSigSafe(X_ERROR, -1, f, args);
829 ErrorFSigSafe(const char *f, ...)
834 VErrorFSigSafe(f, args);
839 LogPrintMarkers(void)
841 /* Show what the message marker symbols mean. */
842 LogWrite(0, "Markers: ");
843 LogMessageVerb(X_PROBED, 0, "probed, ");
844 LogMessageVerb(X_CONFIG, 0, "from config file, ");
845 LogMessageVerb(X_DEFAULT, 0, "default setting,\n\t");
846 LogMessageVerb(X_CMDLINE, 0, "from command line, ");
847 LogMessageVerb(X_NOTICE, 0, "notice, ");
848 LogMessageVerb(X_INFO, 0, "informational,\n\t");
849 LogMessageVerb(X_WARNING, 0, "warning, ");
850 LogMessageVerb(X_ERROR, 0, "error, ");
851 LogMessageVerb(X_NOT_IMPLEMENTED, 0, "not implemented, ");
852 LogMessageVerb(X_UNKNOWN, 0, "unknown.\n");