Ruby  1.9.3p484(2013-11-22revision43786)
syslog.c
Go to the documentation of this file.
1 /*
2  * UNIX Syslog extension for Ruby
3  * Amos Gouaux, University of Texas at Dallas
4  * <amos+ruby@utdallas.edu>
5  * Documented by mathew <meta@pobox.com>
6  *
7  * $RoughId: syslog.c,v 1.21 2002/02/25 12:21:17 knu Exp $
8  * $Id: syslog.c 35740 2012-05-21 07:24:34Z knu $
9  */
10 
11 #include "ruby/ruby.h"
12 #include "ruby/util.h"
13 #include <syslog.h>
14 
15 /* Syslog class */
17 static const char *syslog_ident = NULL;
18 static int syslog_options = -1, syslog_facility = -1, syslog_mask = -1;
19 static int syslog_opened = 0;
20 
21 /* Package helper routines */
22 static void syslog_write(int pri, int argc, VALUE *argv)
23 {
24  VALUE str;
25 
26  rb_secure(4);
27  if (argc < 1) {
28  rb_raise(rb_eArgError, "no log message supplied");
29  }
30 
31  if (!syslog_opened) {
32  rb_raise(rb_eRuntimeError, "must open syslog before write");
33  }
34 
35  str = rb_f_sprintf(argc, argv);
36 
37  syslog(pri, "%s", RSTRING_PTR(str));
38 }
39 
40 /* Closes the syslog facility.
41  * Raises a runtime exception if it is not open.
42  */
44 {
45  rb_secure(4);
46  if (!syslog_opened) {
47  rb_raise(rb_eRuntimeError, "syslog not opened");
48  }
49 
50  closelog();
51 
52  free((void *)syslog_ident);
55  syslog_opened = 0;
56 
57  return Qnil;
58 }
59 
60 /* call-seq:
61  * open(ident, options, facility) => syslog
62  *
63  * :yields: syslog
64  *
65  * Open the syslog facility.
66  * Raises a runtime exception if it is already open.
67  *
68  * Can be called with or without a code block. If called with a block, the
69  * Syslog object created is passed to the block.
70  *
71  * If the syslog is already open, raises a RuntimeError.
72  *
73  * +ident+ is a String which identifies the calling program.
74  *
75  * +options+ is the logical OR of any of the following:
76  *
77  * LOG_CONS:: If there is an error while sending to the system logger,
78  * write directly to the console instead.
79  *
80  * LOG_NDELAY:: Open the connection now, rather than waiting for the first
81  * message to be written.
82  *
83  * LOG_NOWAIT:: Don't wait for any child processes created while logging
84  * messages. (Has no effect on Linux.)
85  *
86  * LOG_ODELAY:: Opposite of LOG_NDELAY; wait until a message is sent before
87  * opening the connection. (This is the default.)
88  *
89  * LOG_PERROR:: Print the message to stderr as well as sending it to syslog.
90  * (Not in POSIX.1-2001.)
91  *
92  * LOG_PID:: Include the current process ID with each message.
93  *
94  * +facility+ describes the type of program opening the syslog, and is
95  * the logical OR of any of the following which are defined for the host OS:
96  *
97  * LOG_AUTH:: Security or authorization. Deprecated, use LOG_AUTHPRIV
98  * instead.
99  *
100  * LOG_AUTHPRIV:: Security or authorization messages which should be kept
101  * private.
102  *
103  * LOG_CONSOLE:: System console message.
104  *
105  * LOG_CRON:: System task scheduler (cron or at).
106  *
107  * LOG_DAEMON:: A system daemon which has no facility value of its own.
108  *
109  * LOG_FTP:: An FTP server.
110  *
111  * LOG_KERN:: A kernel message (not sendable by user processes, so not of
112  * much use to Ruby, but listed here for completeness).
113  *
114  * LOG_LRP:: Line printer subsystem.
115  *
116  * LOG_MAIL:: Mail delivery or transport subsystem.
117  *
118  * LOG_NEWS:: Usenet news system.
119  *
120  * LOG_NTP:: Network Time Protocol server.
121  *
122  * LOG_SECURITY:: General security message.
123  *
124  * LOG_SYSLOG:: Messages generated internally by syslog.
125  *
126  * LOG_USER:: Generic user-level message.
127  *
128  * LOG_UUCP:: UUCP subsystem.
129  *
130  * LOG_LOCAL0 to LOG_LOCAL7:: Locally-defined facilities.
131  *
132  * Example:
133  *
134  * Syslog.open("webrick", Syslog::LOG_PID,
135  * Syslog::LOG_DAEMON | Syslog::LOG_LOCAL3)
136  *
137  */
138 static VALUE mSyslog_open(int argc, VALUE *argv, VALUE self)
139 {
140  VALUE ident, opt, fac;
141 
142  if (syslog_opened) {
143  rb_raise(rb_eRuntimeError, "syslog already open");
144  }
145 
146  rb_scan_args(argc, argv, "03", &ident, &opt, &fac);
147 
148  if (NIL_P(ident)) {
149  ident = rb_gv_get("$0");
150  }
151  SafeStringValue(ident);
152  syslog_ident = strdup(RSTRING_PTR(ident));
153 
154  if (NIL_P(opt)) {
155  syslog_options = LOG_PID | LOG_CONS;
156  } else {
157  syslog_options = NUM2INT(opt);
158  }
159 
160  if (NIL_P(fac)) {
161  syslog_facility = LOG_USER;
162  } else {
163  syslog_facility = NUM2INT(fac);
164  }
165 
167 
168  syslog_opened = 1;
169 
170  setlogmask(syslog_mask = setlogmask(0));
171 
172  /* be like File.new.open {...} */
173  if (rb_block_given_p()) {
174  rb_ensure(rb_yield, self, mSyslog_close, self);
175  }
176 
177  return self;
178 }
179 
180 /* call-seq:
181  * reopen(ident, options, facility) => syslog
182  *
183  * :yields: syslog
184  *
185  * Closes and then reopens the syslog.
186  *
187  * Arguments are the same as for open().
188  */
190 {
191  mSyslog_close(self);
192 
193  return mSyslog_open(argc, argv, self);
194 }
195 
196 /* call-seq:
197  * opened?
198  *
199  * Returns true if the syslog is open.
200  */
202 {
203  return syslog_opened ? Qtrue : Qfalse;
204 }
205 
206 /* Returns the identity string used in the last call to open()
207  */
209 {
211 }
212 
213 /* Returns the options bitmask used in the last call to open()
214  */
216 {
218 }
219 
220 /* Returns the facility number used in the last call to open()
221  */
223 {
225 }
226 
227 /* Returns the log priority mask in effect. The mask is not reset by opening
228  * or closing syslog.
229  */
231 {
233 }
234 
235 /* call-seq:
236  * mask=(priority_mask)
237  *
238  * Sets the log priority mask. A method LOG_UPTO is defined to make it easier
239  * to set mask values. Example:
240  *
241  * Syslog.mask = Syslog::LOG_UPTO(Syslog::LOG_ERR)
242  *
243  * Alternatively, specific priorities can be selected and added together using
244  * binary OR. Example:
245  *
246  * Syslog.mask = Syslog::LOG_MASK(Syslog::LOG_ERR) | Syslog::LOG_MASK(Syslog::LOG_CRIT)
247  *
248  * The priority mask persists through calls to open() and close().
249  */
250 static VALUE mSyslog_set_mask(VALUE self, VALUE mask)
251 {
252  rb_secure(4);
253  if (!syslog_opened) {
254  rb_raise(rb_eRuntimeError, "must open syslog before setting log mask");
255  }
256 
257  setlogmask(syslog_mask = NUM2INT(mask));
258 
259  return mask;
260 }
261 
262 /* call-seq:
263  * log(priority, format_string, *format_args)
264  *
265  * Log a message with the specified priority. Example:
266  *
267  * Syslog.log(Syslog::LOG_CRIT, "Out of disk space")
268  * Syslog.log(Syslog::LOG_CRIT, "User %s logged in", ENV['USER'])
269  *
270  * The priority levels, in descending order, are:
271  *
272  * LOG_EMERG:: System is unusable
273  * LOG_ALERT:: Action needs to be taken immediately
274  * LOG_CRIT:: A critical condition has occurred
275  * LOG_ERR:: An error occurred
276  * LOG_WARNING:: Warning of a possible problem
277  * LOG_NOTICE:: A normal but significant condition occurred
278  * LOG_INFO:: Informational message
279  * LOG_DEBUG:: Debugging information
280  *
281  * Each priority level also has a shortcut method that logs with it's named priority.
282  * As an example, the two following statements would produce the same result:
283  *
284  * Syslog.log(Syslog::LOG_ALERT, "Out of memory")
285  * Syslog.alert("Out of memory")
286  *
287  * Format strings are as for printf/sprintf, except that in addition %m is
288  * replaced with the error message string that would be returned by
289  * strerror(errno).
290  *
291  */
292 static VALUE mSyslog_log(int argc, VALUE *argv, VALUE self)
293 {
294  VALUE pri;
295 
296  if (argc < 2) {
297  rb_raise(rb_eArgError, "wrong number of arguments (%d for 2+)", argc);
298  }
299 
300  argc--;
301  pri = *argv++;
302 
303  if (!FIXNUM_P(pri)) {
304  rb_raise(rb_eTypeError, "type mismatch: %s given", rb_class2name(CLASS_OF(pri)));
305  }
306 
307  syslog_write(FIX2INT(pri), argc, argv);
308 
309  return self;
310 }
311 
312 /* Returns an inspect() string summarizing the object state.
313  */
315 {
316  char buf[1024];
317 
318  Check_Type(self, T_MODULE);
319 
320  if (syslog_opened) {
321  snprintf(buf, sizeof(buf),
322  "<#%s: opened=true, ident=\"%s\", options=%d, facility=%d, mask=%d>",
323  rb_class2name(self),
324  syslog_ident,
327  syslog_mask);
328  } else {
329  snprintf(buf, sizeof(buf),
330  "<#%s: opened=false>", rb_class2name(self));
331  }
332 
333  return rb_str_new2(buf);
334 }
335 
336 /* Returns self, for backward compatibility.
337  */
339 {
340  return self;
341 }
342 
343 #define define_syslog_shortcut_method(pri, name) \
344 static VALUE mSyslog_##name(int argc, VALUE *argv, VALUE self) \
345 { \
346  syslog_write((pri), argc, argv); \
347 \
348  return self; \
349 }
350 
351 #ifdef LOG_EMERG
352 define_syslog_shortcut_method(LOG_EMERG, emerg)
353 #endif
354 #ifdef LOG_ALERT
355 define_syslog_shortcut_method(LOG_ALERT, alert)
356 #endif
357 #ifdef LOG_CRIT
358 define_syslog_shortcut_method(LOG_CRIT, crit)
359 #endif
360 #ifdef LOG_ERR
362 #endif
363 #ifdef LOG_WARNING
364 define_syslog_shortcut_method(LOG_WARNING, warning)
365 #endif
366 #ifdef LOG_NOTICE
367 define_syslog_shortcut_method(LOG_NOTICE, notice)
368 #endif
369 #ifdef LOG_INFO
370 define_syslog_shortcut_method(LOG_INFO, info)
371 #endif
372 #ifdef LOG_DEBUG
374 #endif
375 
376 /* call-seq:
377  * LOG_MASK(priority_level) => priority_mask
378  *
379  * Generates a mask bit for a priority level. See #mask=
380  */
382 {
383  return INT2FIX(LOG_MASK(NUM2INT(pri)));
384 }
385 
386 /* call-seq:
387  * LOG_UPTO(priority_level) => priority_mask
388  *
389  * Generates a mask value for priority levels at or below the level specified.
390  * See #mask=
391  */
393 {
394  return INT2FIX(LOG_UPTO(NUM2INT(pri)));
395 }
396 
397 /* The syslog package provides a Ruby interface to the POSIX system logging
398  * facility.
399  *
400  * Syslog messages are typically passed to a central logging daemon.
401  * The daemon may filter them; route them into different files (usually
402  * found under /var/log); place them in SQL databases; forward
403  * them to centralized logging servers via TCP or UDP; or even alert the
404  * system administrator via email, pager or text message.
405  *
406  * Unlike application-level logging via Logger or Log4r, syslog is designed
407  * to allow secure tamper-proof logging.
408  *
409  * The syslog protocol is standardized in RFC 5424.
410  */
412 {
413  mSyslog = rb_define_module("Syslog");
414 
415  /* Document-module: Syslog::Constants
416  *
417  * Module holding Syslog constants. See Syslog::log and Syslog::open for
418  * constant descriptions.
419  */
421 
423 
428 
432 
437 
440 
443 
446 
447 #define rb_define_syslog_const(id) \
448  rb_define_const(mSyslogConstants, #id, INT2NUM(id))
449 
450  /* Various options when opening log */
451 #ifdef LOG_PID
452  rb_define_syslog_const(LOG_PID);
453 #endif
454 #ifdef LOG_CONS
455  rb_define_syslog_const(LOG_CONS);
456 #endif
457 #ifdef LOG_ODELAY
458  rb_define_syslog_const(LOG_ODELAY); /* deprecated */
459 #endif
460 #ifdef LOG_NDELAY
461  rb_define_syslog_const(LOG_NDELAY);
462 #endif
463 #ifdef LOG_NOWAIT
464  rb_define_syslog_const(LOG_NOWAIT); /* deprecated */
465 #endif
466 #ifdef LOG_PERROR
467  rb_define_syslog_const(LOG_PERROR);
468 #endif
469 
470  /* Various syslog facilities */
471 #ifdef LOG_AUTH
472  rb_define_syslog_const(LOG_AUTH);
473 #endif
474 #ifdef LOG_AUTHPRIV
475  rb_define_syslog_const(LOG_AUTHPRIV);
476 #endif
477 #ifdef LOG_CONSOLE
478  rb_define_syslog_const(LOG_CONSOLE);
479 #endif
480 #ifdef LOG_CRON
481  rb_define_syslog_const(LOG_CRON);
482 #endif
483 #ifdef LOG_DAEMON
484  rb_define_syslog_const(LOG_DAEMON);
485 #endif
486 #ifdef LOG_FTP
487  rb_define_syslog_const(LOG_FTP);
488 #endif
489 #ifdef LOG_KERN
490  rb_define_syslog_const(LOG_KERN);
491 #endif
492 #ifdef LOG_LPR
493  rb_define_syslog_const(LOG_LPR);
494 #endif
495 #ifdef LOG_MAIL
496  rb_define_syslog_const(LOG_MAIL);
497 #endif
498 #ifdef LOG_NEWS
499  rb_define_syslog_const(LOG_NEWS);
500 #endif
501 #ifdef LOG_NTP
502  rb_define_syslog_const(LOG_NTP);
503 #endif
504 #ifdef LOG_SECURITY
505  rb_define_syslog_const(LOG_SECURITY);
506 #endif
507 #ifdef LOG_SYSLOG
508  rb_define_syslog_const(LOG_SYSLOG);
509 #endif
510 #ifdef LOG_USER
511  rb_define_syslog_const(LOG_USER);
512 #endif
513 #ifdef LOG_UUCP
514  rb_define_syslog_const(LOG_UUCP);
515 #endif
516 #ifdef LOG_LOCAL0
517  rb_define_syslog_const(LOG_LOCAL0);
518 #endif
519 #ifdef LOG_LOCAL1
520  rb_define_syslog_const(LOG_LOCAL1);
521 #endif
522 #ifdef LOG_LOCAL2
523  rb_define_syslog_const(LOG_LOCAL2);
524 #endif
525 #ifdef LOG_LOCAL3
526  rb_define_syslog_const(LOG_LOCAL3);
527 #endif
528 #ifdef LOG_LOCAL4
529  rb_define_syslog_const(LOG_LOCAL4);
530 #endif
531 #ifdef LOG_LOCAL5
532  rb_define_syslog_const(LOG_LOCAL5);
533 #endif
534 #ifdef LOG_LOCAL6
535  rb_define_syslog_const(LOG_LOCAL6);
536 #endif
537 #ifdef LOG_LOCAL7
538  rb_define_syslog_const(LOG_LOCAL7);
539 #endif
540 
541 #define rb_define_syslog_shortcut(name) \
542  rb_define_module_function(mSyslog, #name, mSyslog_##name, -1)
543 
544  /* Various syslog priorities and the shortcut methods */
545 #ifdef LOG_EMERG
546  rb_define_syslog_const(LOG_EMERG);
548 #endif
549 #ifdef LOG_ALERT
550  rb_define_syslog_const(LOG_ALERT);
552 #endif
553 #ifdef LOG_CRIT
554  rb_define_syslog_const(LOG_CRIT);
556 #endif
557 #ifdef LOG_ERR
558  rb_define_syslog_const(LOG_ERR);
560 #endif
561 #ifdef LOG_WARNING
562  rb_define_syslog_const(LOG_WARNING);
563  rb_define_syslog_shortcut(warning);
564 #endif
565 #ifdef LOG_NOTICE
566  rb_define_syslog_const(LOG_NOTICE);
568 #endif
569 #ifdef LOG_INFO
570  rb_define_syslog_const(LOG_INFO);
572 #endif
573 #ifdef LOG_DEBUG
574  rb_define_syslog_const(LOG_DEBUG);
576 #endif
577 }
578