xref: /titanic_41/usr/src/lib/libresolv2/common/isc/logging.c (revision 9525b14bcdeb5b5f6f95ab27c2f48f18bd2ec829)
17c478bd9Sstevel@tonic-gate /*
2*9525b14bSRao Shoaib  * Copyright (C) 2004, 2005, 2008  Internet Systems Consortium, Inc. ("ISC")
3*9525b14bSRao Shoaib  * Copyright (C) 1996-1999, 2001, 2003  Internet Software Consortium.
47c478bd9Sstevel@tonic-gate  *
5*9525b14bSRao Shoaib  * Permission to use, copy, modify, and/or distribute this software for any
67c478bd9Sstevel@tonic-gate  * purpose with or without fee is hereby granted, provided that the above
77c478bd9Sstevel@tonic-gate  * copyright notice and this permission notice appear in all copies.
87c478bd9Sstevel@tonic-gate  *
9*9525b14bSRao Shoaib  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10*9525b14bSRao Shoaib  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11*9525b14bSRao Shoaib  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12*9525b14bSRao Shoaib  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13*9525b14bSRao Shoaib  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14*9525b14bSRao Shoaib  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15*9525b14bSRao Shoaib  * PERFORMANCE OF THIS SOFTWARE.
167c478bd9Sstevel@tonic-gate  */
177c478bd9Sstevel@tonic-gate 
187c478bd9Sstevel@tonic-gate #if !defined(LINT) && !defined(CODECENTER)
19*9525b14bSRao Shoaib static const char rcsid[] = "$Id: logging.c,v 1.9 2008/11/14 02:36:51 marka Exp $";
207c478bd9Sstevel@tonic-gate #endif /* not lint */
217c478bd9Sstevel@tonic-gate 
227c478bd9Sstevel@tonic-gate #include "port_before.h"
237c478bd9Sstevel@tonic-gate 
247c478bd9Sstevel@tonic-gate #include <sys/types.h>
257c478bd9Sstevel@tonic-gate #include <sys/time.h>
267c478bd9Sstevel@tonic-gate #include <sys/stat.h>
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <fcntl.h>
297c478bd9Sstevel@tonic-gate #include <limits.h>
307c478bd9Sstevel@tonic-gate #include <stdio.h>
317c478bd9Sstevel@tonic-gate #include <stdlib.h>
327c478bd9Sstevel@tonic-gate #include <string.h>
337c478bd9Sstevel@tonic-gate #include <stdarg.h>
347c478bd9Sstevel@tonic-gate #include <syslog.h>
357c478bd9Sstevel@tonic-gate #include <errno.h>
367c478bd9Sstevel@tonic-gate #include <time.h>
377c478bd9Sstevel@tonic-gate #include <unistd.h>
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate #include <isc/assertions.h>
407c478bd9Sstevel@tonic-gate #include <isc/logging.h>
417c478bd9Sstevel@tonic-gate #include <isc/memcluster.h>
427c478bd9Sstevel@tonic-gate #include <isc/misc.h>
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate #include "port_after.h"
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate #include "logging_p.h"
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate static const int syslog_priority[] = { LOG_DEBUG, LOG_INFO, LOG_NOTICE,
497c478bd9Sstevel@tonic-gate 				       LOG_WARNING, LOG_ERR, LOG_CRIT };
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate static const char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
527c478bd9Sstevel@tonic-gate 				"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate static const char *level_text[] = {
557c478bd9Sstevel@tonic-gate 	"info: ", "notice: ", "warning: ", "error: ", "critical: "
567c478bd9Sstevel@tonic-gate };
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate static void
version_rename(log_channel chan)597c478bd9Sstevel@tonic-gate version_rename(log_channel chan) {
607c478bd9Sstevel@tonic-gate 	unsigned int ver;
617c478bd9Sstevel@tonic-gate 	char old_name[PATH_MAX+1];
627c478bd9Sstevel@tonic-gate 	char new_name[PATH_MAX+1];
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate 	ver = chan->out.file.versions;
657c478bd9Sstevel@tonic-gate 	if (ver < 1)
667c478bd9Sstevel@tonic-gate 		return;
677c478bd9Sstevel@tonic-gate 	if (ver > LOG_MAX_VERSIONS)
687c478bd9Sstevel@tonic-gate 		ver = LOG_MAX_VERSIONS;
697c478bd9Sstevel@tonic-gate 	/*
707c478bd9Sstevel@tonic-gate 	 * Need to have room for '.nn' (XXX assumes LOG_MAX_VERSIONS < 100)
717c478bd9Sstevel@tonic-gate 	 */
72*9525b14bSRao Shoaib 	if (strlen(chan->out.file.name) > (size_t)(PATH_MAX-3))
737c478bd9Sstevel@tonic-gate 		return;
747c478bd9Sstevel@tonic-gate 	for (ver--; ver > 0; ver--) {
757c478bd9Sstevel@tonic-gate 		sprintf(old_name, "%s.%d", chan->out.file.name, ver-1);
767c478bd9Sstevel@tonic-gate 		sprintf(new_name, "%s.%d", chan->out.file.name, ver);
77*9525b14bSRao Shoaib 		(void)isc_movefile(old_name, new_name);
787c478bd9Sstevel@tonic-gate 	}
797c478bd9Sstevel@tonic-gate 	sprintf(new_name, "%s.0", chan->out.file.name);
80*9525b14bSRao Shoaib 	(void)isc_movefile(chan->out.file.name, new_name);
817c478bd9Sstevel@tonic-gate }
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate FILE *
log_open_stream(log_channel chan)847c478bd9Sstevel@tonic-gate log_open_stream(log_channel chan) {
857c478bd9Sstevel@tonic-gate 	FILE *stream;
867c478bd9Sstevel@tonic-gate 	int fd, flags;
877c478bd9Sstevel@tonic-gate 	struct stat sb;
887c478bd9Sstevel@tonic-gate 	int regular;
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate 	if (chan == NULL || chan->type != log_file) {
917c478bd9Sstevel@tonic-gate 		errno = EINVAL;
927c478bd9Sstevel@tonic-gate 		return (NULL);
937c478bd9Sstevel@tonic-gate 	}
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	/*
967c478bd9Sstevel@tonic-gate 	 * Don't open already open streams
977c478bd9Sstevel@tonic-gate 	 */
987c478bd9Sstevel@tonic-gate 	if (chan->out.file.stream != NULL)
997c478bd9Sstevel@tonic-gate 		return (chan->out.file.stream);
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 	if (stat(chan->out.file.name, &sb) < 0) {
1027c478bd9Sstevel@tonic-gate 		if (errno != ENOENT) {
1037c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
1047c478bd9Sstevel@tonic-gate 			       "log_open_stream: stat of %s failed: %s",
1057c478bd9Sstevel@tonic-gate 			       chan->out.file.name, strerror(errno));
1067c478bd9Sstevel@tonic-gate 			chan->flags |= LOG_CHANNEL_BROKEN;
1077c478bd9Sstevel@tonic-gate 			return (NULL);
1087c478bd9Sstevel@tonic-gate 		}
1097c478bd9Sstevel@tonic-gate 		regular = 1;
1107c478bd9Sstevel@tonic-gate 	} else
111*9525b14bSRao Shoaib 		regular = (sb.st_mode & S_IFREG);
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	if (chan->out.file.versions) {
1147c478bd9Sstevel@tonic-gate 		if (!regular) {
1157c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
1167c478bd9Sstevel@tonic-gate        "log_open_stream: want versions but %s isn't a regular file",
1177c478bd9Sstevel@tonic-gate 			       chan->out.file.name);
1187c478bd9Sstevel@tonic-gate 			chan->flags |= LOG_CHANNEL_BROKEN;
1197c478bd9Sstevel@tonic-gate 			errno = EINVAL;
1207c478bd9Sstevel@tonic-gate 			return (NULL);
1217c478bd9Sstevel@tonic-gate 		}
1227c478bd9Sstevel@tonic-gate 	}
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	flags = O_WRONLY|O_CREAT|O_APPEND;
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate 	if ((chan->flags & LOG_TRUNCATE) != 0) {
1277c478bd9Sstevel@tonic-gate 		if (regular) {
1287c478bd9Sstevel@tonic-gate 			(void)unlink(chan->out.file.name);
1297c478bd9Sstevel@tonic-gate 			flags |= O_EXCL;
1307c478bd9Sstevel@tonic-gate 		} else {
1317c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
1327c478bd9Sstevel@tonic-gate        "log_open_stream: want truncation but %s isn't a regular file",
1337c478bd9Sstevel@tonic-gate 			       chan->out.file.name);
1347c478bd9Sstevel@tonic-gate 			chan->flags |= LOG_CHANNEL_BROKEN;
1357c478bd9Sstevel@tonic-gate 			errno = EINVAL;
1367c478bd9Sstevel@tonic-gate 			return (NULL);
1377c478bd9Sstevel@tonic-gate 		}
1387c478bd9Sstevel@tonic-gate 	}
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 	fd = open(chan->out.file.name, flags,
1417c478bd9Sstevel@tonic-gate 		  S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
1427c478bd9Sstevel@tonic-gate 	if (fd < 0) {
1437c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "log_open_stream: open(%s) failed: %s",
1447c478bd9Sstevel@tonic-gate 		       chan->out.file.name, strerror(errno));
1457c478bd9Sstevel@tonic-gate 		chan->flags |= LOG_CHANNEL_BROKEN;
1467c478bd9Sstevel@tonic-gate 		return (NULL);
1477c478bd9Sstevel@tonic-gate 	}
1487c478bd9Sstevel@tonic-gate 	stream = fdopen(fd, "a");
1497c478bd9Sstevel@tonic-gate 	if (stream == NULL) {
1507c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "log_open_stream: fdopen() failed");
1517c478bd9Sstevel@tonic-gate 		chan->flags |= LOG_CHANNEL_BROKEN;
1527c478bd9Sstevel@tonic-gate 		return (NULL);
1537c478bd9Sstevel@tonic-gate 	}
1547c478bd9Sstevel@tonic-gate 	(void) fchown(fd, chan->out.file.owner, chan->out.file.group);
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	chan->out.file.stream = stream;
1577c478bd9Sstevel@tonic-gate 	return (stream);
1587c478bd9Sstevel@tonic-gate }
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate int
log_close_stream(log_channel chan)1617c478bd9Sstevel@tonic-gate log_close_stream(log_channel chan) {
1627c478bd9Sstevel@tonic-gate 	FILE *stream;
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	if (chan == NULL || chan->type != log_file) {
1657c478bd9Sstevel@tonic-gate 		errno = EINVAL;
1667c478bd9Sstevel@tonic-gate 		return (0);
1677c478bd9Sstevel@tonic-gate 	}
1687c478bd9Sstevel@tonic-gate 	stream = chan->out.file.stream;
1697c478bd9Sstevel@tonic-gate 	chan->out.file.stream = NULL;
1707c478bd9Sstevel@tonic-gate 	if (stream != NULL && fclose(stream) == EOF)
1717c478bd9Sstevel@tonic-gate 		return (-1);
1727c478bd9Sstevel@tonic-gate 	return (0);
1737c478bd9Sstevel@tonic-gate }
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate void
log_close_debug_channels(log_context lc)1767c478bd9Sstevel@tonic-gate log_close_debug_channels(log_context lc) {
1777c478bd9Sstevel@tonic-gate 	log_channel_list lcl;
1787c478bd9Sstevel@tonic-gate 	int i;
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	for (i = 0; i < lc->num_categories; i++)
1817c478bd9Sstevel@tonic-gate 		for (lcl = lc->categories[i]; lcl != NULL; lcl = lcl->next)
1827c478bd9Sstevel@tonic-gate 			if (lcl->channel->type == log_file &&
1837c478bd9Sstevel@tonic-gate 			    lcl->channel->out.file.stream != NULL &&
1847c478bd9Sstevel@tonic-gate 			    lcl->channel->flags & LOG_REQUIRE_DEBUG)
1857c478bd9Sstevel@tonic-gate 				(void)log_close_stream(lcl->channel);
1867c478bd9Sstevel@tonic-gate }
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate FILE *
log_get_stream(log_channel chan)1897c478bd9Sstevel@tonic-gate log_get_stream(log_channel chan) {
1907c478bd9Sstevel@tonic-gate 	if (chan == NULL || chan->type != log_file) {
1917c478bd9Sstevel@tonic-gate 		errno = EINVAL;
1927c478bd9Sstevel@tonic-gate 		return (NULL);
1937c478bd9Sstevel@tonic-gate 	}
1947c478bd9Sstevel@tonic-gate 	return (chan->out.file.stream);
1957c478bd9Sstevel@tonic-gate }
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate char *
log_get_filename(log_channel chan)1987c478bd9Sstevel@tonic-gate log_get_filename(log_channel chan) {
1997c478bd9Sstevel@tonic-gate 	if (chan == NULL || chan->type != log_file) {
2007c478bd9Sstevel@tonic-gate 		errno = EINVAL;
2017c478bd9Sstevel@tonic-gate 		return (NULL);
2027c478bd9Sstevel@tonic-gate 	}
2037c478bd9Sstevel@tonic-gate 	return (chan->out.file.name);
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate int
log_check_channel(log_context lc,int level,log_channel chan)2077c478bd9Sstevel@tonic-gate log_check_channel(log_context lc, int level, log_channel chan) {
2087c478bd9Sstevel@tonic-gate 	int debugging, chan_level;
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	REQUIRE(lc != NULL);
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 	debugging = ((lc->flags & LOG_OPTION_DEBUG) != 0);
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	/*
2157c478bd9Sstevel@tonic-gate 	 * If not debugging, short circuit debugging messages very early.
2167c478bd9Sstevel@tonic-gate 	 */
2177c478bd9Sstevel@tonic-gate 	if (level > 0 && !debugging)
2187c478bd9Sstevel@tonic-gate 		return (0);
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	if ((chan->flags & (LOG_CHANNEL_BROKEN|LOG_CHANNEL_OFF)) != 0)
2217c478bd9Sstevel@tonic-gate 		return (0);
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	/* Some channels only log when debugging is on. */
2247c478bd9Sstevel@tonic-gate 	if ((chan->flags & LOG_REQUIRE_DEBUG) && !debugging)
2257c478bd9Sstevel@tonic-gate 		return (0);
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	/* Some channels use the global level. */
2287c478bd9Sstevel@tonic-gate 	if ((chan->flags & LOG_USE_CONTEXT_LEVEL) != 0) {
2297c478bd9Sstevel@tonic-gate 		chan_level = lc->level;
2307c478bd9Sstevel@tonic-gate 	} else
2317c478bd9Sstevel@tonic-gate 		chan_level = chan->level;
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	if (level > chan_level)
2347c478bd9Sstevel@tonic-gate 		return (0);
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 	return (1);
2377c478bd9Sstevel@tonic-gate }
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate int
log_check(log_context lc,int category,int level)2407c478bd9Sstevel@tonic-gate log_check(log_context lc, int category, int level) {
2417c478bd9Sstevel@tonic-gate 	log_channel_list lcl;
2427c478bd9Sstevel@tonic-gate 	int debugging;
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	REQUIRE(lc != NULL);
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	debugging = ((lc->flags & LOG_OPTION_DEBUG) != 0);
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	/*
2497c478bd9Sstevel@tonic-gate 	 * If not debugging, short circuit debugging messages very early.
2507c478bd9Sstevel@tonic-gate 	 */
2517c478bd9Sstevel@tonic-gate 	if (level > 0 && !debugging)
2527c478bd9Sstevel@tonic-gate 		return (0);
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 	if (category < 0 || category > lc->num_categories)
255*9525b14bSRao Shoaib 		category = 0;		/*%< use default */
2567c478bd9Sstevel@tonic-gate 	lcl = lc->categories[category];
2577c478bd9Sstevel@tonic-gate 	if (lcl == NULL) {
2587c478bd9Sstevel@tonic-gate 		category = 0;
2597c478bd9Sstevel@tonic-gate 		lcl = lc->categories[0];
2607c478bd9Sstevel@tonic-gate 	}
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 	for ( /* nothing */; lcl != NULL; lcl = lcl->next) {
2637c478bd9Sstevel@tonic-gate 		if (log_check_channel(lc, level, lcl->channel))
2647c478bd9Sstevel@tonic-gate 			return (1);
2657c478bd9Sstevel@tonic-gate 	}
2667c478bd9Sstevel@tonic-gate 	return (0);
2677c478bd9Sstevel@tonic-gate }
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate void
log_vwrite(log_context lc,int category,int level,const char * format,va_list args)2707c478bd9Sstevel@tonic-gate log_vwrite(log_context lc, int category, int level, const char *format,
2717c478bd9Sstevel@tonic-gate 	   va_list args) {
2727c478bd9Sstevel@tonic-gate 	log_channel_list lcl;
2737c478bd9Sstevel@tonic-gate 	int pri, debugging, did_vsprintf = 0;
2747c478bd9Sstevel@tonic-gate 	int original_category;
2757c478bd9Sstevel@tonic-gate 	FILE *stream;
2767c478bd9Sstevel@tonic-gate 	log_channel chan;
2777c478bd9Sstevel@tonic-gate 	struct timeval tv;
2787c478bd9Sstevel@tonic-gate 	struct tm *local_tm;
2797c478bd9Sstevel@tonic-gate #ifdef HAVE_TIME_R
2807c478bd9Sstevel@tonic-gate 	struct tm tm_tmp;
2817c478bd9Sstevel@tonic-gate #endif
2827c478bd9Sstevel@tonic-gate 	time_t tt;
2837c478bd9Sstevel@tonic-gate 	const char *category_name;
2847c478bd9Sstevel@tonic-gate 	const char *level_str;
2857c478bd9Sstevel@tonic-gate 	char time_buf[256];
2867c478bd9Sstevel@tonic-gate 	char level_buf[256];
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 	REQUIRE(lc != NULL);
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 	debugging = (lc->flags & LOG_OPTION_DEBUG);
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	/*
2937c478bd9Sstevel@tonic-gate 	 * If not debugging, short circuit debugging messages very early.
2947c478bd9Sstevel@tonic-gate 	 */
2957c478bd9Sstevel@tonic-gate 	if (level > 0 && !debugging)
2967c478bd9Sstevel@tonic-gate 		return;
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 	if (category < 0 || category > lc->num_categories)
299*9525b14bSRao Shoaib 		category = 0;		/*%< use default */
3007c478bd9Sstevel@tonic-gate 	original_category = category;
3017c478bd9Sstevel@tonic-gate 	lcl = lc->categories[category];
3027c478bd9Sstevel@tonic-gate 	if (lcl == NULL) {
3037c478bd9Sstevel@tonic-gate 		category = 0;
3047c478bd9Sstevel@tonic-gate 		lcl = lc->categories[0];
3057c478bd9Sstevel@tonic-gate 	}
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 	/*
3087c478bd9Sstevel@tonic-gate 	 * Get the current time and format it.
3097c478bd9Sstevel@tonic-gate 	 */
3107c478bd9Sstevel@tonic-gate 	time_buf[0]='\0';
3117c478bd9Sstevel@tonic-gate 	if (gettimeofday(&tv, NULL) < 0) {
3127c478bd9Sstevel@tonic-gate 		syslog(LOG_INFO, "gettimeofday failed in log_vwrite()");
3137c478bd9Sstevel@tonic-gate 	} else {
3147c478bd9Sstevel@tonic-gate 		tt = tv.tv_sec;
3157c478bd9Sstevel@tonic-gate #ifdef HAVE_TIME_R
3167c478bd9Sstevel@tonic-gate 		local_tm = localtime_r(&tt, &tm_tmp);
3177c478bd9Sstevel@tonic-gate #else
3187c478bd9Sstevel@tonic-gate 		local_tm = localtime(&tt);
3197c478bd9Sstevel@tonic-gate #endif
3207c478bd9Sstevel@tonic-gate 		if (local_tm != NULL) {
3217c478bd9Sstevel@tonic-gate 			sprintf(time_buf, "%02d-%s-%4d %02d:%02d:%02d.%03ld ",
3227c478bd9Sstevel@tonic-gate 				local_tm->tm_mday, months[local_tm->tm_mon],
3237c478bd9Sstevel@tonic-gate 				local_tm->tm_year+1900, local_tm->tm_hour,
3247c478bd9Sstevel@tonic-gate 				local_tm->tm_min, local_tm->tm_sec,
3257c478bd9Sstevel@tonic-gate 				(long)tv.tv_usec/1000);
3267c478bd9Sstevel@tonic-gate 		}
3277c478bd9Sstevel@tonic-gate 	}
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	/*
3307c478bd9Sstevel@tonic-gate 	 * Make a string representation of the current category and level
3317c478bd9Sstevel@tonic-gate 	 */
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 	if (lc->category_names != NULL &&
3347c478bd9Sstevel@tonic-gate 	    lc->category_names[original_category] != NULL)
3357c478bd9Sstevel@tonic-gate 		category_name = lc->category_names[original_category];
3367c478bd9Sstevel@tonic-gate 	else
3377c478bd9Sstevel@tonic-gate 		category_name = "";
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 	if (level >= log_critical) {
3407c478bd9Sstevel@tonic-gate 		if (level >= 0) {
3417c478bd9Sstevel@tonic-gate 			sprintf(level_buf, "debug %d: ", level);
3427c478bd9Sstevel@tonic-gate 			level_str = level_buf;
3437c478bd9Sstevel@tonic-gate 		} else
3447c478bd9Sstevel@tonic-gate 			level_str = level_text[-level-1];
3457c478bd9Sstevel@tonic-gate 	} else {
3467c478bd9Sstevel@tonic-gate 		sprintf(level_buf, "level %d: ", level);
3477c478bd9Sstevel@tonic-gate 		level_str = level_buf;
3487c478bd9Sstevel@tonic-gate 	}
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 	/*
3517c478bd9Sstevel@tonic-gate 	 * Write the message to channels.
3527c478bd9Sstevel@tonic-gate 	 */
3537c478bd9Sstevel@tonic-gate 	for ( /* nothing */; lcl != NULL; lcl = lcl->next) {
3547c478bd9Sstevel@tonic-gate 		chan = lcl->channel;
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 		if (!log_check_channel(lc, level, chan))
3577c478bd9Sstevel@tonic-gate 			continue;
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 		if (!did_vsprintf) {
360*9525b14bSRao Shoaib 			(void)vsprintf(lc->buffer, format, args);
361*9525b14bSRao Shoaib 			if (strlen(lc->buffer) > (size_t)LOG_BUFFER_SIZE) {
3627c478bd9Sstevel@tonic-gate 				syslog(LOG_CRIT,
3637c478bd9Sstevel@tonic-gate 				       "memory overrun in log_vwrite()");
3647c478bd9Sstevel@tonic-gate 				exit(1);
3657c478bd9Sstevel@tonic-gate 			}
3667c478bd9Sstevel@tonic-gate 			did_vsprintf = 1;
3677c478bd9Sstevel@tonic-gate 		}
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 		switch (chan->type) {
3707c478bd9Sstevel@tonic-gate 		case log_syslog:
3717c478bd9Sstevel@tonic-gate 			if (level >= log_critical)
3727c478bd9Sstevel@tonic-gate 				pri = (level >= 0) ? 0 : -level;
3737c478bd9Sstevel@tonic-gate 			else
3747c478bd9Sstevel@tonic-gate 				pri = -log_critical;
3757c478bd9Sstevel@tonic-gate 			syslog(chan->out.facility|syslog_priority[pri],
3767c478bd9Sstevel@tonic-gate 			       "%s%s%s%s",
3777c478bd9Sstevel@tonic-gate 			       (chan->flags & LOG_TIMESTAMP) ?	time_buf : "",
3787c478bd9Sstevel@tonic-gate 			       (chan->flags & LOG_PRINT_CATEGORY) ?
3797c478bd9Sstevel@tonic-gate 			       category_name : "",
3807c478bd9Sstevel@tonic-gate 			       (chan->flags & LOG_PRINT_LEVEL) ?
3817c478bd9Sstevel@tonic-gate 			       level_str : "",
3827c478bd9Sstevel@tonic-gate 			       lc->buffer);
3837c478bd9Sstevel@tonic-gate 			break;
3847c478bd9Sstevel@tonic-gate 		case log_file:
3857c478bd9Sstevel@tonic-gate 			stream = chan->out.file.stream;
3867c478bd9Sstevel@tonic-gate 			if (stream == NULL) {
3877c478bd9Sstevel@tonic-gate 				stream = log_open_stream(chan);
3887c478bd9Sstevel@tonic-gate 				if (stream == NULL)
3897c478bd9Sstevel@tonic-gate 					break;
3907c478bd9Sstevel@tonic-gate 			}
3917c478bd9Sstevel@tonic-gate 			if (chan->out.file.max_size != ULONG_MAX) {
3927c478bd9Sstevel@tonic-gate 				long pos;
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate 				pos = ftell(stream);
3957c478bd9Sstevel@tonic-gate 				if (pos >= 0 &&
3967c478bd9Sstevel@tonic-gate 				    (unsigned long)pos >
3977c478bd9Sstevel@tonic-gate 				    chan->out.file.max_size) {
3987c478bd9Sstevel@tonic-gate 					/*
3997c478bd9Sstevel@tonic-gate 					 * try to roll over the log files,
4007c478bd9Sstevel@tonic-gate 					 * ignoring all all return codes
4017c478bd9Sstevel@tonic-gate 					 * except the open (we don't want
4027c478bd9Sstevel@tonic-gate 					 * to write any more anyway)
4037c478bd9Sstevel@tonic-gate 					 */
4047c478bd9Sstevel@tonic-gate 					log_close_stream(chan);
4057c478bd9Sstevel@tonic-gate 					version_rename(chan);
4067c478bd9Sstevel@tonic-gate 					stream = log_open_stream(chan);
4077c478bd9Sstevel@tonic-gate 					if (stream == NULL)
4087c478bd9Sstevel@tonic-gate 						break;
4097c478bd9Sstevel@tonic-gate 				}
4107c478bd9Sstevel@tonic-gate 			}
4117c478bd9Sstevel@tonic-gate 			fprintf(stream, "%s%s%s%s\n",
4127c478bd9Sstevel@tonic-gate 				(chan->flags & LOG_TIMESTAMP) ?	time_buf : "",
4137c478bd9Sstevel@tonic-gate 				(chan->flags & LOG_PRINT_CATEGORY) ?
4147c478bd9Sstevel@tonic-gate 				category_name : "",
4157c478bd9Sstevel@tonic-gate 				(chan->flags & LOG_PRINT_LEVEL) ?
4167c478bd9Sstevel@tonic-gate 				level_str : "",
4177c478bd9Sstevel@tonic-gate 				lc->buffer);
4187c478bd9Sstevel@tonic-gate 			fflush(stream);
4197c478bd9Sstevel@tonic-gate 			break;
4207c478bd9Sstevel@tonic-gate 		case log_null:
4217c478bd9Sstevel@tonic-gate 			break;
4227c478bd9Sstevel@tonic-gate 		default:
4237c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
4247c478bd9Sstevel@tonic-gate 			       "unknown channel type in log_vwrite()");
4257c478bd9Sstevel@tonic-gate 		}
4267c478bd9Sstevel@tonic-gate 	}
4277c478bd9Sstevel@tonic-gate }
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate void
log_write(log_context lc,int category,int level,const char * format,...)4307c478bd9Sstevel@tonic-gate log_write(log_context lc, int category, int level, const char *format, ...) {
4317c478bd9Sstevel@tonic-gate 	va_list args;
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 	va_start(args, format);
4347c478bd9Sstevel@tonic-gate 	log_vwrite(lc, category, level, format, args);
4357c478bd9Sstevel@tonic-gate 	va_end(args);
4367c478bd9Sstevel@tonic-gate }
4377c478bd9Sstevel@tonic-gate 
438*9525b14bSRao Shoaib /*%
4397c478bd9Sstevel@tonic-gate  * Functions to create, set, or destroy contexts
4407c478bd9Sstevel@tonic-gate  */
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate int
log_new_context(int num_categories,char ** category_names,log_context * lc)4437c478bd9Sstevel@tonic-gate log_new_context(int num_categories, char **category_names, log_context *lc) {
4447c478bd9Sstevel@tonic-gate 	log_context nlc;
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 	nlc = memget(sizeof (struct log_context));
4477c478bd9Sstevel@tonic-gate 	if (nlc == NULL) {
4487c478bd9Sstevel@tonic-gate 		errno = ENOMEM;
4497c478bd9Sstevel@tonic-gate 		return (-1);
4507c478bd9Sstevel@tonic-gate 	}
4517c478bd9Sstevel@tonic-gate 	nlc->num_categories = num_categories;
4527c478bd9Sstevel@tonic-gate 	nlc->category_names = category_names;
4537c478bd9Sstevel@tonic-gate 	nlc->categories = memget(num_categories * sizeof (log_channel_list));
4547c478bd9Sstevel@tonic-gate 	if (nlc->categories == NULL) {
4557c478bd9Sstevel@tonic-gate 		memput(nlc, sizeof (struct log_context));
4567c478bd9Sstevel@tonic-gate 		errno = ENOMEM;
4577c478bd9Sstevel@tonic-gate 		return (-1);
4587c478bd9Sstevel@tonic-gate 	}
4597c478bd9Sstevel@tonic-gate 	memset(nlc->categories, '\0',
4607c478bd9Sstevel@tonic-gate 	       num_categories * sizeof (log_channel_list));
4617c478bd9Sstevel@tonic-gate 	nlc->flags = 0U;
4627c478bd9Sstevel@tonic-gate 	nlc->level = 0;
4637c478bd9Sstevel@tonic-gate 	*lc = nlc;
4647c478bd9Sstevel@tonic-gate 	return (0);
4657c478bd9Sstevel@tonic-gate }
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate void
log_free_context(log_context lc)4687c478bd9Sstevel@tonic-gate log_free_context(log_context lc) {
4697c478bd9Sstevel@tonic-gate 	log_channel_list lcl, lcl_next;
4707c478bd9Sstevel@tonic-gate 	log_channel chan;
4717c478bd9Sstevel@tonic-gate 	int i;
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 	REQUIRE(lc != NULL);
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 	for (i = 0; i < lc->num_categories; i++)
4767c478bd9Sstevel@tonic-gate 		for (lcl = lc->categories[i]; lcl != NULL; lcl = lcl_next) {
4777c478bd9Sstevel@tonic-gate 			lcl_next = lcl->next;
4787c478bd9Sstevel@tonic-gate 			chan = lcl->channel;
4797c478bd9Sstevel@tonic-gate 			(void)log_free_channel(chan);
4807c478bd9Sstevel@tonic-gate 			memput(lcl, sizeof (struct log_channel_list));
4817c478bd9Sstevel@tonic-gate 		}
4827c478bd9Sstevel@tonic-gate 	memput(lc->categories,
4837c478bd9Sstevel@tonic-gate 	       lc->num_categories * sizeof (log_channel_list));
4847c478bd9Sstevel@tonic-gate 	memput(lc, sizeof (struct log_context));
4857c478bd9Sstevel@tonic-gate }
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate int
log_add_channel(log_context lc,int category,log_channel chan)4887c478bd9Sstevel@tonic-gate log_add_channel(log_context lc, int category, log_channel chan) {
4897c478bd9Sstevel@tonic-gate 	log_channel_list lcl;
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate 	if (lc == NULL || category < 0 || category >= lc->num_categories) {
4927c478bd9Sstevel@tonic-gate 		errno = EINVAL;
4937c478bd9Sstevel@tonic-gate 		return (-1);
4947c478bd9Sstevel@tonic-gate 	}
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 	lcl = memget(sizeof (struct log_channel_list));
4977c478bd9Sstevel@tonic-gate 	if (lcl == NULL) {
4987c478bd9Sstevel@tonic-gate 		errno = ENOMEM;
4997c478bd9Sstevel@tonic-gate 		return(-1);
5007c478bd9Sstevel@tonic-gate 	}
5017c478bd9Sstevel@tonic-gate 	lcl->channel = chan;
5027c478bd9Sstevel@tonic-gate 	lcl->next = lc->categories[category];
5037c478bd9Sstevel@tonic-gate 	lc->categories[category] = lcl;
5047c478bd9Sstevel@tonic-gate 	chan->references++;
5057c478bd9Sstevel@tonic-gate 	return (0);
5067c478bd9Sstevel@tonic-gate }
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate int
log_remove_channel(log_context lc,int category,log_channel chan)5097c478bd9Sstevel@tonic-gate log_remove_channel(log_context lc, int category, log_channel chan) {
5107c478bd9Sstevel@tonic-gate 	log_channel_list lcl, prev_lcl, next_lcl;
5117c478bd9Sstevel@tonic-gate 	int found = 0;
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 	if (lc == NULL || category < 0 || category >= lc->num_categories) {
5147c478bd9Sstevel@tonic-gate 		errno = EINVAL;
5157c478bd9Sstevel@tonic-gate 		return (-1);
5167c478bd9Sstevel@tonic-gate 	}
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	for (prev_lcl = NULL, lcl = lc->categories[category];
5197c478bd9Sstevel@tonic-gate 	     lcl != NULL;
5207c478bd9Sstevel@tonic-gate 	     lcl = next_lcl) {
5217c478bd9Sstevel@tonic-gate 		next_lcl = lcl->next;
5227c478bd9Sstevel@tonic-gate 		if (lcl->channel == chan) {
5237c478bd9Sstevel@tonic-gate 			log_free_channel(chan);
5247c478bd9Sstevel@tonic-gate 			if (prev_lcl != NULL)
5257c478bd9Sstevel@tonic-gate 				prev_lcl->next = next_lcl;
5267c478bd9Sstevel@tonic-gate 			else
5277c478bd9Sstevel@tonic-gate 				lc->categories[category] = next_lcl;
5287c478bd9Sstevel@tonic-gate 			memput(lcl, sizeof (struct log_channel_list));
5297c478bd9Sstevel@tonic-gate 			/*
5307c478bd9Sstevel@tonic-gate 			 * We just set found instead of returning because
5317c478bd9Sstevel@tonic-gate 			 * the channel might be on the list more than once.
5327c478bd9Sstevel@tonic-gate 			 */
5337c478bd9Sstevel@tonic-gate 			found = 1;
5347c478bd9Sstevel@tonic-gate 		} else
5357c478bd9Sstevel@tonic-gate 			prev_lcl = lcl;
5367c478bd9Sstevel@tonic-gate 	}
5377c478bd9Sstevel@tonic-gate 	if (!found) {
5387c478bd9Sstevel@tonic-gate 		errno = ENOENT;
5397c478bd9Sstevel@tonic-gate 		return (-1);
5407c478bd9Sstevel@tonic-gate 	}
5417c478bd9Sstevel@tonic-gate 	return (0);
5427c478bd9Sstevel@tonic-gate }
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate int
log_option(log_context lc,int option,int value)5457c478bd9Sstevel@tonic-gate log_option(log_context lc, int option, int value) {
5467c478bd9Sstevel@tonic-gate 	if (lc == NULL) {
5477c478bd9Sstevel@tonic-gate 		errno = EINVAL;
5487c478bd9Sstevel@tonic-gate 		return (-1);
5497c478bd9Sstevel@tonic-gate 	}
5507c478bd9Sstevel@tonic-gate 	switch (option) {
5517c478bd9Sstevel@tonic-gate 	case LOG_OPTION_DEBUG:
5527c478bd9Sstevel@tonic-gate 		if (value)
5537c478bd9Sstevel@tonic-gate 			lc->flags |= option;
5547c478bd9Sstevel@tonic-gate 		else
5557c478bd9Sstevel@tonic-gate 			lc->flags &= ~option;
5567c478bd9Sstevel@tonic-gate 		break;
5577c478bd9Sstevel@tonic-gate 	case LOG_OPTION_LEVEL:
5587c478bd9Sstevel@tonic-gate 		lc->level = value;
5597c478bd9Sstevel@tonic-gate 		break;
5607c478bd9Sstevel@tonic-gate 	default:
5617c478bd9Sstevel@tonic-gate 		errno = EINVAL;
5627c478bd9Sstevel@tonic-gate 		return (-1);
5637c478bd9Sstevel@tonic-gate 	}
5647c478bd9Sstevel@tonic-gate 	return (0);
5657c478bd9Sstevel@tonic-gate }
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate int
log_category_is_active(log_context lc,int category)5687c478bd9Sstevel@tonic-gate log_category_is_active(log_context lc, int category) {
5697c478bd9Sstevel@tonic-gate 	if (lc == NULL) {
5707c478bd9Sstevel@tonic-gate 		errno = EINVAL;
5717c478bd9Sstevel@tonic-gate 		return (-1);
5727c478bd9Sstevel@tonic-gate 	}
5737c478bd9Sstevel@tonic-gate 	if (category >= 0 && category < lc->num_categories &&
5747c478bd9Sstevel@tonic-gate 	    lc->categories[category] != NULL)
5757c478bd9Sstevel@tonic-gate 		return (1);
5767c478bd9Sstevel@tonic-gate 	return (0);
5777c478bd9Sstevel@tonic-gate }
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate log_channel
log_new_syslog_channel(unsigned int flags,int level,int facility)5807c478bd9Sstevel@tonic-gate log_new_syslog_channel(unsigned int flags, int level, int facility) {
5817c478bd9Sstevel@tonic-gate 	log_channel chan;
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 	chan = memget(sizeof (struct log_channel));
5847c478bd9Sstevel@tonic-gate 	if (chan == NULL) {
5857c478bd9Sstevel@tonic-gate 		errno = ENOMEM;
5867c478bd9Sstevel@tonic-gate 		return (NULL);
5877c478bd9Sstevel@tonic-gate 	}
5887c478bd9Sstevel@tonic-gate 	chan->type = log_syslog;
5897c478bd9Sstevel@tonic-gate 	chan->flags = flags;
5907c478bd9Sstevel@tonic-gate 	chan->level = level;
5917c478bd9Sstevel@tonic-gate 	chan->out.facility = facility;
5927c478bd9Sstevel@tonic-gate 	chan->references = 0;
5937c478bd9Sstevel@tonic-gate 	return (chan);
5947c478bd9Sstevel@tonic-gate }
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate log_channel
log_new_file_channel(unsigned int flags,int level,const char * name,FILE * stream,unsigned int versions,unsigned long max_size)5977c478bd9Sstevel@tonic-gate log_new_file_channel(unsigned int flags, int level,
5987c478bd9Sstevel@tonic-gate 		     const char *name, FILE *stream, unsigned int versions,
5997c478bd9Sstevel@tonic-gate 		     unsigned long max_size) {
6007c478bd9Sstevel@tonic-gate 	log_channel chan;
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate 	chan = memget(sizeof (struct log_channel));
6037c478bd9Sstevel@tonic-gate 	if (chan == NULL) {
6047c478bd9Sstevel@tonic-gate 		errno = ENOMEM;
6057c478bd9Sstevel@tonic-gate 		return (NULL);
6067c478bd9Sstevel@tonic-gate 	}
6077c478bd9Sstevel@tonic-gate 	chan->type = log_file;
6087c478bd9Sstevel@tonic-gate 	chan->flags = flags;
6097c478bd9Sstevel@tonic-gate 	chan->level = level;
6107c478bd9Sstevel@tonic-gate 	if (name != NULL) {
6117c478bd9Sstevel@tonic-gate 		size_t len;
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate 		len = strlen(name);
6147c478bd9Sstevel@tonic-gate 		/*
6157c478bd9Sstevel@tonic-gate 		 * Quantize length to a multiple of 256.  There's space for the
6167c478bd9Sstevel@tonic-gate 		 * NUL, since if len is a multiple of 256, the size chosen will
6177c478bd9Sstevel@tonic-gate 		 * be the next multiple.
6187c478bd9Sstevel@tonic-gate 		 */
6197c478bd9Sstevel@tonic-gate 		chan->out.file.name_size = ((len / 256) + 1) * 256;
6207c478bd9Sstevel@tonic-gate 		chan->out.file.name = memget(chan->out.file.name_size);
6217c478bd9Sstevel@tonic-gate 		if (chan->out.file.name == NULL) {
6227c478bd9Sstevel@tonic-gate 			memput(chan, sizeof (struct log_channel));
6237c478bd9Sstevel@tonic-gate 			errno = ENOMEM;
6247c478bd9Sstevel@tonic-gate 			return (NULL);
6257c478bd9Sstevel@tonic-gate 		}
6267c478bd9Sstevel@tonic-gate 		/* This is safe. */
6277c478bd9Sstevel@tonic-gate 		strcpy(chan->out.file.name, name);
6287c478bd9Sstevel@tonic-gate 	} else {
6297c478bd9Sstevel@tonic-gate 		chan->out.file.name_size = 0;
6307c478bd9Sstevel@tonic-gate 		chan->out.file.name = NULL;
6317c478bd9Sstevel@tonic-gate 	}
6327c478bd9Sstevel@tonic-gate 	chan->out.file.stream = stream;
6337c478bd9Sstevel@tonic-gate 	chan->out.file.versions = versions;
6347c478bd9Sstevel@tonic-gate 	chan->out.file.max_size = max_size;
6357c478bd9Sstevel@tonic-gate 	chan->out.file.owner = getuid();
6367c478bd9Sstevel@tonic-gate 	chan->out.file.group = getgid();
6377c478bd9Sstevel@tonic-gate 	chan->references = 0;
6387c478bd9Sstevel@tonic-gate 	return (chan);
6397c478bd9Sstevel@tonic-gate }
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate int
log_set_file_owner(log_channel chan,uid_t owner,gid_t group)6427c478bd9Sstevel@tonic-gate log_set_file_owner(log_channel chan, uid_t owner, gid_t group) {
6437c478bd9Sstevel@tonic-gate 	if (chan->type != log_file) {
6447c478bd9Sstevel@tonic-gate 		errno = EBADF;
6457c478bd9Sstevel@tonic-gate 		return (-1);
6467c478bd9Sstevel@tonic-gate 	}
6477c478bd9Sstevel@tonic-gate 	chan->out.file.owner = owner;
6487c478bd9Sstevel@tonic-gate 	chan->out.file.group = group;
6497c478bd9Sstevel@tonic-gate 	return (0);
6507c478bd9Sstevel@tonic-gate }
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate log_channel
log_new_null_channel()6537c478bd9Sstevel@tonic-gate log_new_null_channel() {
6547c478bd9Sstevel@tonic-gate 	log_channel chan;
6557c478bd9Sstevel@tonic-gate 
6567c478bd9Sstevel@tonic-gate 	chan = memget(sizeof (struct log_channel));
6577c478bd9Sstevel@tonic-gate 	if (chan == NULL) {
6587c478bd9Sstevel@tonic-gate 		errno = ENOMEM;
6597c478bd9Sstevel@tonic-gate 		return (NULL);
6607c478bd9Sstevel@tonic-gate 	}
6617c478bd9Sstevel@tonic-gate 	chan->type = log_null;
6627c478bd9Sstevel@tonic-gate 	chan->flags = LOG_CHANNEL_OFF;
6637c478bd9Sstevel@tonic-gate 	chan->level = log_info;
6647c478bd9Sstevel@tonic-gate 	chan->references = 0;
6657c478bd9Sstevel@tonic-gate 	return (chan);
6667c478bd9Sstevel@tonic-gate }
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate int
log_inc_references(log_channel chan)6697c478bd9Sstevel@tonic-gate log_inc_references(log_channel chan) {
6707c478bd9Sstevel@tonic-gate 	if (chan == NULL) {
6717c478bd9Sstevel@tonic-gate 		errno = EINVAL;
6727c478bd9Sstevel@tonic-gate 		return (-1);
6737c478bd9Sstevel@tonic-gate 	}
6747c478bd9Sstevel@tonic-gate 	chan->references++;
6757c478bd9Sstevel@tonic-gate 	return (0);
6767c478bd9Sstevel@tonic-gate }
6777c478bd9Sstevel@tonic-gate 
6787c478bd9Sstevel@tonic-gate int
log_dec_references(log_channel chan)6797c478bd9Sstevel@tonic-gate log_dec_references(log_channel chan) {
6807c478bd9Sstevel@tonic-gate 	if (chan == NULL || chan->references <= 0) {
6817c478bd9Sstevel@tonic-gate 		errno = EINVAL;
6827c478bd9Sstevel@tonic-gate 		return (-1);
6837c478bd9Sstevel@tonic-gate 	}
6847c478bd9Sstevel@tonic-gate 	chan->references--;
6857c478bd9Sstevel@tonic-gate 	return (0);
6867c478bd9Sstevel@tonic-gate }
6877c478bd9Sstevel@tonic-gate 
6887c478bd9Sstevel@tonic-gate log_channel_type
log_get_channel_type(log_channel chan)6897c478bd9Sstevel@tonic-gate log_get_channel_type(log_channel chan) {
6907c478bd9Sstevel@tonic-gate 	REQUIRE(chan != NULL);
6917c478bd9Sstevel@tonic-gate 
6927c478bd9Sstevel@tonic-gate 	return (chan->type);
6937c478bd9Sstevel@tonic-gate }
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate int
log_free_channel(log_channel chan)6967c478bd9Sstevel@tonic-gate log_free_channel(log_channel chan) {
6977c478bd9Sstevel@tonic-gate 	if (chan == NULL || chan->references <= 0) {
6987c478bd9Sstevel@tonic-gate 		errno = EINVAL;
6997c478bd9Sstevel@tonic-gate 		return (-1);
7007c478bd9Sstevel@tonic-gate 	}
7017c478bd9Sstevel@tonic-gate 	chan->references--;
7027c478bd9Sstevel@tonic-gate 	if (chan->references == 0) {
7037c478bd9Sstevel@tonic-gate 		if (chan->type == log_file) {
7047c478bd9Sstevel@tonic-gate 			if ((chan->flags & LOG_CLOSE_STREAM) &&
7057c478bd9Sstevel@tonic-gate 			    chan->out.file.stream != NULL)
7067c478bd9Sstevel@tonic-gate 				(void)fclose(chan->out.file.stream);
7077c478bd9Sstevel@tonic-gate 			if (chan->out.file.name != NULL)
7087c478bd9Sstevel@tonic-gate 				memput(chan->out.file.name,
7097c478bd9Sstevel@tonic-gate 				       chan->out.file.name_size);
7107c478bd9Sstevel@tonic-gate 		}
7117c478bd9Sstevel@tonic-gate 		memput(chan, sizeof (struct log_channel));
7127c478bd9Sstevel@tonic-gate 	}
7137c478bd9Sstevel@tonic-gate 	return (0);
7147c478bd9Sstevel@tonic-gate }
715*9525b14bSRao Shoaib 
716*9525b14bSRao Shoaib /*! \file */
717