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