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