xref: /freebsd/usr.bin/kdump/kdump.c (revision eb6d21b4ca6d668cf89afd99eef7baeafa712197)
1 /*-
2  * Copyright (c) 1988, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #ifndef lint
35 static const char copyright[] =
36 "@(#) Copyright (c) 1988, 1993\n\
37 	The Regents of the University of California.  All rights reserved.\n";
38 #endif /* not lint */
39 
40 #ifndef lint
41 #if 0
42 static char sccsid[] = "@(#)kdump.c	8.1 (Berkeley) 6/6/93";
43 #endif
44 #endif /* not lint */
45 #include <sys/cdefs.h>
46 __FBSDID("$FreeBSD$");
47 
48 #define _KERNEL
49 extern int errno;
50 #include <sys/errno.h>
51 #undef _KERNEL
52 #include <sys/param.h>
53 #include <sys/errno.h>
54 #define _KERNEL
55 #include <sys/time.h>
56 #undef _KERNEL
57 #include <sys/uio.h>
58 #include <sys/ktrace.h>
59 #include <sys/ioctl.h>
60 #include <sys/socket.h>
61 #include <sys/stat.h>
62 #include <sys/un.h>
63 #ifdef IPX
64 #include <sys/types.h>
65 #include <netipx/ipx.h>
66 #endif
67 #ifdef NETATALK
68 #include <netatalk/at.h>
69 #endif
70 #include <arpa/inet.h>
71 #include <netinet/in.h>
72 #include <ctype.h>
73 #include <dlfcn.h>
74 #include <err.h>
75 #include <grp.h>
76 #include <inttypes.h>
77 #include <locale.h>
78 #include <pwd.h>
79 #include <stdio.h>
80 #include <stdlib.h>
81 #include <string.h>
82 #include <time.h>
83 #include <unistd.h>
84 #include <vis.h>
85 #include "ktrace.h"
86 #include "kdump_subr.h"
87 
88 int fread_tail(void *, int, int);
89 void dumpheader(struct ktr_header *);
90 void ktrsyscall(struct ktr_syscall *);
91 void ktrsysret(struct ktr_sysret *);
92 void ktrnamei(char *, int);
93 void hexdump(char *, int, int);
94 void visdump(char *, int, int);
95 void ktrgenio(struct ktr_genio *, int);
96 void ktrpsig(struct ktr_psig *);
97 void ktrcsw(struct ktr_csw *);
98 void ktruser(int, unsigned char *);
99 void ktrsockaddr(struct sockaddr *);
100 void ktrstat(struct stat *);
101 void ktrstruct(char *, size_t);
102 void usage(void);
103 void sockfamilyname(int);
104 const char *ioctlname(u_long);
105 
106 int timestamp, decimal, fancy = 1, suppressdata, tail, threads, maxdata,
107     resolv = 0;
108 const char *tracefile = DEF_TRACEFILE;
109 struct ktr_header ktr_header;
110 
111 #define TIME_FORMAT	"%b %e %T %Y"
112 #define eqs(s1, s2)	(strcmp((s1), (s2)) == 0)
113 
114 int
115 main(int argc, char *argv[])
116 {
117 	int ch, ktrlen, size;
118 	void *m;
119 	int trpoints = ALL_POINTS;
120 	int drop_logged;
121 	pid_t pid = 0;
122 
123 	(void) setlocale(LC_CTYPE, "");
124 
125 	while ((ch = getopt(argc,argv,"f:dElm:np:HRrsTt:")) != -1)
126 		switch((char)ch) {
127 		case 'f':
128 			tracefile = optarg;
129 			break;
130 		case 'd':
131 			decimal = 1;
132 			break;
133 		case 'l':
134 			tail = 1;
135 			break;
136 		case 'm':
137 			maxdata = atoi(optarg);
138 			break;
139 		case 'n':
140 			fancy = 0;
141 			break;
142 		case 'p':
143 			pid = atoi(optarg);
144 			break;
145 		case 'r':
146 			resolv = 1;
147 			break;
148 		case 's':
149 			suppressdata = 1;
150 			break;
151 		case 'E':
152 			timestamp = 3;	/* elapsed timestamp */
153 			break;
154 		case 'H':
155 			threads = 1;
156 			break;
157 		case 'R':
158 			timestamp = 2;	/* relative timestamp */
159 			break;
160 		case 'T':
161 			timestamp = 1;
162 			break;
163 		case 't':
164 			trpoints = getpoints(optarg);
165 			if (trpoints < 0)
166 				errx(1, "unknown trace point in %s", optarg);
167 			break;
168 		default:
169 			usage();
170 		}
171 
172 	if (argc > optind)
173 		usage();
174 
175 	m = (void *)malloc(size = 1025);
176 	if (m == NULL)
177 		errx(1, "%s", strerror(ENOMEM));
178 	if (!freopen(tracefile, "r", stdin))
179 		err(1, "%s", tracefile);
180 	drop_logged = 0;
181 	while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
182 		if (ktr_header.ktr_type & KTR_DROP) {
183 			ktr_header.ktr_type &= ~KTR_DROP;
184 			if (!drop_logged && threads) {
185 				(void)printf("%6d %6d %-8.*s Events dropped.\n",
186 				    ktr_header.ktr_pid, ktr_header.ktr_tid >
187 				    0 ? ktr_header.ktr_tid : 0, MAXCOMLEN,
188 				    ktr_header.ktr_comm);
189 				drop_logged = 1;
190 			} else if (!drop_logged) {
191 				(void)printf("%6d %-8.*s Events dropped.\n",
192 				    ktr_header.ktr_pid, MAXCOMLEN,
193 				    ktr_header.ktr_comm);
194 				drop_logged = 1;
195 			}
196 		}
197 		if (trpoints & (1<<ktr_header.ktr_type))
198 			if (pid == 0 || ktr_header.ktr_pid == pid)
199 				dumpheader(&ktr_header);
200 		if ((ktrlen = ktr_header.ktr_len) < 0)
201 			errx(1, "bogus length 0x%x", ktrlen);
202 		if (ktrlen > size) {
203 			m = (void *)realloc(m, ktrlen+1);
204 			if (m == NULL)
205 				errx(1, "%s", strerror(ENOMEM));
206 			size = ktrlen;
207 		}
208 		if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
209 			errx(1, "data too short");
210 		if (pid && ktr_header.ktr_pid != pid)
211 			continue;
212 		if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
213 			continue;
214 		drop_logged = 0;
215 		switch (ktr_header.ktr_type) {
216 		case KTR_SYSCALL:
217 			ktrsyscall((struct ktr_syscall *)m);
218 			break;
219 		case KTR_SYSRET:
220 			ktrsysret((struct ktr_sysret *)m);
221 			break;
222 		case KTR_NAMEI:
223 		case KTR_SYSCTL:
224 			ktrnamei(m, ktrlen);
225 			break;
226 		case KTR_GENIO:
227 			ktrgenio((struct ktr_genio *)m, ktrlen);
228 			break;
229 		case KTR_PSIG:
230 			ktrpsig((struct ktr_psig *)m);
231 			break;
232 		case KTR_CSW:
233 			ktrcsw((struct ktr_csw *)m);
234 			break;
235 		case KTR_USER:
236 			ktruser(ktrlen, m);
237 			break;
238 		case KTR_STRUCT:
239 			ktrstruct(m, ktrlen);
240 			break;
241 		default:
242 			printf("\n");
243 			break;
244 		}
245 		if (tail)
246 			(void)fflush(stdout);
247 	}
248 	return 0;
249 }
250 
251 int
252 fread_tail(void *buf, int size, int num)
253 {
254 	int i;
255 
256 	while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
257 		(void)sleep(1);
258 		clearerr(stdin);
259 	}
260 	return (i);
261 }
262 
263 void
264 dumpheader(struct ktr_header *kth)
265 {
266 	static char unknown[64];
267 	static struct timeval prevtime, temp;
268 	const char *type;
269 
270 	switch (kth->ktr_type) {
271 	case KTR_SYSCALL:
272 		type = "CALL";
273 		break;
274 	case KTR_SYSRET:
275 		type = "RET ";
276 		break;
277 	case KTR_NAMEI:
278 		type = "NAMI";
279 		break;
280 	case KTR_GENIO:
281 		type = "GIO ";
282 		break;
283 	case KTR_PSIG:
284 		type = "PSIG";
285 		break;
286 	case KTR_CSW:
287 		type = "CSW ";
288 		break;
289 	case KTR_USER:
290 		type = "USER";
291 		break;
292 	case KTR_STRUCT:
293 		type = "STRU";
294 		break;
295 	case KTR_SYSCTL:
296 		type = "SCTL";
297 		break;
298 	default:
299 		(void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
300 		type = unknown;
301 	}
302 
303 	/*
304 	 * The ktr_tid field was previously the ktr_buffer field, which held
305 	 * the kernel pointer value for the buffer associated with data
306 	 * following the record header.  It now holds a threadid, but only
307 	 * for trace files after the change.  Older trace files still contain
308 	 * kernel pointers.  Detect this and suppress the results by printing
309 	 * negative tid's as 0.
310 	 */
311 	if (threads)
312 		(void)printf("%6d %6d %-8.*s ", kth->ktr_pid, kth->ktr_tid >
313 		    0 ? kth->ktr_tid : 0, MAXCOMLEN, kth->ktr_comm);
314 	else
315 		(void)printf("%6d %-8.*s ", kth->ktr_pid, MAXCOMLEN,
316 		    kth->ktr_comm);
317 	if (timestamp) {
318 		if (timestamp == 3) {
319 			if (prevtime.tv_sec == 0)
320 				prevtime = kth->ktr_time;
321 			timevalsub(&kth->ktr_time, &prevtime);
322 		}
323 		if (timestamp == 2) {
324 			temp = kth->ktr_time;
325 			timevalsub(&kth->ktr_time, &prevtime);
326 			prevtime = temp;
327 		}
328 		(void)printf("%ld.%06ld ",
329 		    kth->ktr_time.tv_sec, kth->ktr_time.tv_usec);
330 	}
331 	(void)printf("%s  ", type);
332 }
333 
334 #include <sys/syscall.h>
335 #define KTRACE
336 #include <sys/kern/syscalls.c>
337 #undef KTRACE
338 int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]);
339 
340 void
341 ktrsyscall(struct ktr_syscall *ktr)
342 {
343 	int narg = ktr->ktr_narg;
344 	register_t *ip;
345 
346 	if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0)
347 		(void)printf("[%d]", ktr->ktr_code);
348 	else
349 		(void)printf("%s", syscallnames[ktr->ktr_code]);
350 	ip = &ktr->ktr_args[0];
351 	if (narg) {
352 		char c = '(';
353 		if (fancy) {
354 
355 #define print_number(i,n,c) do {                      \
356 	if (decimal)                                  \
357 		(void)printf("%c%ld", c, (long)*i);   \
358 	else                                          \
359 		(void)printf("%c%#lx", c, (long)*i);  \
360 	i++;                                          \
361 	n--;                                          \
362 	c = ',';                                      \
363 	} while (0);
364 
365 			if (ktr->ktr_code == SYS_ioctl) {
366 				const char *cp;
367 				print_number(ip,narg,c);
368 				if ((cp = ioctlname(*ip)) != NULL)
369 					(void)printf(",%s", cp);
370 				else {
371 					if (decimal)
372 						(void)printf(",%ld", (long)*ip);
373 					else
374 						(void)printf(",%#lx ", (long)*ip);
375 				}
376 				c = ',';
377 				ip++;
378 				narg--;
379 			} else if (ktr->ktr_code == SYS_ptrace) {
380 				(void)putchar('(');
381 				ptraceopname ((int)*ip);
382 				c = ',';
383 				ip++;
384 				narg--;
385 			} else if (ktr->ktr_code == SYS_access ||
386 				   ktr->ktr_code == SYS_eaccess) {
387 				print_number(ip,narg,c);
388 				(void)putchar(',');
389 				accessmodename ((int)*ip);
390 				ip++;
391 				narg--;
392 			} else if (ktr->ktr_code == SYS_open) {
393 				int	flags;
394 				int	mode;
395 				print_number(ip,narg,c);
396 				flags = *ip;
397 				mode = *++ip;
398 				(void)putchar(',');
399 				flagsandmodename (flags, mode, decimal);
400 				ip++;
401 				narg-=2;
402 			} else if (ktr->ktr_code == SYS_wait4) {
403 				print_number(ip,narg,c);
404 				print_number(ip,narg,c);
405 				(void)putchar(',');
406 				wait4optname ((int)*ip);
407 				ip++;
408 				narg--;
409 			} else if (ktr->ktr_code == SYS_chmod ||
410 				   ktr->ktr_code == SYS_fchmod ||
411 				   ktr->ktr_code == SYS_lchmod) {
412 				print_number(ip,narg,c);
413 				(void)putchar(',');
414 				modename ((int)*ip);
415 				ip++;
416 				narg--;
417 			} else if (ktr->ktr_code == SYS_mknod) {
418 				print_number(ip,narg,c);
419 				(void)putchar(',');
420 				modename ((int)*ip);
421 				ip++;
422 				narg--;
423 			} else if (ktr->ktr_code == SYS_getfsstat) {
424 				print_number(ip,narg,c);
425 				print_number(ip,narg,c);
426 				(void)putchar(',');
427 				getfsstatflagsname ((int)*ip);
428 				ip++;
429 				narg--;
430 			} else if (ktr->ktr_code == SYS_mount) {
431 				print_number(ip,narg,c);
432 				print_number(ip,narg,c);
433 				(void)putchar(',');
434 				mountflagsname ((int)*ip);
435 				ip++;
436 				narg--;
437 			} else if (ktr->ktr_code == SYS_unmount) {
438 				print_number(ip,narg,c);
439 				(void)putchar(',');
440 				mountflagsname ((int)*ip);
441 				ip++;
442 				narg--;
443 			} else if (ktr->ktr_code == SYS_recvmsg ||
444 				   ktr->ktr_code == SYS_sendmsg) {
445 				print_number(ip,narg,c);
446 				print_number(ip,narg,c);
447 				(void)putchar(',');
448 				sendrecvflagsname ((int)*ip);
449 				ip++;
450 				narg--;
451 			} else if (ktr->ktr_code == SYS_recvfrom ||
452 				   ktr->ktr_code == SYS_sendto) {
453 				print_number(ip,narg,c);
454 				print_number(ip,narg,c);
455 				print_number(ip,narg,c);
456 				(void)putchar(',');
457 				sendrecvflagsname ((int)*ip);
458 				ip++;
459 				narg--;
460 			} else if (ktr->ktr_code == SYS_chflags ||
461 				   ktr->ktr_code == SYS_fchflags ||
462 				   ktr->ktr_code == SYS_lchflags) {
463 				print_number(ip,narg,c);
464 				(void)putchar(',');
465 				modename((int)*ip);
466 				ip++;
467 				narg--;
468 			} else if (ktr->ktr_code == SYS_kill) {
469 				print_number(ip,narg,c);
470 				(void)putchar(',');
471 				signame((int)*ip);
472 				ip++;
473 				narg--;
474 			} else if (ktr->ktr_code == SYS_reboot) {
475 				(void)putchar('(');
476 				rebootoptname((int)*ip);
477 				ip++;
478 				narg--;
479 			} else if (ktr->ktr_code == SYS_umask) {
480 				(void)putchar('(');
481 				modename((int)*ip);
482 				ip++;
483 				narg--;
484 			} else if (ktr->ktr_code == SYS_msync) {
485 				print_number(ip,narg,c);
486 				print_number(ip,narg,c);
487 				(void)putchar(',');
488 				msyncflagsname((int)*ip);
489 				ip++;
490 				narg--;
491 #ifdef SYS_freebsd6_mmap
492 			} else if (ktr->ktr_code == SYS_freebsd6_mmap) {
493 				print_number(ip,narg,c);
494 				print_number(ip,narg,c);
495 				(void)putchar(',');
496 				mmapprotname ((int)*ip);
497 				(void)putchar(',');
498 				ip++;
499 				narg--;
500 				mmapflagsname ((int)*ip);
501 				ip++;
502 				narg--;
503 #endif
504 			} else if (ktr->ktr_code == SYS_mmap) {
505 				print_number(ip,narg,c);
506 				print_number(ip,narg,c);
507 				(void)putchar(',');
508 				mmapprotname ((int)*ip);
509 				(void)putchar(',');
510 				ip++;
511 				narg--;
512 				mmapflagsname ((int)*ip);
513 				ip++;
514 				narg--;
515 			} else if (ktr->ktr_code == SYS_mprotect) {
516 				print_number(ip,narg,c);
517 				print_number(ip,narg,c);
518 				(void)putchar(',');
519 				mmapprotname ((int)*ip);
520 				ip++;
521 				narg--;
522 			} else if (ktr->ktr_code == SYS_madvise) {
523 				print_number(ip,narg,c);
524 				print_number(ip,narg,c);
525 				(void)putchar(',');
526 				madvisebehavname((int)*ip);
527 				ip++;
528 				narg--;
529 			} else if (ktr->ktr_code == SYS_setpriority) {
530 				print_number(ip,narg,c);
531 				print_number(ip,narg,c);
532 				(void)putchar(',');
533 				prioname((int)*ip);
534 				ip++;
535 				narg--;
536 			} else if (ktr->ktr_code == SYS_fcntl) {
537 				int cmd;
538 				int arg;
539 				print_number(ip,narg,c);
540 				cmd = *ip;
541 				arg = *++ip;
542 				(void)putchar(',');
543 				fcntlcmdname(cmd, arg, decimal);
544 				ip++;
545 				narg-=2;
546 			} else if (ktr->ktr_code == SYS_socket) {
547 				int sockdomain;
548 				(void)putchar('(');
549 				sockdomain=(int)*ip;
550 				sockdomainname(sockdomain);
551 				ip++;
552 				narg--;
553 				(void)putchar(',');
554 				socktypename((int)*ip);
555 				ip++;
556 				narg--;
557 				if (sockdomain == PF_INET ||
558 				    sockdomain == PF_INET6) {
559 					(void)putchar(',');
560 					sockipprotoname((int)*ip);
561 					ip++;
562 					narg--;
563 				}
564 				c = ',';
565 			} else if (ktr->ktr_code == SYS_setsockopt ||
566 				   ktr->ktr_code == SYS_getsockopt) {
567 				print_number(ip,narg,c);
568 				(void)putchar(',');
569 				sockoptlevelname((int)*ip, decimal);
570 				if ((int)*ip == SOL_SOCKET) {
571 					ip++;
572 					narg--;
573 					(void)putchar(',');
574 					sockoptname((int)*ip);
575 				}
576 				ip++;
577 				narg--;
578 #ifdef SYS_freebsd6_lseek
579 			} else if (ktr->ktr_code == SYS_freebsd6_lseek) {
580 				print_number(ip,narg,c);
581 				/* Hidden 'pad' argument, not in lseek(2) */
582 				print_number(ip,narg,c);
583 				print_number(ip,narg,c);
584 				(void)putchar(',');
585 				whencename ((int)*ip);
586 				ip++;
587 				narg--;
588 #endif
589 			} else if (ktr->ktr_code == SYS_lseek) {
590 				print_number(ip,narg,c);
591 				/* Hidden 'pad' argument, not in lseek(2) */
592 				print_number(ip,narg,c);
593 				(void)putchar(',');
594 				whencename ((int)*ip);
595 				ip++;
596 				narg--;
597 
598 			} else if (ktr->ktr_code == SYS_flock) {
599 				print_number(ip,narg,c);
600 				(void)putchar(',');
601 				flockname((int)*ip);
602 				ip++;
603 				narg--;
604 			} else if (ktr->ktr_code == SYS_mkfifo ||
605 				   ktr->ktr_code == SYS_mkdir) {
606 				print_number(ip,narg,c);
607 				(void)putchar(',');
608 				modename((int)*ip);
609 				ip++;
610 				narg--;
611 			} else if (ktr->ktr_code == SYS_shutdown) {
612 				print_number(ip,narg,c);
613 				(void)putchar(',');
614 				shutdownhowname((int)*ip);
615 				ip++;
616 				narg--;
617 			} else if (ktr->ktr_code == SYS_socketpair) {
618 				(void)putchar('(');
619 				sockdomainname((int)*ip);
620 				ip++;
621 				narg--;
622 				(void)putchar(',');
623 				socktypename((int)*ip);
624 				ip++;
625 				narg--;
626 				c = ',';
627 			} else if (ktr->ktr_code == SYS_getrlimit ||
628 				   ktr->ktr_code == SYS_setrlimit) {
629 				(void)putchar('(');
630 				rlimitname((int)*ip);
631 				ip++;
632 				narg--;
633 				c = ',';
634 			} else if (ktr->ktr_code == SYS_quotactl) {
635 				print_number(ip,narg,c);
636 				(void)putchar(',');
637 				quotactlname((int)*ip);
638 				ip++;
639 				narg--;
640 				c = ',';
641 			} else if (ktr->ktr_code == SYS_nfssvc) {
642 				(void)putchar('(');
643 				nfssvcname((int)*ip);
644 				ip++;
645 				narg--;
646 				c = ',';
647 			} else if (ktr->ktr_code == SYS_rtprio) {
648 				(void)putchar('(');
649 				rtprioname((int)*ip);
650 				ip++;
651 				narg--;
652 				c = ',';
653 			} else if (ktr->ktr_code == SYS___semctl) {
654 				print_number(ip,narg,c);
655 				print_number(ip,narg,c);
656 				(void)putchar(',');
657 				semctlname((int)*ip);
658 				ip++;
659 				narg--;
660 			} else if (ktr->ktr_code == SYS_semget) {
661 				print_number(ip,narg,c);
662 				print_number(ip,narg,c);
663 				(void)putchar(',');
664 				semgetname((int)*ip);
665 				ip++;
666 				narg--;
667 			} else if (ktr->ktr_code == SYS_msgctl) {
668 				print_number(ip,narg,c);
669 				(void)putchar(',');
670 				shmctlname((int)*ip);
671 				ip++;
672 				narg--;
673 			} else if (ktr->ktr_code == SYS_shmat) {
674 				print_number(ip,narg,c);
675 				print_number(ip,narg,c);
676 				(void)putchar(',');
677 				shmatname((int)*ip);
678 				ip++;
679 				narg--;
680 			} else if (ktr->ktr_code == SYS_shmctl) {
681 				print_number(ip,narg,c);
682 				(void)putchar(',');
683 				shmctlname((int)*ip);
684 				ip++;
685 				narg--;
686 			} else if (ktr->ktr_code == SYS_minherit) {
687 				print_number(ip,narg,c);
688 				print_number(ip,narg,c);
689 				(void)putchar(',');
690 				minheritname((int)*ip);
691 				ip++;
692 				narg--;
693 			} else if (ktr->ktr_code == SYS_rfork) {
694 				(void)putchar('(');
695 				rforkname((int)*ip);
696 				ip++;
697 				narg--;
698 				c = ',';
699 			} else if (ktr->ktr_code == SYS_lio_listio) {
700 				(void)putchar('(');
701 				lio_listioname((int)*ip);
702 				ip++;
703 				narg--;
704 				c = ',';
705 			} else if (ktr->ktr_code == SYS_mlockall) {
706 				(void)putchar('(');
707 				mlockallname((int)*ip);
708 				ip++;
709 				narg--;
710 			} else if (ktr->ktr_code == SYS_sched_setscheduler) {
711 				print_number(ip,narg,c);
712 				(void)putchar(',');
713 				schedpolicyname((int)*ip);
714 				ip++;
715 				narg--;
716 			} else if (ktr->ktr_code == SYS_sched_get_priority_max ||
717 				   ktr->ktr_code == SYS_sched_get_priority_min) {
718 				(void)putchar('(');
719 				schedpolicyname((int)*ip);
720 				ip++;
721 				narg--;
722 			} else if (ktr->ktr_code == SYS_sendfile) {
723 				print_number(ip,narg,c);
724 				print_number(ip,narg,c);
725 				print_number(ip,narg,c);
726 				print_number(ip,narg,c);
727 				print_number(ip,narg,c);
728 				print_number(ip,narg,c);
729 				(void)putchar(',');
730 				sendfileflagsname((int)*ip);
731 				ip++;
732 				narg--;
733 			} else if (ktr->ktr_code == SYS_kldsym) {
734 				print_number(ip,narg,c);
735 				(void)putchar(',');
736 				kldsymcmdname((int)*ip);
737 				ip++;
738 				narg--;
739 			} else if (ktr->ktr_code == SYS_sigprocmask) {
740 				(void)putchar('(');
741 				sigprocmaskhowname((int)*ip);
742 				ip++;
743 				narg--;
744 				c = ',';
745 			} else if (ktr->ktr_code == SYS___acl_get_file ||
746 				   ktr->ktr_code == SYS___acl_set_file ||
747 				   ktr->ktr_code == SYS___acl_get_fd ||
748 				   ktr->ktr_code == SYS___acl_set_fd ||
749 				   ktr->ktr_code == SYS___acl_delete_file ||
750 				   ktr->ktr_code == SYS___acl_delete_fd ||
751 				   ktr->ktr_code == SYS___acl_aclcheck_file ||
752 				   ktr->ktr_code == SYS___acl_aclcheck_fd ||
753 				   ktr->ktr_code == SYS___acl_get_link ||
754 				   ktr->ktr_code == SYS___acl_set_link ||
755 				   ktr->ktr_code == SYS___acl_delete_link ||
756 				   ktr->ktr_code == SYS___acl_aclcheck_link) {
757 				print_number(ip,narg,c);
758 				(void)putchar(',');
759 				acltypename((int)*ip);
760 				ip++;
761 				narg--;
762 			} else if (ktr->ktr_code == SYS_sigaction) {
763 				(void)putchar('(');
764 				signame((int)*ip);
765 				ip++;
766 				narg--;
767 				c = ',';
768 			} else if (ktr->ktr_code == SYS_extattrctl) {
769 				print_number(ip,narg,c);
770 				(void)putchar(',');
771 				extattrctlname((int)*ip);
772 				ip++;
773 				narg--;
774 			} else if (ktr->ktr_code == SYS_nmount) {
775 				print_number(ip,narg,c);
776 				print_number(ip,narg,c);
777 				(void)putchar(',');
778 				mountflagsname ((int)*ip);
779 				ip++;
780 				narg--;
781 			} else if (ktr->ktr_code == SYS_thr_create) {
782 				print_number(ip,narg,c);
783 				print_number(ip,narg,c);
784 				(void)putchar(',');
785 				thrcreateflagsname ((int)*ip);
786 				ip++;
787 				narg--;
788 			} else if (ktr->ktr_code == SYS_thr_kill) {
789 				print_number(ip,narg,c);
790 				(void)putchar(',');
791 				signame ((int)*ip);
792 				ip++;
793 				narg--;
794 			} else if (ktr->ktr_code == SYS_kldunloadf) {
795 				print_number(ip,narg,c);
796 				(void)putchar(',');
797 				kldunloadfflagsname ((int)*ip);
798 				ip++;
799 				narg--;
800 			}
801 		}
802 		while (narg > 0) {
803 			print_number(ip,narg,c);
804 		}
805 		(void)putchar(')');
806 	}
807 	(void)putchar('\n');
808 }
809 
810 void
811 ktrsysret(struct ktr_sysret *ktr)
812 {
813 	register_t ret = ktr->ktr_retval;
814 	int error = ktr->ktr_error;
815 	int code = ktr->ktr_code;
816 
817 	if (code >= nsyscalls || code < 0)
818 		(void)printf("[%d] ", code);
819 	else
820 		(void)printf("%s ", syscallnames[code]);
821 
822 	if (error == 0) {
823 		if (fancy) {
824 			(void)printf("%d", ret);
825 			if (ret < 0 || ret > 9)
826 				(void)printf("/%#lx", (long)ret);
827 		} else {
828 			if (decimal)
829 				(void)printf("%ld", (long)ret);
830 			else
831 				(void)printf("%#lx", (long)ret);
832 		}
833 	} else if (error == ERESTART)
834 		(void)printf("RESTART");
835 	else if (error == EJUSTRETURN)
836 		(void)printf("JUSTRETURN");
837 	else {
838 		(void)printf("-1 errno %d", ktr->ktr_error);
839 		if (fancy)
840 			(void)printf(" %s", strerror(ktr->ktr_error));
841 	}
842 	(void)putchar('\n');
843 }
844 
845 void
846 ktrnamei(char *cp, int len)
847 {
848 	(void)printf("\"%.*s\"\n", len, cp);
849 }
850 
851 void
852 hexdump(char *p, int len, int screenwidth)
853 {
854 	int n, i;
855 	int width;
856 
857 	width = 0;
858 	do {
859 		width += 2;
860 		i = 13;			/* base offset */
861 		i += (width / 2) + 1;	/* spaces every second byte */
862 		i += (width * 2);	/* width of bytes */
863 		i += 3;			/* "  |" */
864 		i += width;		/* each byte */
865 		i += 1;			/* "|" */
866 	} while (i < screenwidth);
867 	width -= 2;
868 
869 	for (n = 0; n < len; n += width) {
870 		for (i = n; i < n + width; i++) {
871 			if ((i % width) == 0) {	/* beginning of line */
872 				printf("       0x%04x", i);
873 			}
874 			if ((i % 2) == 0) {
875 				printf(" ");
876 			}
877 			if (i < len)
878 				printf("%02x", p[i] & 0xff);
879 			else
880 				printf("  ");
881 		}
882 		printf("  |");
883 		for (i = n; i < n + width; i++) {
884 			if (i >= len)
885 				break;
886 			if (p[i] >= ' ' && p[i] <= '~')
887 				printf("%c", p[i]);
888 			else
889 				printf(".");
890 		}
891 		printf("|\n");
892 	}
893 	if ((i % width) != 0)
894 		printf("\n");
895 }
896 
897 void
898 visdump(char *dp, int datalen, int screenwidth)
899 {
900 	int col = 0;
901 	char *cp;
902 	int width;
903 	char visbuf[5];
904 
905 	(void)printf("       \"");
906 	col = 8;
907 	for (;datalen > 0; datalen--, dp++) {
908 		(void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
909 		cp = visbuf;
910 		/*
911 		 * Keep track of printables and
912 		 * space chars (like fold(1)).
913 		 */
914 		if (col == 0) {
915 			(void)putchar('\t');
916 			col = 8;
917 		}
918 		switch(*cp) {
919 		case '\n':
920 			col = 0;
921 			(void)putchar('\n');
922 			continue;
923 		case '\t':
924 			width = 8 - (col&07);
925 			break;
926 		default:
927 			width = strlen(cp);
928 		}
929 		if (col + width > (screenwidth-2)) {
930 			(void)printf("\\\n\t");
931 			col = 8;
932 		}
933 		col += width;
934 		do {
935 			(void)putchar(*cp++);
936 		} while (*cp);
937 	}
938 	if (col == 0)
939 		(void)printf("       ");
940 	(void)printf("\"\n");
941 }
942 
943 void
944 ktrgenio(struct ktr_genio *ktr, int len)
945 {
946 	int datalen = len - sizeof (struct ktr_genio);
947 	char *dp = (char *)ktr + sizeof (struct ktr_genio);
948 	static int screenwidth = 0;
949 	int i, binary;
950 
951 	if (screenwidth == 0) {
952 		struct winsize ws;
953 
954 		if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
955 		    ws.ws_col > 8)
956 			screenwidth = ws.ws_col;
957 		else
958 			screenwidth = 80;
959 	}
960 	printf("fd %d %s %d byte%s\n", ktr->ktr_fd,
961 		ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen,
962 		datalen == 1 ? "" : "s");
963 	if (suppressdata)
964 		return;
965 	if (maxdata && datalen > maxdata)
966 		datalen = maxdata;
967 
968 	for (i = 0, binary = 0; i < datalen && binary == 0; i++)  {
969 		if (dp[i] >= 32 && dp[i] < 127)
970 			continue;
971 		if (dp[i] == 10 || dp[i] == 13 || dp[i] == 0 || dp[i] == 9)
972 			continue;
973 		binary = 1;
974 	}
975 	if (binary)
976 		hexdump(dp, datalen, screenwidth);
977 	else
978 		visdump(dp, datalen, screenwidth);
979 }
980 
981 const char *signames[] = {
982 	"NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",	/*  1 - 6  */
983 	"EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",		/*  7 - 12 */
984 	"PIPE", "ALRM",  "TERM", "URG", "STOP", "TSTP",		/* 13 - 18 */
985 	"CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU",		/* 19 - 24 */
986 	"XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1",	/* 25 - 30 */
987 	"USR2", NULL,						/* 31 - 32 */
988 };
989 
990 void
991 ktrpsig(struct ktr_psig *psig)
992 {
993 	if (psig->signo > 0 && psig->signo < NSIG)
994 		(void)printf("SIG%s ", signames[psig->signo]);
995 	else
996 		(void)printf("SIG %d ", psig->signo);
997 	if (psig->action == SIG_DFL)
998 		(void)printf("SIG_DFL\n");
999 	else {
1000 		(void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n",
1001 		    (u_long)psig->action, psig->mask.__bits[0], psig->code);
1002 	}
1003 }
1004 
1005 void
1006 ktrcsw(struct ktr_csw *cs)
1007 {
1008 	(void)printf("%s %s\n", cs->out ? "stop" : "resume",
1009 		cs->user ? "user" : "kernel");
1010 }
1011 
1012 #define	UTRACE_DLOPEN_START		1
1013 #define	UTRACE_DLOPEN_STOP		2
1014 #define	UTRACE_DLCLOSE_START		3
1015 #define	UTRACE_DLCLOSE_STOP		4
1016 #define	UTRACE_LOAD_OBJECT		5
1017 #define	UTRACE_UNLOAD_OBJECT		6
1018 #define	UTRACE_ADD_RUNDEP		7
1019 #define	UTRACE_PRELOAD_FINISHED		8
1020 #define	UTRACE_INIT_CALL		9
1021 #define	UTRACE_FINI_CALL		10
1022 
1023 struct utrace_rtld {
1024 	char sig[4];				/* 'RTLD' */
1025 	int event;
1026 	void *handle;
1027 	void *mapbase;
1028 	size_t mapsize;
1029 	int refcnt;
1030 	char name[MAXPATHLEN];
1031 };
1032 
1033 void
1034 ktruser_rtld(int len, unsigned char *p)
1035 {
1036 	struct utrace_rtld *ut = (struct utrace_rtld *)p;
1037 	void *parent;
1038 	int mode;
1039 
1040 	switch (ut->event) {
1041 	case UTRACE_DLOPEN_START:
1042 		mode = ut->refcnt;
1043 		printf("dlopen(%s, ", ut->name);
1044 		switch (mode & RTLD_MODEMASK) {
1045 		case RTLD_NOW:
1046 			printf("RTLD_NOW");
1047 			break;
1048 		case RTLD_LAZY:
1049 			printf("RTLD_LAZY");
1050 			break;
1051 		default:
1052 			printf("%#x", mode & RTLD_MODEMASK);
1053 		}
1054 		if (mode & RTLD_GLOBAL)
1055 			printf(" | RTLD_GLOBAL");
1056 		if (mode & RTLD_TRACE)
1057 			printf(" | RTLD_TRACE");
1058 		if (mode & ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE))
1059 			printf(" | %#x", mode &
1060 			    ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE));
1061 		printf(")\n");
1062 		break;
1063 	case UTRACE_DLOPEN_STOP:
1064 		printf("%p = dlopen(%s) ref %d\n", ut->handle, ut->name,
1065 		    ut->refcnt);
1066 		break;
1067 	case UTRACE_DLCLOSE_START:
1068 		printf("dlclose(%p) (%s, %d)\n", ut->handle, ut->name,
1069 		    ut->refcnt);
1070 		break;
1071 	case UTRACE_DLCLOSE_STOP:
1072 		printf("dlclose(%p) finished\n", ut->handle);
1073 		break;
1074 	case UTRACE_LOAD_OBJECT:
1075 		printf("RTLD: loaded   %p @ %p - %p (%s)\n", ut->handle,
1076 		    ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
1077 		    ut->name);
1078 		break;
1079 	case UTRACE_UNLOAD_OBJECT:
1080 		printf("RTLD: unloaded %p @ %p - %p (%s)\n", ut->handle,
1081 		    ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
1082 		    ut->name);
1083 		break;
1084 	case UTRACE_ADD_RUNDEP:
1085 		parent = ut->mapbase;
1086 		printf("RTLD: %p now depends on %p (%s, %d)\n", parent,
1087 		    ut->handle, ut->name, ut->refcnt);
1088 		break;
1089 	case UTRACE_PRELOAD_FINISHED:
1090 		printf("RTLD: LD_PRELOAD finished\n");
1091 		break;
1092 	case UTRACE_INIT_CALL:
1093 		printf("RTLD: init %p for %p (%s)\n", ut->mapbase, ut->handle,
1094 		    ut->name);
1095 		break;
1096 	case UTRACE_FINI_CALL:
1097 		printf("RTLD: fini %p for %p (%s)\n", ut->mapbase, ut->handle,
1098 		    ut->name);
1099 		break;
1100 	default:
1101 		p += 4;
1102 		len -= 4;
1103 		printf("RTLD: %d ", len);
1104 		while (len--)
1105 			if (decimal)
1106 				printf(" %d", *p++);
1107 			else
1108 				printf(" %02x", *p++);
1109 		printf("\n");
1110 	}
1111 }
1112 
1113 struct utrace_malloc {
1114 	void *p;
1115 	size_t s;
1116 	void *r;
1117 };
1118 
1119 void
1120 ktruser_malloc(int len, unsigned char *p)
1121 {
1122 	struct utrace_malloc *ut = (struct utrace_malloc *)p;
1123 
1124 	if (ut->p == (void *)(intptr_t)(-1))
1125 		printf("malloc_init()\n");
1126 	else if (ut->s == 0)
1127 		printf("free(%p)\n", ut->p);
1128 	else if (ut->p == NULL)
1129 		printf("%p = malloc(%zu)\n", ut->r, ut->s);
1130 	else
1131 		printf("%p = realloc(%p, %zu)\n", ut->r, ut->p, ut->s);
1132 }
1133 
1134 void
1135 ktruser(int len, unsigned char *p)
1136 {
1137 
1138 	if (len >= 8 && bcmp(p, "RTLD", 4) == 0) {
1139 		ktruser_rtld(len, p);
1140 		return;
1141 	}
1142 
1143 	if (len == sizeof(struct utrace_malloc)) {
1144 		ktruser_malloc(len, p);
1145 		return;
1146 	}
1147 
1148 	(void)printf("%d ", len);
1149 	while (len--)
1150 		if (decimal)
1151 			(void)printf(" %d", *p++);
1152 		else
1153 			(void)printf(" %02x", *p++);
1154 	(void)printf("\n");
1155 }
1156 
1157 void
1158 ktrsockaddr(struct sockaddr *sa)
1159 {
1160 /*
1161  TODO: Support additional address families
1162 	#include <netnatm/natm.h>
1163 	struct sockaddr_natm	*natm;
1164 	#include <netsmb/netbios.h>
1165 	struct sockaddr_nb	*nb;
1166 */
1167 	char addr[64];
1168 
1169 	/*
1170 	 * note: ktrstruct() has already verified that sa points to a
1171 	 * buffer at least sizeof(struct sockaddr) bytes long and exactly
1172 	 * sa->sa_len bytes long.
1173 	 */
1174 	printf("struct sockaddr { ");
1175 	sockfamilyname(sa->sa_family);
1176 	printf(", ");
1177 
1178 #define check_sockaddr_len(n)					\
1179 	if (sa_##n->s##n##_len < sizeof(struct sockaddr_##n)) {	\
1180 		printf("invalid");				\
1181 		break;						\
1182 	}
1183 
1184 	switch(sa->sa_family) {
1185 	case AF_INET: {
1186 		struct sockaddr_in	*sa_in;
1187 
1188 		sa_in = (struct sockaddr_in *)sa;
1189 		check_sockaddr_len(in);
1190 		inet_ntop(AF_INET, &sa_in->sin_addr, addr, sizeof addr);
1191 		printf("%s:%u", addr, ntohs(sa_in->sin_port));
1192 		break;
1193 	}
1194 #ifdef NETATALK
1195 	case AF_APPLETALK: {
1196 		struct sockaddr_at	*sa_at;
1197 		struct netrange		*nr;
1198 
1199 		sa_at = (struct sockaddr_at *)sa;
1200 		check_sockaddr_len(at);
1201 		nr = &sa_at->sat_range.r_netrange;
1202 		printf("%d.%d, %d-%d, %d", ntohs(sa_at->sat_addr.s_net),
1203 			sa_at->sat_addr.s_node, ntohs(nr->nr_firstnet),
1204 			ntohs(nr->nr_lastnet), nr->nr_phase);
1205 		break;
1206 	}
1207 #endif
1208 	case AF_INET6: {
1209 		struct sockaddr_in6	*sa_in6;
1210 
1211 		sa_in6 = (struct sockaddr_in6 *)sa;
1212 		check_sockaddr_len(in6);
1213 		inet_ntop(AF_INET6, &sa_in6->sin6_addr, addr, sizeof addr);
1214 		printf("[%s]:%u", addr, htons(sa_in6->sin6_port));
1215 		break;
1216 	}
1217 #ifdef IPX
1218 	case AF_IPX: {
1219 		struct sockaddr_ipx	*sa_ipx;
1220 
1221 		sa_ipx = (struct sockaddr_ipx *)sa;
1222 		check_sockaddr_len(ipx);
1223 		/* XXX wish we had ipx_ntop */
1224 		printf("%s", ipx_ntoa(sa_ipx->sipx_addr));
1225 		break;
1226 	}
1227 #endif
1228 	case AF_UNIX: {
1229 		struct sockaddr_un *sa_un;
1230 
1231 		sa_un = (struct sockaddr_un *)sa;
1232 		check_sockaddr_len(un);
1233 		printf("%.*s", (int)sizeof(sa_un->sun_path), sa_un->sun_path);
1234 		break;
1235 	}
1236 	default:
1237 		printf("unknown address family");
1238 	}
1239 	printf(" }\n");
1240 }
1241 
1242 void
1243 ktrstat(struct stat *statp)
1244 {
1245 	char mode[12], timestr[PATH_MAX + 4];
1246 	struct passwd *pwd;
1247 	struct group  *grp;
1248 	struct tm *tm;
1249 
1250 	/*
1251 	 * note: ktrstruct() has already verified that statp points to a
1252 	 * buffer exactly sizeof(struct stat) bytes long.
1253 	 */
1254 	printf("struct stat {");
1255 	strmode(statp->st_mode, mode);
1256 	printf("dev=%ju, ino=%ju, mode=%s, nlink=%ju, ",
1257 		(uintmax_t)statp->st_dev, (uintmax_t)statp->st_ino, mode,
1258 		(uintmax_t)statp->st_nlink);
1259 	if (resolv == 0 || (pwd = getpwuid(statp->st_uid)) == NULL)
1260 		printf("uid=%ju, ", (uintmax_t)statp->st_uid);
1261 	else
1262 		printf("uid=\"%s\", ", pwd->pw_name);
1263 	if (resolv == 0 || (grp = getgrgid(statp->st_gid)) == NULL)
1264 		printf("gid=%ju, ", (uintmax_t)statp->st_gid);
1265 	else
1266 		printf("gid=\"%s\", ", grp->gr_name);
1267 	printf("rdev=%ju, ", (uintmax_t)statp->st_rdev);
1268 	printf("atime=");
1269 	if (resolv == 0)
1270 		printf("%ld", statp->st_atimespec.tv_sec);
1271 	else {
1272 		tm = localtime(&statp->st_atimespec.tv_sec);
1273 		(void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
1274 		printf("\"%s\"", timestr);
1275 	}
1276 	if (statp->st_atimespec.tv_nsec != 0)
1277 		printf(".%09ld, ", statp->st_atimespec.tv_nsec);
1278 	else
1279 		printf(", ");
1280 	printf("stime=");
1281 	if (resolv == 0)
1282 		printf("%ld", statp->st_mtimespec.tv_sec);
1283 	else {
1284 		tm = localtime(&statp->st_mtimespec.tv_sec);
1285 		(void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
1286 		printf("\"%s\"", timestr);
1287 	}
1288 	if (statp->st_mtimespec.tv_nsec != 0)
1289 		printf(".%09ld, ", statp->st_mtimespec.tv_nsec);
1290 	else
1291 		printf(", ");
1292 	printf("ctime=");
1293 	if (resolv == 0)
1294 		printf("%ld", statp->st_ctimespec.tv_sec);
1295 	else {
1296 		tm = localtime(&statp->st_ctimespec.tv_sec);
1297 		(void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
1298 		printf("\"%s\"", timestr);
1299 	}
1300 	if (statp->st_ctimespec.tv_nsec != 0)
1301 		printf(".%09ld, ", statp->st_ctimespec.tv_nsec);
1302 	else
1303 		printf(", ");
1304 	printf("birthtime=");
1305 	if (resolv == 0)
1306 		printf("%ld", statp->st_birthtimespec.tv_sec);
1307 	else {
1308 		tm = localtime(&statp->st_birthtimespec.tv_sec);
1309 		(void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
1310 		printf("\"%s\"", timestr);
1311 	}
1312 	if (statp->st_birthtimespec.tv_nsec != 0)
1313 		printf(".%09ld, ", statp->st_birthtimespec.tv_nsec);
1314 	else
1315 		printf(", ");
1316 	printf("size=%jd, blksize=%ju, blocks=%jd, flags=0x%x",
1317 		(uintmax_t)statp->st_size, (uintmax_t)statp->st_blksize,
1318 		(intmax_t)statp->st_blocks, statp->st_flags);
1319 	printf(" }\n");
1320 }
1321 
1322 void
1323 ktrstruct(char *buf, size_t buflen)
1324 {
1325 	char *name, *data;
1326 	size_t namelen, datalen;
1327 	int i;
1328 
1329 	for (name = buf, namelen = 0;
1330 	     namelen < buflen && name[namelen] != '\0';
1331 	     ++namelen)
1332 		/* nothing */;
1333 	if (namelen == buflen)
1334 		goto invalid;
1335 	if (name[namelen] != '\0')
1336 		goto invalid;
1337 	data = buf + namelen + 1;
1338 	datalen = buflen - namelen - 1;
1339 	if (datalen == 0)
1340 		goto invalid;
1341 	/* sanity check */
1342 	for (i = 0; i < namelen; ++i)
1343 		if (!isalpha((unsigned char)name[i]))
1344 			goto invalid;
1345 	if (strcmp(name, "stat") == 0) {
1346 		if (datalen != sizeof(struct stat))
1347 			goto invalid;
1348 		ktrstat((struct stat *)data);
1349 	} else if (strcmp(name, "sockaddr") == 0) {
1350 		if (datalen < sizeof(struct sockaddr) ||
1351 		    datalen != ((struct sockaddr *)(data))->sa_len)
1352 			goto invalid;
1353 		ktrsockaddr((struct sockaddr *)data);
1354 	} else {
1355 		printf("unknown structure\n");
1356 	}
1357 	return;
1358 invalid:
1359 	printf("invalid record\n");
1360 }
1361 
1362 void
1363 usage(void)
1364 {
1365 	fprintf(stderr, "usage: kdump [-dEnlHRrsT] [-f trfile] "
1366 	    "[-m maxdata] [-p pid] [-t trstr]\n");
1367 	exit(1);
1368 }
1369