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.