/*
* Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sendmail.h>
#include <sm/debug.h>
#include <sm/string.h>
SM_RCSID("@(#)$Id: trace.c,v 8.37.4.1 2002/12/05 17:28:05 ca Exp $")
static char *tTnewflag __P((char *));
static char *tToldflag __P((char *));
/*
** TtSETUP -- set up for trace package.
**
** Parameters:
** vect -- pointer to trace vector.
** size -- number of flags in trace vector.
** defflags -- flags to set if no value given.
**
** Returns:
** none
**
** Side Effects:
** environment is set up.
*/
static unsigned char *tTvect;
static unsigned int tTsize;
static char *DefFlags;
void
tTsetup(vect, size, defflags)
unsigned char *vect;
unsigned int size;
char *defflags;
{
tTvect = vect;
tTsize = size;
DefFlags = defflags;
}
/*
** tToldflag -- process an old style trace flag
**
** Parameters:
** s -- points to a [\0, \t] terminated string,
** and the initial character is a digit.
**
** Returns:
** pointer to terminating [\0, \t] character
**
** Side Effects:
** modifies tTvect
*/
static char *
tToldflag(s)
register char *s;
{
unsigned int first, last;
register unsigned int i;
/* find first flag to set */
i = 0;
while (isascii(*s) && isdigit(*s) && i < tTsize)
i = i * 10 + (*s++ - '0');
/*
** skip over rest of a too large number
** Maybe we should complain if out-of-bounds values are used.
*/
while (isascii(*s) && isdigit(*s) && i >= tTsize)
s++;
first = i;
/* find last flag to set */
if (*s == '-')
{
i = 0;
while (isascii(*++s) && isdigit(*s) && i < tTsize)
i = i * 10 + (*s - '0');
/* skip over rest of a too large number */
while (isascii(*s) && isdigit(*s) && i >= tTsize)
s++;
}
last = i;
/* find the level to set it to */
i = 1;
if (*s == '.')
{
i = 0;
while (isascii(*++s) && isdigit(*s))
i = i * 10 + (*s - '0');
}
/* clean up args */
if (first >= tTsize)
first = tTsize - 1;
if (last >= tTsize)
last = tTsize - 1;
/* set the flags */
while (first <= last)
tTvect[first++] = (unsigned char) i;
/* skip trailing junk */
while (*s != '\0' && *s != ',' && *s != ' ' && *s != '\t')
++s;
return s;
}
/*
** tTnewflag -- process a new style trace flag
**
** Parameters:
** s -- Points to a non-empty [\0, \t] terminated string,
** of which the initial character is not a digit.
**
** Returns:
** pointer to terminating [\0, \t] character
**
** Side Effects:
** adds trace flag to libsm debug database
*/
static char *
tTnewflag(s)
register char *s;
{
char *pat, *endpat;
int level;
pat = s;
while (*s != '\0' && *s != ',' && *s != ' ' && *s != '\t' && *s != '.')
++s;
endpat = s;
if (*s == '.')
{
++s;
level = 0;
while (isascii(*s) && isdigit(*s))
{
level = level * 10 + (*s - '0');
++s;
}
if (level < 0)
level = 0;
}
else
{
level = 1;
}
sm_debug_addsetting_x(sm_strndup_x(pat, endpat - pat), level);
/* skip trailing junk */
while (*s != '\0' && *s != ',' && *s != ' ' && *s != '\t')
++s;
return s;
}
/*
** TtFLAG -- process an external trace flag list.
**
** Parameters:
** s -- the trace flag.
**
** The syntax of a trace flag list is as follows:
**
** <flags> ::= <flag> | <flags> "," <flag>
** <flag> ::= <categories> | <categories> "." <level>
** <categories> ::= <int> | <int> "-" <int> | <pattern>
** <pattern> ::= <an sh glob pattern matching a C identifier>
**
** White space is ignored before and after a flag.
** However, note that we skip over anything we don't
** understand, rather than report an error.
**
** Returns:
** none.
**
** Side Effects:
** sets/clears old-style trace flags.
** registers new-style trace flags with the libsm debug package.
*/
void
tTflag(s)
register char *s;
{
if (s == NULL || *s == '\0')
s = DefFlags;
for (;;)
{
if (*s == '\0')
return;
if (*s == ',' || *s == ' ' || *s == '\t')
{
++s;
continue;
}
if (isascii(*s) && isdigit(*s))
s = tToldflag(s);
else
s = tTnewflag(s);
}
}