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
20 SM_RCSID("@(#)$Id: trace.c,v 8.37.4.1 2002/12/05 17:28:05 ca Exp $")
21
22 static char *tTnewflag __P((char *));
23 static 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
40 static unsigned char *tTvect;
41 static unsigned int tTsize;
42 static char *DefFlags;
43
44 void
tTsetup(vect,size,defflags)45 tTsetup(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
69 static char *
tToldflag(s)70 tToldflag(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
143 static char *
tTnewflag(s)144 tTnewflag(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
205 void
tTflag(s)206 tTflag(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