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