Ruby
2.0.0p247(2013-06-27revision41674)
|
00001 /* 00002 * UNIX Syslog extension for Ruby 00003 * Amos Gouaux, University of Texas at Dallas 00004 * <amos+ruby@utdallas.edu> 00005 * Documented by mathew <meta@pobox.com> 00006 * 00007 * $RoughId: syslog.c,v 1.21 2002/02/25 12:21:17 knu Exp $ 00008 * $Id: syslog.c 35739 2012-05-21 07:18:49Z knu $ 00009 */ 00010 00011 #include "ruby/ruby.h" 00012 #include "ruby/util.h" 00013 #include <syslog.h> 00014 00015 /* Syslog class */ 00016 static VALUE mSyslog; 00017 /* 00018 * Module holding all Syslog constants. See Syslog::log and 00019 * Syslog::open for constant descriptions. 00020 */ 00021 static VALUE mSyslogConstants; 00022 /* Module holding Syslog option constants */ 00023 static VALUE mSyslogOption; 00024 /* Module holding Syslog facility constants */ 00025 static VALUE mSyslogFacility; 00026 /* Module holding Syslog level constants */ 00027 static VALUE mSyslogLevel; 00028 /* Module holding Syslog utility macros */ 00029 static VALUE mSyslogMacros; 00030 00031 static const char *syslog_ident = NULL; 00032 static int syslog_options = -1, syslog_facility = -1, syslog_mask = -1; 00033 static int syslog_opened = 0; 00034 00035 /* Package helper routines */ 00036 static void syslog_write(int pri, int argc, VALUE *argv) 00037 { 00038 VALUE str; 00039 00040 rb_secure(4); 00041 if (argc < 1) { 00042 rb_raise(rb_eArgError, "no log message supplied"); 00043 } 00044 00045 if (!syslog_opened) { 00046 rb_raise(rb_eRuntimeError, "must open syslog before write"); 00047 } 00048 00049 str = rb_f_sprintf(argc, argv); 00050 00051 syslog(pri, "%s", RSTRING_PTR(str)); 00052 } 00053 00054 /* Closes the syslog facility. 00055 * Raises a runtime exception if it is not open. 00056 */ 00057 static VALUE mSyslog_close(VALUE self) 00058 { 00059 rb_secure(4); 00060 if (!syslog_opened) { 00061 rb_raise(rb_eRuntimeError, "syslog not opened"); 00062 } 00063 00064 closelog(); 00065 00066 xfree((void *)syslog_ident); 00067 syslog_ident = NULL; 00068 syslog_options = syslog_facility = syslog_mask = -1; 00069 syslog_opened = 0; 00070 00071 return Qnil; 00072 } 00073 00074 /* call-seq: 00075 * open(ident, options, facility) => syslog 00076 * 00077 * :yields: syslog 00078 * 00079 * Open the syslog facility. 00080 * Raises a runtime exception if it is already open. 00081 * 00082 * Can be called with or without a code block. If called with a block, the 00083 * Syslog object created is passed to the block. 00084 * 00085 * If the syslog is already open, raises a RuntimeError. 00086 * 00087 * +ident+ is a String which identifies the calling program. 00088 * 00089 * +options+ is the logical OR of any of the following: 00090 * 00091 * LOG_CONS:: If there is an error while sending to the system logger, 00092 * write directly to the console instead. 00093 * 00094 * LOG_NDELAY:: Open the connection now, rather than waiting for the first 00095 * message to be written. 00096 * 00097 * LOG_NOWAIT:: Don't wait for any child processes created while logging 00098 * messages. (Has no effect on Linux.) 00099 * 00100 * LOG_ODELAY:: Opposite of LOG_NDELAY; wait until a message is sent before 00101 * opening the connection. (This is the default.) 00102 * 00103 * LOG_PERROR:: Print the message to stderr as well as sending it to syslog. 00104 * (Not in POSIX.1-2001.) 00105 * 00106 * LOG_PID:: Include the current process ID with each message. 00107 * 00108 * +facility+ describes the type of program opening the syslog, and is 00109 * the logical OR of any of the following which are defined for the host OS: 00110 * 00111 * LOG_AUTH:: Security or authorization. Deprecated, use LOG_AUTHPRIV 00112 * instead. 00113 * 00114 * LOG_AUTHPRIV:: Security or authorization messages which should be kept 00115 * private. 00116 * 00117 * LOG_CONSOLE:: System console message. 00118 * 00119 * LOG_CRON:: System task scheduler (cron or at). 00120 * 00121 * LOG_DAEMON:: A system daemon which has no facility value of its own. 00122 * 00123 * LOG_FTP:: An FTP server. 00124 * 00125 * LOG_KERN:: A kernel message (not sendable by user processes, so not of 00126 * much use to Ruby, but listed here for completeness). 00127 * 00128 * LOG_LPR:: Line printer subsystem. 00129 * 00130 * LOG_MAIL:: Mail delivery or transport subsystem. 00131 * 00132 * LOG_NEWS:: Usenet news system. 00133 * 00134 * LOG_NTP:: Network Time Protocol server. 00135 * 00136 * LOG_SECURITY:: General security message. 00137 * 00138 * LOG_SYSLOG:: Messages generated internally by syslog. 00139 * 00140 * LOG_USER:: Generic user-level message. 00141 * 00142 * LOG_UUCP:: UUCP subsystem. 00143 * 00144 * LOG_LOCAL0 to LOG_LOCAL7:: Locally-defined facilities. 00145 * 00146 * Example: 00147 * 00148 * Syslog.open("webrick", Syslog::LOG_PID, 00149 * Syslog::LOG_DAEMON | Syslog::LOG_LOCAL3) 00150 * 00151 */ 00152 static VALUE mSyslog_open(int argc, VALUE *argv, VALUE self) 00153 { 00154 VALUE ident, opt, fac; 00155 00156 if (syslog_opened) { 00157 rb_raise(rb_eRuntimeError, "syslog already open"); 00158 } 00159 00160 rb_scan_args(argc, argv, "03", &ident, &opt, &fac); 00161 00162 if (NIL_P(ident)) { 00163 ident = rb_gv_get("$0"); 00164 } 00165 SafeStringValue(ident); 00166 syslog_ident = strdup(RSTRING_PTR(ident)); 00167 00168 if (NIL_P(opt)) { 00169 syslog_options = LOG_PID | LOG_CONS; 00170 } else { 00171 syslog_options = NUM2INT(opt); 00172 } 00173 00174 if (NIL_P(fac)) { 00175 syslog_facility = LOG_USER; 00176 } else { 00177 syslog_facility = NUM2INT(fac); 00178 } 00179 00180 openlog(syslog_ident, syslog_options, syslog_facility); 00181 00182 syslog_opened = 1; 00183 00184 setlogmask(syslog_mask = setlogmask(0)); 00185 00186 /* be like File.new.open {...} */ 00187 if (rb_block_given_p()) { 00188 rb_ensure(rb_yield, self, mSyslog_close, self); 00189 } 00190 00191 return self; 00192 } 00193 00194 /* call-seq: 00195 * reopen(ident, options, facility) => syslog 00196 * 00197 * :yields: syslog 00198 * 00199 * Closes and then reopens the syslog. 00200 * 00201 * Arguments are the same as for open(). 00202 */ 00203 static VALUE mSyslog_reopen(int argc, VALUE *argv, VALUE self) 00204 { 00205 mSyslog_close(self); 00206 00207 return mSyslog_open(argc, argv, self); 00208 } 00209 00210 /* call-seq: 00211 * opened? 00212 * 00213 * Returns true if the syslog is open. 00214 */ 00215 static VALUE mSyslog_isopen(VALUE self) 00216 { 00217 return syslog_opened ? Qtrue : Qfalse; 00218 } 00219 00220 /* Returns the identity string used in the last call to open() 00221 */ 00222 static VALUE mSyslog_ident(VALUE self) 00223 { 00224 return syslog_opened ? rb_str_new2(syslog_ident) : Qnil; 00225 } 00226 00227 /* Returns the options bitmask used in the last call to open() 00228 */ 00229 static VALUE mSyslog_options(VALUE self) 00230 { 00231 return syslog_opened ? INT2NUM(syslog_options) : Qnil; 00232 } 00233 00234 /* Returns the facility number used in the last call to open() 00235 */ 00236 static VALUE mSyslog_facility(VALUE self) 00237 { 00238 return syslog_opened ? INT2NUM(syslog_facility) : Qnil; 00239 } 00240 00241 /* Returns the log priority mask in effect. The mask is not reset by opening 00242 * or closing syslog. 00243 */ 00244 static VALUE mSyslog_get_mask(VALUE self) 00245 { 00246 return syslog_opened ? INT2NUM(syslog_mask) : Qnil; 00247 } 00248 00249 /* call-seq: 00250 * mask=(priority_mask) 00251 * 00252 * Sets the log priority mask. A method LOG_UPTO is defined to make it easier 00253 * to set mask values. Example: 00254 * 00255 * Syslog.mask = Syslog::LOG_UPTO(Syslog::LOG_ERR) 00256 * 00257 * Alternatively, specific priorities can be selected and added together using 00258 * binary OR. Example: 00259 * 00260 * Syslog.mask = Syslog::LOG_MASK(Syslog::LOG_ERR) | Syslog::LOG_MASK(Syslog::LOG_CRIT) 00261 * 00262 * The priority mask persists through calls to open() and close(). 00263 */ 00264 static VALUE mSyslog_set_mask(VALUE self, VALUE mask) 00265 { 00266 rb_secure(4); 00267 if (!syslog_opened) { 00268 rb_raise(rb_eRuntimeError, "must open syslog before setting log mask"); 00269 } 00270 00271 setlogmask(syslog_mask = NUM2INT(mask)); 00272 00273 return mask; 00274 } 00275 00276 /* call-seq: 00277 * log(priority, format_string, *format_args) 00278 * 00279 * Log a message with the specified priority. Example: 00280 * 00281 * Syslog.log(Syslog::LOG_CRIT, "Out of disk space") 00282 * Syslog.log(Syslog::LOG_CRIT, "User %s logged in", ENV['USER']) 00283 * 00284 * The priority levels, in descending order, are: 00285 * 00286 * LOG_EMERG:: System is unusable 00287 * LOG_ALERT:: Action needs to be taken immediately 00288 * LOG_CRIT:: A critical condition has occurred 00289 * LOG_ERR:: An error occurred 00290 * LOG_WARNING:: Warning of a possible problem 00291 * LOG_NOTICE:: A normal but significant condition occurred 00292 * LOG_INFO:: Informational message 00293 * LOG_DEBUG:: Debugging information 00294 * 00295 * Each priority level also has a shortcut method that logs with it's named priority. 00296 * As an example, the two following statements would produce the same result: 00297 * 00298 * Syslog.log(Syslog::LOG_ALERT, "Out of memory") 00299 * Syslog.alert("Out of memory") 00300 * 00301 * Format strings are as for printf/sprintf, except that in addition %m is 00302 * replaced with the error message string that would be returned by 00303 * strerror(errno). 00304 * 00305 */ 00306 static VALUE mSyslog_log(int argc, VALUE *argv, VALUE self) 00307 { 00308 VALUE pri; 00309 00310 if (argc < 2) { 00311 rb_raise(rb_eArgError, "wrong number of arguments (%d for 2+)", argc); 00312 } 00313 00314 argc--; 00315 pri = *argv++; 00316 00317 if (!FIXNUM_P(pri)) { 00318 rb_raise(rb_eTypeError, "type mismatch: %s given", rb_class2name(CLASS_OF(pri))); 00319 } 00320 00321 syslog_write(FIX2INT(pri), argc, argv); 00322 00323 return self; 00324 } 00325 00326 /* Returns an inspect() string summarizing the object state. 00327 */ 00328 static VALUE mSyslog_inspect(VALUE self) 00329 { 00330 Check_Type(self, T_MODULE); 00331 00332 if (!syslog_opened) 00333 return rb_sprintf("<#%s: opened=false>", rb_class2name(self)); 00334 00335 return rb_sprintf("<#%s: opened=true, ident=\"%s\", options=%d, facility=%d, mask=%d>", 00336 rb_class2name(self), 00337 syslog_ident, 00338 syslog_options, 00339 syslog_facility, 00340 syslog_mask); 00341 } 00342 00343 /* Returns self, for backward compatibility. 00344 */ 00345 static VALUE mSyslog_instance(VALUE self) 00346 { 00347 return self; 00348 } 00349 00350 #define define_syslog_shortcut_method(pri, name) \ 00351 static VALUE mSyslog_##name(int argc, VALUE *argv, VALUE self) \ 00352 { \ 00353 syslog_write((pri), argc, argv); \ 00354 \ 00355 return self; \ 00356 } 00357 00358 #ifdef LOG_EMERG 00359 define_syslog_shortcut_method(LOG_EMERG, emerg) 00360 #endif 00361 #ifdef LOG_ALERT 00362 define_syslog_shortcut_method(LOG_ALERT, alert) 00363 #endif 00364 #ifdef LOG_CRIT 00365 define_syslog_shortcut_method(LOG_CRIT, crit) 00366 #endif 00367 #ifdef LOG_ERR 00368 define_syslog_shortcut_method(LOG_ERR, err) 00369 #endif 00370 #ifdef LOG_WARNING 00371 define_syslog_shortcut_method(LOG_WARNING, warning) 00372 #endif 00373 #ifdef LOG_NOTICE 00374 define_syslog_shortcut_method(LOG_NOTICE, notice) 00375 #endif 00376 #ifdef LOG_INFO 00377 define_syslog_shortcut_method(LOG_INFO, info) 00378 #endif 00379 #ifdef LOG_DEBUG 00380 define_syslog_shortcut_method(LOG_DEBUG, debug) 00381 #endif 00382 00383 /* call-seq: 00384 * LOG_MASK(priority_level) => priority_mask 00385 * 00386 * Generates a mask bit for a priority level. See #mask= 00387 */ 00388 static VALUE mSyslogMacros_LOG_MASK(VALUE mod, VALUE pri) 00389 { 00390 return INT2FIX(LOG_MASK(NUM2INT(pri))); 00391 } 00392 00393 /* call-seq: 00394 * LOG_UPTO(priority_level) => priority_mask 00395 * 00396 * Generates a mask value for priority levels at or below the level specified. 00397 * See #mask= 00398 */ 00399 static VALUE mSyslogMacros_LOG_UPTO(VALUE mod, VALUE pri) 00400 { 00401 return INT2FIX(LOG_UPTO(NUM2INT(pri))); 00402 } 00403 00404 static VALUE mSyslogMacros_included(VALUE mod, VALUE target) 00405 { 00406 rb_extend_object(target, mSyslogMacros); 00407 return mod; 00408 } 00409 00410 /* The syslog package provides a Ruby interface to the POSIX system logging 00411 * facility. 00412 * 00413 * Syslog messages are typically passed to a central logging daemon. 00414 * The daemon may filter them; route them into different files (usually 00415 * found under /var/log); place them in SQL databases; forward 00416 * them to centralized logging servers via TCP or UDP; or even alert the 00417 * system administrator via email, pager or text message. 00418 * 00419 * Unlike application-level logging via Logger or Log4r, syslog is designed 00420 * to allow secure tamper-proof logging. 00421 * 00422 * The syslog protocol is standardized in RFC 5424. 00423 */ 00424 void Init_syslog() 00425 { 00426 mSyslog = rb_define_module("Syslog"); 00427 00428 mSyslogConstants = rb_define_module_under(mSyslog, "Constants"); 00429 00430 mSyslogOption = rb_define_module_under(mSyslog, "Option"); 00431 mSyslogFacility = rb_define_module_under(mSyslog, "Facility"); 00432 mSyslogLevel = rb_define_module_under(mSyslog, "Level"); 00433 mSyslogMacros = rb_define_module_under(mSyslog, "Macros"); 00434 00435 rb_define_module_function(mSyslog, "open", mSyslog_open, -1); 00436 rb_define_module_function(mSyslog, "reopen", mSyslog_reopen, -1); 00437 rb_define_module_function(mSyslog, "open!", mSyslog_reopen, -1); 00438 rb_define_module_function(mSyslog, "opened?", mSyslog_isopen, 0); 00439 00440 rb_define_module_function(mSyslog, "ident", mSyslog_ident, 0); 00441 rb_define_module_function(mSyslog, "options", mSyslog_options, 0); 00442 rb_define_module_function(mSyslog, "facility", mSyslog_facility, 0); 00443 00444 rb_define_module_function(mSyslog, "log", mSyslog_log, -1); 00445 rb_define_module_function(mSyslog, "close", mSyslog_close, 0); 00446 rb_define_module_function(mSyslog, "mask", mSyslog_get_mask, 0); 00447 rb_define_module_function(mSyslog, "mask=", mSyslog_set_mask, 1); 00448 00449 rb_define_module_function(mSyslog, "inspect", mSyslog_inspect, 0); 00450 rb_define_module_function(mSyslog, "instance", mSyslog_instance, 0); 00451 00452 /* Syslog options */ 00453 00454 #define rb_define_syslog_option(c) \ 00455 rb_define_const(mSyslogOption, #c, INT2NUM(c)) 00456 00457 #ifdef LOG_PID 00458 rb_define_syslog_option(LOG_PID); 00459 #endif 00460 #ifdef LOG_CONS 00461 rb_define_syslog_option(LOG_CONS); 00462 #endif 00463 #ifdef LOG_ODELAY 00464 rb_define_syslog_option(LOG_ODELAY); /* deprecated */ 00465 #endif 00466 #ifdef LOG_NDELAY 00467 rb_define_syslog_option(LOG_NDELAY); 00468 #endif 00469 #ifdef LOG_NOWAIT 00470 rb_define_syslog_option(LOG_NOWAIT); /* deprecated */ 00471 #endif 00472 #ifdef LOG_PERROR 00473 rb_define_syslog_option(LOG_PERROR); 00474 #endif 00475 00476 /* Syslog facilities */ 00477 00478 #define rb_define_syslog_facility(c) \ 00479 rb_define_const(mSyslogFacility, #c, INT2NUM(c)) 00480 00481 #ifdef LOG_AUTH 00482 rb_define_syslog_facility(LOG_AUTH); 00483 #endif 00484 #ifdef LOG_AUTHPRIV 00485 rb_define_syslog_facility(LOG_AUTHPRIV); 00486 #endif 00487 #ifdef LOG_CONSOLE 00488 rb_define_syslog_facility(LOG_CONSOLE); 00489 #endif 00490 #ifdef LOG_CRON 00491 rb_define_syslog_facility(LOG_CRON); 00492 #endif 00493 #ifdef LOG_DAEMON 00494 rb_define_syslog_facility(LOG_DAEMON); 00495 #endif 00496 #ifdef LOG_FTP 00497 rb_define_syslog_facility(LOG_FTP); 00498 #endif 00499 #ifdef LOG_KERN 00500 rb_define_syslog_facility(LOG_KERN); 00501 #endif 00502 #ifdef LOG_LPR 00503 rb_define_syslog_facility(LOG_LPR); 00504 #endif 00505 #ifdef LOG_MAIL 00506 rb_define_syslog_facility(LOG_MAIL); 00507 #endif 00508 #ifdef LOG_NEWS 00509 rb_define_syslog_facility(LOG_NEWS); 00510 #endif 00511 #ifdef LOG_NTP 00512 rb_define_syslog_facility(LOG_NTP); 00513 #endif 00514 #ifdef LOG_SECURITY 00515 rb_define_syslog_facility(LOG_SECURITY); 00516 #endif 00517 #ifdef LOG_SYSLOG 00518 rb_define_syslog_facility(LOG_SYSLOG); 00519 #endif 00520 #ifdef LOG_USER 00521 rb_define_syslog_facility(LOG_USER); 00522 #endif 00523 #ifdef LOG_UUCP 00524 rb_define_syslog_facility(LOG_UUCP); 00525 #endif 00526 #ifdef LOG_LOCAL0 00527 rb_define_syslog_facility(LOG_LOCAL0); 00528 #endif 00529 #ifdef LOG_LOCAL1 00530 rb_define_syslog_facility(LOG_LOCAL1); 00531 #endif 00532 #ifdef LOG_LOCAL2 00533 rb_define_syslog_facility(LOG_LOCAL2); 00534 #endif 00535 #ifdef LOG_LOCAL3 00536 rb_define_syslog_facility(LOG_LOCAL3); 00537 #endif 00538 #ifdef LOG_LOCAL4 00539 rb_define_syslog_facility(LOG_LOCAL4); 00540 #endif 00541 #ifdef LOG_LOCAL5 00542 rb_define_syslog_facility(LOG_LOCAL5); 00543 #endif 00544 #ifdef LOG_LOCAL6 00545 rb_define_syslog_facility(LOG_LOCAL6); 00546 #endif 00547 #ifdef LOG_LOCAL7 00548 rb_define_syslog_facility(LOG_LOCAL7); 00549 #endif 00550 00551 /* Syslog levels and the shortcut methods */ 00552 00553 #define rb_define_syslog_level(c, m) \ 00554 rb_define_const(mSyslogLevel, #c, INT2NUM(c)); \ 00555 rb_define_module_function(mSyslog, #m, mSyslog_##m, -1) 00556 00557 #ifdef LOG_EMERG 00558 rb_define_syslog_level(LOG_EMERG, emerg); 00559 #endif 00560 #ifdef LOG_ALERT 00561 rb_define_syslog_level(LOG_ALERT, alert); 00562 #endif 00563 #ifdef LOG_CRIT 00564 rb_define_syslog_level(LOG_CRIT, crit); 00565 #endif 00566 #ifdef LOG_ERR 00567 rb_define_syslog_level(LOG_ERR, err); 00568 #endif 00569 #ifdef LOG_WARNING 00570 rb_define_syslog_level(LOG_WARNING, warning); 00571 #endif 00572 #ifdef LOG_NOTICE 00573 rb_define_syslog_level(LOG_NOTICE, notice); 00574 #endif 00575 #ifdef LOG_INFO 00576 rb_define_syslog_level(LOG_INFO, info); 00577 #endif 00578 #ifdef LOG_DEBUG 00579 rb_define_syslog_level(LOG_DEBUG, debug); 00580 #endif 00581 00582 /* Syslog macros */ 00583 00584 rb_define_method(mSyslogMacros, "LOG_MASK", mSyslogMacros_LOG_MASK, 1); 00585 rb_define_method(mSyslogMacros, "LOG_UPTO", mSyslogMacros_LOG_UPTO, 1); 00586 rb_define_singleton_method(mSyslogMacros, "included", mSyslogMacros_included, 1); 00587 00588 rb_include_module(mSyslogConstants, mSyslogOption); 00589 rb_include_module(mSyslogConstants, mSyslogFacility); 00590 rb_include_module(mSyslogConstants, mSyslogLevel); 00591 rb_funcall(mSyslogConstants, rb_intern("include"), 1, mSyslogMacros); 00592 00593 rb_define_singleton_method(mSyslogConstants, "included", mSyslogMacros_included, 1); 00594 rb_funcall(mSyslog, rb_intern("include"), 1, mSyslogConstants); 00595 } 00596