3 * Copyright (C) International Business Machines Corp., 2001
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 * Please send e-mail to kenistoj@users.sourceforge.net if you have
20 * questions or comments.
22 * Project Website: http://evlog.sourceforge.net/
25 #include <linux/config.h>
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/spinlock.h>
29 #include <linux/string.h>
30 #include <linux/ctype.h>
31 #include <linux/slab.h>
32 #include <linux/errno.h>
33 #include <linux/evl_log.h>
36 * This file implements the "legacy" functions defined in early releases of
37 * Event Logging. Consider using the newer functions declared in evlog.h --
38 * e.g., evl_write(), evl_printk(), evl_vprintk().
41 extern spinlock_t evl_msgbuf_lock;
42 extern char evl_msgbuf[];
60 static struct type_info {
65 {sizeof(char), "char"},
66 {sizeof(unsigned char), "uchar"},
67 {sizeof(short), "short"},
68 {sizeof(unsigned short),"ushort"},
70 {sizeof(unsigned int), "uint"},
71 {sizeof(long), "long"},
72 {sizeof(unsigned long), "ulong"},
73 {sizeof(long long), "longlong"},
74 {sizeof(unsigned long long), "ulonglong"},
76 {sizeof(void*), "address"},
80 struct att_type_info {
81 enum base_type at_type; /* TY_INT for "int", "int[]", or "2*int" */
82 int at_nelements; /* 5 for "5*int */
83 int at_array; /* 1 (true) for "int[]" */
87 get_type_by_name(const char *name)
90 for (i = TY_NONE+1; type_info[i].ti_name; i++) {
91 if (!strcmp(name, type_info[i].ti_name)) {
99 * att_type should be a type spec such as "int", "int[]", or "5*int". Parse it
100 * and fill in *ti accordingly. Returns 0 on success, -1 on failure.
103 parse_att_type(const char *att_type, struct att_type_info *ti)
105 const char *s, *left_bracket;
106 const char *type_name;
107 #define MAX_TYPE_NAME_LEN 20
108 char name_buf[MAX_TYPE_NAME_LEN+1];
110 if (isdigit(att_type[0])) {
113 (int) simple_strtoul(att_type, (char**) &s, 10);
119 } else if ((left_bracket = strchr(att_type, '[')) != NULL) {
123 ti->at_nelements = 0;
124 if (0 != strcmp(left_bracket, "[]")) {
127 /* Copy the name to name_buf and point type_name at it. */
128 type_name = name_buf;
129 name_len = left_bracket - att_type;
130 if (name_len == 0 || name_len > MAX_TYPE_NAME_LEN) {
133 (void) memcpy(name_buf, att_type, name_len);
134 name_buf[name_len] = '\0';
137 type_name = att_type;
139 ti->at_nelements = 1;
141 ti->at_type = get_type_by_name(type_name);
142 return (ti->at_type == TY_NONE ? -1 : 0);
146 * COPYARGS copies n args of type lt (little type) from the stack into
147 * buffer b. bt (big type) is the type of the arg as it appears on the stack.
149 #define COPYARGS(lt,bt) \
152 lt v=(lt)va_arg(args,bt); \
153 evl_put(b, &v, sizeof(lt)); \
157 #ifdef CONFIG_ARCH_S390X
164 * pack_typed_args() - Does most of the work of evl_writek.
167 pack_typed_args(struct evl_recbuf *b, va_list args)
171 while ((att_type = va_arg(args, char*)) &&
172 (0 != strcmp(att_type, "endofdata"))) {
173 struct att_type_info ti;
174 if (parse_att_type(att_type, &ti) == -1) {
179 size_t size = type_info[ti.at_type].ti_size;
182 /* Next arg is the array size. */
183 n = va_arg(args, INTARG);
184 /* Next arg is the array address. */
185 array = (char*) va_arg(args, void*);
187 switch (ti.at_type) {
190 /* array points to an array of char* */
191 char **sarray = (char**)array;
193 for (i = 0; i < n; i++) {
194 evl_puts(b, sarray[i], 1);
199 evl_put(b, array, n*size);
204 * One or more args of the same type.
206 int n = ti.at_nelements;
207 switch (ti.at_type) {
210 COPYARGS(char, INTARG)
214 COPYARGS(short, INTARG)
218 COPYARGS(int, INTARG)
226 COPYARGS(long long, long long)
229 COPYARGS(void*, void*)
235 s = (char *) va_arg(args, char*);
242 } /* end of switch */
244 } /* next att_type */
250 * These functions are used for logging events with log_format of
251 * EVL_BINARY. See event logging specification at
252 * http://evlog.sourceforge.net/linuxEvlog.html
255 int evl_writek(posix_log_facility_t facility, int event_type,
256 posix_log_severity_t severity, unsigned int flags, ...)
261 va_start(args, flags);
262 ret = evl_vwritek(facility, event_type, severity, flags, args);
268 int evl_vwritek(posix_log_facility_t facility, int event_type,
269 posix_log_severity_t severity, unsigned int flags, va_list args)
271 unsigned long iflags;
276 spin_lock_irqsave(&evl_msgbuf_lock, iflags);
277 evl_init_recbuf(&b, evl_msgbuf, EVL_ENTRY_MAXLEN);
278 ret = pack_typed_args(&b, args);
280 reclen = evl_datasz(&b, &flags);
281 ret = evl_write(facility, event_type, severity,
282 b.b_buf, reclen, flags, EVL_BINARY);
284 spin_unlock_irqrestore(&evl_msgbuf_lock, iflags);
289 * These functions are used for logging events with log_format of
290 * EVL_STRING. See event logging specification at
291 * http://evlog.sourceforge.net/linuxEvlog.html
294 int posix_log_printf(posix_log_facility_t facility, int event_type,
295 posix_log_severity_t severity, unsigned int flags, const char *fmt, ...)
301 return evl_write(facility, event_type, severity, NULL, 0,
306 ret = posix_log_vprintf(facility, event_type, severity, flags, fmt,
312 int posix_log_vprintf(posix_log_facility_t facility, int event_type,
313 posix_log_severity_t severity, unsigned int flags, const char *fmt,
318 unsigned long iflags;
321 return evl_write(facility, event_type, severity, NULL, 0,
325 spin_lock_irqsave(&evl_msgbuf_lock, iflags);
326 recsize = 1 + vsnprintf(evl_msgbuf, EVL_ENTRY_MAXLEN, fmt, args);
327 if (recsize > EVL_ENTRY_MAXLEN) {
328 recsize = EVL_ENTRY_MAXLEN;
329 flags |= EVL_TRUNCATE;
331 ret = evl_write(facility, event_type, severity, evl_msgbuf, recsize,
333 spin_unlock_irqrestore(&evl_msgbuf_lock, iflags);
338 * This is the standard POSIX function for writing events to the event log.
339 * See event logging specification at:
340 * http://evlog.sourceforge.net/linuxEvlog.html
342 int posix_log_write(posix_log_facility_t facility, int event_type,
343 posix_log_severity_t severity, const void *buf,
344 size_t recsize, int format, unsigned int flags)
346 if (!buf || recsize == 0 || format == EVL_NODATA) {
351 if (format == EVL_STRING && strlen((const char*)buf) != recsize-1) {
355 return evl_write(facility, event_type, severity, buf, recsize, flags,
360 * evl_gen_facility_code() - Generate facility "code" from facility name
361 * The code is just a strdup of the name.
363 int evl_gen_facility_code(const char *fname, posix_log_facility_t *fcode)
368 if (!fname || !fcode) {
372 name_len = strlen(fname);
373 if (name_len == 0 || name_len >= POSIX_LOG_MEMSTR_MAXLEN) {
377 s = kmalloc(name_len+1, GFP_KERNEL);
381 (void) strcpy(s, fname);
387 * evl_register_facility() - Generate "code" from name; pretend to register
388 * We no longer register the facility from the kernel.
390 int evl_register_facility(const char *fname, posix_log_facility_t *fcode)
392 return evl_gen_facility_code(fname, fcode);
395 EXPORT_SYMBOL(evl_writek);
396 EXPORT_SYMBOL(evl_vwritek);
397 EXPORT_SYMBOL(posix_log_write);
398 EXPORT_SYMBOL(posix_log_printf);
399 EXPORT_SYMBOL(posix_log_vprintf);
400 EXPORT_SYMBOL(evl_gen_facility_code);
401 EXPORT_SYMBOL(evl_register_facility);