syslog.c 6.0 KB

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