138032Speter/*
2261363Sgshapiro * Copyright (c) 1998-2001 Proofpoint, Inc. and its suppliers.
364562Sgshapiro *	All rights reserved.
438032Speter * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
538032Speter * Copyright (c) 1988, 1993
638032Speter *	The Regents of the University of California.  All rights reserved.
738032Speter *
838032Speter * By using this file, you agree to the terms and conditions set
938032Speter * forth in the LICENSE file which can be found at the top level of
1038032Speter * the sendmail distribution.
1138032Speter *
1238032Speter */
1338032Speter
1464562Sgshapiro#include <sendmail.h>
1590792Sgshapiro#include <sm/debug.h>
1690792Sgshapiro#include <sm/string.h>
1738032Speter
18266692SgshapiroSM_RCSID("@(#)$Id: trace.c,v 8.39 2013-11-22 20:51:57 ca Exp $")
1990792Sgshapiro
2090792Sgshapirostatic char	*tTnewflag __P((char *));
2190792Sgshapirostatic char	*tToldflag __P((char *));
2290792Sgshapiro
2338032Speter/*
2438032Speter**  TtSETUP -- set up for trace package.
2538032Speter**
2638032Speter**	Parameters:
2738032Speter**		vect -- pointer to trace vector.
2838032Speter**		size -- number of flags in trace vector.
2938032Speter**		defflags -- flags to set if no value given.
3038032Speter**
3138032Speter**	Returns:
3238032Speter**		none
3338032Speter**
3438032Speter**	Side Effects:
3538032Speter**		environment is set up.
3638032Speter*/
3738032Speter
3890792Sgshapirostatic unsigned char	*tTvect;
3990792Sgshapirostatic unsigned int	tTsize;
4038032Speterstatic char	*DefFlags;
4138032Speter
4238032Spetervoid
4338032SpetertTsetup(vect, size, defflags)
4490792Sgshapiro	unsigned char *vect;
4590792Sgshapiro	unsigned int size;
4638032Speter	char *defflags;
4738032Speter{
4838032Speter	tTvect = vect;
4938032Speter	tTsize = size;
5038032Speter	DefFlags = defflags;
5138032Speter}
5290792Sgshapiro
5390792Sgshapiro/*
5490792Sgshapiro**  tToldflag -- process an old style trace flag
5538032Speter**
5638032Speter**	Parameters:
5790792Sgshapiro**		s -- points to a [\0, \t] terminated string,
5890792Sgshapiro**		     and the initial character is a digit.
5938032Speter**
6038032Speter**	Returns:
6190792Sgshapiro**		pointer to terminating [\0, \t] character
6238032Speter**
6338032Speter**	Side Effects:
6490792Sgshapiro**		modifies tTvect
6538032Speter*/
6638032Speter
6790792Sgshapirostatic char *
6890792SgshapirotToldflag(s)
6938032Speter	register char *s;
7038032Speter{
7182017Sgshapiro	unsigned int first, last;
7238032Speter	register unsigned int i;
7338032Speter
7490792Sgshapiro	/* find first flag to set */
7590792Sgshapiro	i = 0;
7690792Sgshapiro	while (isascii(*s) && isdigit(*s) && i < tTsize)
7790792Sgshapiro		i = i * 10 + (*s++ - '0');
7838032Speter
7990792Sgshapiro	/*
8090792Sgshapiro	**  skip over rest of a too large number
8190792Sgshapiro	**  Maybe we should complain if out-of-bounds values are used.
8290792Sgshapiro	*/
8390792Sgshapiro
8490792Sgshapiro	while (isascii(*s) && isdigit(*s) && i >= tTsize)
8590792Sgshapiro		s++;
8690792Sgshapiro	first = i;
8790792Sgshapiro
8890792Sgshapiro	/* find last flag to set */
8990792Sgshapiro	if (*s == '-')
9038032Speter	{
9138032Speter		i = 0;
9290792Sgshapiro		while (isascii(*++s) && isdigit(*s) && i < tTsize)
9390792Sgshapiro			i = i * 10 + (*s - '0');
9482017Sgshapiro
9590792Sgshapiro		/* skip over rest of a too large number */
9682017Sgshapiro		while (isascii(*s) && isdigit(*s) && i >= tTsize)
9782017Sgshapiro			s++;
9890792Sgshapiro	}
9990792Sgshapiro	last = i;
10038032Speter
10190792Sgshapiro	/* find the level to set it to */
10290792Sgshapiro	i = 1;
10390792Sgshapiro	if (*s == '.')
10490792Sgshapiro	{
10590792Sgshapiro		i = 0;
10690792Sgshapiro		while (isascii(*++s) && isdigit(*s))
10790792Sgshapiro			i = i * 10 + (*s - '0');
10890792Sgshapiro	}
10982017Sgshapiro
11090792Sgshapiro	/* clean up args */
11190792Sgshapiro	if (first >= tTsize)
11290792Sgshapiro		first = tTsize - 1;
11390792Sgshapiro	if (last >= tTsize)
11490792Sgshapiro		last = tTsize - 1;
11538032Speter
11690792Sgshapiro	/* set the flags */
11790792Sgshapiro	while (first <= last)
11890792Sgshapiro		tTvect[first++] = (unsigned char) i;
11990792Sgshapiro
12090792Sgshapiro	/* skip trailing junk */
12190792Sgshapiro	while (*s != '\0' && *s != ',' && *s != ' ' && *s != '\t')
12290792Sgshapiro		++s;
12390792Sgshapiro
12490792Sgshapiro	return s;
12590792Sgshapiro}
12690792Sgshapiro
12790792Sgshapiro/*
12890792Sgshapiro**  tTnewflag -- process a new style trace flag
12990792Sgshapiro**
13090792Sgshapiro**	Parameters:
13190792Sgshapiro**		s -- Points to a non-empty [\0, \t] terminated string,
13290792Sgshapiro**		     of which the initial character is not a digit.
13390792Sgshapiro**
13490792Sgshapiro**	Returns:
13590792Sgshapiro**		pointer to terminating [\0, \t] character
13690792Sgshapiro**
13790792Sgshapiro**	Side Effects:
13890792Sgshapiro**		adds trace flag to libsm debug database
13990792Sgshapiro*/
14090792Sgshapiro
14190792Sgshapirostatic char *
14290792SgshapirotTnewflag(s)
14390792Sgshapiro	register char *s;
14490792Sgshapiro{
14590792Sgshapiro	char *pat, *endpat;
14690792Sgshapiro	int level;
14790792Sgshapiro
14890792Sgshapiro	pat = s;
14990792Sgshapiro	while (*s != '\0' && *s != ',' && *s != ' ' && *s != '\t' && *s != '.')
15090792Sgshapiro		++s;
15190792Sgshapiro	endpat = s;
15290792Sgshapiro	if (*s == '.')
15390792Sgshapiro	{
15490792Sgshapiro		++s;
15590792Sgshapiro		level = 0;
15690792Sgshapiro		while (isascii(*s) && isdigit(*s))
15738032Speter		{
15890792Sgshapiro			level = level * 10 + (*s - '0');
15990792Sgshapiro			++s;
16038032Speter		}
16190792Sgshapiro		if (level < 0)
16290792Sgshapiro			level = 0;
16390792Sgshapiro	}
16490792Sgshapiro	else
16590792Sgshapiro	{
16690792Sgshapiro		level = 1;
16790792Sgshapiro	}
16838032Speter
16990792Sgshapiro	sm_debug_addsetting_x(sm_strndup_x(pat, endpat - pat), level);
17038032Speter
17190792Sgshapiro	/* skip trailing junk */
17290792Sgshapiro	while (*s != '\0' && *s != ',' && *s != ' ' && *s != '\t')
17390792Sgshapiro		++s;
17438032Speter
17590792Sgshapiro	return s;
17690792Sgshapiro}
17790792Sgshapiro
17890792Sgshapiro/*
17990792Sgshapiro**  TtFLAG -- process an external trace flag list.
18090792Sgshapiro**
18190792Sgshapiro**	Parameters:
18290792Sgshapiro**		s -- the trace flag.
18390792Sgshapiro**
18490792Sgshapiro**		The syntax of a trace flag list is as follows:
18590792Sgshapiro**
18690792Sgshapiro**		<flags> ::= <flag> | <flags> "," <flag>
18790792Sgshapiro**		<flag> ::= <categories> | <categories> "." <level>
18890792Sgshapiro**		<categories> ::= <int> | <int> "-" <int> | <pattern>
18990792Sgshapiro**		<pattern> ::= <an sh glob pattern matching a C identifier>
19090792Sgshapiro**
19190792Sgshapiro**		White space is ignored before and after a flag.
19290792Sgshapiro**		However, note that we skip over anything we don't
19390792Sgshapiro**		understand, rather than report an error.
19490792Sgshapiro**
19590792Sgshapiro**	Returns:
19690792Sgshapiro**		none.
19790792Sgshapiro**
19890792Sgshapiro**	Side Effects:
19990792Sgshapiro**		sets/clears old-style trace flags.
20090792Sgshapiro**		registers new-style trace flags with the libsm debug package.
20190792Sgshapiro*/
20290792Sgshapiro
20390792Sgshapirovoid
20490792SgshapirotTflag(s)
20590792Sgshapiro	register char *s;
20690792Sgshapiro{
207110560Sgshapiro	if (s == NULL || *s == '\0')
20890792Sgshapiro		s = DefFlags;
20990792Sgshapiro
21090792Sgshapiro	for (;;)
21190792Sgshapiro	{
21290792Sgshapiro		if (*s == '\0')
21338032Speter			return;
21490792Sgshapiro		if (*s == ',' || *s == ' ' || *s == '\t')
21590792Sgshapiro		{
21690792Sgshapiro			++s;
21790792Sgshapiro			continue;
21890792Sgshapiro		}
21990792Sgshapiro		if (isascii(*s) && isdigit(*s))
22090792Sgshapiro			s = tToldflag(s);
22190792Sgshapiro		else
22290792Sgshapiro			s = tTnewflag(s);
22338032Speter	}
22438032Speter}
225