Move everything from /var/adm to /var/log
[unleashed/lotheac.git] / usr / src / lib / smbsrv / libmlsvc / common / eventlog_log.c
blob27d6ab9b3c4b5ad7deff8ed12d1ef89fa05b237f
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <time.h>
29 #include <syslog.h>
30 #include <thread.h>
31 #include <string.h>
32 #include <strings.h>
33 #include <stdarg.h>
34 #include <dlfcn.h>
35 #include <sys/synch.h>
36 #include <sys/stat.h>
37 #include <sys/errno.h>
38 #include <ctype.h>
39 #include <smbsrv/ndl/eventlog.ndl>
40 #include <smbsrv/libmlsvc.h>
42 typedef struct logr_eventlog {
43 const char *el_name;
44 const char *el_path;
45 } logr_eventlog_t;
47 logr_eventlog_t logr_eventlog[] = {
48 { "System", "/var/log/messages" },
49 { "smbd", "/var/smb/smbd_log.txt" },
50 { "smbrdr", "/var/smb/smbrdr_log.txt" }
53 typedef enum {
54 LOGR_MONTH = 0,
55 LOGR_DAY,
56 LOGR_TIME,
57 LOGR_HOST,
58 LOGR_SOURCE,
59 LOGR_IDTAG,
60 LOGR_ID,
61 LOGR_PRI_FAC,
62 LOGR_NARG
63 } logr_syslog_tokens_t;
66 * Event code translation struct for use in processing config file
68 typedef struct logr_priority {
69 char *p_name;
70 int p_value;
71 } logr_priority_t;
73 static logr_priority_t logr_pri_names[] = {
74 "panic", LOG_EMERG,
75 "emerg", LOG_EMERG,
76 "alert", LOG_ALERT,
77 "crit", LOG_CRIT,
78 "err", LOG_ERR,
79 "error", LOG_ERR,
80 "warn", LOG_WARNING,
81 "warning", LOG_WARNING,
82 "notice", LOG_NOTICE,
83 "info", LOG_INFO,
84 "debug", LOG_DEBUG
87 typedef struct logr_syslog_node {
88 list_node_t ln_node;
89 char ln_logline[LOGR_MAXENTRYLEN];
90 } logr_syslog_node_t;
92 static void *logr_interposer_hdl = NULL;
93 static struct {
94 boolean_t (*logr_op_supported)(char *);
95 int (*logr_op_snapshot)(logr_context_t *);
96 } logr_interposer_ops;
99 * Set the syslog timestamp.
101 * This is a private helper for logr_syslog_parse_entry(), which
102 * must ensure that the appropriate argv entries are non-null.
104 static void
105 logr_syslog_set_timestamp(char **argv, logr_entry_t *le)
107 char *month = argv[LOGR_MONTH];
108 char *day = argv[LOGR_DAY];
109 char *time = argv[LOGR_TIME];
110 struct timeval now;
111 struct tm tm, cur_tm;
112 char buf[32];
114 bzero(&tm, sizeof (tm));
115 (void) snprintf(buf, 32, "%s %s %s", month, day, time);
116 if (strptime(buf, "%b" "%d" "%H:%M:%S", &tm) == NULL) {
117 le->le_timestamp.tv_sec = 0;
118 return;
121 (void) gettimeofday(&now, NULL);
122 (void) localtime_r(&now.tv_sec, &cur_tm);
124 tm.tm_isdst = cur_tm.tm_isdst;
125 tm.tm_year = cur_tm.tm_year;
126 if (tm.tm_mon > cur_tm.tm_mon)
127 tm.tm_year--;
129 le->le_timestamp.tv_sec = mktime(&tm);
133 * Set the syslog priority.
135 * This is a private helper for logr_syslog_parse_entry(), which
136 * must ensure that the appropriate argv entries are non-null.
138 static void
139 logr_syslog_set_priority(char **argv, logr_entry_t *le)
141 logr_priority_t *entry;
142 char *token;
143 int sz = sizeof (logr_pri_names) / sizeof (logr_pri_names[0]);
144 int i;
146 le->le_pri = LOG_INFO;
148 if ((token = argv[LOGR_PRI_FAC]) == NULL)
149 return;
151 for (i = 0; i < sz; i++) {
152 entry = &logr_pri_names[i];
154 if (strstr(token, entry->p_name) != NULL) {
155 le->le_pri = entry->p_value;
156 break;
162 * Parse a syslog entry into a log_entry_t structure. A typical syslog
163 * entry has one of the following formats:
165 * <month> <day> <time> <host> <msg>
166 * <month> <day> <time> <host> <source>: [ID <ID> <facility.priority>] <msg>
168 * For Example:
169 * Oct 29 09:49:20 galaxy smbd[104039]: [ID 702911 daemon.info] init done
171 static int
172 logr_syslog_parse_entry(char *logline, logr_entry_t *le)
174 char buf[LOGR_MAXENTRYLEN];
175 char *argv[LOGR_NARG];
176 char *value;
177 char *bp;
178 int i;
180 (void) memset(argv, 0, sizeof (char *) * LOGR_NARG);
181 (void) strlcpy(buf, logline, LOGR_MAXENTRYLEN);
183 for (bp = buf, i = 0; i < LOGR_NARG; ++i) {
184 if (i == LOGR_SOURCE) {
186 * If the [ID key is not present, everything
187 * that follows is the message text.
189 if (strstr(bp, "[ID") == NULL)
190 break;
193 do {
194 if ((value = strsep(&bp, " \t")) == NULL)
195 break;
196 } while (*value == '\0');
198 if ((argv[i] = value) == NULL)
199 return (-1);
203 * bp should be pointing at the remaining message text.
205 if ((value = strchr(bp, '\n')) != NULL)
206 *value = '\0';
208 (void) strlcpy(le->le_msg, bp, LOGR_MAXENTRYLEN);
209 (void) strlcpy(le->le_hostname, argv[LOGR_HOST], MAXHOSTNAMELEN);
210 logr_syslog_set_timestamp(argv, le);
211 logr_syslog_set_priority(argv, le);
212 return (0);
215 static void
216 logr_syslog_destroy_queue(list_t *queue)
218 logr_syslog_node_t *head;
220 while ((head = list_head(queue)) != NULL) {
221 list_remove(queue, head);
222 free(head);
224 list_destroy(queue);
227 static int
228 logr_syslog_construct_queue(FILE *fp, list_t *queue)
230 logr_syslog_node_t *node, *head;
231 int line_num = 0;
232 char logline[LOGR_MAXENTRYLEN];
234 list_create(queue, sizeof (logr_syslog_node_t),
235 offsetof(logr_syslog_node_t, ln_node));
237 bzero(logline, LOGR_MAXENTRYLEN);
238 while (fgets(logline, LOGR_MAXENTRYLEN, fp) != NULL) {
239 /* Read the last 1024 entries in the queue */
240 if (line_num > LOGR_NMSGMASK) {
241 head = list_head(queue);
242 list_remove(queue, head);
243 free(head);
246 if ((node = malloc(sizeof (logr_syslog_node_t))) == NULL) {
247 logr_syslog_destroy_queue(queue);
248 return (-1);
250 bzero(node->ln_logline, LOGR_MAXENTRYLEN);
252 (void) strlcpy(node->ln_logline, logline, LOGR_MAXENTRYLEN);
253 list_insert_tail(queue, node);
254 bzero(logline, LOGR_MAXENTRYLEN);
255 line_num++;
258 return (0);
262 * logr_syslog_load
264 * Loads the given log file into log_info_t structure format.
266 * Returns pointer to the allocated log structure on success.
267 * Note that the caller is responsible for freeing the allocated
268 * memory for returned log_info_t structure.
270 static int
271 logr_syslog_load(FILE *fp, logr_info_t *log)
273 logr_entry_t *entry;
274 int i = 0;
276 list_t queue;
277 logr_syslog_node_t *node;
279 if (logr_syslog_construct_queue(fp, &queue) < 0)
280 return (-1);
282 node = list_head(&queue);
283 while (node) {
284 entry = &log->li_entry[i];
286 if (logr_syslog_parse_entry(node->ln_logline, entry) != 0) {
287 node = list_next(&queue, node);
288 continue;
291 if (++i > LOGR_NMSGMASK)
292 break;
294 node = list_next(&queue, node);
297 logr_syslog_destroy_queue(&queue);
298 log->li_idx = i;
300 return (0);
304 * logr_syslog_snapshot
306 * Return a snapshot of the given log in the buffer
307 * provided by the caller. Returns the number of entries in
308 * the log.
310 static int
311 logr_syslog_snapshot(char *logname, logr_info_t *loginfo)
313 FILE *fp;
314 char path[MAXPATHLEN];
315 int i;
317 if ((loginfo == NULL) || (!logr_is_supported(logname)))
318 return (-1);
320 path[0] = '\0';
321 for (i = 0; i < sizeof (logr_eventlog)/sizeof (logr_eventlog[0]); ++i) {
322 if (strcasecmp(logname, logr_eventlog[i].el_name) == 0)
323 (void) strlcpy(path, logr_eventlog[i].el_path,
324 MAXPATHLEN);
327 if ((fp = fopen(path, "r")) == 0)
328 return (-1);
330 if (logr_syslog_load(fp, loginfo) < 0) {
331 (void) fclose(fp);
332 return (-1);
334 (void) fclose(fp);
336 if (loginfo->li_idx <= LOGR_NMSGMASK)
337 return (loginfo->li_idx);
339 return (LOGR_NMSGMASK+1);
343 * logr_is_supported
345 * Determines if a given log is supported or not.
346 * Returns B_TRUE on success, B_FALSE on failure.
348 boolean_t
349 logr_is_supported(char *log_name)
351 int i;
353 if (log_name == NULL)
354 return (B_FALSE);
356 if (logr_interposer_ops.logr_op_supported != NULL)
357 return (logr_interposer_ops.logr_op_supported(log_name));
359 for (i = 0; i < sizeof (logr_eventlog)/sizeof (logr_eventlog[0]); ++i) {
360 if (strcasecmp(log_name, logr_eventlog[i].el_name) == 0)
361 return (B_TRUE);
364 return (B_FALSE);
368 * logr_get_snapshot
370 * Allocate memory and make a copy, as a snapshot, from system log.
371 * Returns 0 on success, -1 on failure.
374 logr_get_snapshot(logr_context_t *ctx)
376 logr_read_data_t *data = NULL;
378 if (logr_interposer_ops.logr_op_snapshot != NULL)
379 return (logr_interposer_ops.logr_op_snapshot(ctx));
381 ctx->lc_cached_read_data = malloc(sizeof (logr_read_data_t));
382 if (ctx->lc_cached_read_data != NULL) {
383 data = ctx->lc_cached_read_data;
385 data->rd_log = (logr_info_t *)malloc(sizeof (logr_info_t));
386 if (data->rd_log == NULL) {
387 free(data);
388 return (-1);
390 bzero(data->rd_log, sizeof (logr_info_t));
392 data->rd_tot_recnum = logr_syslog_snapshot(ctx->lc_source_name,
393 data->rd_log);
394 if (data->rd_tot_recnum < 0) {
395 free(data->rd_log);
396 free(data);
397 return (-1);
400 data->rd_first_read = 1;
402 return (0);
405 return (-1);
409 * logr_init
411 * Initializes the Eventlog service.
412 * Checks to see if a event log utility library
413 * is interposed. If yes then it'll initializes logr_interposer_ops
414 * structure with function pointers from this library.
416 void
417 logr_init(void)
419 logr_interposer_hdl = smb_dlopen();
420 if (logr_interposer_hdl == NULL)
421 return;
423 bzero((void *)&logr_interposer_ops, sizeof (logr_interposer_ops));
425 logr_interposer_ops.logr_op_supported =
426 (boolean_t (*)())dlsym(logr_interposer_hdl, "logr_is_supported");
428 logr_interposer_ops.logr_op_snapshot =
429 (int (*)())dlsym(logr_interposer_hdl, "logr_get_snapshot");
431 if (logr_interposer_ops.logr_op_supported == NULL ||
432 logr_interposer_ops.logr_op_snapshot == NULL)
433 logr_fini();
437 * logr_fini
439 * Finalizes the Eventlog service.
440 * Closes handle to interposed library.
442 void
443 logr_fini(void)
445 smb_dlclose(logr_interposer_hdl);
446 logr_interposer_hdl = NULL;
447 bzero((void *)&logr_interposer_ops, sizeof (logr_interposer_ops));