3 docCopyright("Jeremy Tregunna", 2005)
4 docLicense("BSD revised")
5 docDescription("""Provides access to a Unix system's system logger.
7 logger = Syslog clone do(
9 facility(facilityMap at("LOG_USER"))
10 options(List append(optionsMap at("LOG_PID"), optionsMap at("LOG_CONS")))
11 priority(priorityMap at("LOG_INFO"))
12 open(facility, options)
13 mask(List append(maskMap at("LOG_PRIMASK")))
14 log(priority, "*** Merely a test ***")
20 Note: This is partially tested. Please let me know of any problems you happen to stumble across, or if it could be better. --Jeremy Tregunna
30 #if defined(unix) || defined(__APPLE__)
31 #include <sys/utsname.h>
34 #define DATA(self) ((IoSyslogData *)IoObject_dataPointer(self))
36 IoTag
*IoSyslog_newTag(void *state
)
38 IoTag
*tag
= IoTag_newWithName_("Syslog");
39 IoTag_state_(tag
, state
);
40 IoTag_markFunc_(tag
, (IoTagMarkFunc
*)IoSyslog_mark
);
41 IoTag_freeFunc_(tag
, (IoTagFreeFunc
*)IoSyslog_free
);
42 IoTag_cloneFunc_(tag
, (IoTagCloneFunc
*)IoSyslog_rawClone
);
46 void IoSyslog_mark(IoSyslog
*self
)
48 IoObject_shouldMark(DATA(self
)->priority
);
49 IoObject_shouldMark(DATA(self
)->facility
);
50 IoObject_shouldMark(DATA(self
)->ident
);
51 IoObject_shouldMark(DATA(self
)->optionsMap
);
52 IoObject_shouldMark(DATA(self
)->facilityMap
);
53 IoObject_shouldMark(DATA(self
)->priorityMap
);
54 IoObject_shouldMark(DATA(self
)->maskMap
);
57 IoSyslog
*IoSyslog_proto(void *state
)
59 IoSyslog
*self
= IoObject_new(state
);
61 IoObject_tag_(self
, IoSyslog_newTag(state
));
62 IoObject_setDataPointer_(self
, calloc(1, sizeof(IoSyslogData
)));
64 DATA(self
)->syslog_opened
= 0;
65 DATA(self
)->priority
= IONUMBER(LOG_INFO
);
66 DATA(self
)->facility
= IONUMBER(LOG_LOCAL0
);
67 DATA(self
)->syslog_mask
= 0;
68 DATA(self
)->ident
= IOSYMBOL("");
69 DATA(self
)->optionsMap
= IoMap_new(IOSTATE
);
70 DATA(self
)->facilityMap
= IoMap_new(IOSTATE
);
71 DATA(self
)->priorityMap
= IoMap_new(IOSTATE
);
72 DATA(self
)->maskMap
= IoMap_new(IOSTATE
);
74 IoState_registerProtoWithFunc_(state
, self
, IoSyslog_proto
);
77 IoMethodTable methodTable
[] = {
78 {"open", IoSyslog_open
},
79 {"reopen", IoSyslog_reopen
},
80 {"isOpen", IoSyslog_isOpen
},
81 {"close", IoSyslog_close
},
82 {"identity", IoSyslog_identity
},
83 {"options", IoSyslog_options
},
84 {"optionsMap", IoSyslog_optionsMap
},
85 {"facility", IoSyslog_facility
},
86 {"facilityMap", IoSyslog_facilityMap
},
87 {"priority", IoSyslog_priority
},
88 {"priorityMap", IoSyslog_priorityMap
},
89 {"mask", IoSyslog_mask
},
90 {"maskMap", IoSyslog_maskMap
},
91 {"log", IoSyslog_log
},
94 IoObject_addMethodTable_(self
, methodTable
);
100 IoSyslog
*IoSyslog_rawClone(IoSyslog
*proto
)
102 IoObject
*self
= IoObject_rawClonePrimitive(proto
);
103 IoObject_setDataPointer_(self
, cpalloc(IoObject_dataPointer(proto
), sizeof(IoSyslogData
)));
107 IoSyslog
*IoSyslog_new(void *state
)
109 IoSyslog
*proto
= IoState_protoWithInitFunction_(state
, IoSyslog_proto
);
110 return IOCLONE(proto
);
113 void IoSyslog_free(IoSyslog
*self
)
115 free(IoObject_dataPointer(self
));
118 /* ----------------------------------------------------------- */
120 void syslog_write(int pri
, char *msg
)
122 syslog(pri
, "%s", msg
);
125 IoObject
*IoSyslog_open(IoSyslog
*self
, IoObject
*locals
, IoMessage
*m
)
128 docSlot("open(aPriority, someOptions, optionalIdentity)", """Opens the syslog for writing. optionaIdentity need not be entered and will default to the name of the distribution of Io you are running (i.e., "IoVM", "IoServer", "IoDesktop" or if you have embedded Io into your application and set Lobby distribution = "foo", it will be set to "foo".""")
130 int syslog_facility
, syslog_options
;
134 if (DATA(self
)->syslog_opened
)
136 IoState_error_(IOSTATE
, m
, "System log is already open");
141 DATA(self
)->facility
= IOREF(IoMessage_locals_numberArgAt_(m
, locals
, 0));
142 if (ISNIL(DATA(self
)->facility
))
144 syslog_facility
= LOG_USER
;
148 syslog_facility
= IoObject_dataUint32(DATA(self
)->facility
);
151 DATA(self
)->options
= IOREF(IoMessage_locals_listArgAt_(m
, locals
, 1));
153 if (ISNIL(DATA(self
)->options
))
155 syslog_options
= LOG_PID
| LOG_CONS
;
159 List
*list
= IoList_rawList(DATA(self
)->options
);
161 LIST_FOREACH(list
, i
, v
,
162 syslog_options
|= (int)CNUMBER(v
);
166 syslog_ident
= (char *)IOSYMBOL_BYTES(DATA(self
)->ident
);
167 if ((strlen(syslog_ident
) == 0) || ISNIL(DATA(self
)->ident
))
169 char *s
= CSTRING(IoState_doCString_(IOSTATE
, "Lobby distribution"));
170 strncpy(syslog_ident
, s
, strlen(s
));
173 openlog(syslog_ident
, syslog_options
, syslog_facility
);
174 DATA(self
)->syslog_opened
= 1;
175 DATA(self
)->syslog_mask
= setlogmask(0);
176 setlogmask(DATA(self
)->syslog_mask
);
182 IoObject
*IoSyslog_reopen(IoSyslog
*self
, IoObject
*locals
, IoMessage
*m
)
185 docSlot("reopen(aFacility, someOptions, optionalIdentity) ", "Reopens an already open log session. This is useful if you wish to change the facility you are logging to, the options you are logging with, or the identity of the session. Takes the same options as the open slot.")
187 /* If the log is already opened, close it, if not, no big deal. */
188 if (DATA(self
)->syslog_opened
)
191 DATA(self
)->syslog_opened
= 0;
193 IoSyslog_open(self
, locals
, m
);
197 IoObject
*IoSyslog_isOpen(IoSyslog
*self
, IoObject
*locals
, IoMessage
*m
)
200 docSlot("isOpen", "Returns self if the log is opened for writing. Otherwise, returns Nil.")
202 return IOBOOL(self
, DATA(self
)->syslog_opened
);
205 IoObject
*IoSyslog_close(IoSyslog
*self
, IoObject
*locals
, IoMessage
*m
)
208 docSlot("close", "Closes a log that has previously been opened for writing.")
210 if (!DATA(self
)->syslog_opened
)
212 IoState_error_(IOSTATE
, m
, "Log is not open");
217 DATA(self
)->syslog_opened
= 0;
222 IoObject
*IoSyslog_identity(IoSyslog
*self
, IoObject
*locals
, IoMessage
*m
)
225 docSlot("identity(optionalIdentity)", "If optionalIdentity is specified, provides an identity for all of the messages you will be sending to the syslog daemon. Returns the identity.")
227 if (IoMessage_argCount(m
) >= 1)
229 DATA(self
)->ident
= IOREF(IoMessage_locals_symbolArgAt_(m
, locals
, 0));
231 return DATA(self
)->ident
;
234 IoObject
*IoSyslog_options(IoSyslog
*self
, IoObject
*locals
, IoMessage
*m
)
237 docSlot("options(optionalOptions)", "If optionalOptions is specified, it should represent a list of the logging options you can find in the optionsMap slot. All the values in the supplied aList will be OR'd together when you call the open or reopen slots. Returns the list of options if optionalFacility is omitted.")
239 if (IoMessage_argCount(m
) >= 1)
241 DATA(self
)->options
= IOREF(IoMessage_locals_listArgAt_(m
, locals
, 0));
243 return DATA(self
)->options
;
246 IoObject
*IoSyslog_optionsMap(IoSyslog
*self
, IoObject
*locals
, IoMessage
*m
)
249 docSlot("optionsMap", "A map containing key/value pairs holding all available options. These include:
255 <li>LOG_PERROR</li>")
257 PHash
*map
= IoObject_dataPointer(DATA(self
)->optionsMap
);
259 PHash_at_put_(map
, IOSYMBOL("LOG_PID"), IONUMBER(1));
260 PHash_at_put_(map
, IOSYMBOL("LOG_CONS"), IONUMBER(2));
261 PHash_at_put_(map
, IOSYMBOL("LOG_ODELAY"), IONUMBER(4));
262 PHash_at_put_(map
, IOSYMBOL("LOG_NDELAY"), IONUMBER(8));
263 PHash_at_put_(map
, IOSYMBOL("LOG_NOWAIT"), IONUMBER(16));
264 PHash_at_put_(map
, IOSYMBOL("LOG_PERROR"), IONUMBER(32));
266 return DATA(self
)->optionsMap
;
269 IoObject
*IoSyslog_facility(IoSyslog
*self
, IoObject
*locals
, IoMessage
*m
)
272 docSlot("facility(optionalFacility)", "Specifies the logging facility, which can be one of any of the values found in the facilityMap map. If optionalFacility is omitted, returns the currently set facility.")
274 if (IoMessage_argCount(m
) >= 1)
276 DATA(self
)->facility
= IOREF(IoMessage_locals_numberArgAt_(m
, locals
, 0));
278 return DATA(self
)->facility
;
281 IoObject
*IoSyslog_facilityMap(IoSyslog
*self
, IoObject
*locals
, IoMessage
*m
)
284 docSlot("facilityMap", "Contains the following keys, which represent numbers that can be used when opening a log:
295 <li>LOG_AUTHPRIV</li>
297 <li>LOG_RESERVED0</li>
298 <li>LOG_RESERVED1</li>
299 <li>LOG_RESERVED2</li>
300 <li>LOG_RESERVED3</li>
308 <li>LOG_LOCAL7</li>")
310 PHash
*map
= IoObject_dataPointer(DATA(self
)->facilityMap
);
312 PHash_at_put_(map
, IOSYMBOL("LOG_KERN"), IONUMBER(0));
313 PHash_at_put_(map
, IOSYMBOL("LOG_USER"), IONUMBER(8));
314 PHash_at_put_(map
, IOSYMBOL("LOG_MAIL"), IONUMBER(16));
315 PHash_at_put_(map
, IOSYMBOL("LOG_DAEMON"), IONUMBER(24));
316 PHash_at_put_(map
, IOSYMBOL("LOG_AUTH"), IONUMBER(32));
317 PHash_at_put_(map
, IOSYMBOL("LOG_SYSLOG"), IONUMBER(40));
318 PHash_at_put_(map
, IOSYMBOL("LOG_LPR"), IONUMBER(48));
319 PHash_at_put_(map
, IOSYMBOL("LOG_NEWS"), IONUMBER(56));
320 PHash_at_put_(map
, IOSYMBOL("LOG_UUCP"), IONUMBER(64));
321 PHash_at_put_(map
, IOSYMBOL("LOG_CRON"), IONUMBER(72));
322 PHash_at_put_(map
, IOSYMBOL("LOG_AUTHPRIV"), IONUMBER(80));
323 PHash_at_put_(map
, IOSYMBOL("LOG_FTP"), IONUMBER(88));
324 PHash_at_put_(map
, IOSYMBOL("LOG_RESERVED0"), IONUMBER(96));
325 PHash_at_put_(map
, IOSYMBOL("LOG_RESERVED1"), IONUMBER(104));
326 PHash_at_put_(map
, IOSYMBOL("LOG_RESERVED2"), IONUMBER(112));
327 PHash_at_put_(map
, IOSYMBOL("LOG_RESERVED3"), IONUMBER(120));
328 PHash_at_put_(map
, IOSYMBOL("LOG_LOCAL0"), IONUMBER(128));
329 PHash_at_put_(map
, IOSYMBOL("LOG_LOCAL1"), IONUMBER(136));
330 PHash_at_put_(map
, IOSYMBOL("LOG_LOCAL2"), IONUMBER(144));
331 PHash_at_put_(map
, IOSYMBOL("LOG_LOCAL3"), IONUMBER(152));
332 PHash_at_put_(map
, IOSYMBOL("LOG_LOCAL4"), IONUMBER(160));
333 PHash_at_put_(map
, IOSYMBOL("LOG_LOCAL5"), IONUMBER(168));
334 PHash_at_put_(map
, IOSYMBOL("LOG_LOCAL6"), IONUMBER(176));
335 PHash_at_put_(map
, IOSYMBOL("LOG_LOCAL7"), IONUMBER(184));
337 return DATA(self
)->facilityMap
;
340 IoObject
*IoSyslog_priority(IoSyslog
*self
, IoObject
*locals
, IoMessage
*m
)
343 docSlot("priority(optionalPriority)", "If optionalPriority is specified, sets the value, and returns it. If no value is specified, will return the previously stored value if one has been set previously.")
346 if (IoMessage_argCount(m
) >= 1)
348 DATA(self
)->priority
= IOREF(IoMessage_locals_numberArgAt_(m
, locals
, 0));
351 return DATA(self
)->priority
;
354 IoObject
*IoSyslog_priorityMap(IoSyslog
*self
, IoObject
*locals
, IoMessage
*m
)
357 docSlot("priorityMap", "Contains key/value pairs for logging priorities for use when calling the log() method. These include:
367 PHash
*map
= IoObject_dataPointer(DATA(self
)->priorityMap
);
368 PHash_at_put_(map
, IOSYMBOL("LOG_EMERG"), IONUMBER(0));
369 PHash_at_put_(map
, IOSYMBOL("LOG_ALERT"), IONUMBER(1));
370 PHash_at_put_(map
, IOSYMBOL("LOG_CRIT"), IONUMBER(2));
371 PHash_at_put_(map
, IOSYMBOL("LOG_ERR"), IONUMBER(3));
372 PHash_at_put_(map
, IOSYMBOL("LOG_WARNING"), IONUMBER(4));
373 PHash_at_put_(map
, IOSYMBOL("LOG_NOTICE"), IONUMBER(5));
374 PHash_at_put_(map
, IOSYMBOL("LOG_INFO"), IONUMBER(6));
375 PHash_at_put_(map
, IOSYMBOL("LOG_DEBUG"), IONUMBER(7));
377 return DATA(self
)->priorityMap
;
380 IoObject
*IoSyslog_mask(IoSyslog
*self
, IoObject
*locals
, IoMessage
*m
)
383 docSlot("mask(optionalMask)", "If optionalMask is specified, optionalMask is a list which contains any one or more values stored in the maskMap hash that will be OR'd together, to provide the proper mask. Returns the logging mask (as a List).")
385 if (IoMessage_argCount(m
) >= 1)
387 if (!DATA(self
)->syslog_opened
)
389 IoState_error_(IOSTATE
, m
, "Log must be opened before setting the logging mask");
393 DATA(self
)->mask
= IOREF(IoMessage_locals_listArgAt_(m
, locals
, 0));
396 List
*list
= IoList_rawList(DATA(self
)->mask
);
398 LIST_FOREACH(list
, i
, v
,
399 DATA(self
)->syslog_mask
|= (int)CNUMBER(v
);
402 setlogmask(DATA(self
)->syslog_mask
);
406 return DATA(self
)->mask
;
409 IoObject
*IoSyslog_maskMap(IoSyslog
*self
, IoObject
*locals
, IoMessage
*m
)
412 docSlot("maskMap", "Contains keys/value pairs which represent numbers that specify the logging mask. These values may be any one (or more) of the following:
414 <li>LOG_FACMASK</li>")
416 PHash
*map
= IoObject_dataPointer(DATA(self
)->maskMap
);
418 PHash_at_put_(map
, IOSYMBOL("LOG_PRIMASK"), IONUMBER(0x07));
419 PHash_at_put_(map
, IOSYMBOL("LOG_FACMASK"), IONUMBER(0x03f8));
421 return DATA(self
)->maskMap
;
424 IoObject
*IoSyslog_log(IoSyslog
*self
, IoObject
*locals
, IoMessage
*m
)
427 docSlot("log", "Writes the supplied data to the log. Requires 2 arguments:
428 <li>Logging Priority</li>
429 <li>Message to log</li>")
433 DATA(self
)->priority
= IOREF(IoMessage_locals_numberArgAt_(m
, locals
, 0));
434 str
= CSTRING(IoMessage_locals_symbolArgAt_(m
, locals
, 1));
436 if (!DATA(self
)->syslog_opened
)
438 IoState_error_(IOSTATE
, m
, "Log is not opened. Run the open slot before log.");
442 syslog_write(CNUMBER((int)DATA(self
)->priority
), str
);