PageRenderTime 40ms CodeModel.GetById 7ms RepoModel.GetById 0ms app.codeStats 0ms

/nx-3.5.0/nx-X11/programs/Xserver/os/log.c

#
C | 716 lines | 490 code | 74 blank | 152 comment | 83 complexity | ba2ba25d73c446cb3b20858c639166f2 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, LGPL-2.0
  1. /*
  2. Copyright 1987, 1998 The Open Group
  3. Permission to use, copy, modify, distribute, and sell this software and its
  4. documentation for any purpose is hereby granted without fee, provided that
  5. the above copyright notice appear in all copies and that both that
  6. copyright notice and this permission notice appear in supporting
  7. documentation.
  8. The above copyright notice and this permission notice shall be included
  9. in all copies or substantial portions of the Software.
  10. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  11. OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  12. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  13. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
  14. OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  15. ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  16. OTHER DEALINGS IN THE SOFTWARE.
  17. Except as contained in this notice, the name of The Open Group shall
  18. not be used in advertising or otherwise to promote the sale, use or
  19. other dealings in this Software without prior written authorization
  20. from The Open Group.
  21. Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
  22. Copyright 1994 Quarterdeck Office Systems.
  23. All Rights Reserved
  24. Permission to use, copy, modify, and distribute this software and its
  25. documentation for any purpose and without fee is hereby granted,
  26. provided that the above copyright notice appear in all copies and that
  27. both that copyright notice and this permission notice appear in
  28. supporting documentation, and that the names of Digital and
  29. Quarterdeck not be used in advertising or publicity pertaining to
  30. distribution of the software without specific, written prior
  31. permission.
  32. DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
  33. SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  34. FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
  35. OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  36. OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  37. OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  38. OR PERFORMANCE OF THIS SOFTWARE.
  39. */
  40. /*
  41. * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
  42. *
  43. * Permission is hereby granted, free of charge, to any person obtaining a
  44. * copy of this software and associated documentation files (the "Software"),
  45. * to deal in the Software without restriction, including without limitation
  46. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  47. * and/or sell copies of the Software, and to permit persons to whom the
  48. * Software is furnished to do so, subject to the following conditions:
  49. *
  50. * The above copyright notice and this permission notice shall be included in
  51. * all copies or substantial portions of the Software.
  52. *
  53. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  54. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  55. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  56. * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  57. * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  58. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  59. * OTHER DEALINGS IN THE SOFTWARE.
  60. *
  61. * Except as contained in this notice, the name of the copyright holder(s)
  62. * and author(s) shall not be used in advertising or otherwise to promote
  63. * the sale, use or other dealings in this Software without prior written
  64. * authorization from the copyright holder(s) and author(s).
  65. */
  66. /* $XFree86: xc/programs/Xserver/os/log.c,v 1.6 2003/11/07 13:45:27 tsi Exp $ */
  67. /**************************************************************************/
  68. /* */
  69. /* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
  70. /* */
  71. /* NX-X11, NX protocol compression and NX extensions to this software */
  72. /* are copyright of NoMachine. Redistribution and use of the present */
  73. /* software is allowed according to terms specified in the file LICENSE */
  74. /* which comes in the source distribution. */
  75. /* */
  76. /* Check http://www.nomachine.com/licensing.html for applicability. */
  77. /* */
  78. /* NX and NoMachine are trademarks of Medialogic S.p.A. */
  79. /* */
  80. /* All rights reserved. */
  81. /* */
  82. /**************************************************************************/
  83. #ifdef HAVE_DIX_CONFIG_H
  84. #include <dix-config.h>
  85. #endif
  86. #include <X11/Xos.h>
  87. #include <stdio.h>
  88. #include <time.h>
  89. #include <sys/stat.h>
  90. #include <stdarg.h>
  91. #include <stdlib.h> /* for malloc() */
  92. #include <errno.h>
  93. #include "site.h"
  94. #include "opaque.h"
  95. #ifdef WIN32
  96. #include <process.h>
  97. #define getpid(x) _getpid(x)
  98. #endif
  99. #ifdef NX_TRANS_SOCKET
  100. #include "NX.h"
  101. #endif
  102. #ifdef DDXOSVERRORF
  103. void (*OsVendorVErrorFProc)(const char *, va_list args) = NULL;
  104. #ifdef NX_TRANS_EXIT
  105. int OsVendorVErrorFFatal = 0;
  106. #endif
  107. #endif
  108. static FILE *logFile = NULL;
  109. static Bool logFlush = FALSE;
  110. static Bool logSync = FALSE;
  111. static int logVerbosity = DEFAULT_LOG_VERBOSITY;
  112. static int logFileVerbosity = DEFAULT_LOG_FILE_VERBOSITY;
  113. /* Buffer to information logged before the log file is opened. */
  114. static char *saveBuffer = NULL;
  115. static int bufferSize = 0, bufferUnused = 0, bufferPos = 0;
  116. static Bool needBuffer = TRUE;
  117. /* Prefix strings for log messages. */
  118. #ifndef X_UNKNOWN_STRING
  119. #define X_UNKNOWN_STRING "(\?\?)"
  120. #endif
  121. #ifndef X_PROBE_STRING
  122. #define X_PROBE_STRING "(--)"
  123. #endif
  124. #ifndef X_CONFIG_STRING
  125. #define X_CONFIG_STRING "(**)"
  126. #endif
  127. #ifndef X_DEFAULT_STRING
  128. #define X_DEFAULT_STRING "(==)"
  129. #endif
  130. #ifndef X_CMDLINE_STRING
  131. #define X_CMDLINE_STRING "(++)"
  132. #endif
  133. #ifndef X_NOTICE_STRING
  134. #define X_NOTICE_STRING "(!!)"
  135. #endif
  136. #ifndef X_ERROR_STRING
  137. #define X_ERROR_STRING "(EE)"
  138. #endif
  139. #ifndef X_WARNING_STRING
  140. #define X_WARNING_STRING "(WW)"
  141. #endif
  142. #ifndef X_INFO_STRING
  143. #define X_INFO_STRING "(II)"
  144. #endif
  145. #ifndef X_NOT_IMPLEMENTED_STRING
  146. #define X_NOT_IMPLEMENTED_STRING "(NI)"
  147. #endif
  148. /*
  149. * LogInit is called to start logging to a file. It is also called (with
  150. * NULL arguments) when logging to a file is not wanted. It must always be
  151. * called, otherwise log messages will continue to accumulate in a buffer.
  152. *
  153. * %s, if present in the fname or backup strings, is expanded to the display
  154. * string.
  155. */
  156. const char *
  157. LogInit(const char *fname, const char *backup)
  158. {
  159. char *logFileName = NULL;
  160. if (fname && *fname) {
  161. /* xalloc() can't be used yet. */
  162. logFileName = malloc(strlen(fname) + strlen(display) + 1);
  163. if (!logFileName)
  164. FatalError("Cannot allocate space for the log file name\n");
  165. sprintf(logFileName, fname, display);
  166. if (backup && *backup) {
  167. struct stat buf;
  168. if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) {
  169. char *suffix;
  170. char *oldLog;
  171. oldLog = malloc(strlen(logFileName) + strlen(backup) +
  172. strlen(display) + 1);
  173. suffix = malloc(strlen(backup) + strlen(display) + 1);
  174. if (!oldLog || !suffix)
  175. FatalError("Cannot allocate space for the log file name\n");
  176. sprintf(suffix, backup, display);
  177. sprintf(oldLog, "%s%s", logFileName, suffix);
  178. free(suffix);
  179. #ifdef __UNIXOS2__
  180. remove(oldLog);
  181. #endif
  182. if (rename(logFileName, oldLog) == -1) {
  183. FatalError("Cannot move old log file (\"%s\" to \"%s\"\n",
  184. logFileName, oldLog);
  185. }
  186. free(oldLog);
  187. }
  188. }
  189. if ((logFile = fopen(logFileName, "w")) == NULL)
  190. FatalError("Cannot open log file \"%s\"\n", logFileName);
  191. setvbuf(logFile, NULL, _IONBF, 0);
  192. /* Flush saved log information. */
  193. if (saveBuffer && bufferSize > 0) {
  194. fwrite(saveBuffer, bufferPos, 1, logFile);
  195. fflush(logFile);
  196. #ifndef WIN32
  197. fsync(fileno(logFile));
  198. #endif
  199. }
  200. }
  201. /*
  202. * Unconditionally free the buffer, and flag that the buffer is no longer
  203. * needed.
  204. */
  205. if (saveBuffer && bufferSize > 0) {
  206. free(saveBuffer); /* Must be free(), not xfree() */
  207. saveBuffer = NULL;
  208. bufferSize = 0;
  209. }
  210. needBuffer = FALSE;
  211. return logFileName;
  212. }
  213. void
  214. LogClose()
  215. {
  216. if (logFile) {
  217. fclose(logFile);
  218. logFile = NULL;
  219. }
  220. }
  221. Bool
  222. LogSetParameter(LogParameter param, int value)
  223. {
  224. switch (param) {
  225. case XLOG_FLUSH:
  226. logFlush = value ? TRUE : FALSE;
  227. return TRUE;
  228. case XLOG_SYNC:
  229. logSync = value ? TRUE : FALSE;
  230. return TRUE;
  231. case XLOG_VERBOSITY:
  232. logVerbosity = value;
  233. return TRUE;
  234. case XLOG_FILE_VERBOSITY:
  235. logFileVerbosity = value;
  236. return TRUE;
  237. default:
  238. return FALSE;
  239. }
  240. }
  241. /* This function does the actual log message writes. */
  242. void
  243. LogVWrite(int verb, const char *f, va_list args)
  244. {
  245. static char tmpBuffer[1024];
  246. int len = 0;
  247. /*
  248. * Since a va_list can only be processed once, write the string to a
  249. * buffer, and then write the buffer out to the appropriate output
  250. * stream(s).
  251. */
  252. if (verb < 0 || logFileVerbosity >= verb || logVerbosity >= verb) {
  253. vsnprintf(tmpBuffer, sizeof(tmpBuffer), f, args);
  254. #ifdef NX_TRANS_EXIT
  255. /*
  256. * Beautify the message. Make the
  257. * first letter uppercase.
  258. */
  259. *tmpBuffer = toupper(*tmpBuffer);
  260. /*
  261. * Remove the trailing newline.
  262. */
  263. if (strlen(tmpBuffer) > 0 &&
  264. *(tmpBuffer + strlen(tmpBuffer) - 1) == '\n') {
  265. *(tmpBuffer + strlen(tmpBuffer) - 1) = '\0';
  266. }
  267. /*
  268. * Remove the trailing full-stop.
  269. */
  270. if (strlen(tmpBuffer) > 0 &&
  271. *(tmpBuffer + strlen(tmpBuffer) - 1) == '.') {
  272. *(tmpBuffer + strlen(tmpBuffer) - 1) = '\0';
  273. }
  274. #endif /* #ifdef NX_TRANS_EXIT */
  275. len = strlen(tmpBuffer);
  276. }
  277. if ((verb < 0 || logVerbosity >= verb) && len > 0)
  278. fwrite(tmpBuffer, len, 1, stderr);
  279. if ((verb < 0 || logFileVerbosity >= verb) && len > 0) {
  280. if (logFile) {
  281. fwrite(tmpBuffer, len, 1, logFile);
  282. if (logFlush) {
  283. fflush(logFile);
  284. #ifndef WIN32
  285. if (logSync)
  286. fsync(fileno(logFile));
  287. #endif
  288. }
  289. } else if (needBuffer) {
  290. /*
  291. * Note, this code is used before OsInit() has been called, so
  292. * xalloc() and friends can't be used.
  293. */
  294. if (len > bufferUnused) {
  295. bufferSize += 1024;
  296. bufferUnused += 1024;
  297. if (saveBuffer)
  298. saveBuffer = realloc(saveBuffer, bufferSize);
  299. else
  300. saveBuffer = malloc(bufferSize);
  301. if (!saveBuffer)
  302. FatalError("realloc() failed while saving log messages\n");
  303. }
  304. bufferUnused -= len;
  305. memcpy(saveBuffer + bufferPos, tmpBuffer, len);
  306. bufferPos += len;
  307. }
  308. }
  309. }
  310. void
  311. LogWrite(int verb, const char *f, ...)
  312. {
  313. va_list args;
  314. va_start(args, f);
  315. LogVWrite(verb, f, args);
  316. va_end(args);
  317. }
  318. void
  319. LogVMessageVerb(MessageType type, int verb, const char *format, va_list args)
  320. {
  321. const char *s = X_UNKNOWN_STRING;
  322. char *tmpBuf = NULL;
  323. /* Ignore verbosity for X_ERROR */
  324. if (logVerbosity >= verb || logFileVerbosity >= verb || type == X_ERROR) {
  325. switch (type) {
  326. case X_PROBED:
  327. s = X_PROBE_STRING;
  328. break;
  329. case X_CONFIG:
  330. s = X_CONFIG_STRING;
  331. break;
  332. case X_DEFAULT:
  333. s = X_DEFAULT_STRING;
  334. break;
  335. case X_CMDLINE:
  336. s = X_CMDLINE_STRING;
  337. break;
  338. case X_NOTICE:
  339. s = X_NOTICE_STRING;
  340. break;
  341. case X_ERROR:
  342. s = X_ERROR_STRING;
  343. if (verb > 0)
  344. verb = 0;
  345. break;
  346. case X_WARNING:
  347. s = X_WARNING_STRING;
  348. break;
  349. case X_INFO:
  350. s = X_INFO_STRING;
  351. break;
  352. case X_NOT_IMPLEMENTED:
  353. s = X_NOT_IMPLEMENTED_STRING;
  354. break;
  355. case X_UNKNOWN:
  356. s = X_UNKNOWN_STRING;
  357. break;
  358. case X_NONE:
  359. s = NULL;
  360. break;
  361. }
  362. /*
  363. * Prefix the format string with the message type. We do it this way
  364. * so that LogVWrite() is only called once per message.
  365. */
  366. if (s) {
  367. tmpBuf = malloc(strlen(format) + strlen(s) + 1 + 1);
  368. /* Silently return if malloc fails here. */
  369. if (!tmpBuf)
  370. return;
  371. sprintf(tmpBuf, "%s ", s);
  372. strcat(tmpBuf, format);
  373. LogVWrite(verb, tmpBuf, args);
  374. free(tmpBuf);
  375. } else
  376. LogVWrite(verb, format, args);
  377. }
  378. }
  379. /* Log message with verbosity level specified. */
  380. void
  381. LogMessageVerb(MessageType type, int verb, const char *format, ...)
  382. {
  383. va_list ap;
  384. va_start(ap, format);
  385. LogVMessageVerb(type, verb, format, ap);
  386. va_end(ap);
  387. }
  388. /* Log a message with the standard verbosity level of 1. */
  389. void
  390. LogMessage(MessageType type, const char *format, ...)
  391. {
  392. va_list ap;
  393. va_start(ap, format);
  394. LogVMessageVerb(type, 1, format, ap);
  395. va_end(ap);
  396. }
  397. #ifdef __GNUC__
  398. void AbortServer(void) __attribute__((noreturn));
  399. #endif
  400. void
  401. AbortServer(void)
  402. {
  403. #if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
  404. fprintf(stderr, "AbortServer: Going to abort the current server.\n");
  405. #endif
  406. OsCleanup(TRUE);
  407. AbortDDX();
  408. fflush(stderr);
  409. if (CoreDump)
  410. abort();
  411. #ifdef NX_TRANS_EXIT
  412. #ifdef NX_TRANS_TEST
  413. fprintf(stderr, "AbortServer: Going to clean up NX resources and exit.\n");
  414. #endif
  415. NXTransExit(1);
  416. #else /* #ifdef NX_TRANS_EXIT */
  417. exit (1);
  418. #endif
  419. }
  420. #ifndef AUDIT_PREFIX
  421. #define AUDIT_PREFIX "AUDIT: %s: %ld %s: "
  422. #endif
  423. #ifndef AUDIT_TIMEOUT
  424. #define AUDIT_TIMEOUT ((CARD32)(120 * 1000)) /* 2 mn */
  425. #endif
  426. static int nrepeat = 0;
  427. static int oldlen = -1;
  428. static OsTimerPtr auditTimer = NULL;
  429. void
  430. FreeAuditTimer(void)
  431. {
  432. if (auditTimer != NULL) {
  433. /* Force output of pending messages */
  434. TimerForce(auditTimer);
  435. TimerFree(auditTimer);
  436. auditTimer = NULL;
  437. }
  438. }
  439. static char *
  440. AuditPrefix(void)
  441. {
  442. time_t tm;
  443. char *autime, *s;
  444. char *tmpBuf;
  445. int len;
  446. time(&tm);
  447. autime = ctime(&tm);
  448. if ((s = strchr(autime, '\n')))
  449. *s = '\0';
  450. if ((s = strrchr(argvGlobal[0], '/')))
  451. s++;
  452. else
  453. s = argvGlobal[0];
  454. len = strlen(AUDIT_PREFIX) + strlen(autime) + 10 + strlen(s) + 1;
  455. tmpBuf = malloc(len);
  456. if (!tmpBuf)
  457. return NULL;
  458. snprintf(tmpBuf, len, AUDIT_PREFIX, autime, (unsigned long)getpid(), s);
  459. return tmpBuf;
  460. }
  461. void
  462. AuditF(const char * f, ...)
  463. {
  464. va_list args;
  465. va_start(args, f);
  466. VAuditF(f, args);
  467. va_end(args);
  468. }
  469. static CARD32
  470. AuditFlush(OsTimerPtr timer, CARD32 now, pointer arg)
  471. {
  472. char *prefix;
  473. if (nrepeat > 0) {
  474. prefix = AuditPrefix();
  475. ErrorF("%slast message repeated %d times\n",
  476. prefix != NULL ? prefix : "", nrepeat);
  477. nrepeat = 0;
  478. if (prefix != NULL)
  479. free(prefix);
  480. return AUDIT_TIMEOUT;
  481. } else {
  482. /* if the timer expires without anything to print, flush the message */
  483. oldlen = -1;
  484. return 0;
  485. }
  486. }
  487. void
  488. VAuditF(const char *f, va_list args)
  489. {
  490. char *prefix;
  491. char buf[1024];
  492. int len;
  493. static char oldbuf[1024];
  494. prefix = AuditPrefix();
  495. len = vsnprintf(buf, sizeof(buf), f, args);
  496. #if 1
  497. /* XXX Compressing duplicated messages is temporarily disabled to
  498. * work around bugzilla 964:
  499. * https://freedesktop.org/bugzilla/show_bug.cgi?id=964
  500. */
  501. ErrorF("%s%s", prefix != NULL ? prefix : "", buf);
  502. oldlen = -1;
  503. nrepeat = 0;
  504. #else
  505. if (len == oldlen && strcmp(buf, oldbuf) == 0) {
  506. /* Message already seen */
  507. nrepeat++;
  508. } else {
  509. /* new message */
  510. if (auditTimer != NULL)
  511. TimerForce(auditTimer);
  512. ErrorF("%s%s", prefix != NULL ? prefix : "", buf);
  513. strlcpy(oldbuf, buf, sizeof(oldbuf));
  514. oldlen = len;
  515. nrepeat = 0;
  516. auditTimer = TimerSet(auditTimer, 0, AUDIT_TIMEOUT, AuditFlush, NULL);
  517. }
  518. #endif
  519. if (prefix != NULL)
  520. free(prefix);
  521. }
  522. void
  523. FatalError(const char *f, ...)
  524. {
  525. va_list args;
  526. static Bool beenhere = FALSE;
  527. #ifdef NX_TRANS_EXIT
  528. if (beenhere) {
  529. fprintf(stderr, "Error: Aborting session with fatal error function reentered.\n");
  530. }
  531. else {
  532. /*
  533. * Tell to the log function that this
  534. * is a fatal error.
  535. */
  536. OsVendorVErrorFFatal = 1;
  537. fprintf(stderr, "Error: Aborting session with '");
  538. va_start(args, f);
  539. VErrorF(f, args);
  540. va_end(args);
  541. fprintf(stderr, "'.\n");
  542. }
  543. #else /* #ifdef NX_TRANS_EXIT */
  544. if (beenhere)
  545. ErrorF("\nFatalError re-entered, aborting\n");
  546. else
  547. ErrorF("\nFatal server error:\n");
  548. va_start(args, f);
  549. VErrorF(f, args);
  550. va_end(args);
  551. ErrorF("\n");
  552. #endif /* #ifdef NX_TRANS_EXIT */
  553. #ifdef DDXOSFATALERROR
  554. if (!beenhere)
  555. OsVendorFatalError();
  556. #endif
  557. #ifdef ABORTONFATALERROR
  558. abort();
  559. #endif
  560. if (!beenhere) {
  561. beenhere = TRUE;
  562. AbortServer();
  563. } else
  564. abort();
  565. /*NOTREACHED*/
  566. }
  567. void
  568. VErrorF(const char *f, va_list args)
  569. {
  570. #ifdef DDXOSVERRORF
  571. if (OsVendorVErrorFProc)
  572. OsVendorVErrorFProc(f, args);
  573. else
  574. LogVWrite(-1, f, args);
  575. #else
  576. LogVWrite(-1, f, args);
  577. #endif
  578. }
  579. void
  580. ErrorF(const char * f, ...)
  581. {
  582. va_list args;
  583. va_start(args, f);
  584. VErrorF(f, args);
  585. va_end(args);
  586. }
  587. /* A perror() workalike. */
  588. #ifndef NEED_STRERROR
  589. #ifdef SYSV
  590. #if !defined(ISC) || defined(ISC202) || defined(ISC22)
  591. #define NEED_STRERROR
  592. #endif
  593. #endif
  594. #endif
  595. #if defined(NEED_STRERROR) && !defined(strerror)
  596. extern char *sys_errlist[];
  597. extern int sys_nerr;
  598. #define strerror(n) \
  599. ((n) >= 0 && (n) < sys_nerr) ? sys_errlist[(n)] : "unknown error"
  600. #endif
  601. void
  602. Error(char *str)
  603. {
  604. char *err = NULL;
  605. int saveErrno = errno;
  606. if (str) {
  607. err = malloc(strlen(strerror(saveErrno)) + strlen(str) + 2 + 1);
  608. if (!err)
  609. return;
  610. sprintf(err, "%s: ", str);
  611. strcat(err, strerror(saveErrno));
  612. LogWrite(-1, err);
  613. } else
  614. LogWrite(-1, strerror(saveErrno));
  615. }
  616. void
  617. LogPrintMarkers()
  618. {
  619. /* Show what the message marker symbols mean. */
  620. ErrorF("Markers: ");
  621. LogMessageVerb(X_PROBED, -1, "probed, ");
  622. LogMessageVerb(X_CONFIG, -1, "from config file, ");
  623. LogMessageVerb(X_DEFAULT, -1, "default setting,\n\t");
  624. LogMessageVerb(X_CMDLINE, -1, "from command line, ");
  625. LogMessageVerb(X_NOTICE, -1, "notice, ");
  626. LogMessageVerb(X_INFO, -1, "informational,\n\t");
  627. LogMessageVerb(X_WARNING, -1, "warning, ");
  628. LogMessageVerb(X_ERROR, -1, "error, ");
  629. LogMessageVerb(X_NOT_IMPLEMENTED, -1, "not implemented, ");
  630. LogMessageVerb(X_UNKNOWN, -1, "unknown.\n");
  631. }