|
|
1.1 root 1: /*
2: * D U M P C A T C H
3: *
4: * This program examines kernel memory through /dev/kmem, and looks at
5: * the dump buffers in the dumpld line discipline (see /usr/sys/dev/dumpld.c).
6: * The command takes a filename prefix. For any active dump buffers,
7: * an identification code is appended to the filename prefix, and everything
8: * placed into the buffer by dumpld is appended to the resulting file.
9: * The identification code is 'M.m.ls', where 'M' is the major device number,
10: * 'm' is the minor device number, 'l' is the line-discipline number (from 0),
11: * and 's' (side) is 'w' for the writer or 'r' for the reader. If the old
12: * version of dumpld is installed in the kernel, the identification code is
13: * just the buffer number (from 0).
14: *
15: *
16: * Written by Kurt Gollhardt (Nirvonics, Inc.)
17: * Last update Sun Mar 31 03:32:57 1985
18: *
19: */
20:
21: #include <stdio.h>
22: #include <ctype.h>
23: #include <nlist.h>
24: #include <sys/types.h>
25: #include <sys/dumpl.h>
26: #include <sys/stream.h>
27:
28: #define getme(s, kind, off, type) _get(kind, off, 1, sizeof(type), &s)
29: #define getarray(s, kind, n, type) _get(kind, 0, n, sizeof(type), s)
30: #define getspace(s, n, type) s = (type *)malloc((n) * sizeof(type))
31:
32: struct nlist nl[] = {
33: #define _ndumpbuf 0
34: {"_ndumpbuf"},
35: #define _dumpld 1
36: {"_dumpld"},
37: #define _dumpver 2
38: {"_dumpver"},
39: #define _dumpinf 3
40: {"_dumpinf"},
41: {""}
42: };
43:
44: #define MEMFILE "/dev/kmem"
45: #define SYMFILE "/unix"
46:
47: struct blockdump {
48: struct dumpheader h;
49: char buf[1024];
50: char *fillp;
51: };
52:
53: int mem;
54: struct dumpld *dumpld;
55: struct dumpinf *dumpinf;
56: struct blockdump *bdump;
57: int ndumpbuf, dumpver;
58: FILE **file;
59: char **readp;
60:
61: char *malloc(), *calloc();
62:
63:
64: main(ac, av)
65: char *av[];
66: {
67: struct dumpld *di;
68: register int i;
69:
70: if (ac != 2) {
71: fprintf(stderr, "Usage: %s filename_prefix\n", av[0]);
72: exit(1);
73: }
74:
75: if (access(SYMFILE, 0) < 0) {
76: perror(SYMFILE);
77: exit(2);
78: }
79: if ((mem = open(MEMFILE, 0)) < 0) {
80: perror(MEMFILE);
81: exit(2);
82: }
83:
84: nlist(SYMFILE, nl);
85: if (nl[_ndumpbuf].n_value == 0) {
86: fprintf(stderr, "No dumpld line-discipline present\n");
87: exit(5);
88: }
89: getme(ndumpbuf, _ndumpbuf, 0, int);
90:
91: if (nl[_dumpver].n_value == 0)
92: dumpver = 0;
93: else
94: getme(dumpver, _dumpver, 0, int);
95:
96: getspace(dumpld, ndumpbuf, struct dumpld);
97: getspace(readp, ndumpbuf, char *);
98: file = (FILE **)calloc(sizeof(FILE *), ndumpbuf);
99: if (dumpld == NULL || file == NULL || readp == NULL) {
100: fprintf(stderr, "Can't allocate enough memory\n");
101: exit(3);
102: }
103: if (dumpver > 0) {
104: getspace(dumpinf, ndumpbuf, struct dumpinf);
105: getspace(bdump, ndumpbuf, struct blockdump);
106: if (dumpinf == NULL || bdump== NULL) {
107: fprintf(stderr, "Can't allocate enough memory\n");
108: exit(3);
109: }
110: for (i = 0; i < ndumpbuf; ++i)
111: bdump[i].fillp = (char *)&bdump[i];
112: }
113:
114: for (;;) {
115: getarray(dumpld, _dumpld, ndumpbuf, struct dumpld);
116: if (dumpver > 0)
117: getarray(dumpinf, _dumpinf, ndumpbuf, struct dumpinf);
118: for (di = dumpld; di < &dumpld[ndumpbuf]; di++)
119: if (di->base != NULL) {
120: if (file[di - dumpld] == 0)
121: new_file(di - dumpld, av[1]);
122: if (readp[di - dumpld] != di->fillp)
123: read_buf(di - dumpld, di);
124: }
125: }
126: }
127:
128:
129: new_file(i, prefix)
130: char *prefix;
131: {
132: char filename[100];
133:
134: if (dumpver == 0)
135: sprintf(filename, "%s%d", prefix, i);
136: else
137: sprintf(filename, "%s%d.%d.%d%c", prefix, major(dumpinf[i].dev),
138: minor(dumpinf[i].dev), i/2, (i&1 ? 'w' : 'r'));
139: if ((file[i] = fopen(filename, "a")) == NULL) {
140: perror(filename);
141: exit(4);
142: }
143:
144: readp[i] = dumpld[i].base;
145: }
146:
147:
148: read_buf(i, di)
149: register struct dumpld *di;
150: {
151: if (di->fillp < readp[i]) {
152: dump(readp[i], (di->base + di->size) - readp[i], file[i], i);
153: readp[i] = di->base;
154: }
155: if (di->fillp > readp[i]) {
156: dump(readp[i], di->fillp - readp[i], file[i], i);
157: readp[i] = di->fillp;
158: }
159: fflush(file[i]);
160: }
161:
162:
163: char buf[BUFSIZ];
164:
165: dump(loc, n, stream, i)
166: char *loc;
167: FILE *stream;
168: {
169: int count;
170:
171: if (dumpver > 0)
172: return fancy_dump(loc, n, stream, i);
173:
174: while (n > 0) {
175: count = (n > BUFSIZ ? BUFSIZ : n);
176: getarray(buf, loc, count, char);
177: fwrite(buf, 1, count, stream);
178: n -= count;
179: loc += count;
180: }
181: }
182:
183:
184: fancy_dump(loc, count, stream, i)
185: char *loc;
186: FILE *stream;
187: {
188: register struct blockdump *bd = &bdump[i];
189: register int n, have_block;
190:
191: while (count > 0) {
192: have_block = 0;
193: n = bd->buf - bd->fillp;
194: if (n <= 0) {
195: have_block = 1;
196: n += bd->h.count;
197: }
198: if (count < n) {
199: have_block = 0;
200: n = count;
201: }
202: if (n > 0) {
203: getarray(bd->fillp, loc, n, char);
204: loc += n; bd->fillp += n;
205: count -= n;
206: }
207: if (have_block) {
208: dump_block(bd, stream);
209: bd->fillp = (char *)bd;
210: }
211: }
212: }
213:
214:
215: #define BYTE_PER_LINE 16
216:
217: dump_block(bd, stream)
218: struct blockdump *bd;
219: FILE *stream;
220: {
221: print_type(bd->h.type, stream);
222: fprintf(stream, ":%s", (bd->h.count == 0 ? "\n" : ""));
223: bd->fillp = bd->buf;
224: while (bd->h.count > 0) {
225: dump_line(bd, stream);
226: bd->h.count -= BYTE_PER_LINE;
227: bd->fillp += BYTE_PER_LINE;
228: }
229: }
230:
231:
232: dump_line(bd, stream)
233: struct blockdump *bd;
234: FILE *stream;
235: {
236: register int n, byte;
237: register char *p;
238: char ascii[BYTE_PER_LINE+1];
239:
240: putc('\t', stream);
241: p = bd->fillp;
242: for (n = 0; n < BYTE_PER_LINE; n++) {
243: byte = *p++ & 0xFF;
244: if (n < bd->h.count)
245: fprintf(stream, "%02x ", byte);
246: else
247: fprintf(stream, " ");
248: ascii[n] = (n < bd->h.count && isprint(byte) ? byte : '.');
249: }
250: ascii[BYTE_PER_LINE] = '\0';
251: fprintf(stream, "!%s!\n", ascii);
252: }
253:
254:
255: char *mtype_names[] = {
256: "DATA", "BREAK", "HANGUP", "DELIM", "ECHO", "ACK", "IOCTL",
257: "DELAY", "CTL", "PASS", "SIGNAL", "FLUSH", "STOP", "START",
258: "IOCACK", "IOCNAK", "CLOSE", "YDEL", "NDEL", "IOCWAIT",NULL
259: };
260: int mtype_codes[] = {
261: M_DATA, M_BREAK, M_HANGUP, M_DELIM, M_ECHO, M_ACK, M_IOCTL,
262: M_DELAY, M_CTL, M_PASS, M_SIGNAL, M_FLUSH, M_STOP, M_START,
263: M_IOCACK, M_IOCNAK, M_CLOSE, M_YDEL, M_NDEL, M_IOCWAIT,0
264: };
265:
266: print_type(type, stream)
267: FILE *stream;
268: {
269: register int i;
270:
271: for (i = 0; mtype_names[i] != NULL; ++i)
272: if (mtype_codes[i] == type) {
273: fputs(mtype_names[i], stream);
274: return;
275: }
276:
277: fprintf(stream, "[%02x]", type);
278: }
279:
280:
281: _get(addr, off, n, size, loc)
282: unsigned long addr;
283: char *loc;
284: {
285: if (addr < sizeof(nl)/sizeof(nl[0]))
286: addr = nl[addr].n_value;
287: addr += off*size;
288: lseek(mem, addr, 0);
289: read(mem, loc, n*size);
290: return(addr);
291: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.