Addons updated to new doc format
[io.git] / addons / Syslog / source / IoSyslog.c
blob0f2a2b2b31d56fd56ac1caecc7bb81b5fadc5457
1 /*metadoc Syslog copyright
2 Jeremy Tregunna, 2005
3 */
5 /*metadoc Syslog license
6 Revised BSD Revised
7 */
9 /*metadoc Syslog description
10 Provides access to a Unix system's system logger.
11 <code>
12 logger = Syslog clone do(
13 identity("SyslogTest")
14 facility(facilityMap at("LOG_USER"))
15 options(List append(optionsMap at("LOG_PID"), optionsMap at("LOG_CONS")))
16 priority(priorityMap at("LOG_INFO"))
17 open(facility, options)
18 mask(List append(maskMap at("LOG_PRIMASK")))
19 log(priority, "*** Merely a test ***")
20 close
22 </code>
24 <p>
25 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
26 <p>
29 /*metadoc Syslog category
30 Server
33 #include "IoSyslog.h"
34 #include "IoState.h"
35 #include "IoList.h"
36 #include <syslog.h>
38 #if defined(unix) || defined(__APPLE__)
39 #include <sys/utsname.h>
40 #endif
42 #define DATA(self) ((IoSyslogData *)IoObject_dataPointer(self))
44 IoTag *IoSyslog_newTag(void *state)
46 IoTag *tag = IoTag_newWithName_("Syslog");
47 IoTag_state_(tag, state);
48 IoTag_markFunc_(tag, (IoTagMarkFunc *)IoSyslog_mark);
49 IoTag_freeFunc_(tag, (IoTagFreeFunc *)IoSyslog_free);
50 IoTag_cloneFunc_(tag, (IoTagCloneFunc *)IoSyslog_rawClone);
51 return tag;
54 void IoSyslog_mark(IoSyslog *self)
56 IoObject_shouldMark(DATA(self)->priority);
57 IoObject_shouldMark(DATA(self)->facility);
58 IoObject_shouldMark(DATA(self)->ident);
59 IoObject_shouldMark(DATA(self)->optionsMap);
60 IoObject_shouldMark(DATA(self)->facilityMap);
61 IoObject_shouldMark(DATA(self)->priorityMap);
62 IoObject_shouldMark(DATA(self)->maskMap);
65 IoSyslog *IoSyslog_proto(void *state)
67 IoSyslog *self = IoObject_new(state);
69 IoObject_tag_(self, IoSyslog_newTag(state));
70 IoObject_setDataPointer_(self, calloc(1, sizeof(IoSyslogData)));
72 DATA(self)->syslog_opened = 0;
73 DATA(self)->priority = IONUMBER(LOG_INFO);
74 DATA(self)->facility = IONUMBER(LOG_LOCAL0);
75 DATA(self)->syslog_mask = 0;
76 DATA(self)->ident = IOSYMBOL("");
77 DATA(self)->optionsMap = IoMap_new(IOSTATE);
78 DATA(self)->facilityMap = IoMap_new(IOSTATE);
79 DATA(self)->priorityMap = IoMap_new(IOSTATE);
80 DATA(self)->maskMap = IoMap_new(IOSTATE);
82 IoState_registerProtoWithFunc_(state, self, IoSyslog_proto);
85 IoMethodTable methodTable[] = {
86 {"open", IoSyslog_open},
87 {"reopen", IoSyslog_reopen},
88 {"isOpen", IoSyslog_isOpen},
89 {"close", IoSyslog_close},
90 {"identity", IoSyslog_identity},
91 {"options", IoSyslog_options},
92 {"optionsMap", IoSyslog_optionsMap},
93 {"facility", IoSyslog_facility},
94 {"facilityMap", IoSyslog_facilityMap},
95 {"priority", IoSyslog_priority},
96 {"priorityMap", IoSyslog_priorityMap},
97 {"mask", IoSyslog_mask},
98 {"maskMap", IoSyslog_maskMap},
99 {"log", IoSyslog_log},
100 {NULL, NULL},
102 IoObject_addMethodTable_(self, methodTable);
105 return self;
108 IoSyslog *IoSyslog_rawClone(IoSyslog *proto)
110 IoObject *self = IoObject_rawClonePrimitive(proto);
111 IoObject_setDataPointer_(self, cpalloc(IoObject_dataPointer(proto), sizeof(IoSyslogData)));
112 return self;
115 IoSyslog *IoSyslog_new(void *state)
117 IoSyslog *proto = IoState_protoWithInitFunction_(state, IoSyslog_proto);
118 return IOCLONE(proto);
121 void IoSyslog_free(IoSyslog *self)
123 free(IoObject_dataPointer(self));
126 /* ----------------------------------------------------------- */
128 void syslog_write(int pri, char *msg)
130 syslog(pri, "%s", msg);
133 IoObject *IoSyslog_open(IoSyslog *self, IoObject *locals, IoMessage *m)
135 /*doc Syslog open(aPriority, someOptions, optionalIdentity)
136 Opens the syslog for writing. optionalIdentity need not be entered
137 and will default to the name of the distribution of Io you are running
138 or if you have embedded Io into your application and set
139 Lobby distribution = "foo", it will be set to "foo".
142 int syslog_facility, syslog_options;
143 //int i, max;
144 char *syslog_ident;
146 if (DATA(self)->syslog_opened)
148 IoState_error_(IOSTATE, m, "System log is already open");
149 return IONIL(self);
153 DATA(self)->facility = IOREF(IoMessage_locals_numberArgAt_(m, locals, 0));
154 if (ISNIL(DATA(self)->facility))
156 syslog_facility = LOG_USER;
158 else
160 syslog_facility = IoObject_dataUint32(DATA(self)->facility);
163 DATA(self)->options = IOREF(IoMessage_locals_listArgAt_(m, locals, 1));
164 syslog_options = 0;
165 if (ISNIL(DATA(self)->options))
167 syslog_options = LOG_PID | LOG_CONS;
169 else
171 List *list = IoList_rawList(DATA(self)->options);
173 LIST_FOREACH(list, i, v,
174 syslog_options |= (int)CNUMBER(v);
178 syslog_ident = (char *)IOSYMBOL_BYTES(DATA(self)->ident);
179 if ((strlen(syslog_ident) == 0) || ISNIL(DATA(self)->ident))
181 char *s = CSTRING(IoState_doCString_(IOSTATE, "Lobby distribution"));
182 strncpy(syslog_ident, s, strlen(s));
185 openlog(syslog_ident, syslog_options, syslog_facility);
186 DATA(self)->syslog_opened = 1;
187 DATA(self)->syslog_mask = setlogmask(0);
188 setlogmask(DATA(self)->syslog_mask);
191 return self;
194 IoObject *IoSyslog_reopen(IoSyslog *self, IoObject *locals, IoMessage *m)
196 /*doc Syslog reopen(aFacility, someOptions, optionalIdentity)
197 Reopens an already open log session. This is useful if you wish to
198 change the facility you are logging to, the options you are logging
199 with, or the identity of the session. Takes the same options as the open slot.
202 /* If the log is already opened, close it, if not, no big deal. */
203 if (DATA(self)->syslog_opened)
205 closelog();
206 DATA(self)->syslog_opened = 0;
208 IoSyslog_open(self, locals, m);
209 return self;
212 IoObject *IoSyslog_isOpen(IoSyslog *self, IoObject *locals, IoMessage *m)
214 /*doc Syslog isOpen
215 Returns self if the log is opened for writing. Otherwise, returns Nil.")
218 return IOBOOL(self, DATA(self)->syslog_opened);
221 IoObject *IoSyslog_close(IoSyslog *self, IoObject *locals, IoMessage *m)
223 /*doc Syslog close
224 Closes a log that has previously been opened for writing.")
227 if (!DATA(self)->syslog_opened)
229 IoState_error_(IOSTATE, m, "Log is not open");
230 return IONIL(self);
233 closelog();
234 DATA(self)->syslog_opened = 0;
236 return self;
239 IoObject *IoSyslog_identity(IoSyslog *self, IoObject *locals, IoMessage *m)
241 /*doc Syslog identity(optionalIdentity)
242 If optionalIdentity is specified, provides an identity for all of the messages you will be sending to the syslog daemon. Returns the identity.")
245 if (IoMessage_argCount(m) >= 1)
247 DATA(self)->ident = IOREF(IoMessage_locals_symbolArgAt_(m, locals, 0));
249 return DATA(self)->ident;
252 IoObject *IoSyslog_options(IoSyslog *self, IoObject *locals, IoMessage *m)
254 /*doc Syslog options(optionalOptions)
255 If optionalOptions is specified, it should represent a list of the logging
256 options you can find in the optionsMap slot. All the values in the supplied
257 aList will be OR'd together when you call the open or reopen slots.
258 Returns the list of options if optionalFacility is omitted.
261 if (IoMessage_argCount(m) >= 1)
263 DATA(self)->options = IOREF(IoMessage_locals_listArgAt_(m, locals, 0));
265 return DATA(self)->options;
268 IoObject *IoSyslog_optionsMap(IoSyslog *self, IoObject *locals, IoMessage *m)
270 /*doc Syslog optionsMap
271 A map containing key/value pairs holding all available options. These include:
272 <li>LOG_PID</li>
273 <li>LOG_CONS</li>
274 <li>LOG_ODELAY</li>
275 <li>LOG_NDELAY</li>
276 <li>LOG_NOWAIT</li>
277 <li>LOG_PERROR</li>
279 PHash *map = IoObject_dataPointer(DATA(self)->optionsMap);
281 PHash_at_put_(map, IOSYMBOL("LOG_PID"), IONUMBER(1));
282 PHash_at_put_(map, IOSYMBOL("LOG_CONS"), IONUMBER(2));
283 PHash_at_put_(map, IOSYMBOL("LOG_ODELAY"), IONUMBER(4));
284 PHash_at_put_(map, IOSYMBOL("LOG_NDELAY"), IONUMBER(8));
285 PHash_at_put_(map, IOSYMBOL("LOG_NOWAIT"), IONUMBER(16));
286 PHash_at_put_(map, IOSYMBOL("LOG_PERROR"), IONUMBER(32));
288 return DATA(self)->optionsMap;
291 IoObject *IoSyslog_facility(IoSyslog *self, IoObject *locals, IoMessage *m)
293 /*doc Syslog facility(optionalFacility)
294 Specifies the logging facility, which can be one of any of the values
295 found in the facilityMap map. If optionalFacility is omitted, returns
296 the currently set facility.
298 if (IoMessage_argCount(m) >= 1)
300 DATA(self)->facility = IOREF(IoMessage_locals_numberArgAt_(m, locals, 0));
302 return DATA(self)->facility;
305 IoObject *IoSyslog_facilityMap(IoSyslog *self, IoObject *locals, IoMessage *m)
307 /*doc Syslog facilityMap
308 Contains the following keys, which represent numbers that can be used when opening a log:
309 <li>LOG_KERN</li>
310 <li>LOG_USER</li>
311 <li>LOG_MAIL</li>
312 <li>LOG_DAEMON</li>
313 <li>LOG_AUTH</li>
314 <li>LOG_SYSLOG</li>
315 <li>LOG_LPR</li>
316 <li>LOG_NEWS</li>
317 <li>LOG_UUCP</li>
318 <li>LOG_CRON</li>
319 <li>LOG_AUTHPRIV</li>
320 <li>LOG_FTP</li>
321 <li>LOG_RESERVED0</li>
322 <li>LOG_RESERVED1</li>
323 <li>LOG_RESERVED2</li>
324 <li>LOG_RESERVED3</li>
325 <li>LOG_LOCAL0</li>
326 <li>LOG_LOCAL1</li>
327 <li>LOG_LOCAL2</li>
328 <li>LOG_LOCAL3</li>
329 <li>LOG_LOCAL4</li>
330 <li>LOG_LOCAL5</li>
331 <li>LOG_LOCAL6</li>
332 <li>LOG_LOCAL7</li>
335 PHash *map = IoObject_dataPointer(DATA(self)->facilityMap);
337 PHash_at_put_(map, IOSYMBOL("LOG_KERN"), IONUMBER(0));
338 PHash_at_put_(map, IOSYMBOL("LOG_USER"), IONUMBER(8));
339 PHash_at_put_(map, IOSYMBOL("LOG_MAIL"), IONUMBER(16));
340 PHash_at_put_(map, IOSYMBOL("LOG_DAEMON"), IONUMBER(24));
341 PHash_at_put_(map, IOSYMBOL("LOG_AUTH"), IONUMBER(32));
342 PHash_at_put_(map, IOSYMBOL("LOG_SYSLOG"), IONUMBER(40));
343 PHash_at_put_(map, IOSYMBOL("LOG_LPR"), IONUMBER(48));
344 PHash_at_put_(map, IOSYMBOL("LOG_NEWS"), IONUMBER(56));
345 PHash_at_put_(map, IOSYMBOL("LOG_UUCP"), IONUMBER(64));
346 PHash_at_put_(map, IOSYMBOL("LOG_CRON"), IONUMBER(72));
347 PHash_at_put_(map, IOSYMBOL("LOG_AUTHPRIV"), IONUMBER(80));
348 PHash_at_put_(map, IOSYMBOL("LOG_FTP"), IONUMBER(88));
349 PHash_at_put_(map, IOSYMBOL("LOG_RESERVED0"), IONUMBER(96));
350 PHash_at_put_(map, IOSYMBOL("LOG_RESERVED1"), IONUMBER(104));
351 PHash_at_put_(map, IOSYMBOL("LOG_RESERVED2"), IONUMBER(112));
352 PHash_at_put_(map, IOSYMBOL("LOG_RESERVED3"), IONUMBER(120));
353 PHash_at_put_(map, IOSYMBOL("LOG_LOCAL0"), IONUMBER(128));
354 PHash_at_put_(map, IOSYMBOL("LOG_LOCAL1"), IONUMBER(136));
355 PHash_at_put_(map, IOSYMBOL("LOG_LOCAL2"), IONUMBER(144));
356 PHash_at_put_(map, IOSYMBOL("LOG_LOCAL3"), IONUMBER(152));
357 PHash_at_put_(map, IOSYMBOL("LOG_LOCAL4"), IONUMBER(160));
358 PHash_at_put_(map, IOSYMBOL("LOG_LOCAL5"), IONUMBER(168));
359 PHash_at_put_(map, IOSYMBOL("LOG_LOCAL6"), IONUMBER(176));
360 PHash_at_put_(map, IOSYMBOL("LOG_LOCAL7"), IONUMBER(184));
362 return DATA(self)->facilityMap;
365 IoObject *IoSyslog_priority(IoSyslog *self, IoObject *locals, IoMessage *m)
367 /*doc Syslog priority(optionalPriority)
368 If optionalPriority is specified, sets the value, and returns it.
369 If no value is specified, will return the previously stored value if
370 one has been set previously.
373 if (IoMessage_argCount(m) >= 1)
375 DATA(self)->priority = IOREF(IoMessage_locals_numberArgAt_(m, locals, 0));
378 return DATA(self)->priority;
381 IoObject *IoSyslog_priorityMap(IoSyslog *self, IoObject *locals, IoMessage *m)
383 /*doc Syslog priorityMap
384 Contains key/value pairs for logging priorities for use when calling the log() method. These include:
385 <li>LOG_EMERG</li>
386 <li>LOG_ALERT</li>
387 <li>LOG_CRIT</li>
388 <li>LOG_ERR</li>
389 <li>LOG_WARNING</li>
390 <li>LOG_NOTICE</li>
391 <li>LOG_INFO</li>
392 <li>LOG_DEBUG</li>
395 PHash *map = IoObject_dataPointer(DATA(self)->priorityMap);
396 PHash_at_put_(map, IOSYMBOL("LOG_EMERG"), IONUMBER(0));
397 PHash_at_put_(map, IOSYMBOL("LOG_ALERT"), IONUMBER(1));
398 PHash_at_put_(map, IOSYMBOL("LOG_CRIT"), IONUMBER(2));
399 PHash_at_put_(map, IOSYMBOL("LOG_ERR"), IONUMBER(3));
400 PHash_at_put_(map, IOSYMBOL("LOG_WARNING"), IONUMBER(4));
401 PHash_at_put_(map, IOSYMBOL("LOG_NOTICE"), IONUMBER(5));
402 PHash_at_put_(map, IOSYMBOL("LOG_INFO"), IONUMBER(6));
403 PHash_at_put_(map, IOSYMBOL("LOG_DEBUG"), IONUMBER(7));
405 return DATA(self)->priorityMap;
408 IoObject *IoSyslog_mask(IoSyslog *self, IoObject *locals, IoMessage *m)
410 /*doc Syslog mask(optionalMask)
411 If optionalMask is specified, optionalMask is a list which contains
412 any one or more values stored in the maskMap hash that will be OR'd
413 together, to provide the proper mask. Returns the logging mask (as a List).
416 if (IoMessage_argCount(m) >= 1)
418 if (!DATA(self)->syslog_opened)
420 IoState_error_(IOSTATE, m, "Log must be opened before setting the logging mask");
421 return IONIL(self);
424 DATA(self)->mask = IOREF(IoMessage_locals_listArgAt_(m, locals, 0));
427 List *list = IoList_rawList(DATA(self)->mask);
429 LIST_FOREACH(list, i, v,
430 DATA(self)->syslog_mask |= (int)CNUMBER(v);
433 setlogmask(DATA(self)->syslog_mask);
437 return DATA(self)->mask;
440 IoObject *IoSyslog_maskMap(IoSyslog *self, IoObject *locals, IoMessage *m)
442 /*doc Syslog maskMap
443 Contains keys/value pairs which represent numbers that specify the
444 logging mask. These values may be any one (or more) of the following:
445 <li>LOG_PRIMASK</li>
446 <li>LOG_FACMASK</li>
449 PHash *map = IoObject_dataPointer(DATA(self)->maskMap);
451 PHash_at_put_(map, IOSYMBOL("LOG_PRIMASK"), IONUMBER(0x07));
452 PHash_at_put_(map, IOSYMBOL("LOG_FACMASK"), IONUMBER(0x03f8));
454 return DATA(self)->maskMap;
457 IoObject *IoSyslog_log(IoSyslog *self, IoObject *locals, IoMessage *m)
459 /*doc Syslog log
460 Writes the supplied data to the log. Requires 2 arguments:
461 <li>Logging Priority</li>
462 <li>Message to log</li>
465 char *str;
467 DATA(self)->priority = IOREF(IoMessage_locals_numberArgAt_(m, locals, 0));
468 str = CSTRING(IoMessage_locals_symbolArgAt_(m, locals, 1));
470 if (!DATA(self)->syslog_opened)
472 IoState_error_(IOSTATE, m, "Log is not opened. Run the open slot before log.");
473 return IONIL(self);
476 syslog_write(CNUMBER((int)DATA(self)->priority), str);
478 return self;