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
18 SM_RCSID("@(#)$Id: trace.c,v 8.39 2013-11-22 20:51:57 ca Exp $")
19
20 static char *tTnewflag __P((char *));
21 static 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
38 static unsigned char *tTvect;
39 static unsigned int tTsize;
40 static char *DefFlags;
41
42 void
tTsetup(vect,size,defflags)43 tTsetup(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
67 static char *
tToldflag(s)68 tToldflag(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
141 static char *
tTnewflag(s)142 tTnewflag(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
203 void
tTflag(s)204 tTflag(s)
205 register char *s;
206 {
207 if (SM_IS_EMPTY(s))
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