xref: /onnv-gate/usr/src/cmd/sendmail/libsm/debug.c (revision 11440:802724e2906a)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * Copyright (c) 2000, 2001, 2003, 2004 Sendmail, Inc. and its suppliers.
30Sstevel@tonic-gate  *	All rights reserved.
40Sstevel@tonic-gate  *
50Sstevel@tonic-gate  * By using this file, you agree to the terms and conditions set
60Sstevel@tonic-gate  * forth in the LICENSE file which can be found at the top level of
70Sstevel@tonic-gate  * the sendmail distribution.
80Sstevel@tonic-gate  */
90Sstevel@tonic-gate 
100Sstevel@tonic-gate #include <sm/gen.h>
11*11440SJohn.Beck@Sun.COM SM_RCSID("@(#)$Id: debug.c,v 1.32 2009/09/20 05:38:46 ca Exp $")
120Sstevel@tonic-gate 
130Sstevel@tonic-gate /*
140Sstevel@tonic-gate **  libsm debugging and tracing
150Sstevel@tonic-gate **  For documentation, see debug.html.
160Sstevel@tonic-gate */
170Sstevel@tonic-gate 
180Sstevel@tonic-gate #include <ctype.h>
190Sstevel@tonic-gate #include <stdlib.h>
20*11440SJohn.Beck@Sun.COM #if _FFR_DEBUG_PID_TIME
21*11440SJohn.Beck@Sun.COM #include <unistd.h>
22*11440SJohn.Beck@Sun.COM #include <time.h>
23*11440SJohn.Beck@Sun.COM #endif /* _FFR_DEBUG_PID_TIME */
240Sstevel@tonic-gate #include <setjmp.h>
250Sstevel@tonic-gate #include <sm/io.h>
260Sstevel@tonic-gate #include <sm/assert.h>
270Sstevel@tonic-gate #include <sm/conf.h>
280Sstevel@tonic-gate #include <sm/debug.h>
290Sstevel@tonic-gate #include <sm/string.h>
300Sstevel@tonic-gate #include <sm/varargs.h>
310Sstevel@tonic-gate #include <sm/heap.h>
320Sstevel@tonic-gate 
330Sstevel@tonic-gate static void		 sm_debug_reset __P((void));
340Sstevel@tonic-gate static const char	*parse_named_setting_x __P((const char *));
350Sstevel@tonic-gate 
360Sstevel@tonic-gate /*
370Sstevel@tonic-gate **  Abstractions for printing trace messages.
380Sstevel@tonic-gate */
390Sstevel@tonic-gate 
400Sstevel@tonic-gate /*
410Sstevel@tonic-gate **  The output file to which trace output is directed.
420Sstevel@tonic-gate **  There is a controversy over whether this variable
430Sstevel@tonic-gate **  should be process global or thread local.
440Sstevel@tonic-gate **  To make the interface more abstract, we've hidden the
450Sstevel@tonic-gate **  variable behind access functions.
460Sstevel@tonic-gate */
470Sstevel@tonic-gate 
480Sstevel@tonic-gate static SM_FILE_T *SmDebugOutput = smioout;
490Sstevel@tonic-gate 
500Sstevel@tonic-gate /*
510Sstevel@tonic-gate **  SM_DEBUG_FILE -- Returns current debug file pointer.
520Sstevel@tonic-gate **
530Sstevel@tonic-gate **	Parameters:
540Sstevel@tonic-gate **		none.
550Sstevel@tonic-gate **
560Sstevel@tonic-gate **	Returns:
570Sstevel@tonic-gate **		current debug file pointer.
580Sstevel@tonic-gate */
590Sstevel@tonic-gate 
600Sstevel@tonic-gate SM_FILE_T *
sm_debug_file()610Sstevel@tonic-gate sm_debug_file()
620Sstevel@tonic-gate {
630Sstevel@tonic-gate 	return SmDebugOutput;
640Sstevel@tonic-gate }
650Sstevel@tonic-gate 
660Sstevel@tonic-gate /*
670Sstevel@tonic-gate **  SM_DEBUG_SETFILE -- Sets debug file pointer.
680Sstevel@tonic-gate **
690Sstevel@tonic-gate **	Parameters:
700Sstevel@tonic-gate **		fp -- new debug file pointer.
710Sstevel@tonic-gate **
720Sstevel@tonic-gate **	Returns:
730Sstevel@tonic-gate **		none.
740Sstevel@tonic-gate **
750Sstevel@tonic-gate **	Side Effects:
760Sstevel@tonic-gate **		Sets SmDebugOutput.
770Sstevel@tonic-gate */
780Sstevel@tonic-gate 
790Sstevel@tonic-gate void
sm_debug_setfile(fp)800Sstevel@tonic-gate sm_debug_setfile(fp)
810Sstevel@tonic-gate 	SM_FILE_T *fp;
820Sstevel@tonic-gate {
830Sstevel@tonic-gate 	SmDebugOutput = fp;
840Sstevel@tonic-gate }
850Sstevel@tonic-gate 
860Sstevel@tonic-gate /*
870Sstevel@tonic-gate **  SM_DEBUG_CLOSE -- Close debug file pointer.
880Sstevel@tonic-gate **
890Sstevel@tonic-gate **	Parameters:
900Sstevel@tonic-gate **		none.
910Sstevel@tonic-gate **
920Sstevel@tonic-gate **	Returns:
930Sstevel@tonic-gate **		none.
940Sstevel@tonic-gate **
950Sstevel@tonic-gate **	Side Effects:
960Sstevel@tonic-gate **		Closes SmDebugOutput.
970Sstevel@tonic-gate */
980Sstevel@tonic-gate 
990Sstevel@tonic-gate void
sm_debug_close()1000Sstevel@tonic-gate sm_debug_close()
1010Sstevel@tonic-gate {
1020Sstevel@tonic-gate 	if (SmDebugOutput != NULL && SmDebugOutput != smioout)
1030Sstevel@tonic-gate 	{
1040Sstevel@tonic-gate 		sm_io_close(SmDebugOutput, SM_TIME_DEFAULT);
1050Sstevel@tonic-gate 		SmDebugOutput = NULL;
1060Sstevel@tonic-gate 	}
1070Sstevel@tonic-gate }
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate /*
1100Sstevel@tonic-gate **  SM_DPRINTF -- printf() for debug output.
1110Sstevel@tonic-gate **
1120Sstevel@tonic-gate **	Parameters:
1130Sstevel@tonic-gate **		fmt -- format for printf()
1140Sstevel@tonic-gate **
1150Sstevel@tonic-gate **	Returns:
1160Sstevel@tonic-gate **		none.
1170Sstevel@tonic-gate */
1180Sstevel@tonic-gate 
119*11440SJohn.Beck@Sun.COM #if _FFR_DEBUG_PID_TIME
120*11440SJohn.Beck@Sun.COM SM_DEBUG_T SmDBGPidTime = SM_DEBUG_INITIALIZER("sm_trace_pid_time",
121*11440SJohn.Beck@Sun.COM 	"@(#)$Debug: sm_trace_pid_time - print pid and time in debug $");
122*11440SJohn.Beck@Sun.COM #endif /* _FFR_DEBUG_PID_TIME */
123*11440SJohn.Beck@Sun.COM 
1240Sstevel@tonic-gate void
1250Sstevel@tonic-gate #if SM_VA_STD
sm_dprintf(char * fmt,...)1260Sstevel@tonic-gate sm_dprintf(char *fmt, ...)
1270Sstevel@tonic-gate #else /* SM_VA_STD */
1280Sstevel@tonic-gate sm_dprintf(fmt, va_alist)
1290Sstevel@tonic-gate 	char *fmt;
1300Sstevel@tonic-gate 	va_dcl
1310Sstevel@tonic-gate #endif /* SM_VA_STD */
1320Sstevel@tonic-gate {
1330Sstevel@tonic-gate 	SM_VA_LOCAL_DECL
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 	if (SmDebugOutput == NULL)
1360Sstevel@tonic-gate 		return;
137*11440SJohn.Beck@Sun.COM #if _FFR_DEBUG_PID_TIME
138*11440SJohn.Beck@Sun.COM 	/* note: this is ugly if the output isn't a full line! */
139*11440SJohn.Beck@Sun.COM 	if (sm_debug_active(&SmDBGPidTime, 1))
140*11440SJohn.Beck@Sun.COM 	{
141*11440SJohn.Beck@Sun.COM 		static char str[32] = "[1900-00-00/00:00:00] ";
142*11440SJohn.Beck@Sun.COM 		struct tm *tmp;
143*11440SJohn.Beck@Sun.COM 		time_t currt;
144*11440SJohn.Beck@Sun.COM 
145*11440SJohn.Beck@Sun.COM 		currt = time((time_t *)0);
146*11440SJohn.Beck@Sun.COM 		tmp = localtime(&currt);
147*11440SJohn.Beck@Sun.COM 		snprintf(str, sizeof(str), "[%d-%02d-%02d/%02d:%02d:%02d] ",
148*11440SJohn.Beck@Sun.COM 			1900 + tmp->tm_year,	/* HACK */
149*11440SJohn.Beck@Sun.COM 			tmp->tm_mon + 1,
150*11440SJohn.Beck@Sun.COM 			tmp->tm_mday,
151*11440SJohn.Beck@Sun.COM 			tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
152*11440SJohn.Beck@Sun.COM 		sm_io_fprintf(SmDebugOutput, SmDebugOutput->f_timeout,
153*11440SJohn.Beck@Sun.COM 			"%ld: %s ", (long) getpid(), str);
154*11440SJohn.Beck@Sun.COM 	}
155*11440SJohn.Beck@Sun.COM #endif /* _FFR_DEBUG_PID_TIME */
156*11440SJohn.Beck@Sun.COM 
1570Sstevel@tonic-gate 	SM_VA_START(ap, fmt);
1580Sstevel@tonic-gate 	sm_io_vfprintf(SmDebugOutput, SmDebugOutput->f_timeout, fmt, ap);
1590Sstevel@tonic-gate 	SM_VA_END(ap);
1600Sstevel@tonic-gate }
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate /*
1630Sstevel@tonic-gate **  SM_DFLUSH -- Flush debug output.
1640Sstevel@tonic-gate **
1650Sstevel@tonic-gate **	Parameters:
1660Sstevel@tonic-gate **		none.
1670Sstevel@tonic-gate **
1680Sstevel@tonic-gate **	Returns:
1690Sstevel@tonic-gate **		none.
1700Sstevel@tonic-gate */
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate void
sm_dflush()1730Sstevel@tonic-gate sm_dflush()
1740Sstevel@tonic-gate {
1750Sstevel@tonic-gate 	sm_io_flush(SmDebugOutput, SM_TIME_DEFAULT);
1760Sstevel@tonic-gate }
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate /*
1790Sstevel@tonic-gate **  This is the internal database of debug settings.
1800Sstevel@tonic-gate **  The semantics of looking up a setting in the settings database
1810Sstevel@tonic-gate **  are that the *last* setting specified in a -d option on the sendmail
1820Sstevel@tonic-gate **  command line that matches a given SM_DEBUG structure is the one that is
1830Sstevel@tonic-gate **  used.  That is necessary to conform to the existing semantics of
1840Sstevel@tonic-gate **  the sendmail -d option.  We store the settings as a linked list in
1850Sstevel@tonic-gate **  reverse order, so when we do a lookup, we take the *first* entry
1860Sstevel@tonic-gate **  that matches.
1870Sstevel@tonic-gate */
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate typedef struct sm_debug_setting SM_DEBUG_SETTING_T;
1900Sstevel@tonic-gate struct sm_debug_setting
1910Sstevel@tonic-gate {
1920Sstevel@tonic-gate 	const char		*ds_pattern;
1930Sstevel@tonic-gate 	unsigned int		ds_level;
1940Sstevel@tonic-gate 	SM_DEBUG_SETTING_T	*ds_next;
1950Sstevel@tonic-gate };
1960Sstevel@tonic-gate SM_DEBUG_SETTING_T *SmDebugSettings = NULL;
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate /*
1990Sstevel@tonic-gate **  We keep a linked list of SM_DEBUG structures that have been initialized,
2000Sstevel@tonic-gate **  for use by sm_debug_reset.
2010Sstevel@tonic-gate */
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate SM_DEBUG_T *SmDebugInitialized = NULL;
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate const char SmDebugMagic[] = "sm_debug";
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate /*
2080Sstevel@tonic-gate **  SM_DEBUG_RESET -- Reset SM_DEBUG structures.
2090Sstevel@tonic-gate **
2100Sstevel@tonic-gate **	Reset all SM_DEBUG structures back to the uninitialized state.
2110Sstevel@tonic-gate **	This is used by sm_debug_addsetting to ensure that references to
2120Sstevel@tonic-gate **	SM_DEBUG structures that occur before sendmail processes its -d flags
2130Sstevel@tonic-gate **	do not cause those structures to be permanently forced to level 0.
2140Sstevel@tonic-gate **
2150Sstevel@tonic-gate **	Parameters:
2160Sstevel@tonic-gate **		none.
2170Sstevel@tonic-gate **
2180Sstevel@tonic-gate **	Returns:
2190Sstevel@tonic-gate **		none.
2200Sstevel@tonic-gate */
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate static void
sm_debug_reset()2230Sstevel@tonic-gate sm_debug_reset()
2240Sstevel@tonic-gate {
2250Sstevel@tonic-gate 	SM_DEBUG_T *debug;
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 	for (debug = SmDebugInitialized;
2280Sstevel@tonic-gate 	     debug != NULL;
2290Sstevel@tonic-gate 	     debug = debug->debug_next)
2300Sstevel@tonic-gate 	{
2310Sstevel@tonic-gate 		debug->debug_level = SM_DEBUG_UNKNOWN;
2320Sstevel@tonic-gate 	}
2330Sstevel@tonic-gate 	SmDebugInitialized = NULL;
2340Sstevel@tonic-gate }
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate /*
2370Sstevel@tonic-gate **  SM_DEBUG_ADDSETTING_X -- add an entry to the database of debug settings
2380Sstevel@tonic-gate **
2390Sstevel@tonic-gate **	Parameters:
2400Sstevel@tonic-gate **		pattern -- a shell-style glob pattern (see sm_match).
2410Sstevel@tonic-gate **			WARNING: the storage for 'pattern' will be owned by
2420Sstevel@tonic-gate **			the debug package, so it should either be a string
2430Sstevel@tonic-gate **			literal or the result of a call to sm_strdup_x.
2440Sstevel@tonic-gate **		level -- a non-negative integer.
2450Sstevel@tonic-gate **
2460Sstevel@tonic-gate **	Returns:
2470Sstevel@tonic-gate **		none.
2480Sstevel@tonic-gate **
2490Sstevel@tonic-gate **	Exceptions:
2500Sstevel@tonic-gate **		F:sm_heap -- out of memory
2510Sstevel@tonic-gate */
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate void
sm_debug_addsetting_x(pattern,level)2540Sstevel@tonic-gate sm_debug_addsetting_x(pattern, level)
2550Sstevel@tonic-gate 	const char *pattern;
2560Sstevel@tonic-gate 	int level;
2570Sstevel@tonic-gate {
2580Sstevel@tonic-gate 	SM_DEBUG_SETTING_T *s;
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 	SM_REQUIRE(pattern != NULL);
2610Sstevel@tonic-gate 	SM_REQUIRE(level >= 0);
2620Sstevel@tonic-gate 	s = sm_malloc_x(sizeof(SM_DEBUG_SETTING_T));
2630Sstevel@tonic-gate 	s->ds_pattern = pattern;
2640Sstevel@tonic-gate 	s->ds_level = (unsigned int) level;
2650Sstevel@tonic-gate 	s->ds_next = SmDebugSettings;
2660Sstevel@tonic-gate 	SmDebugSettings = s;
2670Sstevel@tonic-gate 	sm_debug_reset();
2680Sstevel@tonic-gate }
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate /*
2710Sstevel@tonic-gate **  PARSE_NAMED_SETTING_X -- process a symbolic debug setting
2720Sstevel@tonic-gate **
2730Sstevel@tonic-gate **	Parameters:
2740Sstevel@tonic-gate **		s -- Points to a non-empty \0 or , terminated string,
2750Sstevel@tonic-gate **		     of which the initial character is not a digit.
2760Sstevel@tonic-gate **
2770Sstevel@tonic-gate **	Returns:
2780Sstevel@tonic-gate **		pointer to terminating \0 or , character.
2790Sstevel@tonic-gate **
2800Sstevel@tonic-gate **	Exceptions:
2810Sstevel@tonic-gate **		F:sm.heap -- out of memory.
2820Sstevel@tonic-gate **
2830Sstevel@tonic-gate **	Side Effects:
2840Sstevel@tonic-gate **		adds the setting to the database.
2850Sstevel@tonic-gate */
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate static const char *
parse_named_setting_x(s)2880Sstevel@tonic-gate parse_named_setting_x(s)
2890Sstevel@tonic-gate 	const char *s;
2900Sstevel@tonic-gate {
2910Sstevel@tonic-gate 	const char *pat, *endpat;
2920Sstevel@tonic-gate 	int level;
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 	pat = s;
2950Sstevel@tonic-gate 	while (*s != '\0' && *s != ',' && *s != '.')
2960Sstevel@tonic-gate 		++s;
2970Sstevel@tonic-gate 	endpat = s;
2980Sstevel@tonic-gate 	if (*s == '.')
2990Sstevel@tonic-gate 	{
3000Sstevel@tonic-gate 		++s;
3010Sstevel@tonic-gate 		level = 0;
3020Sstevel@tonic-gate 		while (isascii(*s) && isdigit(*s))
3030Sstevel@tonic-gate 		{
3040Sstevel@tonic-gate 			level = level * 10 + (*s - '0');
3050Sstevel@tonic-gate 			++s;
3060Sstevel@tonic-gate 		}
3070Sstevel@tonic-gate 		if (level < 0)
3080Sstevel@tonic-gate 			level = 0;
3090Sstevel@tonic-gate 	}
3100Sstevel@tonic-gate 	else
3110Sstevel@tonic-gate 		level = 1;
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate 	sm_debug_addsetting_x(sm_strndup_x(pat, endpat - pat), level);
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 	/* skip trailing junk */
3160Sstevel@tonic-gate 	while (*s != '\0' && *s != ',')
3170Sstevel@tonic-gate 		++s;
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 	return s;
3200Sstevel@tonic-gate }
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate /*
3230Sstevel@tonic-gate **  SM_DEBUG_ADDSETTINGS_X -- process a list of debug options
3240Sstevel@tonic-gate **
3250Sstevel@tonic-gate **	Parameters:
3260Sstevel@tonic-gate **		s -- a list of debug settings, eg the argument to the
3270Sstevel@tonic-gate **		     sendmail -d option.
3280Sstevel@tonic-gate **
3290Sstevel@tonic-gate **		The syntax of the string s is as follows:
3300Sstevel@tonic-gate **
3310Sstevel@tonic-gate **		<settings> ::= <setting> | <settings> "," <setting>
3320Sstevel@tonic-gate **		<setting> ::= <categories> | <categories> "." <level>
3330Sstevel@tonic-gate **		<categories> ::= [a-zA-Z_*?][a-zA-Z0-9_*?]*
3340Sstevel@tonic-gate **
3350Sstevel@tonic-gate **		However, note that we skip over anything we don't
3360Sstevel@tonic-gate **		understand, rather than report an error.
3370Sstevel@tonic-gate **
3380Sstevel@tonic-gate **	Returns:
3390Sstevel@tonic-gate **		none.
3400Sstevel@tonic-gate **
3410Sstevel@tonic-gate **	Exceptions:
3420Sstevel@tonic-gate **		F:sm.heap -- out of memory
3430Sstevel@tonic-gate **
3440Sstevel@tonic-gate **	Side Effects:
3450Sstevel@tonic-gate **		updates the database of debug settings.
3460Sstevel@tonic-gate */
3470Sstevel@tonic-gate 
3480Sstevel@tonic-gate void
sm_debug_addsettings_x(s)3490Sstevel@tonic-gate sm_debug_addsettings_x(s)
3500Sstevel@tonic-gate 	const char *s;
3510Sstevel@tonic-gate {
3520Sstevel@tonic-gate 	for (;;)
3530Sstevel@tonic-gate 	{
3540Sstevel@tonic-gate 		if (*s == '\0')
3550Sstevel@tonic-gate 			return;
3560Sstevel@tonic-gate 		if (*s == ',')
3570Sstevel@tonic-gate 		{
3580Sstevel@tonic-gate 			++s;
3590Sstevel@tonic-gate 			continue;
3600Sstevel@tonic-gate 		}
3610Sstevel@tonic-gate 		s = parse_named_setting_x(s);
3620Sstevel@tonic-gate 	}
3630Sstevel@tonic-gate }
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate /*
3660Sstevel@tonic-gate **  SM_DEBUG_LOADLEVEL -- Get activation level of the specified debug object.
3670Sstevel@tonic-gate **
3680Sstevel@tonic-gate **	Parameters:
3690Sstevel@tonic-gate **		debug -- debug object.
3700Sstevel@tonic-gate **
3710Sstevel@tonic-gate **	Returns:
3720Sstevel@tonic-gate **		Activation level of the specified debug object.
3730Sstevel@tonic-gate **
3740Sstevel@tonic-gate **	Side Effects:
3750Sstevel@tonic-gate **		Ensures that the debug object is initialized.
3760Sstevel@tonic-gate */
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate int
sm_debug_loadlevel(debug)3790Sstevel@tonic-gate sm_debug_loadlevel(debug)
3800Sstevel@tonic-gate 	SM_DEBUG_T *debug;
3810Sstevel@tonic-gate {
3820Sstevel@tonic-gate 	if (debug->debug_level == SM_DEBUG_UNKNOWN)
3830Sstevel@tonic-gate 	{
3840Sstevel@tonic-gate 		SM_DEBUG_SETTING_T *s;
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 		for (s = SmDebugSettings; s != NULL; s = s->ds_next)
3870Sstevel@tonic-gate 		{
3880Sstevel@tonic-gate 			if (sm_match(debug->debug_name, s->ds_pattern))
3890Sstevel@tonic-gate 			{
3900Sstevel@tonic-gate 				debug->debug_level = s->ds_level;
3910Sstevel@tonic-gate 				goto initialized;
3920Sstevel@tonic-gate 			}
3930Sstevel@tonic-gate 		}
3940Sstevel@tonic-gate 		debug->debug_level = 0;
3950Sstevel@tonic-gate 	initialized:
3960Sstevel@tonic-gate 		debug->debug_next = SmDebugInitialized;
3970Sstevel@tonic-gate 		SmDebugInitialized = debug;
3980Sstevel@tonic-gate 	}
3990Sstevel@tonic-gate 	return (int) debug->debug_level;
4000Sstevel@tonic-gate }
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate /*
4030Sstevel@tonic-gate **  SM_DEBUG_LOADACTIVE -- Activation level reached?
4040Sstevel@tonic-gate **
4050Sstevel@tonic-gate **	Parameters:
4060Sstevel@tonic-gate **		debug -- debug object.
4070Sstevel@tonic-gate **		level -- level to check.
4080Sstevel@tonic-gate **
4090Sstevel@tonic-gate **	Returns:
4100Sstevel@tonic-gate **		true iff the activation level of the specified debug
4110Sstevel@tonic-gate **			object >= level.
4120Sstevel@tonic-gate **
4130Sstevel@tonic-gate **	Side Effects:
4140Sstevel@tonic-gate **		Ensures that the debug object is initialized.
4150Sstevel@tonic-gate */
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate bool
sm_debug_loadactive(debug,level)4180Sstevel@tonic-gate sm_debug_loadactive(debug, level)
4190Sstevel@tonic-gate 	SM_DEBUG_T *debug;
4200Sstevel@tonic-gate 	int level;
4210Sstevel@tonic-gate {
4220Sstevel@tonic-gate 	return sm_debug_loadlevel(debug) >= level;
4230Sstevel@tonic-gate }
424