ftp.nice.ch/pub/next/unix/network/system/gated.2.1pl2.NI.bs.tar.gz#/gated-2.1/src/trace.c

This is trace.c in view mode; [Download] [Up]

/*
 *  $Header: /disk/d/src/devel/gated/dist/src/RCS/trace.c,v 2.1 92/02/24 14:13:07 jch Exp $
 */

/*%Copyright%*/
/************************************************************************
*									*
*	GateD, Release 2						*
*									*
*	Copyright (c) 1990,1991,1992 by Cornell University		*
*	    All rights reserved.					*
*									*
*	THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY		*
*	EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT		*
*	LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY		*
*	AND FITNESS FOR A PARTICULAR PURPOSE.				*
*									*
*	Royalty-free licenses to redistribute GateD Release		*
*	2 in whole or in part may be obtained by writing to:		*
*									*
*	    GateDaemon Project						*
*	    Information Technologies/Network Resources			*
*	    143 Caldwell Hall						*
*	    Cornell University						*
*	    Ithaca, NY 14853-2602					*
*									*
*	GateD is based on Kirton's EGP, UC Berkeley's routing		*
*	daemon	 (routed), and DCN's HELLO routing Protocol.		*
*	Development of Release 2 has been supported by the		*
*	National Science Foundation.					*
*									*
*	Please forward bug fixes, enhancements and questions to the	*
*	gated mailing list: gated-people@gated.cornell.edu.		*
*									*
*	Authors:							*
*									*
*		Jeffrey C Honig <jch@gated.cornell.edu>			*
*		Scott W Brim <swb@gated.cornell.edu>			*
*									*
*************************************************************************
*									*
*      Portions of this software may fall under the following		*
*      copyrights:							*
*									*
*	Copyright (c) 1988 Regents of the University of California.	*
*	All rights reserved.						*
*									*
*	Redistribution and use in source and binary forms are		*
*	permitted provided that the above copyright notice and		*
*	this paragraph are duplicated in all such forms and that	*
*	any documentation, advertising materials, and other		*
*	materials related to such distribution and use			*
*	acknowledge that the software was developed by the		*
*	University of California, Berkeley.  The name of the		*
*	University may not be used to endorse or promote		*
*	products derived from this software without specific		*
*	prior written permission.  THIS SOFTWARE IS PROVIDED		*
*	``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,	*
*	INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF	*
*	MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.		*
*									*
************************************************************************/


#include "include.h"
#if	defined(_IBMR2)
#include <time.h>
#endif				/* defined(_IBMR2) */
#include <sys/time.h>
#ifndef vax11c
#include <sys/file.h>
#include <sys/stat.h>
#endif				/* vax11c */

flag_t trace_flags;			/* log errors, route changes &/or packets */
flag_t trace_flags_save;		/* save trace flags */
char *trace_file = NULL;		/* File to trace to */
static FILE *trace_FILE = NULL;
static char trace_buffer[BUFSIZ];

static const char *month_names[12] =
{
    "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

bits trace_types[] =
{
    {TR_INT | TR_EXT | TR_RT, "general"},
    {TR_ALL, "all"},
    {TR_INT, "internal"},
    {TR_EXT, "external"},
    {TR_RT, "route"},
    {TR_PARSE, "parse"},
    {TR_CONFIG, "config"},
    {TR_LEX, "lex"},
#ifdef	PROTO_EGP
    {TR_EGP, "egp"},
#endif				/* PROTO_EGP */
    {TR_UPDATE, "update"},
#ifdef	PROTO_RIP
    {TR_RIP, "rip"},
#endif				/* PROTO_RIP */
#ifdef	PROTO_HELLO
    {TR_HELLO, "hello"},
#endif				/* PROTO_HELLO */
#ifdef	PROTO_ICMP
    {TR_ICMP, "icmp"},
#endif				/* PROTO_ICMP */
    {TR_TASK, "task"},
    {TR_TIMER, "timer"},
    {TR_NOSTAMP, "nostamp"},
    {TR_MARK, "mark"},
    {TR_PROTOCOL, "protocol"},
    {TR_KRT, "kernel"},
#ifdef	PROTO_OSPF
    {TR_OSPF, "ospf"},
#endif				/* PROTO_OSPF */
#ifdef	PROTO_IGRP
    {TR_IGRP, "igrp"},
#endif				/* PROTO_IGRP */
#ifdef	PROTO_BGP
    {TR_BGP, "bgp"},
#endif				/* PROTO_BGP */
#if	defined(AGENT_SNMP)
    {TR_SNMP, "snmp"},
#endif				/* defined(AGENT_SNMP) */
    {0, 0}
};


/*
 *	Display trace options enabled
 */
void
trace_display(tr_flags)
flag_t tr_flags;
{

    trace(TR_ALL, 0, NULL);
    trace(TR_ALL, 0, "Tracing flags enabled: %s", tr_flags ? trace_bits(trace_types, tr_flags) : "none");
    trace(TR_ALL, 0, NULL);
}


/*
 * Turn off tracing.
 */
void
trace_off()
{
    if (!trace_flags) {
	return;
    }
    if (trace_FILE != NULL) {
	trace(TR_ALL, 0, NULL);
	trace(TR_ALL, LOG_NOTICE, "Tracing to \"%s\" suspended", trace_file ? trace_file : "(stdout)");
	trace(TR_ALL, 0, NULL);
	trace_flags = 0;
	(void) fclose(trace_FILE);
	trace_FILE = NULL;
    }
    return;
}


/*
 * Close trace file
 */
void
trace_close()
{
    if (trace_FILE != NULL) {
	trace_flags = 0;
	(void) fclose(trace_FILE);
	trace_FILE = NULL;
    }
    return;
}


/*
 * Turn on tracing.
 */
void
trace_on(file, append)
char *file;
int append;
{
#ifndef vax11c
    struct stat stbuf;

#endif				/* vax11c */

    if (file == NULL) {
	trace_FILE = stdout;
    } else {
	if (trace_FILE == NULL) {
#ifndef vax11c
	    if (stat(file, &stbuf)) {
		if (errno != ENOENT) {
		    trace(TR_ALL, LOG_ERR, "trace_on: stat(%s): %m", file);
		    return;
		}
	    } else if ((stbuf.st_mode & S_IFMT) != S_IFREG) {
		trace(TR_ALL, LOG_ERR, "trace_on: \"%s\" is not a regular file", file);
		return;
	    }
#endif				/* vax11c */
	    if ((trace_FILE = fopen(file, append ? "a" : "w")) == NULL) {
		trace(TR_ALL, LOG_ERR, "trace_on: open(%s): %m", file);
		return;
	    }
	}
#ifndef vax11c
	setlinebuf(trace_FILE);
#endif				/* vax11c */
	trace(TR_ALL, LOG_ERR, "tracing to \"%s\" started", file ? file : "(stdout)");
    }

    trace_flags = trace_flags_save;
    trace_display(trace_flags);
}


/*
 *  Parse trace flags specified on the command line
 */
flag_t
trace_args(flag)
char *flag;
{
    int tr_flags = 0, new_trace;
    struct chars {
	u_int c_bits;
	char c_char;
    } *p;
    static struct chars trace_chars[] =
    {
	{TR_INT, 'i'},
	{TR_EXT, 'e'},
	{TR_RT, 'r'},
#ifdef	PROTO_EGP
	{TR_EGP, 'p'},
#endif				/* PROTO_EGP */
	{TR_UPDATE, 'u'},
	{TR_PROTOCOL, 'P'},
	{TR_ALL, 'A'},
	{TR_TASK | TR_TIMER, 'T'},
#ifdef	PROTO_ICMP
	{TR_ICMP, 'C'},
#endif				/* PROTO_ICMP */
	{TR_MARK, 'm'},
	{TR_NOSTAMP, 't'},
#ifdef	PROTO_RIP
	{TR_RIP, 'R'},
#endif				/* PROTO_RIP */
#ifdef	PROTO_HELLO
	{TR_HELLO, 'H'},
#endif				/* PROTO_HELLO */
#ifdef	PROTO_OSPF
	{TR_OSPF, 'O'},
#endif				/* PROTO_OSPF */
#ifdef	PROTO_IGRP
	{TR_IGRP, 'G'},
#endif				/* PROTO_IGRP */
	{TR_KRT, 'k'},
#ifdef	PROTO_BGP
	{TR_BGP, 'B'},
#endif				/* PROTO_BGP */
#if	defined(AGENT_SNMP)
	{TR_SNMP, 'M'},
#endif				/* defined(AGENT_SNMP) */
	{0, (char) 0}};


    if (*flag == (char) 0) {
	return (TR_GEN);
    }
    for (; *flag; flag++) {
	new_trace = 0;
	for (p = trace_chars; p->c_bits; p++) {
	    if (*flag == p->c_char) {
		new_trace = p->c_bits;
		break;
	    }
	}
	if (!(new_trace)) {
	    (void) fprintf(stderr, "%s: unknown trace flag: %c\n", my_name, *flag);
	} else {
	    tr_flags |= new_trace;
	}
    }
    return (tr_flags);
}


char *
trace_bits(bp, mask)
bits *bp;
flag_t mask;
{
    static char string[BUFSIZ];
    int first = TRUE;
    bits *p;

    *string = (char) 0;

    for (p = bp; p->t_bits; p++) {
	if ((mask & p->t_bits) == p->t_bits) {
	    if (first) {
		first = FALSE;
	    } else {
		(void) strcat(string, " ");
	    }
	    (void) strcat(string, p->t_name);
	}
    }

    return (string);
}


#ifndef	trace_state
char *
trace_state(bp, mask)
bits *bp;
flag_t mask;
{

    return (bp[mask].t_name);
}

#endif				/* trace_state */

/*
 *  Dump everything
 */
static void
trace_do_dump()
{
    FILE *fd;

    if ((fd = fopen(DUMPFILE, "a")) <= (FILE *) 0) {
	trace(TR_ALL, LOG_ERR, "trace_dump: %m");
	return;
    }
#ifndef vax11c
    setlinebuf(fd);
#endif				/* vax11c */
    trace(TR_ALL, LOG_NOTICE, "trace_dump: processing dump to %s", DUMPFILE);
    (void) fprintf(fd, "\f\n\t%s[%d] version %s memory dump on %s at %s\n", my_name, my_mpid, version, my_hostname, time_full);
    if (version_kernel) {
	(void) fprintf(fd, "\t\t%s\n\n", version_kernel);
    }
    /* Task_dump dumps all protocols */
    task_dump(fd);

    (void) fflush(fd);
    (void) fclose(fd);
    trace(TR_ALL, LOG_NOTICE, "trace_dump: dump completed to %s", DUMPFILE);
}


#ifndef	NO_FORK
static task *trace_dump_task;		/* Pointer to the dump task */

static void
trace_dump_done(tp)
task *tp;
{
    trace_dump_task = (task *) 0;
    task_delete(tp);
}

#endif				/* NO_FORK */


void
trace_dump(now)
int now;
{

#ifndef	NO_FORK
    if (trace_dump_task) {
	trace(TR_ALL, LOG_ERR, "trace_dump: %s already active",
	      task_name(trace_dump_task));
    } else if (now) {
	trace_do_dump();
    } else {
	trace_dump_task = task_alloc("TraceDump");
	trace_dump_task->task_child = trace_dump_done;
	trace_dump_task->task_process = trace_do_dump;
	if (!task_fork(trace_dump_task)) {
	    quit(EINVAL);
	}
    }
#else				/* NO_FORK */
    trace_do_dump();
#endif				/* NO_FORK */
}


/*ARGSUSED*/
void
trace_mark(tp)
task *tp;
{
    struct tm *tm;

    tm = localtime(&time_sec);
    trace(TR_MARK | TR_NOSTAMP, 0, "%s %2d %02d:%02d:%02d MARK",
	  month_names[tm->tm_mon], tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);

    return;
}


/*
 *	Trace to the log and syslog
 */
#ifdef	STDARG
/*VARARGS2*/
void
trace(flag_t flags, int pri, const char *fmt,...)
#else				/* STDARG */
/*ARGSUSED*/
/*VARARGS0*/
void
trace(va_alist)
va_dcl

#endif				/* STDARG */
{
    struct tm *tm;
    char time_buffer[BUFSIZ];
    va_list args;

#ifdef	STDARG

    va_start(args, fmt);
#else				/* STDARG */
    int flags, pri;
    u_char *fmt;

    va_start(args);

    flags = va_arg(args, int);
    pri = va_arg(args, int);
    fmt = va_arg(args, u_char *);
#endif				/* STDARG */

    if (fmt && *fmt) {
	(void) vsprintf(&trace_buffer[strlen((char *) trace_buffer)], fmt, &args);
    }
    va_end(args);

#ifdef	vax11c
    if (trace_FILE && (trace_FILE != sstdout)) {
#endif	/* vax11c */
	if ((trace_flags & flags) & ~TR_NOSTAMP) {
	    *time_buffer = 0;
	    if (!((trace_flags | flags) & TR_NOSTAMP)) {
		tm = localtime(&time_sec);
		(void) sprintf(time_buffer, "%s %2d %02d:%02d:%02d ",
			       month_names[tm->tm_mon], tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
	    }
	    if (my_mpid != my_pid) {
		(void) sprintf(&time_buffer[strlen(time_buffer)], "[%d] ",
			       my_pid);
	    }
	    if (*time_buffer) {
		(void) fputs(time_buffer, trace_FILE);
	    }
	    (void) fputs((char *) trace_buffer, trace_FILE);
	    (void) fputc('\n', trace_FILE);
	}
	if (pri && !test_flag) {
	    syslog(pri, (char *) trace_buffer);
	}
#ifdef	vax11c
    } else {
	if (((trace_flags & flags) & ~TR_NOSTAMP) || (pri && !test_flag))
	    syslog(pri, (char *) trace_buffer);
    }
#endif	/* vax11c */
    trace_buffer[0] = (char) 0;
}


/*
 *	Prefill the trace buffer
 */
#ifdef	STDARG
/*VARARGS2*/
void
tracef(const char *fmt,...)
#else				/* STDARG */
/*ARGSUSED*/
/*VARARGS0*/
void
tracef(va_alist)
va_dcl

#endif				/* STDARG */
{
    va_list args;

#ifdef	STDARG

    va_start(args, fmt);
#else				/* STDARG */
    u_char *fmt;

    va_start(args);

    fmt = va_arg(args, u_char *);
#endif				/* STDARG */

    if (fmt && *fmt) {
	(void) vsprintf(&trace_buffer[strlen((char *) trace_buffer)], fmt, &args);
    }
    va_end(args);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.