1/*
2 * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.
3 *	All rights reserved.
4 * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
5 * Copyright (c) 1988, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * By using this file, you agree to the terms and conditions set
9 * forth in the LICENSE file which can be found at the top level of
10 * the sendmail distribution.
11 *
12 */
13
14#pragma ident	"%Z%%M%	%I%	%E% SMI"
15
16#include <sendmail.h>
17#include <sm/debug.h>
18#include <sm/string.h>
19
20SM_RCSID("@(#)$Id: trace.c,v 8.37.4.1 2002/12/05 17:28:05 ca Exp $")
21
22static char	*tTnewflag __P((char *));
23static char	*tToldflag __P((char *));
24
25/*
26**  TtSETUP -- set up for trace package.
27**
28**	Parameters:
29**		vect -- pointer to trace vector.
30**		size -- number of flags in trace vector.
31**		defflags -- flags to set if no value given.
32**
33**	Returns:
34**		none
35**
36**	Side Effects:
37**		environment is set up.
38*/
39
40static unsigned char	*tTvect;
41static unsigned int	tTsize;
42static char	*DefFlags;
43
44void
45tTsetup(vect, size, defflags)
46	unsigned char *vect;
47	unsigned int size;
48	char *defflags;
49{
50	tTvect = vect;
51	tTsize = size;
52	DefFlags = defflags;
53}
54
55/*
56**  tToldflag -- process an old style trace flag
57**
58**	Parameters:
59**		s -- points to a [\0, \t] terminated string,
60**		     and the initial character is a digit.
61**
62**	Returns:
63**		pointer to terminating [\0, \t] character
64**
65**	Side Effects:
66**		modifies tTvect
67*/
68
69static char *
70tToldflag(s)
71	register char *s;
72{
73	unsigned int first, last;
74	register unsigned int i;
75
76	/* find first flag to set */
77	i = 0;
78	while (isascii(*s) && isdigit(*s) && i < tTsize)
79		i = i * 10 + (*s++ - '0');
80
81	/*
82	**  skip over rest of a too large number
83	**  Maybe we should complain if out-of-bounds values are used.
84	*/
85
86	while (isascii(*s) && isdigit(*s) && i >= tTsize)
87		s++;
88	first = i;
89
90	/* find last flag to set */
91	if (*s == '-')
92	{
93		i = 0;
94		while (isascii(*++s) && isdigit(*s) && i < tTsize)
95			i = i * 10 + (*s - '0');
96
97		/* skip over rest of a too large number */
98		while (isascii(*s) && isdigit(*s) && i >= tTsize)
99			s++;
100	}
101	last = i;
102
103	/* find the level to set it to */
104	i = 1;
105	if (*s == '.')
106	{
107		i = 0;
108		while (isascii(*++s) && isdigit(*s))
109			i = i * 10 + (*s - '0');
110	}
111
112	/* clean up args */
113	if (first >= tTsize)
114		first = tTsize - 1;
115	if (last >= tTsize)
116		last = tTsize - 1;
117
118	/* set the flags */
119	while (first <= last)
120		tTvect[first++] = (unsigned char) i;
121
122	/* skip trailing junk */
123	while (*s != '\0' && *s != ',' && *s != ' ' && *s != '\t')
124		++s;
125
126	return s;
127}
128
129/*
130**  tTnewflag -- process a new style trace flag
131**
132**	Parameters:
133**		s -- Points to a non-empty [\0, \t] terminated string,
134**		     of which the initial character is not a digit.
135**
136**	Returns:
137**		pointer to terminating [\0, \t] character
138**
139**	Side Effects:
140**		adds trace flag to libsm debug database
141*/
142
143static char *
144tTnewflag(s)
145	register char *s;
146{
147	char *pat, *endpat;
148	int level;
149
150	pat = s;
151	while (*s != '\0' && *s != ',' && *s != ' ' && *s != '\t' && *s != '.')
152		++s;
153	endpat = s;
154	if (*s == '.')
155	{
156		++s;
157		level = 0;
158		while (isascii(*s) && isdigit(*s))
159		{
160			level = level * 10 + (*s - '0');
161			++s;
162		}
163		if (level < 0)
164			level = 0;
165	}
166	else
167	{
168		level = 1;
169	}
170
171	sm_debug_addsetting_x(sm_strndup_x(pat, endpat - pat), level);
172
173	/* skip trailing junk */
174	while (*s != '\0' && *s != ',' && *s != ' ' && *s != '\t')
175		++s;
176
177	return s;
178}
179
180/*
181**  TtFLAG -- process an external trace flag list.
182**
183**	Parameters:
184**		s -- the trace flag.
185**
186**		The syntax of a trace flag list is as follows:
187**
188**		<flags> ::= <flag> | <flags> "," <flag>
189**		<flag> ::= <categories> | <categories> "." <level>
190**		<categories> ::= <int> | <int> "-" <int> | <pattern>
191**		<pattern> ::= <an sh glob pattern matching a C identifier>
192**
193**		White space is ignored before and after a flag.
194**		However, note that we skip over anything we don't
195**		understand, rather than report an error.
196**
197**	Returns:
198**		none.
199**
200**	Side Effects:
201**		sets/clears old-style trace flags.
202**		registers new-style trace flags with the libsm debug package.
203*/
204
205void
206tTflag(s)
207	register char *s;
208{
209	if (s == NULL || *s == '\0')
210		s = DefFlags;
211
212	for (;;)
213	{
214		if (*s == '\0')
215			return;
216		if (*s == ',' || *s == ' ' || *s == '\t')
217		{
218			++s;
219			continue;
220		}
221		if (isascii(*s) && isdigit(*s))
222			s = tToldflag(s);
223		else
224			s = tTnewflag(s);
225	}
226}
227