warnp.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #include <errno.h>
  2. #include <stdarg.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <syslog.h>
  7. #include "warnp.h"
  8. static int initialized = 0;
  9. static char * name = NULL;
  10. static int use_syslog = 0;
  11. static int syslog_priority = LOG_WARNING;
  12. /* Free the name string and clean up writing to the syslog (if applicable). */
  13. static void
  14. warnp_atexit(void)
  15. {
  16. /* Clean up writing to the syslog (if applicable). */
  17. if (use_syslog)
  18. closelog();
  19. free(name);
  20. name = NULL;
  21. }
  22. /**
  23. * warnp_setprogname(progname):
  24. * Set the program name to be used by warn() and warnx() to ${progname}.
  25. */
  26. void
  27. warnp_setprogname(const char * progname)
  28. {
  29. const char * p;
  30. /* Free the name if we already have one. */
  31. free(name);
  32. /* Find the last segment of the program name. */
  33. for (p = progname; progname[0] != '\0'; progname++)
  34. if (progname[0] == '/')
  35. p = progname + 1;
  36. /* Copy the name string. */
  37. name = strdup(p);
  38. /* If we haven't already done so, register our exit handler. */
  39. if (initialized == 0) {
  40. atexit(warnp_atexit);
  41. initialized = 1;
  42. }
  43. }
  44. /* This function will preserve errno. */
  45. void
  46. warn(const char * fmt, ...)
  47. {
  48. va_list ap;
  49. char msgbuf[WARNP_SYSLOG_MAX_LINE + 1];
  50. int saved_errno;
  51. /* Save errno in case it gets clobbered. */
  52. saved_errno = errno;
  53. va_start(ap, fmt);
  54. if (use_syslog == 0) {
  55. /* Stop other threads writing to stderr. */
  56. flockfile(stderr);
  57. /* Print to stderr. */
  58. fprintf(stderr, "%s", (name != NULL) ? name : "(unknown)");
  59. if (fmt != NULL) {
  60. fprintf(stderr, ": ");
  61. vfprintf(stderr, fmt, ap);
  62. }
  63. fprintf(stderr, ": %s\n", strerror(saved_errno));
  64. /* Allow other threads to write to stderr. */
  65. funlockfile(stderr);
  66. } else {
  67. /* Print to syslog. */
  68. if (fmt != NULL) {
  69. /* No need to print "${name}: "; syslog does it. */
  70. vsnprintf(msgbuf, WARNP_SYSLOG_MAX_LINE + 1, fmt, ap);
  71. syslog(syslog_priority, "%s: %s\n", msgbuf,
  72. strerror(saved_errno));
  73. } else
  74. syslog(syslog_priority, "%s\n", strerror(saved_errno));
  75. }
  76. va_end(ap);
  77. /* Restore saved errno. */
  78. errno = saved_errno;
  79. }
  80. /* This function will preserve errno. */
  81. void
  82. warnx(const char * fmt, ...)
  83. {
  84. va_list ap;
  85. char msgbuf[WARNP_SYSLOG_MAX_LINE + 1];
  86. int saved_errno;
  87. /* Save errno in case it gets clobbered. */
  88. saved_errno = errno;
  89. va_start(ap, fmt);
  90. if (use_syslog == 0) {
  91. /* Stop other threads writing to stderr. */
  92. flockfile(stderr);
  93. /* Print to stderr. */
  94. fprintf(stderr, "%s", (name != NULL) ? name : "(unknown)");
  95. if (fmt != NULL) {
  96. fprintf(stderr, ": ");
  97. vfprintf(stderr, fmt, ap);
  98. }
  99. fprintf(stderr, "\n");
  100. /* Allow other threads to write to stderr. */
  101. funlockfile(stderr);
  102. } else {
  103. /* Print to syslog. */
  104. if (fmt != NULL) {
  105. /* No need to print "${name}: "; syslog does it. */
  106. vsnprintf(msgbuf, WARNP_SYSLOG_MAX_LINE + 1, fmt, ap);
  107. syslog(syslog_priority, "%s\n", msgbuf);
  108. } else
  109. syslog(syslog_priority, "\n");
  110. }
  111. va_end(ap);
  112. /* Restore saved errno. */
  113. errno = saved_errno;
  114. }
  115. /**
  116. * warnp_syslog(enable):
  117. * Send future messages to syslog if ${enable} is non-zero. Messages to
  118. * syslog will be truncated at WARNP_SYSLOG_MAX_LINE characters.
  119. */
  120. void
  121. warnp_syslog(int enable)
  122. {
  123. /* Clean up writing to the syslog (if applicable). */
  124. if (use_syslog && !enable)
  125. closelog();
  126. use_syslog = enable;
  127. }
  128. /**
  129. * warnp_syslog_priority(priority):
  130. * Tag future syslog messages with priority ${priority}. Do not enable
  131. * syslog messages; for that, use warnp_syslog().
  132. */
  133. void
  134. warnp_syslog_priority(int priority)
  135. {
  136. syslog_priority = priority;
  137. }