|
|
1.1 root 1: /*
2: * stream tracer
3: */
4:
5: #include "trc.h"
6: #if NTRC > 0
7: #include "../h/param.h"
8: #include "../h/stream.h"
9: #include "../h/ioctl.h"
10: #include "../h/conf.h"
11: #include "../h/strace.h"
12:
13:
14: extern int nulldev();
15:
16: struct trc trc[NTRC];
17:
18: int trcclose(), /* queue close routine */
19: trcopen(), /* queue open routine */
20: trcput(); /* queue put routine */
21:
22: static struct qinit rinit = { trcput, nulldev, trcopen, trcclose, 300, 0 },
23: winit = { trcput, nulldev, trcopen, trcclose, 300, 200 };
24: struct streamtab trcinfo = { &rinit, &winit };
25:
26:
27: trcclose (q)
28: register struct queue *q;
29: {
30: register struct trc *tr = (struct trc *) q->ptr;
31:
32: trcupdate (q);
33: trcupdate (WR (q));
34: tr->tr_state = 0;
35: printf ("%s: close\n", tr->tr_name);
36: return;
37: }
38:
39:
40: /*
41: * I/O control operations.
42: * Process request and return nonzero iff request is for us.
43: */
44:
45: trcioctl (q, b)
46: register struct queue *q;
47: register struct block *b;
48: {
49: register struct trc *tr = (struct trc *) q->ptr;
50: register struct trcioc *ioc = (struct trcioc *) b->rptr;
51:
52: switch (ioc->command) {
53:
54: /*
55: * get name
56: */
57: case TRCGNAME:
58: bcopy (tr->tr_name, ioc->arg.name, TR_NAME-1);
59: printf ("%s: get name %d\n", tr->tr_name, tr-trc);
60: b->wptr = b->rptr + sizeof (int) + TR_NAME - 1;
61: break;
62:
63: /*
64: * set name
65: */
66: case TRCSNAME:
67: bcopy (ioc->arg.name, tr->tr_name, TR_NAME-1);
68: tr->tr_name[TR_NAME-1] = '\0';
69: printf ("%s: set name %d\n", tr->tr_name, tr-trc);
70: b->wptr = b->rptr;
71: break;
72:
73: /*
74: * get block type trace mask
75: */
76: case TRCGMASK:
77: ioc->arg.mask = tr->tr_mask;
78: printf ("%s: get mask 0x%x\n", tr->tr_name, tr->tr_mask);
79: b->wptr = b->rptr + 2 * sizeof (int);
80: break;
81:
82: /*
83: * set block type trace mask
84: */
85: case TRCSMASK:
86: tr->tr_mask = ioc->arg.mask;
87: printf ("%s: set mask 0x%x\n", tr->tr_name, tr->tr_mask);
88: b->wptr = b->rptr;
89: break;
90:
91: default:
92: return (0);
93: }
94:
95: b->type = M_IOCACK;
96: qreply (q, b);
97: return (1);
98: }
99:
100:
101: /*ARGSUSED*/
102:
103: int
104: trcopen (q, dev)
105: register struct queue *q;
106: int dev;
107: {
108: register struct trc *tr;
109:
110: if (q->ptr)
111: return (1); /* already attached */
112:
113: for (tr = trc; tr->tr_state & TR_USE; tr++)
114: if (tr >= &trc[NTRC-1])
115: return (0);
116:
117: WR (q)->ptr = q->ptr = (caddr_t) tr;
118:
119: tr->tr_state = TR_USE;
120: tr->tr_mask = ~0; /* trace all block types */
121: bcopy ("trc", tr->tr_name, 4);
122: trcupdate (q);
123: trcupdate (WR (q));
124: printf ("trc: open %d\n", tr-trc);
125:
126: return (1);
127: }
128:
129:
130: trcprb (b)
131: register struct block *b;
132: {
133: u_char buf[1+4+4*64]; /* 64 is max # bytes in a block */
134: register u_char *nl, *s, *t, *u;
135: register int c;
136:
137: for (s = b->rptr, t = b->wptr, nl = u = buf; s < t; s++) {
138: if ((c = *s) & 0x80) {
139: *u++ = 'M';
140: *u++ = '-';
141: c &= ~0x80;
142: }
143: if (c == 0x7f) {
144: *u++ = '^';
145: c = '?';
146: }
147: else if (c < ' ') {
148: *u++ = '^';
149: c += '@';
150: }
151: *u++ = c;
152: if (u - nl > 64)
153: *(nl = u++) = '\n';
154: }
155:
156: *u = '\0';
157: printf ("%s", buf);
158: return;
159: }
160:
161:
162: #define trcpr(x) printf ("%s: %s %d bytes: %s", tr->tr_name, \
163: rw, b->wptr-b->rptr, x)
164:
165: trcprint (q, b)
166: register struct queue *q;
167: register struct block *b;
168: {
169: register struct trc *tr = (struct trc *) q->ptr;
170: register char *rw = q->flag & QREADR ? "read" : "write";
171:
172: switch (b->type) {
173: case M_ACK:
174: if (tr->tr_mask & TR_ACK)
175: trcpr ("M_ACK\n");
176: break;
177: case M_BREAK:
178: if (tr->tr_mask & TR_BREAK)
179: trcpr ("M_BREAK\n");
180: break;
181: case M_CLOSE:
182: if (tr->tr_mask & TR_CLOSE)
183: trcpr ("M_CLOSE\n");
184: break;
185: case M_CTL:
186: if (tr->tr_mask & TR_CTL)
187: trcpr ("M_CTL\n");
188: break;
189: case M_DATA:
190: if (tr->tr_mask & TR_DATA)
191: trcpr ("M_DATA: ``"), trcprb (b), printf ("''\n");
192: break;
193: case M_DELAY:
194: if (tr->tr_mask & TR_DELAY)
195: trcpr ("M_DELAY"), printf (": %d\n", (int) *b->rptr);
196: break;
197: case M_DELIM:
198: if (tr->tr_mask & TR_DELIM)
199: trcpr ("M_DELIM\n");
200: break;
201: case M_ECHO:
202: if (tr->tr_mask & TR_ECHO)
203: trcpr ("M_ECHO: ``"), trcprb (b), printf ("''\n");
204: break;
205: case M_FLUSH:
206: if (tr->tr_mask & TR_FLUSH)
207: trcpr ("M_FLUSH\n");
208: break;
209: case M_HANGUP:
210: if (tr->tr_mask & TR_HANGUP)
211: trcpr ("M_HANGUP\n");
212: break;
213: case M_IOCACK:
214: if (tr->tr_mask & TR_IOCACK)
215: trcpr ("M_IOCACK\n");
216: break;
217: case M_IOCNAK:
218: if (tr->tr_mask & TR_IOCNAK)
219: trcpr ("M_IOCNAK\n");
220: break;
221: case M_IOCTL:
222: if (tr->tr_mask & TR_IOCTL) {
223: register int l = * (int *) b->rptr, h = l>>8;
224:
225: trcpr ("M_IOCTL");
226: if (h >= ' ' && h < '\177')
227: printf (": ('%c'<<8)|%d\n", h, l & 0xff);
228: else printf (": 0x%x\n", l);
229: }
230: break;
231: case M_SIGNAL:
232: if (tr->tr_mask & TR_SIGNAL)
233: trcpr ("M_SIGNAL"), printf (": %d\n", (int) *b->rptr);
234: break;
235: case M_START:
236: if (tr->tr_mask & TR_START)
237: trcpr ("M_START\n");
238: break;
239: case M_STOP:
240: if (tr->tr_mask & TR_STOP)
241: trcpr ("M_STOP\n");
242: break;
243: default:
244: trcpr ("BAD BLOCK"), printf (": type %d\n", b->type);
245: break;
246: }
247: return;
248: }
249:
250:
251: /*
252: * Reader/Writer queue put routine.
253: */
254:
255: trcput (q, b)
256: register struct queue *q;
257: register struct block *b;
258: {
259: register struct queue *qnext = q->next;
260:
261: if (b->type != M_IOCTL || !trcioctl (q, b)) {
262: trcprint (q, b);
263: (*qnext->qinfo->putp)(qnext, b);
264: }
265: trcupdate (q);
266: return;
267: }
268:
269:
270: trcupdate (q)
271: register struct queue *q;
272: {
273: register struct queue *qnext = q->next;
274:
275: q->flag |= qnext->flag & (QFULL|QWANTR) | backq(q)->flag & QDELIM;
276: qnext->flag |= q->flag & QWANTW;
277: q->count = qnext->count;
278: return;
279: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.