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