syslog.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /* Copyright (c) 1993-2000 by Richard Kelsey and Jonathan Rees.
  2. See file COPYING. */
  3. #include <syslog.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include "scheme48.h"
  7. static s48_ref_t posix_openlog(s48_call_t call,
  8. s48_ref_t sch_ident, s48_ref_t sch_option, s48_ref_t sch_facility);
  9. static s48_ref_t posix_setlogmask(s48_call_t call, s48_ref_t sch_logmask);
  10. static s48_ref_t posix_syslog(s48_call_t call,
  11. s48_ref_t sch_level, s48_ref_t sch_facility, s48_ref_t sch_message);
  12. static s48_ref_t posix_closelog(s48_call_t call);
  13. /*
  14. * Install all exported functions in Scheme 48.
  15. */
  16. void
  17. s48_init_posix_syslog(void)
  18. {
  19. S48_EXPORT_FUNCTION(posix_openlog);
  20. S48_EXPORT_FUNCTION(posix_syslog);
  21. S48_EXPORT_FUNCTION(posix_setlogmask);
  22. S48_EXPORT_FUNCTION(posix_closelog);
  23. }
  24. /* Syslog options.
  25. *
  26. * We translate the our own bits into local bits
  27. */
  28. /* The order of these is known to the Scheme code. */
  29. static int
  30. extract_syslog_options(s48_call_t call, s48_ref_t sch_syslog_options)
  31. {
  32. long options = s48_extract_long_2(call, sch_syslog_options);
  33. return
  34. (00001 & options ? LOG_CONS : 0) |
  35. (00002 & options ? LOG_ODELAY : 0) |
  36. (00004 & options ? LOG_NDELAY : 0) |
  37. (00010 & options ? LOG_PID : 0);
  38. (00020 & options ? LOG_NOWAIT : 0);
  39. }
  40. /* Syslog facility.
  41. *
  42. * We translate the local facility into our own encoding and vice versa.
  43. */
  44. /* The order of these is known to the Scheme code. */
  45. static int syslog_facilities[] = {
  46. LOG_AUTH,
  47. LOG_CRON,
  48. LOG_DAEMON,
  49. LOG_KERN,
  50. LOG_LPR,
  51. LOG_MAIL,
  52. LOG_NEWS,
  53. LOG_USER,
  54. LOG_UUCP,
  55. LOG_LOCAL0, LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3,
  56. LOG_LOCAL4, LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7
  57. };
  58. static int
  59. extract_syslog_facility(s48_call_t call, s48_ref_t sch_syslog_facility)
  60. {
  61. return syslog_facilities[s48_extract_long_2(call, sch_syslog_facility)];
  62. }
  63. /* ************************************************************ */
  64. /* Syslog level.
  65. *
  66. * We translate the local level into our own encoding and vice versa.
  67. */
  68. /* The order of these is known to the Scheme code. */
  69. static int syslog_levels[] = {
  70. LOG_EMERG,
  71. LOG_ALERT,
  72. LOG_CRIT,
  73. LOG_ERR,
  74. LOG_WARNING,
  75. LOG_NOTICE,
  76. LOG_INFO,
  77. LOG_DEBUG
  78. };
  79. static int
  80. extract_syslog_level(s48_call_t call, s48_ref_t sch_syslog_level)
  81. {
  82. return syslog_levels[s48_extract_long_2(call, sch_syslog_level)];
  83. }
  84. /* ************************************************************ */
  85. /* Syslog mask.
  86. *
  87. * We translate the local bits into our own bits and vice versa.
  88. */
  89. /* The order of these is known to the Scheme code. */
  90. static s48_ref_t
  91. enter_syslog_mask(s48_call_t call, int syslog_mask)
  92. {
  93. long my_syslog_mask;
  94. my_syslog_mask =
  95. (LOG_MASK(LOG_EMERG) & syslog_mask ? 00001 : 0) |
  96. (LOG_MASK(LOG_ALERT) & syslog_mask ? 00002 : 0) |
  97. (LOG_MASK(LOG_CRIT) & syslog_mask ? 00004 : 0) |
  98. (LOG_MASK(LOG_ERR) & syslog_mask ? 00010 : 0) |
  99. (LOG_MASK(LOG_WARNING) & syslog_mask ? 00020 : 0) |
  100. (LOG_MASK(LOG_NOTICE) & syslog_mask ? 00040 : 0) |
  101. (LOG_MASK(LOG_INFO) & syslog_mask ? 00100 : 0) |
  102. (LOG_MASK(LOG_DEBUG) & syslog_mask ? 00200 : 0);
  103. return s48_enter_long_as_fixnum_2(call, my_syslog_mask);
  104. }
  105. static int
  106. extract_syslog_mask(s48_call_t call, s48_ref_t sch_syslog_mask)
  107. {
  108. long syslog_mask = s48_extract_long_2(call, sch_syslog_mask);
  109. return
  110. (00001 & syslog_mask ? LOG_MASK(LOG_EMERG) : 0) |
  111. (00002 & syslog_mask ? LOG_MASK(LOG_ALERT) : 0) |
  112. (00004 & syslog_mask ? LOG_MASK(LOG_CRIT) : 0) |
  113. (00010 & syslog_mask ? LOG_MASK(LOG_ERR) : 0) |
  114. (00010 & syslog_mask ? LOG_MASK(LOG_WARNING) : 0) |
  115. (00010 & syslog_mask ? LOG_MASK(LOG_NOTICE) : 0) |
  116. (00010 & syslog_mask ? LOG_MASK(LOG_INFO) : 0) |
  117. (00020 & syslog_mask ? LOG_MASK(LOG_DEBUG) : 0);
  118. }
  119. #define SYSLOG_IDENT_SIZE 256 /* should be ample */
  120. static int syslog_open = 0;
  121. static char syslog_ident_initial[SYSLOG_IDENT_SIZE];
  122. static char* syslog_ident = syslog_ident_initial;
  123. static size_t syslog_ident_size = SYSLOG_IDENT_SIZE;
  124. static s48_ref_t
  125. posix_openlog(s48_call_t call,
  126. s48_ref_t sch_ident, s48_ref_t sch_options, s48_ref_t sch_facility)
  127. {
  128. if (syslog_open)
  129. s48_assertion_violation_2(call,
  130. "posix_openlog", "syslog is already open",
  131. 3, sch_ident, sch_options, sch_facility);
  132. {
  133. /*
  134. * openlog doesn't copy the input string, at least not
  135. * on every system. That's just great.
  136. */
  137. char* ident = s48_extract_byte_vector_readonly_2(call, sch_ident);
  138. size_t ident_size = strlen(ident) + 1;
  139. if (ident_size > syslog_ident_size)
  140. {
  141. if (syslog_ident != syslog_ident_initial)
  142. free(syslog_ident);
  143. syslog_ident = malloc(ident_size);
  144. if (syslog_ident == NULL)
  145. s48_out_of_memory_error_2(call);
  146. syslog_ident_size = ident_size;
  147. }
  148. strcpy(syslog_ident, ident);
  149. openlog(syslog_ident,
  150. extract_syslog_options(call, sch_options),
  151. extract_syslog_facility(call, sch_facility));
  152. }
  153. syslog_open = 1;
  154. return s48_unspecific_2(call);
  155. }
  156. static s48_ref_t
  157. posix_setlogmask(s48_call_t call, s48_ref_t sch_logmask)
  158. {
  159. return enter_syslog_mask(call, setlogmask(extract_syslog_mask(call, sch_logmask)));
  160. }
  161. static s48_ref_t
  162. posix_syslog(s48_call_t call,
  163. s48_ref_t sch_level, s48_ref_t sch_opt_facility, s48_ref_t sch_message)
  164. {
  165. int facility = s48_false_p_2(call, sch_opt_facility)
  166. ? 0 : extract_syslog_facility(call, sch_opt_facility);
  167. int level = extract_syslog_level(call, sch_level);
  168. if (!syslog_open)
  169. s48_assertion_violation_2(call, "posix_syslog", "syslog isn't open",
  170. 3, sch_level, sch_opt_facility, sch_message);
  171. syslog(facility | level, "%s", s48_extract_byte_vector_readonly_2(call, sch_message));
  172. return s48_unspecific_2(call);
  173. }
  174. static s48_ref_t
  175. posix_closelog(s48_call_t call)
  176. {
  177. if (!syslog_open)
  178. s48_assertion_violation_2(call, "posix_closelog", "syslog isn't open", 0);
  179. closelog();
  180. syslog_open = 0;
  181. return s48_unspecific_2(call);
  182. }
  183. void
  184. s48_uninit_posix_syslog(void)
  185. {
  186. if (syslog_ident != syslog_ident_initial)
  187. free(syslog_ident);
  188. }