Ruby 2.7.6p219 (2022-04-12 revision c9c2245c0a25176072e02db9254f0e0c84c805cd)
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$
9 */
10
11#include "ruby/ruby.h"
12#include "ruby/util.h"
13#include <syslog.h>
14
15/* Syslog class */
16static VALUE mSyslog;
17/*
18 * Module holding all Syslog constants. See Syslog::log and
19 * Syslog::open for constant descriptions.
20 */
21static VALUE mSyslogConstants;
22/* Module holding Syslog option constants */
23static VALUE mSyslogOption;
24/* Module holding Syslog facility constants */
25static VALUE mSyslogFacility;
26/* Module holding Syslog level constants */
27static VALUE mSyslogLevel;
28/* Module holding Syslog utility macros */
29static VALUE mSyslogMacros;
30
31static const char *syslog_ident = NULL;
32static int syslog_options = -1, syslog_facility = -1, syslog_mask = -1;
33static int syslog_opened = 0;
34
35/* Package helper routines */
36static void syslog_write(int pri, int argc, VALUE *argv)
37{
38 VALUE str;
39
40 if (argc < 1) {
41 rb_raise(rb_eArgError, "no log message supplied");
42 }
43
44 if (!syslog_opened) {
45 rb_raise(rb_eRuntimeError, "must open syslog before write");
46 }
47
49
50 syslog(pri, "%s", RSTRING_PTR(str));
51}
52
53/* Closes the syslog facility.
54 * Raises a runtime exception if it is not open.
55 */
56static VALUE mSyslog_close(VALUE self)
57{
58 if (!syslog_opened) {
59 rb_raise(rb_eRuntimeError, "syslog not opened");
60 }
61
62 closelog();
63
64 xfree((void *)syslog_ident);
65 syslog_ident = NULL;
66 syslog_options = syslog_facility = syslog_mask = -1;
67 syslog_opened = 0;
68
69 return Qnil;
70}
71
72/* call-seq:
73 * open(ident, options, facility) => syslog
74 *
75 * :yields: syslog
76 *
77 * Open the syslog facility.
78 * Raises a runtime exception if it is already open.
79 *
80 * Can be called with or without a code block. If called with a block, the
81 * Syslog object created is passed to the block.
82 *
83 * If the syslog is already open, raises a RuntimeError.
84 *
85 * +ident+ is a String which identifies the calling program.
86 *
87 * +options+ is the logical OR of any of the following:
88 *
89 * LOG_CONS:: If there is an error while sending to the system logger,
90 * write directly to the console instead.
91 *
92 * LOG_NDELAY:: Open the connection now, rather than waiting for the first
93 * message to be written.
94 *
95 * LOG_NOWAIT:: Don't wait for any child processes created while logging
96 * messages. (Has no effect on Linux.)
97 *
98 * LOG_ODELAY:: Opposite of LOG_NDELAY; wait until a message is sent before
99 * opening the connection. (This is the default.)
100 *
101 * LOG_PERROR:: Print the message to stderr as well as sending it to syslog.
102 * (Not in POSIX.1-2001.)
103 *
104 * LOG_PID:: Include the current process ID with each message.
105 *
106 * +facility+ describes the type of program opening the syslog, and is
107 * the logical OR of any of the following which are defined for the host OS:
108 *
109 * LOG_AUTH:: Security or authorization. Deprecated, use LOG_AUTHPRIV
110 * instead.
111 *
112 * LOG_AUTHPRIV:: Security or authorization messages which should be kept
113 * private.
114 *
115 * LOG_CONSOLE:: System console message.
116 *
117 * LOG_CRON:: System task scheduler (cron or at).
118 *
119 * LOG_DAEMON:: A system daemon which has no facility value of its own.
120 *
121 * LOG_FTP:: An FTP server.
122 *
123 * LOG_KERN:: A kernel message (not sendable by user processes, so not of
124 * much use to Ruby, but listed here for completeness).
125 *
126 * LOG_LPR:: Line printer subsystem.
127 *
128 * LOG_MAIL:: Mail delivery or transport subsystem.
129 *
130 * LOG_NEWS:: Usenet news system.
131 *
132 * LOG_NTP:: Network Time Protocol server.
133 *
134 * LOG_SECURITY:: General security message.
135 *
136 * LOG_SYSLOG:: Messages generated internally by syslog.
137 *
138 * LOG_USER:: Generic user-level message.
139 *
140 * LOG_UUCP:: UUCP subsystem.
141 *
142 * LOG_LOCAL0 to LOG_LOCAL7:: Locally-defined facilities.
143 *
144 * Example:
145 *
146 * Syslog.open("webrick", Syslog::LOG_PID,
147 * Syslog::LOG_DAEMON | Syslog::LOG_LOCAL3)
148 *
149 */
150static VALUE mSyslog_open(int argc, VALUE *argv, VALUE self)
151{
152 VALUE ident, opt, fac;
153 const char *ident_ptr;
154
155 if (syslog_opened) {
156 rb_raise(rb_eRuntimeError, "syslog already open");
157 }
158
159 rb_scan_args(argc, argv, "03", &ident, &opt, &fac);
160
161 if (NIL_P(ident)) {
162 ident = rb_gv_get("$0");
163 }
164 ident_ptr = StringValueCStr(ident);
165 syslog_ident = strdup(ident_ptr);
166
167 if (NIL_P(opt)) {
168 syslog_options = LOG_PID | LOG_CONS;
169 } else {
170 syslog_options = NUM2INT(opt);
171 }
172
173 if (NIL_P(fac)) {
174 syslog_facility = LOG_USER;
175 } else {
176 syslog_facility = NUM2INT(fac);
177 }
178
179 openlog(syslog_ident, syslog_options, syslog_facility);
180
181 syslog_opened = 1;
182
183 setlogmask(syslog_mask = setlogmask(0));
184
185 /* be like File.new.open {...} */
186 if (rb_block_given_p()) {
187 rb_ensure(rb_yield, self, mSyslog_close, self);
188 }
189
190 return self;
191}
192
193/* call-seq:
194 * reopen(ident, options, facility) => syslog
195 *
196 * :yields: syslog
197 *
198 * Closes and then reopens the syslog.
199 *
200 * Arguments are the same as for open().
201 */
202static VALUE mSyslog_reopen(int argc, VALUE *argv, VALUE self)
203{
204 mSyslog_close(self);
205
206 return mSyslog_open(argc, argv, self);
207}
208
209/* call-seq:
210 * opened?
211 *
212 * Returns true if the syslog is open.
213 */
214static VALUE mSyslog_isopen(VALUE self)
215{
216 return syslog_opened ? Qtrue : Qfalse;
217}
218
219/* Returns the identity string used in the last call to open()
220 */
221static VALUE mSyslog_ident(VALUE self)
222{
223 return syslog_opened ? rb_str_new2(syslog_ident) : Qnil;
224}
225
226/* Returns the options bitmask used in the last call to open()
227 */
228static VALUE mSyslog_options(VALUE self)
229{
230 return syslog_opened ? INT2NUM(syslog_options) : Qnil;
231}
232
233/* Returns the facility number used in the last call to open()
234 */
235static VALUE mSyslog_facility(VALUE self)
236{
237 return syslog_opened ? INT2NUM(syslog_facility) : Qnil;
238}
239
240/* Returns the log priority mask in effect. The mask is not reset by opening
241 * or closing syslog.
242 */
243static VALUE mSyslog_get_mask(VALUE self)
244{
245 return syslog_opened ? INT2NUM(syslog_mask) : Qnil;
246}
247
248/* call-seq:
249 * mask=(priority_mask)
250 *
251 * Sets the log priority mask. A method LOG_UPTO is defined to make it easier
252 * to set mask values. Example:
253 *
254 * Syslog.mask = Syslog::LOG_UPTO(Syslog::LOG_ERR)
255 *
256 * Alternatively, specific priorities can be selected and added together using
257 * binary OR. Example:
258 *
259 * Syslog.mask = Syslog::LOG_MASK(Syslog::LOG_ERR) | Syslog::LOG_MASK(Syslog::LOG_CRIT)
260 *
261 * The priority mask persists through calls to open() and close().
262 */
263static VALUE mSyslog_set_mask(VALUE self, VALUE mask)
264{
265 if (!syslog_opened) {
266 rb_raise(rb_eRuntimeError, "must open syslog before setting log mask");
267 }
268
269 setlogmask(syslog_mask = NUM2INT(mask));
270
271 return mask;
272}
273
274/* call-seq:
275 * log(priority, format_string, *format_args)
276 *
277 * Log a message with the specified priority. Example:
278 *
279 * Syslog.log(Syslog::LOG_CRIT, "Out of disk space")
280 * Syslog.log(Syslog::LOG_CRIT, "User %s logged in", ENV['USER'])
281 *
282 * The priority levels, in descending order, are:
283 *
284 * LOG_EMERG:: System is unusable
285 * LOG_ALERT:: Action needs to be taken immediately
286 * LOG_CRIT:: A critical condition has occurred
287 * LOG_ERR:: An error occurred
288 * LOG_WARNING:: Warning of a possible problem
289 * LOG_NOTICE:: A normal but significant condition occurred
290 * LOG_INFO:: Informational message
291 * LOG_DEBUG:: Debugging information
292 *
293 * Each priority level also has a shortcut method that logs with it's named priority.
294 * As an example, the two following statements would produce the same result:
295 *
296 * Syslog.log(Syslog::LOG_ALERT, "Out of memory")
297 * Syslog.alert("Out of memory")
298 *
299 */
300static VALUE mSyslog_log(int argc, VALUE *argv, VALUE self)
301{
302 VALUE pri;
303
305
306 argc--;
307 pri = *argv++;
308
309 if (!FIXNUM_P(pri)) {
310 rb_raise(rb_eTypeError, "type mismatch: %"PRIsVALUE" given", rb_obj_class(pri));
311 }
312
313 syslog_write(FIX2INT(pri), argc, argv);
314
315 return self;
316}
317
318/* Returns an inspect() string summarizing the object state.
319 */
320static VALUE mSyslog_inspect(VALUE self)
321{
322 Check_Type(self, T_MODULE);
323
324 if (!syslog_opened)
325 return rb_sprintf("<#%"PRIsVALUE": opened=false>", self);
326
327 return rb_sprintf("<#%"PRIsVALUE": opened=true, ident=\"%s\", options=%d, facility=%d, mask=%d>",
328 self,
329 syslog_ident,
330 syslog_options,
331 syslog_facility,
332 syslog_mask);
333}
334
335/* Returns self, for backward compatibility.
336 */
337static VALUE mSyslog_instance(VALUE self)
338{
339 return self;
340}
341
342#define define_syslog_shortcut_method(pri, name) \
343static VALUE mSyslog_##name(int argc, VALUE *argv, VALUE self) \
344{ \
345 syslog_write((pri), argc, argv); \
346\
347 return self; \
348}
349
350#ifdef LOG_EMERG
351define_syslog_shortcut_method(LOG_EMERG, emerg)
352#endif
353#ifdef LOG_ALERT
354define_syslog_shortcut_method(LOG_ALERT, alert)
355#endif
356#ifdef LOG_CRIT
358#endif
359#ifdef LOG_ERR
361#endif
362#ifdef LOG_WARNING
363define_syslog_shortcut_method(LOG_WARNING, warning)
364#endif
365#ifdef LOG_NOTICE
366define_syslog_shortcut_method(LOG_NOTICE, notice)
367#endif
368#ifdef LOG_INFO
369define_syslog_shortcut_method(LOG_INFO, info)
370#endif
371#ifdef LOG_DEBUG
373#endif
374
375/* call-seq:
376 * LOG_MASK(priority_level) => priority_mask
377 *
378 * Generates a mask bit for a priority level. See #mask=
379 */
380static VALUE mSyslogMacros_LOG_MASK(VALUE mod, VALUE pri)
381{
382 return INT2FIX(LOG_MASK(NUM2INT(pri)));
383}
384
385/* call-seq:
386 * LOG_UPTO(priority_level) => priority_mask
387 *
388 * Generates a mask value for priority levels at or below the level specified.
389 * See #mask=
390 */
391static VALUE mSyslogMacros_LOG_UPTO(VALUE mod, VALUE pri)
392{
393 return INT2FIX(LOG_UPTO(NUM2INT(pri)));
394}
395
396static VALUE mSyslogMacros_included(VALUE mod, VALUE target)
397{
398 rb_extend_object(target, mSyslogMacros);
399 return mod;
400}
401
402/* The syslog package provides a Ruby interface to the POSIX system logging
403 * facility.
404 *
405 * Syslog messages are typically passed to a central logging daemon.
406 * The daemon may filter them; route them into different files (usually
407 * found under /var/log); place them in SQL databases; forward
408 * them to centralized logging servers via TCP or UDP; or even alert the
409 * system administrator via email, pager or text message.
410 *
411 * Unlike application-level logging via Logger or Log4r, syslog is designed
412 * to allow secure tamper-proof logging.
413 *
414 * The syslog protocol is standardized in RFC 5424.
415 */
416void Init_syslog(void)
417{
418#undef rb_intern
419 mSyslog = rb_define_module("Syslog");
420
421 mSyslogConstants = rb_define_module_under(mSyslog, "Constants");
422
423 mSyslogOption = rb_define_module_under(mSyslog, "Option");
424 mSyslogFacility = rb_define_module_under(mSyslog, "Facility");
425 mSyslogLevel = rb_define_module_under(mSyslog, "Level");
426 mSyslogMacros = rb_define_module_under(mSyslog, "Macros");
427
428 rb_define_module_function(mSyslog, "open", mSyslog_open, -1);
429 rb_define_module_function(mSyslog, "reopen", mSyslog_reopen, -1);
430 rb_define_module_function(mSyslog, "open!", mSyslog_reopen, -1);
431 rb_define_module_function(mSyslog, "opened?", mSyslog_isopen, 0);
432
433 rb_define_module_function(mSyslog, "ident", mSyslog_ident, 0);
434 rb_define_module_function(mSyslog, "options", mSyslog_options, 0);
435 rb_define_module_function(mSyslog, "facility", mSyslog_facility, 0);
436
437 rb_define_module_function(mSyslog, "log", mSyslog_log, -1);
438 rb_define_module_function(mSyslog, "close", mSyslog_close, 0);
439 rb_define_module_function(mSyslog, "mask", mSyslog_get_mask, 0);
440 rb_define_module_function(mSyslog, "mask=", mSyslog_set_mask, 1);
441
442 rb_define_singleton_method(mSyslog, "inspect", mSyslog_inspect, 0);
443 rb_define_module_function(mSyslog, "instance", mSyslog_instance, 0);
444
445 /* Syslog options */
446
447#define rb_define_syslog_option(c) \
448 rb_define_const(mSyslogOption, #c, INT2NUM(c))
449
450#ifdef LOG_PID
452#endif
453#ifdef LOG_CONS
454 rb_define_syslog_option(LOG_CONS);
455#endif
456#ifdef LOG_ODELAY
457 rb_define_syslog_option(LOG_ODELAY); /* deprecated */
458#endif
459#ifdef LOG_NDELAY
460 rb_define_syslog_option(LOG_NDELAY);
461#endif
462#ifdef LOG_NOWAIT
463 rb_define_syslog_option(LOG_NOWAIT); /* deprecated */
464#endif
465#ifdef LOG_PERROR
466 rb_define_syslog_option(LOG_PERROR);
467#endif
468
469 /* Syslog facilities */
470
471#define rb_define_syslog_facility(c) \
472 rb_define_const(mSyslogFacility, #c, INT2NUM(c))
473
474#ifdef LOG_AUTH
476#endif
477#ifdef LOG_AUTHPRIV
478 rb_define_syslog_facility(LOG_AUTHPRIV);
479#endif
480#ifdef LOG_CONSOLE
481 rb_define_syslog_facility(LOG_CONSOLE);
482#endif
483#ifdef LOG_CRON
485#endif
486#ifdef LOG_DAEMON
487 rb_define_syslog_facility(LOG_DAEMON);
488#endif
489#ifdef LOG_FTP
491#endif
492#ifdef LOG_KERN
494#endif
495#ifdef LOG_LPR
497#endif
498#ifdef LOG_MAIL
500#endif
501#ifdef LOG_NEWS
503#endif
504#ifdef LOG_NTP
506#endif
507#ifdef LOG_SECURITY
508 rb_define_syslog_facility(LOG_SECURITY);
509#endif
510#ifdef LOG_SYSLOG
511 rb_define_syslog_facility(LOG_SYSLOG);
512#endif
513#ifdef LOG_USER
515#endif
516#ifdef LOG_UUCP
518#endif
519#ifdef LOG_LOCAL0
520 rb_define_syslog_facility(LOG_LOCAL0);
521#endif
522#ifdef LOG_LOCAL1
523 rb_define_syslog_facility(LOG_LOCAL1);
524#endif
525#ifdef LOG_LOCAL2
526 rb_define_syslog_facility(LOG_LOCAL2);
527#endif
528#ifdef LOG_LOCAL3
529 rb_define_syslog_facility(LOG_LOCAL3);
530#endif
531#ifdef LOG_LOCAL4
532 rb_define_syslog_facility(LOG_LOCAL4);
533#endif
534#ifdef LOG_LOCAL5
535 rb_define_syslog_facility(LOG_LOCAL5);
536#endif
537#ifdef LOG_LOCAL6
538 rb_define_syslog_facility(LOG_LOCAL6);
539#endif
540#ifdef LOG_LOCAL7
541 rb_define_syslog_facility(LOG_LOCAL7);
542#endif
543
544 /* Syslog levels and the shortcut methods */
545
546#define rb_define_syslog_level(c, m) \
547 rb_define_const(mSyslogLevel, #c, INT2NUM(c)); \
548 rb_define_module_function(mSyslog, #m, mSyslog_##m, -1)
549
550#ifdef LOG_EMERG
551 rb_define_syslog_level(LOG_EMERG, emerg);
552#endif
553#ifdef LOG_ALERT
554 rb_define_syslog_level(LOG_ALERT, alert);
555#endif
556#ifdef LOG_CRIT
557 rb_define_syslog_level(LOG_CRIT, crit);
558#endif
559#ifdef LOG_ERR
560 rb_define_syslog_level(LOG_ERR, err);
561#endif
562#ifdef LOG_WARNING
563 rb_define_syslog_level(LOG_WARNING, warning);
564#endif
565#ifdef LOG_NOTICE
566 rb_define_syslog_level(LOG_NOTICE, notice);
567#endif
568#ifdef LOG_INFO
569 rb_define_syslog_level(LOG_INFO, info);
570#endif
571#ifdef LOG_DEBUG
572 rb_define_syslog_level(LOG_DEBUG, debug);
573#endif
574
575 /* Syslog macros */
576
577 rb_define_method(mSyslogMacros, "LOG_MASK", mSyslogMacros_LOG_MASK, 1);
578 rb_define_method(mSyslogMacros, "LOG_UPTO", mSyslogMacros_LOG_UPTO, 1);
579 rb_define_singleton_method(mSyslogMacros, "included", mSyslogMacros_included, 1);
580
581 rb_include_module(mSyslogConstants, mSyslogOption);
582 rb_include_module(mSyslogConstants, mSyslogFacility);
583 rb_include_module(mSyslogConstants, mSyslogLevel);
584 rb_funcall(mSyslogConstants, rb_intern("include"), 1, mSyslogMacros);
585
586 rb_define_singleton_method(mSyslogConstants, "included", mSyslogMacros_included, 1);
587 rb_funcall(mSyslog, rb_intern("include"), 1, mSyslogConstants);
588}
#define mod(x, y)
Definition: date_strftime.c:28
enum @73::@75::@76 mask
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
void rb_include_module(VALUE, VALUE)
Definition: class.c:882
void rb_extend_object(VALUE, VALUE)
Extend the object with the module.
Definition: eval.c:1701
VALUE rb_define_module(const char *)
Definition: class.c:785
VALUE rb_define_module_under(VALUE, const char *)
Definition: class.c:810
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:898
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2671
VALUE rb_eTypeError
Definition: error.c:924
VALUE rb_eRuntimeError
Definition: error.c:922
VALUE rb_eArgError
Definition: error.c:925
VALUE rb_ensure(VALUE(*)(VALUE), VALUE, VALUE(*)(VALUE), VALUE)
An equivalent to ensure clause.
Definition: eval.c:1115
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
Definition: object.c:217
#define debug(lvl, x...)
Definition: ffi.c:52
#define rb_str_new2
#define NULL
#define UNLIMITED_ARGUMENTS
#define xfree
#define RSTRING_PTR(str)
#define NIL_P(v)
unsigned long VALUE
#define T_MODULE
#define INT2NUM(x)
void rb_define_module_function(VALUE, const char *, VALUE(*)(), int)
#define NUM2INT(x)
void rb_define_singleton_method(VALUE, const char *, VALUE(*)(), int)
#define PRIsVALUE
#define rb_funcall(recv, mid, argc,...)
#define FIX2INT(x)
#define rb_scan_args(argc, argvp, fmt,...)
#define rb_intern(str)
#define Qtrue
char * strdup(const char *) __attribute__((__malloc__)) __attribute__((__warn_unused_result__))
VALUE rb_f_sprintf(int, const VALUE *)
Definition: sprintf.c:198
#define Qnil
#define Qfalse
VALUE rb_gv_get(const char *)
Definition: variable.c:680
#define INT2FIX(i)
const VALUE * argv
#define FIXNUM_P(f)
#define Check_Type(v, t)
#define rb_check_arity
VALUE rb_sprintf(const char *,...) __attribute__((format(printf
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1237
void rb_define_method(VALUE, const char *, VALUE(*)(), int)
#define StringValueCStr(v)
#define rb_define_syslog_option(c)
#define define_syslog_shortcut_method(pri, name)
Definition: syslog.c:342
#define rb_define_syslog_level(c, m)
#define rb_define_syslog_facility(c)
void Init_syslog(void)
Definition: syslog.c:416