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