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