|
|
1.1 root 1: #include <stdio.h>
2: #include <sys/types.h>
3: #include <sys/stat.h>
4:
5: #define INTERVAL 60
6: #define STRSIZE 64
7: #define TABLESIZE 32
8: #define PRINTFARGS fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10
9: #define IDLECYCLE 1000
10:
11: static char *ControlFile = "TRACE";
12:
13: static struct TraceRange {
14: char srcfile[STRSIZE];
15: int from;
16: int to;
17: };
18: static int TableSize;
19: static struct TraceRange RangeTable[TABLESIZE];
20: static struct TraceRange Context[16];
21: static int ContextIndex;
22: static Calls;
23:
24: static FILE *Tty;
25: static char Device[STRSIZE];
26:
27: static void ifprintf( PRINTFARGS )
28: {
29: if( Tty ){
30: fprintf( Tty, PRINTFARGS );
31: fflush( Tty );
32: }
33: }
34:
35: #define SEMANTICS(text) { ifprintf( "Error: %s\n", text ); return 1; }
36:
37: static int RangeCmd( cmd )
38: char *cmd;
39: {
40: struct TraceRange r, x;
41:
42: switch( sscanf( cmd, "range %s %d %d", r.srcfile, &r.from, &r.to ) ){
43: case 2: r.to = r.from;
44: break;
45: case 3: break;
46: default:
47: return 0;
48: }
49: if( r.to < r.from ) { x = r; x.from = r.to; x.to = r.from; r = x; }
50: if( TableSize >= TABLESIZE ) SEMANTICS( "table overflow" );
51: RangeTable[TableSize++] = r;
52: return 1;
53: }
54:
55: static int DeviceCmd( cmd )
56: char *cmd;
57: {
58: if( sscanf( cmd, "device %s", Device ) != 1 ) return 0;
59: return 1;
60: }
61:
62: static void Commands(f)
63: FILE *f;
64: {
65: char cmd[STRSIZE];
66:
67: TableSize = 0;
68: strcpy( Device, "/dev/null" );
69: while( fgets( cmd, STRSIZE, f ) ){
70: ifprintf( "%s", cmd );
71: if( !RangeCmd(cmd) &&
72: !DeviceCmd(cmd) ) ifprintf( "Syntax Error\n" );
73: }
74: }
75:
76: static void Update()
77: {
78: static time_t modified;
79: FILE *f;
80: struct stat buf;
81: char shcmd[STRSIZE];
82:
83: ifprintf( "trace 831120\n" );
84: if( !(f = fopen( ControlFile, "r" ))) return;
85: fstat( fileno(f), &buf );
86: if( buf.st_mtime != modified ) Commands(f);
87: modified = buf.st_mtime;
88: fclose(f);
89: if( !strcmp( Device, "/dev/null") ){
90: if( Tty ) fclose( Tty );
91: Tty = 0;
92: return;
93: }
94: if( f = fopen( Device, "w" ) ){
95: if( Tty ) fclose( Tty );
96: Tty = f;
97: }
98: else ifprintf( "Cannot open: %s\n", Device );
99: }
100:
101: static void CheckTime(t)
102: long t;
103: {
104: static timestamp;
105:
106: if( t > timestamp+INTERVAL ){
107: Update();
108: timestamp = t;
109: }
110: }
111:
112: static int ContextSelected()
113: {
114: int i, line, from, to;
115:
116: for( i = 0; i < TableSize; ++i )
117: if( !strcmp(Context[ContextIndex].srcfile, RangeTable[i].srcfile) ){
118: line = Context[ContextIndex].from;
119: from = RangeTable[i].from;
120: to = RangeTable[i].to;
121: if( line>=from && line<=to ) return 1;
122: if( -line>=from && -line<=to ) return 0;
123: }
124: return 0;
125: }
126:
127: static TraceArgs( PRINTFARGS )
128: {
129: char mmss[32];
130: long time(), t = time(0L);
131: char *ctime();
132:
133: --ContextIndex;
134: CheckTime(t);
135: if( !Tty || !ContextSelected() ) return 0;
136: strcpy( mmss, &ctime(&t)[14]); /* "Sun Sep 16 01:03:52 1973\n\0" */
137: mmss[5] = '\0';
138: fprintf(Tty, "%d %s %s:%d ",
139: Calls, mmss, Context[ContextIndex].srcfile, Context[ContextIndex].from);
140: fprintf( Tty, PRINTFARGS );
141: fputc( '\n', Tty );
142: fflush( Tty );
143: return 1;
144: }
145:
146: typedef int (*PFI)();
147:
148: static long *watchloc, watchval;
149:
150: PFI trace_fcn( srcfile, line )
151: char *srcfile;
152: {
153: static idle;
154:
155: ++Calls;
156: if( !Tty && idle ){
157: idle = (idle+1)%IDLECYCLE;
158: return 0;
159: }
160: if( watchloc && watchval!=*watchloc ){
161: ifprintf(Tty, "!!!!!!! %s:%d *%d: %d -> %d\n",
162: srcfile, line, watchloc, watchval, *watchloc );
163: watchval = *watchloc;
164: }
165: strncpy( Context[ContextIndex].srcfile, srcfile, STRSIZE );
166: Context[ContextIndex].to = Context[ContextIndex].from = line;
167: ++ContextIndex;
168: return TraceArgs;
169: }
170:
171: watch(loc)
172: long *loc;
173: {
174: if( watchloc = loc ){
175: watchval = *watchloc;
176: ifprintf(Tty, "watching *%d = %d\n", watchloc, watchval );
177: }
178: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.