xref: /freebsd/contrib/sendmail/libsm/debug.c (revision e2c0e292e8a7ca00ba99bcfccc9e637f45c3e8b1)
140266059SGregory Neil Shapiro /*
25dd76dd0SGregory Neil Shapiro  * Copyright (c) 2000, 2001, 2003, 2004 Proofpoint, Inc. and its suppliers.
340266059SGregory Neil Shapiro  *	All rights reserved.
440266059SGregory Neil Shapiro  *
540266059SGregory Neil Shapiro  * By using this file, you agree to the terms and conditions set
640266059SGregory Neil Shapiro  * forth in the LICENSE file which can be found at the top level of
740266059SGregory Neil Shapiro  * the sendmail distribution.
840266059SGregory Neil Shapiro  */
940266059SGregory Neil Shapiro 
1040266059SGregory Neil Shapiro #include <sm/gen.h>
114313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: debug.c,v 1.33 2013-11-22 20:51:42 ca Exp $")
1240266059SGregory Neil Shapiro 
1340266059SGregory Neil Shapiro /*
1440266059SGregory Neil Shapiro **  libsm debugging and tracing
1540266059SGregory Neil Shapiro **  For documentation, see debug.html.
1640266059SGregory Neil Shapiro */
1740266059SGregory Neil Shapiro 
1840266059SGregory Neil Shapiro #include <ctype.h>
1940266059SGregory Neil Shapiro #include <stdlib.h>
209bd497b8SGregory Neil Shapiro #if _FFR_DEBUG_PID_TIME
219bd497b8SGregory Neil Shapiro #include <unistd.h>
22*5b0945b5SGregory Neil Shapiro #include <sm/types.h>
23*5b0945b5SGregory Neil Shapiro #include <sm/time.h>
249bd497b8SGregory Neil Shapiro #include <time.h>
259bd497b8SGregory Neil Shapiro #endif /* _FFR_DEBUG_PID_TIME */
2640266059SGregory Neil Shapiro #include <setjmp.h>
2740266059SGregory Neil Shapiro #include <sm/io.h>
2840266059SGregory Neil Shapiro #include <sm/assert.h>
2940266059SGregory Neil Shapiro #include <sm/conf.h>
3040266059SGregory Neil Shapiro #include <sm/debug.h>
3140266059SGregory Neil Shapiro #include <sm/string.h>
3240266059SGregory Neil Shapiro #include <sm/varargs.h>
3340266059SGregory Neil Shapiro #include <sm/heap.h>
3440266059SGregory Neil Shapiro 
35b6bacd31SGregory Neil Shapiro static void		 sm_debug_reset __P((void));
36b6bacd31SGregory Neil Shapiro static const char	*parse_named_setting_x __P((const char *));
37b6bacd31SGregory Neil Shapiro 
3840266059SGregory Neil Shapiro /*
3940266059SGregory Neil Shapiro **  Abstractions for printing trace messages.
4040266059SGregory Neil Shapiro */
4140266059SGregory Neil Shapiro 
4240266059SGregory Neil Shapiro /*
4340266059SGregory Neil Shapiro **  The output file to which trace output is directed.
4440266059SGregory Neil Shapiro **  There is a controversy over whether this variable
4540266059SGregory Neil Shapiro **  should be process global or thread local.
4640266059SGregory Neil Shapiro **  To make the interface more abstract, we've hidden the
4740266059SGregory Neil Shapiro **  variable behind access functions.
4840266059SGregory Neil Shapiro */
4940266059SGregory Neil Shapiro 
5040266059SGregory Neil Shapiro static SM_FILE_T *SmDebugOutput = smioout;
5140266059SGregory Neil Shapiro 
5240266059SGregory Neil Shapiro /*
5340266059SGregory Neil Shapiro **  SM_DEBUG_FILE -- Returns current debug file pointer.
5440266059SGregory Neil Shapiro **
5540266059SGregory Neil Shapiro **	Parameters:
5640266059SGregory Neil Shapiro **		none.
5740266059SGregory Neil Shapiro **
5840266059SGregory Neil Shapiro **	Returns:
5940266059SGregory Neil Shapiro **		current debug file pointer.
6040266059SGregory Neil Shapiro */
6140266059SGregory Neil Shapiro 
6240266059SGregory Neil Shapiro SM_FILE_T *
sm_debug_file()6340266059SGregory Neil Shapiro sm_debug_file()
6440266059SGregory Neil Shapiro {
6540266059SGregory Neil Shapiro 	return SmDebugOutput;
6640266059SGregory Neil Shapiro }
6740266059SGregory Neil Shapiro 
6840266059SGregory Neil Shapiro /*
6940266059SGregory Neil Shapiro **  SM_DEBUG_SETFILE -- Sets debug file pointer.
7040266059SGregory Neil Shapiro **
7140266059SGregory Neil Shapiro **	Parameters:
7240266059SGregory Neil Shapiro **		fp -- new debug file pointer.
7340266059SGregory Neil Shapiro **
7440266059SGregory Neil Shapiro **	Returns:
7540266059SGregory Neil Shapiro **		none.
7640266059SGregory Neil Shapiro **
7740266059SGregory Neil Shapiro **	Side Effects:
7840266059SGregory Neil Shapiro **		Sets SmDebugOutput.
7940266059SGregory Neil Shapiro */
8040266059SGregory Neil Shapiro 
8140266059SGregory Neil Shapiro void
sm_debug_setfile(fp)8240266059SGregory Neil Shapiro sm_debug_setfile(fp)
8340266059SGregory Neil Shapiro 	SM_FILE_T *fp;
8440266059SGregory Neil Shapiro {
8540266059SGregory Neil Shapiro 	SmDebugOutput = fp;
8640266059SGregory Neil Shapiro }
8740266059SGregory Neil Shapiro 
8840266059SGregory Neil Shapiro /*
89e92d3f3fSGregory Neil Shapiro **  SM_DEBUG_CLOSE -- Close debug file pointer.
90e92d3f3fSGregory Neil Shapiro **
91e92d3f3fSGregory Neil Shapiro **	Parameters:
92e92d3f3fSGregory Neil Shapiro **		none.
93e92d3f3fSGregory Neil Shapiro **
94e92d3f3fSGregory Neil Shapiro **	Returns:
95e92d3f3fSGregory Neil Shapiro **		none.
96e92d3f3fSGregory Neil Shapiro **
97e92d3f3fSGregory Neil Shapiro **	Side Effects:
98e92d3f3fSGregory Neil Shapiro **		Closes SmDebugOutput.
99e92d3f3fSGregory Neil Shapiro */
100e92d3f3fSGregory Neil Shapiro 
101e92d3f3fSGregory Neil Shapiro void
sm_debug_close()102e92d3f3fSGregory Neil Shapiro sm_debug_close()
103e92d3f3fSGregory Neil Shapiro {
104e92d3f3fSGregory Neil Shapiro 	if (SmDebugOutput != NULL && SmDebugOutput != smioout)
105e92d3f3fSGregory Neil Shapiro 	{
106e92d3f3fSGregory Neil Shapiro 		sm_io_close(SmDebugOutput, SM_TIME_DEFAULT);
107e92d3f3fSGregory Neil Shapiro 		SmDebugOutput = NULL;
108e92d3f3fSGregory Neil Shapiro 	}
109e92d3f3fSGregory Neil Shapiro }
110e92d3f3fSGregory Neil Shapiro 
111e92d3f3fSGregory Neil Shapiro /*
11240266059SGregory Neil Shapiro **  SM_DPRINTF -- printf() for debug output.
11340266059SGregory Neil Shapiro **
11440266059SGregory Neil Shapiro **	Parameters:
11540266059SGregory Neil Shapiro **		fmt -- format for printf()
11640266059SGregory Neil Shapiro **
11740266059SGregory Neil Shapiro **	Returns:
11840266059SGregory Neil Shapiro **		none.
11940266059SGregory Neil Shapiro */
12040266059SGregory Neil Shapiro 
1219bd497b8SGregory Neil Shapiro #if _FFR_DEBUG_PID_TIME
1229bd497b8SGregory Neil Shapiro SM_DEBUG_T SmDBGPidTime = SM_DEBUG_INITIALIZER("sm_trace_pid_time",
1239bd497b8SGregory Neil Shapiro 	"@(#)$Debug: sm_trace_pid_time - print pid and time in debug $");
124*5b0945b5SGregory Neil Shapiro #endif
1259bd497b8SGregory Neil Shapiro 
12640266059SGregory Neil Shapiro void
12740266059SGregory Neil Shapiro #if SM_VA_STD
sm_dprintf(char * fmt,...)12840266059SGregory Neil Shapiro sm_dprintf(char *fmt, ...)
12940266059SGregory Neil Shapiro #else /* SM_VA_STD */
13040266059SGregory Neil Shapiro sm_dprintf(fmt, va_alist)
13140266059SGregory Neil Shapiro 	char *fmt;
13240266059SGregory Neil Shapiro 	va_dcl
13340266059SGregory Neil Shapiro #endif /* SM_VA_STD */
13440266059SGregory Neil Shapiro {
13540266059SGregory Neil Shapiro 	SM_VA_LOCAL_DECL
136*5b0945b5SGregory Neil Shapiro #if _FFR_DEBUG_PID_TIME
137*5b0945b5SGregory Neil Shapiro 	static struct timeval lasttv;
138*5b0945b5SGregory Neil Shapiro #endif
13940266059SGregory Neil Shapiro 
14040266059SGregory Neil Shapiro 	if (SmDebugOutput == NULL)
14140266059SGregory Neil Shapiro 		return;
1429bd497b8SGregory Neil Shapiro #if _FFR_DEBUG_PID_TIME
1439bd497b8SGregory Neil Shapiro 	/* note: this is ugly if the output isn't a full line! */
144*5b0945b5SGregory Neil Shapiro 	if (sm_debug_active(&SmDBGPidTime, 3))
145*5b0945b5SGregory Neil Shapiro 	{
146*5b0945b5SGregory Neil Shapiro 		struct timeval tv, tvd;
147*5b0945b5SGregory Neil Shapiro 
148*5b0945b5SGregory Neil Shapiro 		gettimeofday(&tv, NULL);
149*5b0945b5SGregory Neil Shapiro 		if (timerisset(&lasttv))
150*5b0945b5SGregory Neil Shapiro 			timersub(&tv, &lasttv, &tvd);
151*5b0945b5SGregory Neil Shapiro 		else
152*5b0945b5SGregory Neil Shapiro 			timerclear(&tvd);
153*5b0945b5SGregory Neil Shapiro 		sm_io_fprintf(SmDebugOutput, SmDebugOutput->f_timeout,
154*5b0945b5SGregory Neil Shapiro 			"%ld: %ld.%06ld ",
155*5b0945b5SGregory Neil Shapiro 			(long) getpid(),
156*5b0945b5SGregory Neil Shapiro 			(long) tvd.tv_sec,
157*5b0945b5SGregory Neil Shapiro 			(long) tvd.tv_usec);
158*5b0945b5SGregory Neil Shapiro 		lasttv = tv;
159*5b0945b5SGregory Neil Shapiro 	}
160*5b0945b5SGregory Neil Shapiro 	else if (sm_debug_active(&SmDBGPidTime, 2))
161*5b0945b5SGregory Neil Shapiro 	{
162*5b0945b5SGregory Neil Shapiro 		struct timeval tv;
163*5b0945b5SGregory Neil Shapiro 
164*5b0945b5SGregory Neil Shapiro 		gettimeofday(&tv, NULL);
165*5b0945b5SGregory Neil Shapiro 		sm_io_fprintf(SmDebugOutput, SmDebugOutput->f_timeout,
166*5b0945b5SGregory Neil Shapiro 			"%ld: %ld.%06ld ",
167*5b0945b5SGregory Neil Shapiro 			(long) getpid(),
168*5b0945b5SGregory Neil Shapiro 			(long) tv.tv_sec,
169*5b0945b5SGregory Neil Shapiro 			(long) tv.tv_usec);
170*5b0945b5SGregory Neil Shapiro 	}
171*5b0945b5SGregory Neil Shapiro 	else if (sm_debug_active(&SmDBGPidTime, 1))
1729bd497b8SGregory Neil Shapiro 	{
1739bd497b8SGregory Neil Shapiro 		static char str[32] = "[1900-00-00/00:00:00] ";
1749bd497b8SGregory Neil Shapiro 		struct tm *tmp;
1759bd497b8SGregory Neil Shapiro 		time_t currt;
1769bd497b8SGregory Neil Shapiro 
1779bd497b8SGregory Neil Shapiro 		currt = time((time_t *)0);
1789bd497b8SGregory Neil Shapiro 		tmp = localtime(&currt);
1799bd497b8SGregory Neil Shapiro 		snprintf(str, sizeof(str), "[%d-%02d-%02d/%02d:%02d:%02d] ",
1809bd497b8SGregory Neil Shapiro 			1900 + tmp->tm_year,	/* HACK */
1819bd497b8SGregory Neil Shapiro 			tmp->tm_mon + 1,
1829bd497b8SGregory Neil Shapiro 			tmp->tm_mday,
1839bd497b8SGregory Neil Shapiro 			tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
1849bd497b8SGregory Neil Shapiro 		sm_io_fprintf(SmDebugOutput, SmDebugOutput->f_timeout,
1859bd497b8SGregory Neil Shapiro 			"%ld: %s ", (long) getpid(), str);
1869bd497b8SGregory Neil Shapiro 	}
1879bd497b8SGregory Neil Shapiro #endif /* _FFR_DEBUG_PID_TIME */
1889bd497b8SGregory Neil Shapiro 
18940266059SGregory Neil Shapiro 	SM_VA_START(ap, fmt);
19040266059SGregory Neil Shapiro 	sm_io_vfprintf(SmDebugOutput, SmDebugOutput->f_timeout, fmt, ap);
19140266059SGregory Neil Shapiro 	SM_VA_END(ap);
19240266059SGregory Neil Shapiro }
19340266059SGregory Neil Shapiro 
19440266059SGregory Neil Shapiro /*
19540266059SGregory Neil Shapiro **  SM_DFLUSH -- Flush debug output.
19640266059SGregory Neil Shapiro **
19740266059SGregory Neil Shapiro **	Parameters:
19840266059SGregory Neil Shapiro **		none.
19940266059SGregory Neil Shapiro **
20040266059SGregory Neil Shapiro **	Returns:
20140266059SGregory Neil Shapiro **		none.
20240266059SGregory Neil Shapiro */
20340266059SGregory Neil Shapiro 
20440266059SGregory Neil Shapiro void
sm_dflush()20540266059SGregory Neil Shapiro sm_dflush()
20640266059SGregory Neil Shapiro {
20740266059SGregory Neil Shapiro 	sm_io_flush(SmDebugOutput, SM_TIME_DEFAULT);
20840266059SGregory Neil Shapiro }
20940266059SGregory Neil Shapiro 
21040266059SGregory Neil Shapiro /*
21140266059SGregory Neil Shapiro **  This is the internal database of debug settings.
21240266059SGregory Neil Shapiro **  The semantics of looking up a setting in the settings database
21340266059SGregory Neil Shapiro **  are that the *last* setting specified in a -d option on the sendmail
21440266059SGregory Neil Shapiro **  command line that matches a given SM_DEBUG structure is the one that is
21540266059SGregory Neil Shapiro **  used.  That is necessary to conform to the existing semantics of
21640266059SGregory Neil Shapiro **  the sendmail -d option.  We store the settings as a linked list in
21740266059SGregory Neil Shapiro **  reverse order, so when we do a lookup, we take the *first* entry
21840266059SGregory Neil Shapiro **  that matches.
21940266059SGregory Neil Shapiro */
22040266059SGregory Neil Shapiro 
22140266059SGregory Neil Shapiro typedef struct sm_debug_setting SM_DEBUG_SETTING_T;
22240266059SGregory Neil Shapiro struct sm_debug_setting
22340266059SGregory Neil Shapiro {
22440266059SGregory Neil Shapiro 	const char		*ds_pattern;
22540266059SGregory Neil Shapiro 	unsigned int		ds_level;
22640266059SGregory Neil Shapiro 	SM_DEBUG_SETTING_T	*ds_next;
22740266059SGregory Neil Shapiro };
22840266059SGregory Neil Shapiro SM_DEBUG_SETTING_T *SmDebugSettings = NULL;
22940266059SGregory Neil Shapiro 
23040266059SGregory Neil Shapiro /*
23140266059SGregory Neil Shapiro **  We keep a linked list of SM_DEBUG structures that have been initialized,
23240266059SGregory Neil Shapiro **  for use by sm_debug_reset.
23340266059SGregory Neil Shapiro */
23440266059SGregory Neil Shapiro 
23540266059SGregory Neil Shapiro SM_DEBUG_T *SmDebugInitialized = NULL;
23640266059SGregory Neil Shapiro 
23740266059SGregory Neil Shapiro const char SmDebugMagic[] = "sm_debug";
23840266059SGregory Neil Shapiro 
23940266059SGregory Neil Shapiro /*
24040266059SGregory Neil Shapiro **  SM_DEBUG_RESET -- Reset SM_DEBUG structures.
24140266059SGregory Neil Shapiro **
24240266059SGregory Neil Shapiro **	Reset all SM_DEBUG structures back to the uninitialized state.
24340266059SGregory Neil Shapiro **	This is used by sm_debug_addsetting to ensure that references to
24440266059SGregory Neil Shapiro **	SM_DEBUG structures that occur before sendmail processes its -d flags
24540266059SGregory Neil Shapiro **	do not cause those structures to be permanently forced to level 0.
24640266059SGregory Neil Shapiro **
24740266059SGregory Neil Shapiro **	Parameters:
24840266059SGregory Neil Shapiro **		none.
24940266059SGregory Neil Shapiro **
25040266059SGregory Neil Shapiro **	Returns:
25140266059SGregory Neil Shapiro **		none.
25240266059SGregory Neil Shapiro */
25340266059SGregory Neil Shapiro 
254b6bacd31SGregory Neil Shapiro static void
sm_debug_reset()25540266059SGregory Neil Shapiro sm_debug_reset()
25640266059SGregory Neil Shapiro {
25740266059SGregory Neil Shapiro 	SM_DEBUG_T *debug;
25840266059SGregory Neil Shapiro 
25940266059SGregory Neil Shapiro 	for (debug = SmDebugInitialized;
26040266059SGregory Neil Shapiro 	     debug != NULL;
26140266059SGregory Neil Shapiro 	     debug = debug->debug_next)
26240266059SGregory Neil Shapiro 	{
26340266059SGregory Neil Shapiro 		debug->debug_level = SM_DEBUG_UNKNOWN;
26440266059SGregory Neil Shapiro 	}
26540266059SGregory Neil Shapiro 	SmDebugInitialized = NULL;
26640266059SGregory Neil Shapiro }
26740266059SGregory Neil Shapiro 
26840266059SGregory Neil Shapiro /*
26940266059SGregory Neil Shapiro **  SM_DEBUG_ADDSETTING_X -- add an entry to the database of debug settings
27040266059SGregory Neil Shapiro **
27140266059SGregory Neil Shapiro **	Parameters:
27240266059SGregory Neil Shapiro **		pattern -- a shell-style glob pattern (see sm_match).
27340266059SGregory Neil Shapiro **			WARNING: the storage for 'pattern' will be owned by
27440266059SGregory Neil Shapiro **			the debug package, so it should either be a string
27540266059SGregory Neil Shapiro **			literal or the result of a call to sm_strdup_x.
27640266059SGregory Neil Shapiro **		level -- a non-negative integer.
27740266059SGregory Neil Shapiro **
27840266059SGregory Neil Shapiro **	Returns:
27940266059SGregory Neil Shapiro **		none.
28040266059SGregory Neil Shapiro **
28140266059SGregory Neil Shapiro **	Exceptions:
28240266059SGregory Neil Shapiro **		F:sm_heap -- out of memory
28340266059SGregory Neil Shapiro */
28440266059SGregory Neil Shapiro 
28540266059SGregory Neil Shapiro void
sm_debug_addsetting_x(pattern,level)28640266059SGregory Neil Shapiro sm_debug_addsetting_x(pattern, level)
28740266059SGregory Neil Shapiro 	const char *pattern;
28840266059SGregory Neil Shapiro 	int level;
28940266059SGregory Neil Shapiro {
29040266059SGregory Neil Shapiro 	SM_DEBUG_SETTING_T *s;
29140266059SGregory Neil Shapiro 
29240266059SGregory Neil Shapiro 	SM_REQUIRE(pattern != NULL);
29340266059SGregory Neil Shapiro 	SM_REQUIRE(level >= 0);
29440266059SGregory Neil Shapiro 	s = sm_malloc_x(sizeof(SM_DEBUG_SETTING_T));
29540266059SGregory Neil Shapiro 	s->ds_pattern = pattern;
29640266059SGregory Neil Shapiro 	s->ds_level = (unsigned int) level;
29740266059SGregory Neil Shapiro 	s->ds_next = SmDebugSettings;
29840266059SGregory Neil Shapiro 	SmDebugSettings = s;
29940266059SGregory Neil Shapiro 	sm_debug_reset();
30040266059SGregory Neil Shapiro }
30140266059SGregory Neil Shapiro 
30240266059SGregory Neil Shapiro /*
30340266059SGregory Neil Shapiro **  PARSE_NAMED_SETTING_X -- process a symbolic debug setting
30440266059SGregory Neil Shapiro **
30540266059SGregory Neil Shapiro **	Parameters:
30640266059SGregory Neil Shapiro **		s -- Points to a non-empty \0 or , terminated string,
30740266059SGregory Neil Shapiro **		     of which the initial character is not a digit.
30840266059SGregory Neil Shapiro **
30940266059SGregory Neil Shapiro **	Returns:
31040266059SGregory Neil Shapiro **		pointer to terminating \0 or , character.
31140266059SGregory Neil Shapiro **
31240266059SGregory Neil Shapiro **	Exceptions:
31340266059SGregory Neil Shapiro **		F:sm.heap -- out of memory.
31440266059SGregory Neil Shapiro **
31540266059SGregory Neil Shapiro **	Side Effects:
31640266059SGregory Neil Shapiro **		adds the setting to the database.
31740266059SGregory Neil Shapiro */
31840266059SGregory Neil Shapiro 
31940266059SGregory Neil Shapiro static const char *
parse_named_setting_x(s)32040266059SGregory Neil Shapiro parse_named_setting_x(s)
321b6bacd31SGregory Neil Shapiro 	const char *s;
32240266059SGregory Neil Shapiro {
32340266059SGregory Neil Shapiro 	const char *pat, *endpat;
32440266059SGregory Neil Shapiro 	int level;
32540266059SGregory Neil Shapiro 
32640266059SGregory Neil Shapiro 	pat = s;
32740266059SGregory Neil Shapiro 	while (*s != '\0' && *s != ',' && *s != '.')
32840266059SGregory Neil Shapiro 		++s;
32940266059SGregory Neil Shapiro 	endpat = s;
33040266059SGregory Neil Shapiro 	if (*s == '.')
33140266059SGregory Neil Shapiro 	{
33240266059SGregory Neil Shapiro 		++s;
33340266059SGregory Neil Shapiro 		level = 0;
33440266059SGregory Neil Shapiro 		while (isascii(*s) && isdigit(*s))
33540266059SGregory Neil Shapiro 		{
33640266059SGregory Neil Shapiro 			level = level * 10 + (*s - '0');
33740266059SGregory Neil Shapiro 			++s;
33840266059SGregory Neil Shapiro 		}
33940266059SGregory Neil Shapiro 		if (level < 0)
34040266059SGregory Neil Shapiro 			level = 0;
34140266059SGregory Neil Shapiro 	}
34240266059SGregory Neil Shapiro 	else
34340266059SGregory Neil Shapiro 		level = 1;
34440266059SGregory Neil Shapiro 
34540266059SGregory Neil Shapiro 	sm_debug_addsetting_x(sm_strndup_x(pat, endpat - pat), level);
34640266059SGregory Neil Shapiro 
34740266059SGregory Neil Shapiro 	/* skip trailing junk */
34840266059SGregory Neil Shapiro 	while (*s != '\0' && *s != ',')
34940266059SGregory Neil Shapiro 		++s;
35040266059SGregory Neil Shapiro 
35140266059SGregory Neil Shapiro 	return s;
35240266059SGregory Neil Shapiro }
35340266059SGregory Neil Shapiro 
35440266059SGregory Neil Shapiro /*
35540266059SGregory Neil Shapiro **  SM_DEBUG_ADDSETTINGS_X -- process a list of debug options
35640266059SGregory Neil Shapiro **
35740266059SGregory Neil Shapiro **	Parameters:
35840266059SGregory Neil Shapiro **		s -- a list of debug settings, eg the argument to the
35940266059SGregory Neil Shapiro **		     sendmail -d option.
36040266059SGregory Neil Shapiro **
36140266059SGregory Neil Shapiro **		The syntax of the string s is as follows:
36240266059SGregory Neil Shapiro **
36340266059SGregory Neil Shapiro **		<settings> ::= <setting> | <settings> "," <setting>
36440266059SGregory Neil Shapiro **		<setting> ::= <categories> | <categories> "." <level>
36540266059SGregory Neil Shapiro **		<categories> ::= [a-zA-Z_*?][a-zA-Z0-9_*?]*
36640266059SGregory Neil Shapiro **
36740266059SGregory Neil Shapiro **		However, note that we skip over anything we don't
36840266059SGregory Neil Shapiro **		understand, rather than report an error.
36940266059SGregory Neil Shapiro **
37040266059SGregory Neil Shapiro **	Returns:
37140266059SGregory Neil Shapiro **		none.
37240266059SGregory Neil Shapiro **
37340266059SGregory Neil Shapiro **	Exceptions:
37440266059SGregory Neil Shapiro **		F:sm.heap -- out of memory
37540266059SGregory Neil Shapiro **
37640266059SGregory Neil Shapiro **	Side Effects:
37740266059SGregory Neil Shapiro **		updates the database of debug settings.
37840266059SGregory Neil Shapiro */
37940266059SGregory Neil Shapiro 
38040266059SGregory Neil Shapiro void
sm_debug_addsettings_x(s)38140266059SGregory Neil Shapiro sm_debug_addsettings_x(s)
382b6bacd31SGregory Neil Shapiro 	const char *s;
38340266059SGregory Neil Shapiro {
38440266059SGregory Neil Shapiro 	for (;;)
38540266059SGregory Neil Shapiro 	{
38640266059SGregory Neil Shapiro 		if (*s == '\0')
38740266059SGregory Neil Shapiro 			return;
38840266059SGregory Neil Shapiro 		if (*s == ',')
38940266059SGregory Neil Shapiro 		{
39040266059SGregory Neil Shapiro 			++s;
39140266059SGregory Neil Shapiro 			continue;
39240266059SGregory Neil Shapiro 		}
39340266059SGregory Neil Shapiro 		s = parse_named_setting_x(s);
39440266059SGregory Neil Shapiro 	}
39540266059SGregory Neil Shapiro }
39640266059SGregory Neil Shapiro 
39740266059SGregory Neil Shapiro /*
39840266059SGregory Neil Shapiro **  SM_DEBUG_LOADLEVEL -- Get activation level of the specified debug object.
39940266059SGregory Neil Shapiro **
40040266059SGregory Neil Shapiro **	Parameters:
40140266059SGregory Neil Shapiro **		debug -- debug object.
40240266059SGregory Neil Shapiro **
40340266059SGregory Neil Shapiro **	Returns:
40440266059SGregory Neil Shapiro **		Activation level of the specified debug object.
40540266059SGregory Neil Shapiro **
40640266059SGregory Neil Shapiro **	Side Effects:
40740266059SGregory Neil Shapiro **		Ensures that the debug object is initialized.
40840266059SGregory Neil Shapiro */
40940266059SGregory Neil Shapiro 
41040266059SGregory Neil Shapiro int
sm_debug_loadlevel(debug)41140266059SGregory Neil Shapiro sm_debug_loadlevel(debug)
41240266059SGregory Neil Shapiro 	SM_DEBUG_T *debug;
41340266059SGregory Neil Shapiro {
41440266059SGregory Neil Shapiro 	if (debug->debug_level == SM_DEBUG_UNKNOWN)
41540266059SGregory Neil Shapiro 	{
41640266059SGregory Neil Shapiro 		SM_DEBUG_SETTING_T *s;
41740266059SGregory Neil Shapiro 
41840266059SGregory Neil Shapiro 		for (s = SmDebugSettings; s != NULL; s = s->ds_next)
41940266059SGregory Neil Shapiro 		{
42040266059SGregory Neil Shapiro 			if (sm_match(debug->debug_name, s->ds_pattern))
42140266059SGregory Neil Shapiro 			{
42240266059SGregory Neil Shapiro 				debug->debug_level = s->ds_level;
42340266059SGregory Neil Shapiro 				goto initialized;
42440266059SGregory Neil Shapiro 			}
42540266059SGregory Neil Shapiro 		}
42640266059SGregory Neil Shapiro 		debug->debug_level = 0;
42740266059SGregory Neil Shapiro 	initialized:
42840266059SGregory Neil Shapiro 		debug->debug_next = SmDebugInitialized;
42940266059SGregory Neil Shapiro 		SmDebugInitialized = debug;
43040266059SGregory Neil Shapiro 	}
43140266059SGregory Neil Shapiro 	return (int) debug->debug_level;
43240266059SGregory Neil Shapiro }
43340266059SGregory Neil Shapiro 
43440266059SGregory Neil Shapiro /*
43540266059SGregory Neil Shapiro **  SM_DEBUG_LOADACTIVE -- Activation level reached?
43640266059SGregory Neil Shapiro **
43740266059SGregory Neil Shapiro **	Parameters:
43840266059SGregory Neil Shapiro **		debug -- debug object.
43940266059SGregory Neil Shapiro **		level -- level to check.
44040266059SGregory Neil Shapiro **
44140266059SGregory Neil Shapiro **	Returns:
44240266059SGregory Neil Shapiro **		true iff the activation level of the specified debug
44340266059SGregory Neil Shapiro **			object >= level.
44440266059SGregory Neil Shapiro **
44540266059SGregory Neil Shapiro **	Side Effects:
44640266059SGregory Neil Shapiro **		Ensures that the debug object is initialized.
44740266059SGregory Neil Shapiro */
44840266059SGregory Neil Shapiro 
44940266059SGregory Neil Shapiro bool
sm_debug_loadactive(debug,level)45040266059SGregory Neil Shapiro sm_debug_loadactive(debug, level)
45140266059SGregory Neil Shapiro 	SM_DEBUG_T *debug;
45240266059SGregory Neil Shapiro 	int level;
45340266059SGregory Neil Shapiro {
45440266059SGregory Neil Shapiro 	return sm_debug_loadlevel(debug) >= level;
45540266059SGregory Neil Shapiro }
456